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