never@1445: /* stefank@2314: * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. twisti@2762: * Copyright 2009, 2010, 2011 Red Hat, Inc. never@1445: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. never@1445: * never@1445: * This code is free software; you can redistribute it and/or modify it never@1445: * under the terms of the GNU General Public License version 2 only, as never@1445: * published by the Free Software Foundation. never@1445: * never@1445: * This code is distributed in the hope that it will be useful, but WITHOUT never@1445: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or never@1445: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License never@1445: * version 2 for more details (a copy is included in the LICENSE file that never@1445: * accompanied this code). never@1445: * never@1445: * You should have received a copy of the GNU General Public License version never@1445: * 2 along with this work; if not, write to the Free Software Foundation, never@1445: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. never@1445: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. never@1445: * never@1445: */ never@1445: stefank@2314: #include "precompiled.hpp" twisti@4237: #include "interpreter/interpreterGenerator.hpp" stefank@2314: #include "interpreter/interpreter.hpp" stefank@2314: #include "memory/allocation.inline.hpp" stefank@2314: #include "prims/methodHandles.hpp" twisti@1781: twisti@4237: void MethodHandles::invoke_target(Method* method, TRAPS) { twisti@4237: twisti@4237: JavaThread *thread = (JavaThread *) THREAD; twisti@4237: ZeroStack *stack = thread->zero_stack(); twisti@4237: InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); twisti@4237: interpreterState istate = frame->interpreter_state(); twisti@4237: twisti@4237: // Trim back the stack to put the parameters at the top twisti@4237: stack->set_sp(istate->stack() + 1); twisti@4237: twisti@4237: Interpreter::invoke_method(method, method->from_interpreted_entry(), THREAD); twisti@4237: twisti@4237: // Convert the result twisti@4237: istate->set_stack(stack->sp() - 1); twisti@4237: twisti@1865: } twisti@1865: twisti@4237: oop MethodHandles::popFromStack(TRAPS) { twisti@4237: twisti@4237: JavaThread *thread = (JavaThread *) THREAD; twisti@4237: InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); twisti@4237: interpreterState istate = frame->interpreter_state(); twisti@4237: intptr_t* topOfStack = istate->stack(); twisti@4237: twisti@4237: oop top = STACK_OBJECT(-1); twisti@4237: MORE_STACK(-1); twisti@4237: istate->set_stack(topOfStack); twisti@4237: twisti@4237: return top; twisti@4237: twisti@1781: } twisti@4237: twisti@4237: int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) { twisti@4237: twisti@4237: JavaThread *thread = (JavaThread *) THREAD; twisti@4237: InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); twisti@4237: interpreterState istate = frame->interpreter_state(); twisti@4237: intptr_t* topOfStack = istate->stack(); twisti@4237: twisti@4237: // 'this' is a MethodHandle. We resolve the target method by accessing this.form.vmentry.vmtarget. twisti@4237: int numArgs = method->size_of_parameters(); twisti@4237: oop lform1 = java_lang_invoke_MethodHandle::form(STACK_OBJECT(-numArgs)); // this.form twisti@4237: oop vmEntry1 = java_lang_invoke_LambdaForm::vmentry(lform1); twisti@4237: Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmEntry1); twisti@4237: twisti@4237: invoke_target(vmtarget, THREAD); twisti@4237: twisti@4237: // No deoptimized frames on the stack twisti@4237: return 0; twisti@4237: } twisti@4237: twisti@4237: int MethodHandles::method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS) { twisti@4237: twisti@4237: // Pop appendix argument from stack. This is a MemberName which we resolve to the twisti@4237: // target method. twisti@4237: oop vmentry = popFromStack(THREAD); twisti@4237: twisti@4237: Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry); twisti@4237: twisti@4237: invoke_target(vmtarget, THREAD); twisti@4237: twisti@4237: return 0; twisti@4237: } twisti@4237: twisti@4237: int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t UNUSED, TRAPS) { twisti@4237: JavaThread *thread = (JavaThread *) THREAD; twisti@4237: InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); twisti@4237: interpreterState istate = frame->interpreter_state(); twisti@4237: twisti@4237: // Pop appendix argument from stack. This is a MemberName which we resolve to the twisti@4237: // target method. twisti@4237: oop vmentry = popFromStack(THREAD); twisti@4237: intptr_t* topOfStack = istate->stack(); twisti@4237: twisti@4237: // Resolve target method by looking up in the receiver object's itable. twisti@4237: Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(vmentry)); twisti@4237: intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry); twisti@4237: Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry); twisti@4237: twisti@4237: int numArgs = target->size_of_parameters(); twisti@4237: oop recv = STACK_OBJECT(-numArgs); twisti@4237: twisti@4237: InstanceKlass* klass_part = InstanceKlass::cast(recv->klass()); twisti@4237: itableOffsetEntry* ki = (itableOffsetEntry*) klass_part->start_of_itable(); twisti@4237: int i; twisti@4237: for ( i = 0 ; i < klass_part->itable_length() ; i++, ki++ ) { twisti@4237: if (ki->interface_klass() == clazz) break; twisti@4237: } twisti@4237: twisti@4237: itableMethodEntry* im = ki->first_method_entry(recv->klass()); twisti@4237: Method* vmtarget = im[vmindex].method(); twisti@4237: twisti@4237: invoke_target(vmtarget, THREAD); twisti@4237: twisti@4237: return 0; twisti@4237: } twisti@4237: twisti@4237: int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS) { twisti@4237: JavaThread *thread = (JavaThread *) THREAD; twisti@4237: twisti@4237: InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame(); twisti@4237: interpreterState istate = frame->interpreter_state(); twisti@4237: twisti@4237: // Pop appendix argument from stack. This is a MemberName which we resolve to the twisti@4237: // target method. twisti@4237: oop vmentry = popFromStack(THREAD); twisti@4237: intptr_t* topOfStack = istate->stack(); twisti@4237: twisti@4237: // Resolve target method by looking up in the receiver object's vtable. twisti@4237: intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry); twisti@4237: Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry); twisti@4237: int numArgs = target->size_of_parameters(); twisti@4237: oop recv = STACK_OBJECT(-numArgs); twisti@4237: Klass* clazz = recv->klass(); twisti@4237: Klass* klass_part = InstanceKlass::cast(clazz); twisti@4237: klassVtable* vtable = klass_part->vtable(); twisti@4237: Method* vmtarget = vtable->method_at(vmindex); twisti@4237: twisti@4237: invoke_target(vmtarget, THREAD); twisti@4237: twisti@4237: return 0; twisti@4237: } twisti@4237: twisti@4237: int MethodHandles::method_handle_entry_invalid(Method* method, intptr_t UNUSED, TRAPS) { twisti@4237: ShouldNotReachHere(); twisti@4237: return 0; twisti@4237: } twisti@4237: twisti@4237: address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* masm, twisti@4237: vmIntrinsics::ID iid) { twisti@4237: switch (iid) { twisti@4237: case vmIntrinsics::_invokeGeneric: twisti@4237: case vmIntrinsics::_compiledLambdaForm: twisti@4237: // Perhaps surprisingly, the symbolic references visible to Java are not directly used. twisti@4237: // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod. twisti@4237: // They all allow an appendix argument. twisti@4237: return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_invalid); twisti@4237: case vmIntrinsics::_invokeBasic: twisti@4237: return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_invokeBasic); twisti@4237: case vmIntrinsics::_linkToStatic: twisti@4237: case vmIntrinsics::_linkToSpecial: twisti@4237: return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToStaticOrSpecial); twisti@4237: case vmIntrinsics::_linkToInterface: twisti@4237: return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToInterface); twisti@4237: case vmIntrinsics::_linkToVirtual: twisti@4237: return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToVirtual); twisti@4237: default: twisti@4237: ShouldNotReachHere(); twisti@4237: return NULL; twisti@4237: } twisti@4237: }