int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); // Pop appendix argument from stack. This is a MemberName which we resolve to the // target method. oop vmentry = popFromStack(THREAD); intptr_t* topOfStack = istate->stack(); // Resolve target method by looking up in the receiver object's itable. Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(vmentry)); intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry); Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry); int numArgs = target->size_of_parameters(); oop recv = STACK_OBJECT(-numArgs); InstanceKlass* klass_part = InstanceKlass::cast(recv->klass()); itableOffsetEntry* ki = (itableOffsetEntry*) klass_part->start_of_itable(); int i; for ( i = 0 ; i < klass_part->itable_length() ; i++, ki++ ) { if (ki->interface_klass() == clazz) break; } itableMethodEntry* im = ki->first_method_entry(recv->klass()); Method* vmtarget = im[vmindex].method(); invoke_target(vmtarget, THREAD); return 0; }
int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); // Pop appendix argument from stack. This is a MemberName which we resolve to the // target method. oop vmentry = popFromStack(THREAD); intptr_t* topOfStack = istate->stack(); // Resolve target method by looking up in the receiver object's vtable. intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry); Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry); int numArgs = target->size_of_parameters(); oop recv = STACK_OBJECT(-numArgs); Klass* clazz = recv->klass(); Klass* klass_part = InstanceKlass::cast(clazz); klassVtable* vtable = klass_part->vtable(); Method* vmtarget = vtable->method_at(vmindex); invoke_target(vmtarget, THREAD); return 0; }
oop MethodHandles::popFromStack(TRAPS) { JavaThread *thread = (JavaThread *) THREAD; InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); intptr_t* topOfStack = istate->stack(); oop top = STACK_OBJECT(-1); MORE_STACK(-1); istate->set_stack(topOfStack); return top; }
void ZeroStack::handle_overflow(TRAPS) { JavaThread *thread = (JavaThread *) THREAD; // Set up the frame anchor if it isn't already bool has_last_Java_frame = thread->has_last_Java_frame(); if (!has_last_Java_frame) { intptr_t *sp = thread->zero_stack()->sp(); ZeroFrame *frame = thread->top_zero_frame(); while (frame) { if (frame->is_shark_frame()) break; if (frame->is_interpreter_frame()) { interpreterState istate = frame->as_interpreter_frame()->interpreter_state(); if (istate->self_link() == istate) break; } sp = ((intptr_t *) frame) + 1; frame = frame->next(); } if (frame == NULL) fatal("unrecoverable stack overflow"); thread->set_last_Java_frame(frame, sp); } // Throw the exception switch (thread->thread_state()) { case _thread_in_Java: InterpreterRuntime::throw_StackOverflowError(thread); break; case _thread_in_vm: Exceptions::throw_stack_overflow_exception(thread, __FILE__, __LINE__, methodHandle()); break; default: ShouldNotReachHere(); } // Reset the frame anchor if necessary if (!has_last_Java_frame) thread->reset_last_Java_frame(); }
void MethodHandles::invoke_target(Method* method, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); // Trim back the stack to put the parameters at the top stack->set_sp(istate->stack() + 1); Interpreter::invoke_method(method, method->from_interpreted_entry(), THREAD); // Convert the result istate->set_stack(stack->sp() - 1); }
int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); intptr_t* topOfStack = istate->stack(); // 'this' is a MethodHandle. We resolve the target method by accessing this.form.vmentry.vmtarget. int numArgs = method->size_of_parameters(); oop lform1 = java_lang_invoke_MethodHandle::form(STACK_OBJECT(-numArgs)); // this.form oop vmEntry1 = java_lang_invoke_LambdaForm::vmentry(lform1); Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmEntry1); invoke_target(vmtarget, THREAD); // No deoptimized frames on the stack return 0; }
void CppInterpreter::main_loop(int recurse, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); // If we are entering from a deopt we may need to call // ourself a few times in order to get to our frame. if (recurse) main_loop(recurse - 1, THREAD); InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); interpreterState istate = frame->interpreter_state(); methodOop method = istate->method(); intptr_t *result = NULL; int result_slots = 0; while (true) { // We can set up the frame anchor with everything we want at // this point as we are thread_in_Java and no safepoints can // occur until we go to vm mode. We do have to clear flags // on return from vm but that is it. thread->set_last_Java_frame(); // Call the interpreter if (JvmtiExport::can_post_interpreter_events()) BytecodeInterpreter::runWithChecks(istate); else BytecodeInterpreter::run(istate); fixup_after_potential_safepoint(); // Clear the frame anchor thread->reset_last_Java_frame(); // Examine the message from the interpreter to decide what to do if (istate->msg() == BytecodeInterpreter::call_method) { methodOop callee = istate->callee(); // Trim back the stack to put the parameters at the top stack->set_sp(istate->stack() + 1); // Make the call Interpreter::invoke_method(callee, istate->callee_entry_point(), THREAD); fixup_after_potential_safepoint(); // Convert the result istate->set_stack(stack->sp() - 1); // Restore the stack stack->set_sp(istate->stack_limit() + 1); // Resume the interpreter istate->set_msg(BytecodeInterpreter::method_resume); } else if (istate->msg() == BytecodeInterpreter::more_monitors) { int monitor_words = frame::interpreter_frame_monitor_size(); // Allocate the space stack->overflow_check(monitor_words, THREAD); if (HAS_PENDING_EXCEPTION) break; stack->alloc(monitor_words * wordSize); // Move the expression stack contents for (intptr_t *p = istate->stack() + 1; p < istate->stack_base(); p++) *(p - monitor_words) = *p; // Move the expression stack pointers istate->set_stack_limit(istate->stack_limit() - monitor_words); istate->set_stack(istate->stack() - monitor_words); istate->set_stack_base(istate->stack_base() - monitor_words); // Zero the new monitor so the interpreter can find it. ((BasicObjectLock *) istate->stack_base())->set_obj(NULL); // Resume the interpreter istate->set_msg(BytecodeInterpreter::got_monitors); } else if (istate->msg() == BytecodeInterpreter::return_from_method) { // Copy the result into the caller's frame result_slots = type2size[result_type_of(method)]; assert(result_slots >= 0 && result_slots <= 2, "what?"); result = istate->stack() + result_slots; break; } else if (istate->msg() == BytecodeInterpreter::throwing_exception) { assert(HAS_PENDING_EXCEPTION, "should do"); break; } else if (istate->msg() == BytecodeInterpreter::do_osr) { // Unwind the current frame thread->pop_zero_frame(); // Remove any extension of the previous frame int extra_locals = method->max_locals() - method->size_of_parameters(); stack->set_sp(stack->sp() + extra_locals); // Jump into the OSR method Interpreter::invoke_osr( method, istate->osr_entry(), istate->osr_buf(), THREAD); return; } else { ShouldNotReachHere(); } } // Unwind the current frame thread->pop_zero_frame(); // Pop our local variables stack->set_sp(stack->sp() + method->max_locals()); // Push our result for (int i = 0; i < result_slots; i++) stack->push(result[-i]); }