--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Jul 23 13:04:59 2012 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Jul 24 10:51:00 2012 -0700
@@ -88,8 +88,6 @@
RuntimeStub* SharedRuntime::_resolve_static_call_blob;
DeoptimizationBlob* SharedRuntime::_deopt_blob;
-RicochetBlob* SharedRuntime::_ricochet_blob;
-
SafepointBlob* SharedRuntime::_polling_page_safepoint_handler_blob;
SafepointBlob* SharedRuntime::_polling_page_return_handler_blob;
@@ -109,7 +107,6 @@
_polling_page_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), false);
_polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), true);
- generate_ricochet_blob();
generate_deopt_blob();
#ifdef COMPILER2
@@ -117,33 +114,6 @@
#endif // COMPILER2
}
-//----------------------------generate_ricochet_blob---------------------------
-void SharedRuntime::generate_ricochet_blob() {
- if (!EnableInvokeDynamic) return; // leave it as a null
-
- // allocate space for the code
- ResourceMark rm;
- // setup code generation tools
- CodeBuffer buffer("ricochet_blob", 256 LP64_ONLY(+ 256), 256); // XXX x86 LP64L: 512, 512
- MacroAssembler* masm = new MacroAssembler(&buffer);
-
- int bounce_offset = -1, exception_offset = -1, frame_size_in_words = -1;
- MethodHandles::RicochetFrame::generate_ricochet_blob(masm, &bounce_offset, &exception_offset, &frame_size_in_words);
-
- // -------------
- // make sure all code is generated
- masm->flush();
-
- // failed to generate?
- if (bounce_offset < 0 || exception_offset < 0 || frame_size_in_words < 0) {
- assert(false, "bad ricochet blob");
- return;
- }
-
- _ricochet_blob = RicochetBlob::create(&buffer, bounce_offset, exception_offset, frame_size_in_words);
-}
-
-
#include <math.h>
#ifndef USDT2
@@ -527,10 +497,6 @@
if (Interpreter::contains(return_address)) {
return Interpreter::rethrow_exception_entry();
}
- // Ricochet frame unwind code
- if (SharedRuntime::ricochet_blob() != NULL && SharedRuntime::ricochet_blob()->returns_to_bounce_addr(return_address)) {
- return SharedRuntime::ricochet_blob()->exception_addr();
- }
guarantee(blob == NULL || !blob->is_runtime_stub(), "caller should have skipped stub");
guarantee(!VtableStubs::contains(return_address), "NULL exceptions in vtables should have been handled already!");
@@ -768,13 +734,6 @@
throw_and_post_jvmti_exception(thread, exception);
JRT_END
-JRT_ENTRY(void, SharedRuntime::throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual))
- assert(thread == JavaThread::current() && required->is_oop() && actual->is_oop(), "bad args");
- ResourceMark rm;
- char* message = SharedRuntime::generate_wrong_method_type_message(thread, required, actual);
- throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_invoke_WrongMethodTypeException(), message);
-JRT_END
-
address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
address pc,
SharedRuntime::ImplicitExceptionKind exception_kind)
@@ -857,6 +816,12 @@
return StubRoutines::throw_NullPointerException_at_call_entry();
}
+ if (nm->method()->is_method_handle_intrinsic()) {
+ // exception happened inside MH dispatch code, similar to a vtable stub
+ Events::log_exception(thread, "NullPointerException in MH adapter " INTPTR_FORMAT, pc);
+ return StubRoutines::throw_NullPointerException_at_call_entry();
+ }
+
#ifndef PRODUCT
_implicit_null_throws++;
#endif
@@ -1045,16 +1010,17 @@
assert(!vfst.at_end(), "Java frame must exist");
// Find caller and bci from vframe
- methodHandle caller (THREAD, vfst.method());
- int bci = vfst.bci();
+ methodHandle caller(THREAD, vfst.method());
+ int bci = vfst.bci();
// Find bytecode
Bytecode_invoke bytecode(caller, bci);
- bc = bytecode.java_code();
+ bc = bytecode.invoke_code();
int bytecode_index = bytecode.index();
// Find receiver for non-static call
- if (bc != Bytecodes::_invokestatic) {
+ if (bc != Bytecodes::_invokestatic &&
+ bc != Bytecodes::_invokedynamic) {
// This register map must be update since we need to find the receiver for
// compiled frames. The receiver might be in a register.
RegisterMap reg_map2(thread);
@@ -1075,25 +1041,32 @@
}
// Resolve method. This is parameterized by bytecode.
- constantPoolHandle constants (THREAD, caller->constants());
- assert (receiver.is_null() || receiver->is_oop(), "wrong receiver");
+ constantPoolHandle constants(THREAD, caller->constants());
+ assert(receiver.is_null() || receiver->is_oop(), "wrong receiver");
LinkResolver::resolve_invoke(callinfo, receiver, constants, bytecode_index, bc, CHECK_(nullHandle));
#ifdef ASSERT
// Check that the receiver klass is of the right subtype and that it is initialized for virtual calls
if (bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic) {
assert(receiver.not_null(), "should have thrown exception");
- KlassHandle receiver_klass (THREAD, receiver->klass());
+ KlassHandle receiver_klass(THREAD, receiver->klass());
klassOop rk = constants->klass_ref_at(bytecode_index, CHECK_(nullHandle));
// klass is already loaded
- KlassHandle static_receiver_klass (THREAD, rk);
- assert(receiver_klass->is_subtype_of(static_receiver_klass()), "actual receiver must be subclass of static receiver klass");
+ KlassHandle static_receiver_klass(THREAD, rk);
+ // Method handle invokes might have been optimized to a direct call
+ // so don't check for the receiver class.
+ // FIXME this weakens the assert too much
+ methodHandle callee = callinfo.selected_method();
+ assert(receiver_klass->is_subtype_of(static_receiver_klass()) ||
+ callee->is_method_handle_intrinsic() ||
+ callee->is_compiled_lambda_form(),
+ "actual receiver must be subclass of static receiver klass");
if (receiver_klass->oop_is_instance()) {
if (instanceKlass::cast(receiver_klass())->is_not_initialized()) {
tty->print_cr("ERROR: Klass not yet initialized!!");
receiver_klass.print();
}
- assert (!instanceKlass::cast(receiver_klass())->is_not_initialized(), "receiver_klass must be initialized");
+ assert(!instanceKlass::cast(receiver_klass())->is_not_initialized(), "receiver_klass must be initialized");
}
}
#endif
@@ -1186,8 +1159,10 @@
call_info, CHECK_(methodHandle()));
methodHandle callee_method = call_info.selected_method();
- assert((!is_virtual && invoke_code == Bytecodes::_invokestatic) ||
- ( is_virtual && invoke_code != Bytecodes::_invokestatic), "inconsistent bytecode");
+ assert((!is_virtual && invoke_code == Bytecodes::_invokestatic ) ||
+ (!is_virtual && invoke_code == Bytecodes::_invokehandle ) ||
+ (!is_virtual && invoke_code == Bytecodes::_invokedynamic) ||
+ ( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode");
#ifndef PRODUCT
// tracing/debugging/statistics
@@ -1202,16 +1177,17 @@
(is_optimized) ? "optimized " : "", (is_virtual) ? "virtual" : "static",
Bytecodes::name(invoke_code));
callee_method->print_short_name(tty);
- tty->print_cr(" code: " INTPTR_FORMAT, callee_method->code());
+ tty->print_cr(" at pc: " INTPTR_FORMAT " to code: " INTPTR_FORMAT, caller_frame.pc(), callee_method->code());
}
#endif
- // JSR 292
+ // JSR 292 key invariant:
// If the resolved method is a MethodHandle invoke target the call
- // site must be a MethodHandle call site.
- if (callee_method->is_method_handle_invoke()) {
- assert(caller_nm->is_method_handle_return(caller_frame.pc()), "must be MH call site");
- }
+ // site must be a MethodHandle call site, because the lambda form might tail-call
+ // leaving the stack in a state unknown to either caller or callee
+ // TODO detune for now but we might need it again
+// assert(!callee_method->is_compiled_lambda_form() ||
+// caller_nm->is_method_handle_return(caller_frame.pc()), "must be MH call site");
// Compute entry points. This might require generation of C2I converter
// frames, so we cannot be holding any locks here. Furthermore, the
@@ -1284,7 +1260,6 @@
assert(stub_frame.is_runtime_frame(), "sanity check");
frame caller_frame = stub_frame.sender(®_map);
assert(!caller_frame.is_interpreted_frame() && !caller_frame.is_entry_frame(), "unexpected frame");
- assert(!caller_frame.is_ricochet_frame(), "unexpected frame");
#endif /* ASSERT */
methodHandle callee_method;
@@ -1320,21 +1295,9 @@
address sender_pc = caller_frame.pc();
CodeBlob* sender_cb = caller_frame.cb();
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
- bool is_mh_invoke_via_adapter = false; // Direct c2c call or via adapter?
- if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
- // If the callee_target is set, then we have come here via an i2c
- // adapter.
- methodOop callee = thread->callee_target();
- if (callee != NULL) {
- assert(callee->is_method(), "sanity");
- is_mh_invoke_via_adapter = true;
- }
- }
if (caller_frame.is_interpreted_frame() ||
- caller_frame.is_entry_frame() ||
- caller_frame.is_ricochet_frame() ||
- is_mh_invoke_via_adapter) {
+ caller_frame.is_entry_frame()) {
methodOop callee = thread->callee_target();
guarantee(callee != NULL && callee->is_method(), "bad handshake");
thread->set_vm_result(callee);
@@ -1677,12 +1640,6 @@
// Get the return PC for the passed caller PC.
address return_pc = caller_pc + frame::pc_return_offset;
- // Don't fixup method handle call sites as the executed method
- // handle adapters are doing the required MethodHandle chain work.
- if (nm->is_method_handle_return(return_pc)) {
- return;
- }
-
// There is a benign race here. We could be attempting to patch to a compiled
// entry point at the same time the callee is being deoptimized. If that is
// the case then entry_point may in fact point to a c2i and we'd patch the
@@ -1788,97 +1745,6 @@
return generate_class_cast_message(objName, targetKlass->external_name());
}
-char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
- oopDesc* required,
- oopDesc* actual) {
- if (TraceMethodHandles) {
- tty->print_cr("WrongMethodType thread="PTR_FORMAT" req="PTR_FORMAT" act="PTR_FORMAT"",
- thread, required, actual);
- }
- assert(EnableInvokeDynamic, "");
- oop singleKlass = wrong_method_type_is_for_single_argument(thread, required);
- char* message = NULL;
- if (singleKlass != NULL) {
- const char* objName = "argument or return value";
- if (actual != NULL) {
- // be flexible about the junk passed in:
- klassOop ak = (actual->is_klass()
- ? (klassOop)actual
- : actual->klass());
- objName = Klass::cast(ak)->external_name();
- }
- Klass* targetKlass = Klass::cast(required->is_klass()
- ? (klassOop)required
- : java_lang_Class::as_klassOop(required));
- message = generate_class_cast_message(objName, targetKlass->external_name());
- } else {
- // %%% need to get the MethodType string, without messing around too much
- const char* desc = NULL;
- // Get a signature from the invoke instruction
- const char* mhName = "method handle";
- const char* targetType = "the required signature";
- int targetArity = -1, mhArity = -1;
- vframeStream vfst(thread, true);
- if (!vfst.at_end()) {
- Bytecode_invoke call(vfst.method(), vfst.bci());
- methodHandle target;
- {
- EXCEPTION_MARK;
- target = call.static_target(THREAD);
- if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; }
- }
- if (target.not_null()
- && target->is_method_handle_invoke()
- && required == target->method_handle_type()) {
- targetType = target->signature()->as_C_string();
- targetArity = ArgumentCount(target->signature()).size();
- }
- }
- KlassHandle kignore; int dmf_flags = 0;
- methodHandle actual_method = MethodHandles::decode_method(actual, kignore, dmf_flags);
- if ((dmf_flags & ~(MethodHandles::_dmf_has_receiver |
- MethodHandles::_dmf_does_dispatch |
- MethodHandles::_dmf_from_interface)) != 0)
- actual_method = methodHandle(); // MH does extra binds, drops, etc.
- bool has_receiver = ((dmf_flags & MethodHandles::_dmf_has_receiver) != 0);
- if (actual_method.not_null()) {
- mhName = actual_method->signature()->as_C_string();
- mhArity = ArgumentCount(actual_method->signature()).size();
- if (!actual_method->is_static()) mhArity += 1;
- } else if (java_lang_invoke_MethodHandle::is_instance(actual)) {
- oopDesc* mhType = java_lang_invoke_MethodHandle::type(actual);
- mhArity = java_lang_invoke_MethodType::ptype_count(mhType);
- stringStream st;
- java_lang_invoke_MethodType::print_signature(mhType, &st);
- mhName = st.as_string();
- }
- if (targetArity != -1 && targetArity != mhArity) {
- if (has_receiver && targetArity == mhArity-1)
- desc = " cannot be called without a receiver argument as ";
- else
- desc = " cannot be called with a different arity as ";
- }
- message = generate_class_cast_message(mhName, targetType,
- desc != NULL ? desc :
- " cannot be called as ");
- }
- if (TraceMethodHandles) {
- tty->print_cr("WrongMethodType => message=%s", message);
- }
- return message;
-}
-
-oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr,
- oopDesc* required) {
- if (required == NULL) return NULL;
- if (required->klass() == SystemDictionary::Class_klass())
- return required;
- if (required->is_klass())
- return Klass::cast(klassOop(required))->java_mirror();
- return NULL;
-}
-
-
char* SharedRuntime::generate_class_cast_message(
const char* objName, const char* targetKlassName, const char* desc) {
size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
@@ -2119,8 +1985,17 @@
// that allows sharing of adapters for the same calling convention.
class AdapterFingerPrint : public CHeapObj<mtCode> {
private:
+ enum {
+ _basic_type_bits = 4,
+ _basic_type_mask = right_n_bits(_basic_type_bits),
+ _basic_types_per_int = BitsPerInt / _basic_type_bits,
+ _compact_int_count = 3
+ };
+ // TO DO: Consider integrating this with a more global scheme for compressing signatures.
+ // For now, 4 bits per components (plus T_VOID gaps after double/long) is not excessive.
+
union {
- int _compact[3];
+ int _compact[_compact_int_count];
int* _fingerprint;
} _value;
int _length; // A negative length indicates the fingerprint is in the compact form,
@@ -2129,8 +2004,7 @@
// Remap BasicTypes that are handled equivalently by the adapters.
// These are correct for the current system but someday it might be
// necessary to make this mapping platform dependent.
- static BasicType adapter_encoding(BasicType in) {
- assert((~0xf & in) == 0, "must fit in 4 bits");
+ static int adapter_encoding(BasicType in) {
switch(in) {
case T_BOOLEAN:
case T_BYTE:
@@ -2141,6 +2015,8 @@
case T_OBJECT:
case T_ARRAY:
+ // In other words, we assume that any register good enough for
+ // an int or long is good enough for a managed pointer.
#ifdef _LP64
return T_LONG;
#else
@@ -2165,8 +2041,9 @@
// The fingerprint is based on the BasicType signature encoded
// into an array of ints with eight entries per int.
int* ptr;
- int len = (total_args_passed + 7) >> 3;
- if (len <= (int)(sizeof(_value._compact) / sizeof(int))) {
+ int len = (total_args_passed + (_basic_types_per_int-1)) / _basic_types_per_int;
+ if (len <= _compact_int_count) {
+ assert(_compact_int_count == 3, "else change next line");
_value._compact[0] = _value._compact[1] = _value._compact[2] = 0;
// Storing the signature encoded as signed chars hits about 98%
// of the time.
@@ -2182,10 +2059,12 @@
int sig_index = 0;
for (int index = 0; index < len; index++) {
int value = 0;
- for (int byte = 0; byte < 8; byte++) {
- if (sig_index < total_args_passed) {
- value = (value << 4) | adapter_encoding(sig_bt[sig_index++]);
- }
+ for (int byte = 0; byte < _basic_types_per_int; byte++) {
+ int bt = ((sig_index < total_args_passed)
+ ? adapter_encoding(sig_bt[sig_index++])
+ : 0);
+ assert((bt & _basic_type_mask) == bt, "must fit in 4 bits");
+ value = (value << _basic_type_bits) | bt;
}
ptr[index] = value;
}
@@ -2235,6 +2114,7 @@
return false;
}
if (_length < 0) {
+ assert(_compact_int_count == 3, "else change next line");
return _value._compact[0] == other->_value._compact[0] &&
_value._compact[1] == other->_value._compact[1] &&
_value._compact[2] == other->_value._compact[2];
@@ -2531,13 +2411,17 @@
entry->relocate(B->content_begin());
#ifndef PRODUCT
// debugging suppport
- if (PrintAdapterHandlers) {
- tty->cr();
- tty->print_cr("i2c argument handler #%d for: %s %s (fingerprint = %s, %d bytes generated)",
+ if (PrintAdapterHandlers || PrintStubCode) {
+ entry->print_adapter_on(tty);
+ tty->print_cr("i2c argument handler #%d for: %s %s (%d bytes generated)",
_adapters->number_of_entries(), (method->is_static() ? "static" : "receiver"),
- method->signature()->as_C_string(), fingerprint->as_string(), insts_size );
+ method->signature()->as_C_string(), insts_size);
tty->print_cr("c2i argument handler starts at %p",entry->get_c2i_entry());
- Disassembler::decode(entry->get_i2c_entry(), entry->get_i2c_entry() + insts_size);
+ if (Verbose || PrintStubCode) {
+ address first_pc = entry->base_address();
+ if (first_pc != NULL)
+ Disassembler::decode(first_pc, first_pc + insts_size);
+ }
}
#endif
@@ -2561,11 +2445,25 @@
return entry;
}
+address AdapterHandlerEntry::base_address() {
+ address base = _i2c_entry;
+ if (base == NULL) base = _c2i_entry;
+ assert(base <= _c2i_entry || _c2i_entry == NULL, "");
+ assert(base <= _c2i_unverified_entry || _c2i_unverified_entry == NULL, "");
+ return base;
+}
+
void AdapterHandlerEntry::relocate(address new_base) {
- ptrdiff_t delta = new_base - _i2c_entry;
+ address old_base = base_address();
+ assert(old_base != NULL, "");
+ ptrdiff_t delta = new_base - old_base;
+ if (_i2c_entry != NULL)
_i2c_entry += delta;
+ if (_c2i_entry != NULL)
_c2i_entry += delta;
+ if (_c2i_unverified_entry != NULL)
_c2i_unverified_entry += delta;
+ assert(base_address() == new_base, "");
}
@@ -2614,7 +2512,9 @@
ResourceMark rm;
nmethod* nm = NULL;
- assert(method->has_native_function(), "must have something valid to call!");
+ assert(method->is_native(), "must be native");
+ assert(method->is_method_handle_intrinsic() ||
+ method->has_native_function(), "must have something valid to call!");
{
// perform the work while holding the lock, but perform any printing outside the lock
@@ -2651,9 +2551,11 @@
assert( i==total_args_passed, "" );
BasicType ret_type = ss.type();
- // Now get the compiled-Java layout as input arguments
- int comp_args_on_stack;
- comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, false);
+ // Now get the compiled-Java layout as input (or output) arguments.
+ // NOTE: Stubs for compiled entry points of method handle intrinsics
+ // are just trampolines so the argument registers must be outgoing ones.
+ const bool is_outgoing = method->is_method_handle_intrinsic();
+ int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, is_outgoing);
// Generate the compiled-to-native wrapper code
nm = SharedRuntime::generate_native_wrapper(&_masm,
@@ -2939,18 +2841,22 @@
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
- if ( b == CodeCache::find_blob(a->get_i2c_entry()) ) {
+ if (b == CodeCache::find_blob(a->get_i2c_entry())) {
st->print("Adapter for signature: ");
- st->print_cr("%s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
- a->fingerprint()->as_string(),
- a->get_i2c_entry(), a->get_c2i_entry(), a->get_c2i_unverified_entry());
-
+ a->print_adapter_on(tty);
return;
}
}
assert(false, "Should have found handler");
}
+void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
+ st->print_cr("AHE@" INTPTR_FORMAT ": %s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
+ (intptr_t) this, fingerprint()->as_string(),
+ get_i2c_entry(), get_c2i_entry(), get_c2i_unverified_entry());
+
+}
+
#ifndef PRODUCT
void AdapterHandlerLibrary::print_statistics() {