src/share/vm/interpreter/interpreterRuntime.cpp

changeset 1161
be93aad57795
parent 1145
e5b0439ef4ae
child 1376
8b46c4d82093
     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  

mercurial