Missing invokehandle handling in bytecodeInterpreter.cpp

Roman Kennke rkennke at redhat.com
Thu Aug 2 03:55:34 PDT 2012


> > Am Dienstag, den 31.07.2012, 17:28 -0700 schrieb Christian Thalinger:
> > > On Jul 31, 2012, at 8:24 AM, Roman Kennke wrote:
> > > 
> > > > Am Dienstag, den 31.07.2012, 14:19 +0200 schrieb Roman Kennke:
> > > >> Hi there,
> > > >> 
> > > >> I am currently (trying to) get the Hotspot-Zero port in shape for MLVM.
> > > >> I am running into a road block here:
> > > >> 
> > > >> #  Internal Error
> > > >> (/home/rkennke/src/openjdk/hotspot-comp/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp:2464), pid=18585, tid=140737337317120
> > > >> #  fatal error: Unimplemented opcode 232 = invokehandle
> > > >> 
> > > >> Looking at bytecodeInterpreter.cpp it seem to simply not handle
> > > >> invokehandle. I would like to add this, but I don't know what exactly
> > > >> this bytecode is supposed to do. Could you give me pointers to the
> > > >> necessary information or provide some help with this? (Or maybe I am
> > > >> doing something wrong here, and should not arrive there at all?)
> > > > 
> > > > I disabled the invokevirtual->invokehandle rewriting for now (this
> > > > should be safe/correct, right?), and it brings me further into my
> > > > unimplemented handler for vmIntrinsics::_invokeBasic. Need to figure out
> > > > what this is supposed to do (any hints about this one?)..
> > > 
> > > You can't disable the rewriting and run JSR 292 code.  That simply won't work.  Look at one of the implementations of TemplateTable::_invokehandle and try to do the same in the C++ interpreter.
> > > 
> > > -- Chris

Ok, I think I made some progress, but now got stuck again. I implemented
invokehandle like this:

      CASE(_invokehandle): {
        if (!EnableInvokeDynamic) {
          ShouldNotReachHere();
        }

        u2 index = Bytes::get_native_u2(pc+1);

        ConstantPoolCacheEntry* cache = cp->entry_at(index);

        if (! cache->is_resolved((Bytecodes::Code) opcode)) {
          CALL_VM(InterpreterRuntime::resolve_invokehandle(THREAD),
                  handle_exception);
          cache = cp->entry_at(index);
        }
        methodOop method = cache->f2_as_vfinal_method();

        VERIFY_OOP(method);

        if (cache->has_appendix()) {
          SET_STACK_OBJECT(cache->f1_appendix(), 0);
        }


istate->set_callee_entry_point(method->from_interpreted_entry());
        istate->set_msg(call_method);
        istate->set_callee(method);
        istate->set_bcp_advance(3);

        UPDATE_PC_AND_RETURN(0); // I'll be back...
      }




This seems to work, at least I now end up (correctly, I hope) in
MH.invokeBasic() intrinsic. This I implemented like:



int MethodHandles::method_handle_entry_invokeBasic(methodOop method,
intptr_t UNUSED, TRAPS) {
  JavaThread *thread = (JavaThread *) THREAD;
  ZeroStack *stack = thread->zero_stack();
  intptr_t *vmslots = stack->sp();

  InterpreterFrame *frame =
thread->top_zero_frame()->as_interpreter_frame();
  interpreterState istate = frame->interpreter_state();
  intptr_t* locals = istate->locals();

  oop method_handle = LOCALS_OBJECT(0);
  oop lform = java_lang_invoke_MethodHandle::form(method_handle);
  oop vmEntry = java_lang_invoke_LambdaForm::vmentry(lform);
  methodOop methodTmp = (methodOop)
java_lang_invoke_MemberName::vmtarget(vmEntry);


  Interpreter::invoke_method(methodTmp,
methodTmp->from_interpreted_entry(), THREAD);

  // No deoptimized frames on the stack
  return 0;
}

I.e. call the lambda form of the MH. However, I end up with a NPE in the
lambda form.

Inspecting the method signatures of the invokeBasic() call and the
lambda form, they look like this:

 - name:              'invokeBasic'
 - signature:
'(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;I)Ljava/lang/Object;'

and:

 - name:              'interpret_I'
 - signature:
'(Ljava/lang/invoke/MethodHandle;Ljava/lang/Object;I)I'

On my call stack I get 3 objects (a MethodHandle, a MethodType and a
LambdaForm) and an int (0). This seems to match the invokeBasic()
signature. However, I don't know what should be the arguments to the
lambda form. Maybe I am missing something. Studying the x86 or sparc
versions of the invokeBasic() intrinsics doesn't seem to reveal much (at
least not to me), except:

  if (!is_signature_polymorphic_static(iid)) {
    __ movptr(rcx_mh, rdx_first_arg_addr);
    DEBUG_ONLY(rdx_argp = noreg);
  }


This seems to be related to the invokeBasic() intrinsic and the argument
list of the lambdaform, but I really don't know what it does or how I
could translate this to plain CPP.

Any hints?

Regards, Roman




More information about the mlvm-dev mailing list