1.1 --- a/src/share/vm/interpreter/interpreterRuntime.cpp Mon Apr 20 14:48:03 2009 -0700 1.2 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Tue Apr 21 23:21:04 2009 -0700 1.3 @@ -681,6 +681,133 @@ 1.4 IRT_END 1.5 1.6 1.7 +// First time execution: Resolve symbols, create a permanent CallSiteImpl object. 1.8 +IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { 1.9 + ResourceMark rm(thread); 1.10 + 1.11 + assert(EnableInvokeDynamic, ""); 1.12 + 1.13 + const Bytecodes::Code bytecode = Bytecodes::_invokedynamic; 1.14 + 1.15 + methodHandle caller_method(thread, method(thread)); 1.16 + 1.17 + // first determine if there is a bootstrap method 1.18 + { 1.19 + KlassHandle caller_klass(thread, caller_method->method_holder()); 1.20 + Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, KlassHandle(), CHECK); 1.21 + if (bootm.is_null()) { 1.22 + // If there is no bootstrap method, throw IncompatibleClassChangeError. 1.23 + // This is a valid generic error type for resolution (JLS 12.3.3). 1.24 + char buf[200]; 1.25 + jio_snprintf(buf, sizeof(buf), "Class %s has not declared a bootstrap method for invokedynamic", 1.26 + (Klass::cast(caller_klass()))->external_name()); 1.27 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.28 + } 1.29 + } 1.30 + 1.31 + constantPoolHandle pool(thread, caller_method->constants()); 1.32 + pool->set_invokedynamic(); // mark header to flag active call sites 1.33 + 1.34 + int raw_index = four_byte_index(thread); 1.35 + assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "invokedynamic indexes marked specially"); 1.36 + 1.37 + // there are two CPC entries that are of interest: 1.38 + int site_index = constantPoolCacheOopDesc::decode_secondary_index(raw_index); 1.39 + int main_index = pool->cache()->entry_at(site_index)->main_entry_index(); 1.40 + // and there is one CP entry, a NameAndType: 1.41 + int nt_index = pool->map_instruction_operand_to_index(raw_index); 1.42 + 1.43 + // first resolve the signature to a MH.invoke methodOop 1.44 + if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) { 1.45 + JvmtiHideSingleStepping jhss(thread); 1.46 + CallInfo info; 1.47 + LinkResolver::resolve_invoke(info, Handle(), pool, 1.48 + raw_index, bytecode, CHECK); 1.49 + // The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves 1.50 + // as a common reference point for all invokedynamic call sites with 1.51 + // that exact call descriptor. We will link it in the CP cache exactly 1.52 + // as if it were an invokevirtual of MethodHandle.invoke. 1.53 + pool->cache()->entry_at(main_index)->set_method( 1.54 + bytecode, 1.55 + info.resolved_method(), 1.56 + info.vtable_index()); 1.57 + assert(pool->cache()->entry_at(main_index)->is_vfinal(), "f2 must be a methodOop"); 1.58 + } 1.59 + 1.60 + // The method (f2 entry) of the main entry is the MH.invoke for the 1.61 + // invokedynamic target call signature. 1.62 + intptr_t f2_value = pool->cache()->entry_at(main_index)->f2(); 1.63 + methodHandle mh_invdyn(THREAD, (methodOop) f2_value); 1.64 + assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(), 1.65 + "correct result from LinkResolver::resolve_invokedynamic"); 1.66 + 1.67 + symbolHandle call_site_name(THREAD, pool->nt_name_ref_at(nt_index)); 1.68 + Handle call_site 1.69 + = SystemDictionary::make_dynamic_call_site(caller_method->method_holder(), 1.70 + caller_method->method_idnum(), 1.71 + caller_method->bci_from(bcp(thread)), 1.72 + call_site_name, 1.73 + mh_invdyn, 1.74 + CHECK); 1.75 + 1.76 + // In the secondary entry, the f1 field is the call site, and the f2 (index) 1.77 + // field is some data about the invoke site. 1.78 + int extra_data = 0; 1.79 + pool->cache()->entry_at(site_index)->set_dynamic_call(call_site(), extra_data); 1.80 +} 1.81 +IRT_END 1.82 + 1.83 + 1.84 +// Called on first time execution, and also whenever the CallSite.target is null. 1.85 +// FIXME: Do more of this in Java code. 1.86 +IRT_ENTRY(void, InterpreterRuntime::bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site)) { 1.87 + methodHandle mh_invdyn(thread, (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site)); 1.88 + Handle mh_type(thread, mh_invdyn->method_handle_type()); 1.89 + objArrayHandle mh_ptypes(thread, java_dyn_MethodType::ptypes(mh_type())); 1.90 + 1.91 + // squish the arguments down to a single array 1.92 + int nargs = mh_ptypes->length(); 1.93 + objArrayHandle arg_array; 1.94 + { 1.95 + objArrayOop aaoop = oopFactory::new_objArray(SystemDictionary::object_klass(), nargs, CHECK); 1.96 + arg_array = objArrayHandle(thread, aaoop); 1.97 + } 1.98 + frame fr = thread->last_frame(); 1.99 + assert(fr.interpreter_frame_bcp() != NULL, "sanity"); 1.100 + int tos_offset = 0; 1.101 + for (int i = nargs; --i >= 0; ) { 1.102 + intptr_t* slot_addr = fr.interpreter_frame_tos_at(tos_offset++); 1.103 + oop ptype = mh_ptypes->obj_at(i); 1.104 + oop arg = NULL; 1.105 + if (!java_lang_Class::is_primitive(ptype)) { 1.106 + arg = *(oop*) slot_addr; 1.107 + } else { 1.108 + BasicType bt = java_lang_Class::primitive_type(ptype); 1.109 + assert(frame::interpreter_frame_expression_stack_direction() < 0, "else reconsider this code"); 1.110 + jvalue value; 1.111 + Interpreter::get_jvalue_in_slot(slot_addr, bt, &value); 1.112 + tos_offset += type2size[bt]-1; 1.113 + arg = java_lang_boxing_object::create(bt, &value, CHECK); 1.114 + // FIXME: These boxing objects are not canonicalized under 1.115 + // the Java autoboxing rules. They should be... 1.116 + // The best approach would be to push the arglist creation into Java. 1.117 + // The JVM should use a lower-level interface to communicate argument lists. 1.118 + } 1.119 + arg_array->obj_at_put(i, arg); 1.120 + } 1.121 + 1.122 + // now find the bootstrap method 1.123 + oop bootstrap_mh_oop = instanceKlass::cast(fr.interpreter_frame_method()->method_holder())->bootstrap_method(); 1.124 + assert(bootstrap_mh_oop != NULL, "resolve_invokedynamic ensures a BSM"); 1.125 + 1.126 + // return the bootstrap method and argument array via vm_result/_2 1.127 + thread->set_vm_result(bootstrap_mh_oop); 1.128 + thread->set_vm_result_2(arg_array()); 1.129 +} 1.130 +IRT_END 1.131 + 1.132 + 1.133 + 1.134 //------------------------------------------------------------------------------------------------------------------------ 1.135 // Miscellaneous 1.136