| |
| /* |
| * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. |
| * Copyright 2012, 2014 SAP AG. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| #include "precompiled.hpp" |
| #include "asm/assembler.hpp" |
| #include "asm/macroAssembler.inline.hpp" |
| #include "interpreter/bytecodeHistogram.hpp" |
| #include "interpreter/cppInterpreter.hpp" |
| #include "interpreter/interpreter.hpp" |
| #include "interpreter/interpreterGenerator.hpp" |
| #include "interpreter/interpreterRuntime.hpp" |
| #include "oops/arrayOop.hpp" |
| #include "oops/methodData.hpp" |
| #include "oops/method.hpp" |
| #include "oops/oop.inline.hpp" |
| #include "prims/jvmtiExport.hpp" |
| #include "prims/jvmtiThreadState.hpp" |
| #include "runtime/arguments.hpp" |
| #include "runtime/deoptimization.hpp" |
| #include "runtime/frame.inline.hpp" |
| #include "runtime/interfaceSupport.hpp" |
| #include "runtime/sharedRuntime.hpp" |
| #include "runtime/stubRoutines.hpp" |
| #include "runtime/synchronizer.hpp" |
| #include "runtime/timer.hpp" |
| #include "runtime/vframeArray.hpp" |
| #include "utilities/debug.hpp" |
| #ifdef SHARK |
| #include "shark/shark_globals.hpp" |
| #endif |
| |
| #ifdef CC_INTERP |
| |
| #define __ _masm-> |
| |
| // Contains is used for identifying interpreter frames during a stack-walk. |
| // A frame with a PC in InterpretMethod must be identified as a normal C frame. |
| bool CppInterpreter::contains(address pc) { |
| return _code->contains(pc); |
| } |
| |
| #ifdef PRODUCT |
| #define BLOCK_COMMENT(str) // nothing |
| #else |
| #define BLOCK_COMMENT(str) __ block_comment(str) |
| #endif |
| |
| #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") |
| |
| static address interpreter_frame_manager = NULL; |
| static address frame_manager_specialized_return = NULL; |
| static address native_entry = NULL; |
| |
| static address interpreter_return_address = NULL; |
| |
| static address unctrap_frame_manager_entry = NULL; |
| |
| static address deopt_frame_manager_return_atos = NULL; |
| static address deopt_frame_manager_return_btos = NULL; |
| static address deopt_frame_manager_return_itos = NULL; |
| static address deopt_frame_manager_return_ltos = NULL; |
| static address deopt_frame_manager_return_ftos = NULL; |
| static address deopt_frame_manager_return_dtos = NULL; |
| static address deopt_frame_manager_return_vtos = NULL; |
| |
| // A result handler converts/unboxes a native call result into |
| // a java interpreter/compiler result. The current frame is an |
| // interpreter frame. |
| address CppInterpreterGenerator::generate_result_handler_for(BasicType type) { |
| return AbstractInterpreterGenerator::generate_result_handler_for(type); |
| } |
| |
| // tosca based result to c++ interpreter stack based result. |
| address CppInterpreterGenerator::generate_tosca_to_stack_converter(BasicType type) { |
| // |
| // A result is in the native abi result register from a native |
| // method call. We need to return this result to the interpreter by |
| // pushing the result on the interpreter's stack. |
| // |
| // Registers alive: |
| // R3_ARG1(R3_RET)/F1_ARG1(F1_RET) - result to move |
| // R4_ARG2 - address of tos |
| // LR |
| // |
| // Registers updated: |
| // R3_RET(R3_ARG1) - address of new tos (== R17_tos for T_VOID) |
| // |
| |
| int number_of_used_slots = 1; |
| |
| const Register tos = R4_ARG2; |
| Label done; |
| Label is_false; |
| |
| address entry = __ pc(); |
| |
| switch (type) { |
| case T_BOOLEAN: |
| __ cmpwi(CCR0, R3_RET, 0); |
| __ beq(CCR0, is_false); |
| __ li(R3_RET, 1); |
| __ stw(R3_RET, 0, tos); |
| __ b(done); |
| __ bind(is_false); |
| __ li(R3_RET, 0); |
| __ stw(R3_RET, 0, tos); |
| break; |
| case T_BYTE: |
| case T_CHAR: |
| case T_SHORT: |
| case T_INT: |
| __ stw(R3_RET, 0, tos); |
| break; |
| case T_LONG: |
| number_of_used_slots = 2; |
| // mark unused slot for debugging |
| // long goes to topmost slot |
| __ std(R3_RET, -BytesPerWord, tos); |
| __ li(R3_RET, 0); |
| __ std(R3_RET, 0, tos); |
| break; |
| case T_OBJECT: |
| __ verify_oop(R3_RET); |
| __ std(R3_RET, 0, tos); |
| break; |
| case T_FLOAT: |
| __ stfs(F1_RET, 0, tos); |
| break; |
| case T_DOUBLE: |
| number_of_used_slots = 2; |
| // mark unused slot for debugging |
| __ li(R3_RET, 0); |
| __ std(R3_RET, 0, tos); |
| // double goes to topmost slot |
| __ stfd(F1_RET, -BytesPerWord, tos); |
| break; |
| case T_VOID: |
| number_of_used_slots = 0; |
| break; |
| default: |
| ShouldNotReachHere(); |
| } |
| |
| __ BIND(done); |
| |
| // new expression stack top |
| __ addi(R3_RET, tos, -BytesPerWord * number_of_used_slots); |
| |
| __ blr(); |
| |
| return entry; |
| } |
| |
| address CppInterpreterGenerator::generate_stack_to_stack_converter(BasicType type) { |
| // |
| // Copy the result from the callee's stack to the caller's stack, |
| // caller and callee both being interpreted. |
| // |
| // Registers alive |
| // R3_ARG1 - address of callee's tos + BytesPerWord |
| // R4_ARG2 - address of caller's tos [i.e. free location] |
| // LR |
| // |
| // stack grows upwards, memory grows downwards. |
| // |
| // [ free ] <-- callee's tos |
| // [ optional result ] <-- R3_ARG1 |
| // [ optional dummy ] |
| // ... |
| // [ free ] <-- caller's tos, R4_ARG2 |
| // ... |
| // Registers updated |
| // R3_RET(R3_ARG1) - address of caller's new tos |
| // |
| // stack grows upwards, memory grows downwards. |
| // |
| // [ free ] <-- current tos, R3_RET |
| // [ optional result ] |
| // [ optional dummy ] |
| // ... |
| // |
| |
| const Register from = R3_ARG1; |
| const Register ret = R3_ARG1; |
| const Register tos = R4_ARG2; |
| const Register tmp1 = R21_tmp1; |
| const Register tmp2 = R22_tmp2; |
| |
| address entry = __ pc(); |
| |
| switch (type) { |
| case T_BOOLEAN: |
| case T_BYTE: |
| case T_CHAR: |
| case T_SHORT: |
| case T_INT: |
| case T_FLOAT: |
| __ lwz(tmp1, 0, from); |
| __ stw(tmp1, 0, tos); |
| // New expression stack top. |
| __ addi(ret, tos, - BytesPerWord); |
| break; |
| case T_LONG: |
| case T_DOUBLE: |
| // Move both entries for debug purposes even though only one is live. |
| __ ld(tmp1, BytesPerWord, from); |
| __ ld(tmp2, 0, from); |
| __ std(tmp1, 0, tos); |
| __ std(tmp2, -BytesPerWord, tos); |
| // New expression stack top. |
| __ addi(ret, tos, - 2 * BytesPerWord); // two slots |
| break; |
| case T_OBJECT: |
| __ ld(tmp1, 0, from); |
| __ verify_oop(tmp1); |
| __ std(tmp1, 0, tos); |
| // New expression stack top. |
| __ addi(ret, tos, - BytesPerWord); |
| break; |
| case T_VOID: |
| // New expression stack top. |
| __ mr(ret, tos); |
| break; |
| default: |
| ShouldNotReachHere(); |
| } |
| |
| __ blr(); |
| |
| return entry; |
| } |
| |
| address CppInterpreterGenerator::generate_stack_to_native_abi_converter(BasicType type) { |
| // |
| // Load a result from the callee's stack into the caller's expecting |
| // return register, callee being interpreted, caller being call stub |
| // or jit code. |
| // |
| // Registers alive |
| // R3_ARG1 - callee expression tos + BytesPerWord |
| // LR |
| // |
| // stack grows upwards, memory grows downwards. |
| // |
| // [ free ] <-- callee's tos |
| // [ optional result ] <-- R3_ARG1 |
| // [ optional dummy ] |
| // ... |
| // |
| // Registers updated |
| // R3_RET(R3_ARG1)/F1_RET - result |
| // |
| |
| const Register from = R3_ARG1; |
| const Register ret = R3_ARG1; |
| const FloatRegister fret = F1_ARG1; |
| |
| address entry = __ pc(); |
| |
| // Implemented uniformly for both kinds of endianness. The interpreter |
| // implements boolean, byte, char, and short as jint (4 bytes). |
| switch (type) { |
| case T_BOOLEAN: |
| case T_CHAR: |
| // zero extension |
| __ lwz(ret, 0, from); |
| break; |
| case T_BYTE: |
| case T_SHORT: |
| case T_INT: |
| // sign extension |
| __ lwa(ret, 0, from); |
| break; |
| case T_LONG: |
| __ ld(ret, 0, from); |
| break; |
| case T_OBJECT: |
| __ ld(ret, 0, from); |
| __ verify_oop(ret); |
| break; |
| case T_FLOAT: |
| __ lfs(fret, 0, from); |
| break; |
| case T_DOUBLE: |
| __ lfd(fret, 0, from); |
| break; |
| case T_VOID: |
| break; |
| default: |
| ShouldNotReachHere(); |
| } |
| |
| __ blr(); |
| |
| return entry; |
| } |
| |
| address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { |
| assert(interpreter_return_address != NULL, "Not initialized"); |
| return interpreter_return_address; |
| } |
| |
| address CppInterpreter::deopt_entry(TosState state, int length) { |
| address ret = NULL; |
| if (length != 0) { |
| switch (state) { |
| case atos: ret = deopt_frame_manager_return_atos; break; |
| case btos: ret = deopt_frame_manager_return_itos; break; |
| case ctos: |
| case stos: |
| case itos: ret = deopt_frame_manager_return_itos; break; |
| case ltos: ret = deopt_frame_manager_return_ltos; break; |
| case ftos: ret = deopt_frame_manager_return_ftos; break; |
| case dtos: ret = deopt_frame_manager_return_dtos; break; |
| case vtos: ret = deopt_frame_manager_return_vtos; break; |
| default: ShouldNotReachHere(); |
| } |
| } else { |
| ret = unctrap_frame_manager_entry; // re-execute the bytecode (e.g. uncommon trap, popframe) |
| } |
| assert(ret != NULL, "Not initialized"); |
| return ret; |
| } |
| |
| // |
| // Helpers for commoning out cases in the various type of method entries. |
| // |
| |
| // |
| // Registers alive |
| // R16_thread - JavaThread* |
| // R1_SP - old stack pointer |
| // R19_method - callee's Method |
| // R17_tos - address of caller's tos (prepushed) |
| // R15_prev_state - address of caller's BytecodeInterpreter or 0 |
| // return_pc in R21_tmp15 (only when called within generate_native_entry) |
| // |
| // Registers updated |
| // R14_state - address of callee's interpreter state |
| // R1_SP - new stack pointer |
| // CCR4_is_synced - current method is synchronized |
| // |
| void CppInterpreterGenerator::generate_compute_interpreter_state(Label& stack_overflow_return) { |
| // |
| // Stack layout at this point: |
| // |
| // F1 [TOP_IJAVA_FRAME_ABI] <-- R1_SP |
| // alignment (optional) |
| // [F1's outgoing Java arguments] <-- R17_tos |
| // ... |
| // F2 [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| |
| //============================================================================= |
| // Allocate space for locals other than the parameters, the |
| // interpreter state, monitors, and the expression stack. |
| |
| const Register local_count = R21_tmp1; |
| const Register parameter_count = R22_tmp2; |
| const Register max_stack = R23_tmp3; |
| // Must not be overwritten within this method! |
| // const Register return_pc = R29_tmp9; |
| |
| const ConditionRegister is_synced = CCR4_is_synced; |
| const ConditionRegister is_native = CCR6; |
| const ConditionRegister is_static = CCR7; |
| |
| assert(is_synced != is_native, "condition code registers must be distinct"); |
| assert(is_synced != is_static, "condition code registers must be distinct"); |
| assert(is_native != is_static, "condition code registers must be distinct"); |
| |
| { |
| |
| // Local registers |
| const Register top_frame_size = R24_tmp4; |
| const Register access_flags = R25_tmp5; |
| const Register state_offset = R26_tmp6; |
| Register mem_stack_limit = R27_tmp7; |
| const Register page_size = R28_tmp8; |
| |
| BLOCK_COMMENT("compute_interpreter_state {"); |
| |
| // access_flags = method->access_flags(); |
| // TODO: PPC port: assert(4 == sizeof(AccessFlags), "unexpected field size"); |
| __ lwa(access_flags, method_(access_flags)); |
| |
| // parameter_count = method->constMethod->size_of_parameters(); |
| // TODO: PPC port: assert(2 == ConstMethod::sz_size_of_parameters(), "unexpected field size"); |
| __ ld(max_stack, in_bytes(Method::const_offset()), R19_method); // Max_stack holds constMethod for a while. |
| __ lhz(parameter_count, in_bytes(ConstMethod::size_of_parameters_offset()), max_stack); |
| |
| // local_count = method->constMethod()->max_locals(); |
| // TODO: PPC port: assert(2 == ConstMethod::sz_max_locals(), "unexpected field size"); |
| __ lhz(local_count, in_bytes(ConstMethod::size_of_locals_offset()), max_stack); |
| |
| // max_stack = method->constMethod()->max_stack(); |
| // TODO: PPC port: assert(2 == ConstMethod::sz_max_stack(), "unexpected field size"); |
| __ lhz(max_stack, in_bytes(ConstMethod::max_stack_offset()), max_stack); |
| |
| if (EnableInvokeDynamic) { |
| // Take into account 'extra_stack_entries' needed by method handles (see method.hpp). |
| __ addi(max_stack, max_stack, Method::extra_stack_entries()); |
| } |
| |
| // mem_stack_limit = thread->stack_limit(); |
| __ ld(mem_stack_limit, thread_(stack_overflow_limit)); |
| |
| // Point locals at the first argument. Method's locals are the |
| // parameters on top of caller's expression stack. |
| |
| // tos points past last Java argument |
| __ sldi(R18_locals, parameter_count, Interpreter::logStackElementSize); |
| __ add(R18_locals, R17_tos, R18_locals); |
| |
| // R18_locals - i*BytesPerWord points to i-th Java local (i starts at 0) |
| |
| // Set is_native, is_synced, is_static - will be used later. |
| __ testbitdi(is_native, R0, access_flags, JVM_ACC_NATIVE_BIT); |
| __ testbitdi(is_synced, R0, access_flags, JVM_ACC_SYNCHRONIZED_BIT); |
| assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); |
| __ testbitdi(is_static, R0, access_flags, JVM_ACC_STATIC_BIT); |
| |
| // PARENT_IJAVA_FRAME_ABI |
| // |
| // frame_size = |
| // round_to((local_count - parameter_count)*BytesPerWord + |
| // 2*BytesPerWord + |
| // alignment + |
| // frame::interpreter_frame_cinterpreterstate_size_in_bytes() |
| // sizeof(PARENT_IJAVA_FRAME_ABI) |
| // method->is_synchronized() ? sizeof(BasicObjectLock) : 0 + |
| // max_stack*BytesPerWord, |
| // 16) |
| // |
| // Note that this calculation is exactly mirrored by |
| // AbstractInterpreter::layout_activation_impl() [ and |
| // AbstractInterpreter::size_activation() ]. Which is used by |
| // deoptimization so that it can allocate the proper sized |
| // frame. This only happens for interpreted frames so the extra |
| // notes below about max_stack below are not important. The other |
| // thing to note is that for interpreter frames other than the |
| // current activation the size of the stack is the size of the live |
| // portion of the stack at the particular bcp and NOT the maximum |
| // stack that the method might use. |
| // |
| // If we're calling a native method, we replace max_stack (which is |
| // zero) with space for the worst-case signature handler varargs |
| // vector, which is: |
| // |
| // max_stack = max(Argument::n_register_parameters, parameter_count+2); |
| // |
| // We add two slots to the parameter_count, one for the jni |
| // environment and one for a possible native mirror. We allocate |
| // space for at least the number of ABI registers, even though |
| // InterpreterRuntime::slow_signature_handler won't write more than |
| // parameter_count+2 words when it creates the varargs vector at the |
| // top of the stack. The generated slow signature handler will just |
| // load trash into registers beyond the necessary number. We're |
| // still going to cut the stack back by the ABI register parameter |
| // count so as to get SP+16 pointing at the ABI outgoing parameter |
| // area, so we need to allocate at least that much even though we're |
| // going to throw it away. |
| // |
| |
| // Adjust max_stack for native methods: |
| Label skip_native_calculate_max_stack; |
| __ bfalse(is_native, skip_native_calculate_max_stack); |
| // if (is_native) { |
| // max_stack = max(Argument::n_register_parameters, parameter_count+2); |
| __ addi(max_stack, parameter_count, 2*Interpreter::stackElementWords); |
| __ cmpwi(CCR0, max_stack, Argument::n_register_parameters); |
| __ bge(CCR0, skip_native_calculate_max_stack); |
| __ li(max_stack, Argument::n_register_parameters); |
| // } |
| __ bind(skip_native_calculate_max_stack); |
| // max_stack is now in bytes |
| __ slwi(max_stack, max_stack, Interpreter::logStackElementSize); |
| |
| // Calculate number of non-parameter locals (in slots): |
| Label not_java; |
| __ btrue(is_native, not_java); |
| // if (!is_native) { |
| // local_count = non-parameter local count |
| __ sub(local_count, local_count, parameter_count); |
| // } else { |
| // // nothing to do: method->max_locals() == 0 for native methods |
| // } |
| __ bind(not_java); |
| |
| |
| // Calculate top_frame_size and parent_frame_resize. |
| { |
| const Register parent_frame_resize = R12_scratch2; |
| |
| BLOCK_COMMENT("Compute top_frame_size."); |
| // top_frame_size = TOP_IJAVA_FRAME_ABI |
| // + size of interpreter state |
| __ li(top_frame_size, frame::top_ijava_frame_abi_size |
| + frame::interpreter_frame_cinterpreterstate_size_in_bytes()); |
| // + max_stack |
| __ add(top_frame_size, top_frame_size, max_stack); |
| // + stack slots for a BasicObjectLock for synchronized methods |
| { |
| Label not_synced; |
| __ bfalse(is_synced, not_synced); |
| __ addi(top_frame_size, top_frame_size, frame::interpreter_frame_monitor_size_in_bytes()); |
| __ bind(not_synced); |
| } |
| // align |
| __ round_to(top_frame_size, frame::alignment_in_bytes); |
| |
| |
| BLOCK_COMMENT("Compute parent_frame_resize."); |
| // parent_frame_resize = R1_SP - R17_tos |
| __ sub(parent_frame_resize, R1_SP, R17_tos); |
| //__ li(parent_frame_resize, 0); |
| // + PARENT_IJAVA_FRAME_ABI |
| // + extra two slots for the no-parameter/no-locals |
| // method result |
| __ addi(parent_frame_resize, parent_frame_resize, |
| frame::parent_ijava_frame_abi_size |
| + 2*Interpreter::stackElementSize); |
| // + (locals_count - params_count) |
| __ sldi(R0, local_count, Interpreter::logStackElementSize); |
| __ add(parent_frame_resize, parent_frame_resize, R0); |
| // align |
| __ round_to(parent_frame_resize, frame::alignment_in_bytes); |
| |
| // |
| // Stack layout at this point: |
| // |
| // The new frame F0 hasn't yet been pushed, F1 is still the top frame. |
| // |
| // F0 [TOP_IJAVA_FRAME_ABI] |
| // alignment (optional) |
| // [F0's full operand stack] |
| // [F0's monitors] (optional) |
| // [F0's BytecodeInterpreter object] |
| // F1 [PARENT_IJAVA_FRAME_ABI] |
| // alignment (optional) |
| // [F0's Java result] |
| // [F0's non-arg Java locals] |
| // [F1's outgoing Java arguments] <-- R17_tos |
| // ... |
| // F2 [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| |
| |
| // Calculate new R14_state |
| // and |
| // test that the new memory stack pointer is above the limit, |
| // throw a StackOverflowError otherwise. |
| __ sub(R11_scratch1/*F1's SP*/, R1_SP, parent_frame_resize); |
| __ addi(R14_state, R11_scratch1/*F1's SP*/, |
| -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); |
| __ sub(R11_scratch1/*F0's SP*/, |
| R11_scratch1/*F1's SP*/, top_frame_size); |
| |
| BLOCK_COMMENT("Test for stack overflow:"); |
| __ cmpld(CCR0/*is_stack_overflow*/, R11_scratch1, mem_stack_limit); |
| __ blt(CCR0/*is_stack_overflow*/, stack_overflow_return); |
| |
| |
| //============================================================================= |
| // Frame_size doesn't overflow the stack. Allocate new frame and |
| // initialize interpreter state. |
| |
| // Register state |
| // |
| // R15 - local_count |
| // R16 - parameter_count |
| // R17 - max_stack |
| // |
| // R18 - frame_size |
| // R19 - access_flags |
| // CCR4_is_synced - is_synced |
| // |
| // GR_Lstate - pointer to the uninitialized new BytecodeInterpreter. |
| |
| // _last_Java_pc just needs to be close enough that we can identify |
| // the frame as an interpreted frame. It does not need to be the |
| // exact return address from either calling |
| // BytecodeInterpreter::InterpretMethod or the call to a jni native method. |
| // So we can initialize it here with a value of a bundle in this |
| // code fragment. We only do this initialization for java frames |
| // where InterpretMethod needs a a way to get a good pc value to |
| // store in the thread state. For interpreter frames used to call |
| // jni native code we just zero the value in the state and move an |
| // ip as needed in the native entry code. |
| // |
| // const Register last_Java_pc_addr = GR24_SCRATCH; // QQQ 27 |
| // const Register last_Java_pc = GR26_SCRATCH; |
| |
| // Must reference stack before setting new SP since Windows |
| // will not be able to deliver the exception on a bad SP. |
| // Windows also insists that we bang each page one at a time in order |
| // for the OS to map in the reserved pages. If we bang only |
| // the final page, Windows stops delivering exceptions to our |
| // VectoredExceptionHandler and terminates our program. |
| // Linux only requires a single bang but it's rare to have |
| // to bang more than 1 page so the code is enabled for both OS's. |
| |
| // BANG THE STACK |
| // |
| // Nothing to do for PPC, because updating the SP will automatically |
| // bang the page. |
| |
| // Up to here we have calculated the delta for the new C-frame and |
| // checked for a stack-overflow. Now we can savely update SP and |
| // resize the C-frame. |
| |
| // R14_state has already been calculated. |
| __ push_interpreter_frame(top_frame_size, parent_frame_resize, |
| R25_tmp5, R26_tmp6, R27_tmp7, R28_tmp8); |
| |
| } |
| |
| // |
| // Stack layout at this point: |
| // |
| // F0 has been been pushed! |
| // |
| // F0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP |
| // alignment (optional) (now it's here, if required) |
| // [F0's full operand stack] |
| // [F0's monitors] (optional) |
| // [F0's BytecodeInterpreter object] |
| // F1 [PARENT_IJAVA_FRAME_ABI] |
| // alignment (optional) (now it's here, if required) |
| // [F0's Java result] |
| // [F0's non-arg Java locals] |
| // [F1's outgoing Java arguments] |
| // ... |
| // F2 [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| // |
| // R14_state points to F0's BytecodeInterpreter object. |
| // |
| |
| } |
| |
| //============================================================================= |
| // new BytecodeInterpreter-object is save, let's initialize it: |
| BLOCK_COMMENT("New BytecodeInterpreter-object is save."); |
| |
| { |
| // Locals |
| const Register bytecode_addr = R24_tmp4; |
| const Register constants = R25_tmp5; |
| const Register tos = R26_tmp6; |
| const Register stack_base = R27_tmp7; |
| const Register local_addr = R28_tmp8; |
| { |
| Label L; |
| __ btrue(is_native, L); |
| // if (!is_native) { |
| // bytecode_addr = constMethod->codes(); |
| __ ld(bytecode_addr, method_(const)); |
| __ addi(bytecode_addr, bytecode_addr, in_bytes(ConstMethod::codes_offset())); |
| // } |
| __ bind(L); |
| } |
| |
| __ ld(constants, in_bytes(Method::const_offset()), R19_method); |
| __ ld(constants, in_bytes(ConstMethod::constants_offset()), constants); |
| |
| // state->_prev_link = prev_state; |
| __ std(R15_prev_state, state_(_prev_link)); |
| |
| // For assertions only. |
| // TODO: not needed anyway because it coincides with `_monitor_base'. remove! |
| // state->_self_link = state; |
| DEBUG_ONLY(__ std(R14_state, state_(_self_link));) |
| |
| // state->_thread = thread; |
| __ std(R16_thread, state_(_thread)); |
| |
| // state->_method = method; |
| __ std(R19_method, state_(_method)); |
| |
| // state->_locals = locals; |
| __ std(R18_locals, state_(_locals)); |
| |
| // state->_oop_temp = NULL; |
| __ li(R0, 0); |
| __ std(R0, state_(_oop_temp)); |
| |
| // state->_last_Java_fp = *R1_SP // Use *R1_SP as fp |
| __ ld(R0, _abi(callers_sp), R1_SP); |
| __ std(R0, state_(_last_Java_fp)); |
| |
| BLOCK_COMMENT("load Stack base:"); |
| { |
| // Stack_base. |
| // if (!method->synchronized()) { |
| // stack_base = state; |
| // } else { |
| // stack_base = (uintptr_t)state - sizeof(BasicObjectLock); |
| // } |
| Label L; |
| __ mr(stack_base, R14_state); |
| __ bfalse(is_synced, L); |
| __ addi(stack_base, stack_base, -frame::interpreter_frame_monitor_size_in_bytes()); |
| __ bind(L); |
| } |
| |
| // state->_mdx = NULL; |
| __ li(R0, 0); |
| __ std(R0, state_(_mdx)); |
| |
| { |
| // if (method->is_native()) state->_bcp = NULL; |
| // else state->_bcp = bytecode_addr; |
| Label label1, label2; |
| __ bfalse(is_native, label1); |
| __ std(R0, state_(_bcp)); |
| __ b(label2); |
| __ bind(label1); |
| __ std(bytecode_addr, state_(_bcp)); |
| __ bind(label2); |
| } |
| |
| |
| // state->_result._to_call._callee = NULL; |
| __ std(R0, state_(_result._to_call._callee)); |
| |
| // state->_monitor_base = state; |
| __ std(R14_state, state_(_monitor_base)); |
| |
| // state->_msg = BytecodeInterpreter::method_entry; |
| __ li(R0, BytecodeInterpreter::method_entry); |
| __ stw(R0, state_(_msg)); |
| |
| // state->_last_Java_sp = R1_SP; |
| __ std(R1_SP, state_(_last_Java_sp)); |
| |
| // state->_stack_base = stack_base; |
| __ std(stack_base, state_(_stack_base)); |
| |
| // tos = stack_base - 1 slot (prepushed); |
| // state->_stack.Tos(tos); |
| __ addi(tos, stack_base, - Interpreter::stackElementSize); |
| __ std(tos, state_(_stack)); |
| |
| |
| { |
| BLOCK_COMMENT("get last_Java_pc:"); |
| // if (!is_native) state->_last_Java_pc = <some_ip_in_this_code_buffer>; |
| // else state->_last_Java_pc = NULL; (just for neatness) |
| Label label1, label2; |
| __ btrue(is_native, label1); |
| __ get_PC_trash_LR(R0); |
| __ std(R0, state_(_last_Java_pc)); |
| __ b(label2); |
| __ bind(label1); |
| __ li(R0, 0); |
| __ std(R0, state_(_last_Java_pc)); |
| __ bind(label2); |
| } |
| |
| |
| // stack_limit = tos - max_stack; |
| __ sub(R0, tos, max_stack); |
| // state->_stack_limit = stack_limit; |
| __ std(R0, state_(_stack_limit)); |
| |
| |
| // cache = method->constants()->cache(); |
| __ ld(R0, ConstantPool::cache_offset_in_bytes(), constants); |
| // state->_constants = method->constants()->cache(); |
| __ std(R0, state_(_constants)); |
| |
| |
| |
| //============================================================================= |
| // synchronized method, allocate and initialize method object lock. |
| // if (!method->is_synchronized()) goto fill_locals_with_0x0s; |
| Label fill_locals_with_0x0s; |
| __ bfalse(is_synced, fill_locals_with_0x0s); |
| |
| // pool_holder = method->constants()->pool_holder(); |
| const int mirror_offset = in_bytes(Klass::java_mirror_offset()); |
| { |
| Label label1, label2; |
| // lockee = NULL; for java methods, correct value will be inserted in BytecodeInterpretMethod.hpp |
| __ li(R0,0); |
| __ bfalse(is_native, label2); |
| |
| __ bfalse(is_static, label1); |
| // if (method->is_static()) lockee = |
| // pool_holder->klass_part()->java_mirror(); |
| __ ld(R11_scratch1/*pool_holder*/, ConstantPool::pool_holder_offset_in_bytes(), constants); |
| __ ld(R0/*lockee*/, mirror_offset, R11_scratch1/*pool_holder*/); |
| __ b(label2); |
| |
| __ bind(label1); |
| // else lockee = *(oop*)locals; |
| __ ld(R0/*lockee*/, 0, R18_locals); |
| __ bind(label2); |
| |
| // monitor->set_obj(lockee); |
| __ std(R0/*lockee*/, BasicObjectLock::obj_offset_in_bytes(), stack_base); |
| } |
| |
| // See if we need to zero the locals |
| __ BIND(fill_locals_with_0x0s); |
| |
| |
| //============================================================================= |
| // fill locals with 0x0s |
| Label locals_zeroed; |
| __ btrue(is_native, locals_zeroed); |
| |
| if (true /* zerolocals */ || ClearInterpreterLocals) { |
| // local_count is already num_locals_slots - num_param_slots |
| __ sldi(R0, parameter_count, Interpreter::logStackElementSize); |
| __ sub(local_addr, R18_locals, R0); |
| __ cmpdi(CCR0, local_count, 0); |
| __ ble(CCR0, locals_zeroed); |
| |
| __ mtctr(local_count); |
| //__ ld_const_addr(R0, (address) 0xcafe0000babe); |
| __ li(R0, 0); |
| |
| Label zero_slot; |
| __ bind(zero_slot); |
| |
| // first local is at local_addr |
| __ std(R0, 0, local_addr); |
| __ addi(local_addr, local_addr, -BytesPerWord); |
| __ bdnz(zero_slot); |
| } |
| |
| __ BIND(locals_zeroed); |
| |
| } |
| BLOCK_COMMENT("} compute_interpreter_state"); |
| } |
| |
| // Generate code to initiate compilation on invocation counter overflow. |
| void CppInterpreterGenerator::generate_counter_overflow(Label& continue_entry) { |
| // Registers alive |
| // R14_state |
| // R16_thread |
| // |
| // Registers updated |
| // R14_state |
| // R3_ARG1 (=R3_RET) |
| // R4_ARG2 |
| |
| // After entering the vm we remove the activation and retry the |
| // entry point in case the compilation is complete. |
| |
| // InterpreterRuntime::frequency_counter_overflow takes one argument |
| // that indicates if the counter overflow occurs at a backwards |
| // branch (NULL bcp). We pass zero. The call returns the address |
| // of the verified entry point for the method or NULL if the |
| // compilation did not complete (either went background or bailed |
| // out). |
| __ li(R4_ARG2, 0); |
| |
| // Pass false to call_VM so it doesn't check for pending exceptions, |
| // since at this point in the method invocation the exception |
| // handler would try to exit the monitor of synchronized methods |
| // which haven't been entered yet. |
| // |
| // Returns verified_entry_point or NULL, we don't care which. |
| // |
| // Do not use the variant `frequency_counter_overflow' that returns |
| // a structure, because this will change the argument list by a |
| // hidden parameter (gcc 4.1). |
| |
| __ call_VM(noreg, |
| CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), |
| R4_ARG2, |
| false); |
| // Returns verified_entry_point or NULL, we don't care which as we ignore it |
| // and run interpreted. |
| |
| // Reload method, it may have moved. |
| __ ld(R19_method, state_(_method)); |
| |
| // We jump now to the label "continue_after_compile". |
| __ b(continue_entry); |
| } |
| |
| // Increment invocation count and check for overflow. |
| // |
| // R19_method must contain Method* of method to profile. |
| void CppInterpreterGenerator::generate_counter_incr(Label& overflow) { |
| Label done; |
| const Register Rcounters = R12_scratch2; |
| const Register iv_be_count = R11_scratch1; |
| const Register invocation_limit = R12_scratch2; |
| const Register invocation_limit_addr = invocation_limit; |
| |
| // Load and ev. allocate MethodCounters object. |
| __ get_method_counters(R19_method, Rcounters, done); |
| |
| // Update standard invocation counters. |
| __ increment_invocation_counter(Rcounters, iv_be_count, R0); |
| |
| // Compare against limit. |
| BLOCK_COMMENT("Compare counter against limit:"); |
| assert(4 == sizeof(InvocationCounter::InterpreterInvocationLimit), |
| "must be 4 bytes"); |
| __ load_const(invocation_limit_addr, (address)&InvocationCounter::InterpreterInvocationLimit); |
| __ lwa(invocation_limit, 0, invocation_limit_addr); |
| __ cmpw(CCR0, iv_be_count, invocation_limit); |
| __ bge(CCR0, overflow); |
| __ bind(done); |
| } |
| |
| // |
| // Call a JNI method. |
| // |
| // Interpreter stub for calling a native method. (C++ interpreter) |
| // This sets up a somewhat different looking stack for calling the native method |
| // than the typical interpreter frame setup. |
| // |
| address CppInterpreterGenerator::generate_native_entry(void) { |
| if (native_entry != NULL) return native_entry; |
| address entry = __ pc(); |
| |
| // Read |
| // R16_thread |
| // R15_prev_state - address of caller's BytecodeInterpreter, if this snippet |
| // gets called by the frame manager. |
| // R19_method - callee's Method |
| // R17_tos - address of caller's tos |
| // R1_SP - caller's stack pointer |
| // R21_sender_SP - initial caller sp |
| // |
| // Update |
| // R14_state - address of caller's BytecodeInterpreter |
| // R3_RET - integer result, if any. |
| // F1_RET - float result, if any. |
| // |
| // |
| // Stack layout at this point: |
| // |
| // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP |
| // alignment (optional) |
| // [outgoing Java arguments] <-- R17_tos |
| // ... |
| // PARENT [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| // |
| |
| const bool inc_counter = UseCompiler || CountCompiledCalls; |
| |
| const Register signature_handler_fd = R21_tmp1; |
| const Register pending_exception = R22_tmp2; |
| const Register result_handler_addr = R23_tmp3; |
| const Register native_method_fd = R24_tmp4; |
| const Register access_flags = R25_tmp5; |
| const Register active_handles = R26_tmp6; |
| const Register sync_state = R27_tmp7; |
| const Register sync_state_addr = sync_state; // Address is dead after use. |
| const Register suspend_flags = R24_tmp4; |
| |
| const Register return_pc = R28_tmp8; // Register will be locked for some time. |
| |
| const ConditionRegister is_synced = CCR4_is_synced; // Live-on-exit from compute_interpreter_state. |
| |
| |
| // R1_SP still points to caller's SP at this point. |
| |
| // Save initial_caller_sp to caller's abi. The caller frame must be |
| // resized before returning to get rid of the c2i arguments (if |
| // any). |
| // Override the saved SP with the senderSP so we can pop c2i |
| // arguments (if any) off when we return |
| __ std(R21_sender_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); |
| |
| // Save LR to caller's frame. We don't use _abi(lr) here, because it is not safe. |
| __ mflr(return_pc); |
| __ std(return_pc, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
| |
| assert(return_pc->is_nonvolatile(), "return_pc must be a non-volatile register"); |
| |
| __ verify_method_ptr(R19_method); |
| |
| //============================================================================= |
| |
| // If this snippet gets called by the frame manager (at label |
| // `call_special'), then R15_prev_state is valid. If this snippet |
| // is not called by the frame manager, but e.g. by the call stub or |
| // by compiled code, then R15_prev_state is invalid. |
| { |
| // Set R15_prev_state to 0 if we don't return to the frame |
| // manager; we will return to the call_stub or to compiled code |
| // instead. If R15_prev_state is 0 there will be only one |
| // interpreter frame (we will set this up later) in this C frame! |
| // So we must take care about retrieving prev_state_(_prev_link) |
| // and restoring R1_SP when popping that interpreter. |
| Label prev_state_is_valid; |
| |
| __ load_const(R11_scratch1/*frame_manager_returnpc_addr*/, (address)&frame_manager_specialized_return); |
| __ ld(R12_scratch2/*frame_manager_returnpc*/, 0, R11_scratch1/*frame_manager_returnpc_addr*/); |
| __ cmpd(CCR0, return_pc, R12_scratch2/*frame_manager_returnpc*/); |
| __ beq(CCR0, prev_state_is_valid); |
| |
| __ li(R15_prev_state, 0); |
| |
| __ BIND(prev_state_is_valid); |
| } |
| |
| //============================================================================= |
| // Allocate new frame and initialize interpreter state. |
| |
| Label exception_return; |
| Label exception_return_sync_check; |
| Label stack_overflow_return; |
| |
| // Generate new interpreter state and jump to stack_overflow_return in case of |
| // a stack overflow. |
| generate_compute_interpreter_state(stack_overflow_return); |
| |
| //============================================================================= |
| // Increment invocation counter. On overflow, entry to JNI method |
| // will be compiled. |
| Label invocation_counter_overflow; |
| if (inc_counter) { |
| generate_counter_incr(invocation_counter_overflow); |
| } |
| |
| Label continue_after_compile; |
| __ BIND(continue_after_compile); |
| |
| // access_flags = method->access_flags(); |
| // Load access flags. |
| assert(access_flags->is_nonvolatile(), |
| "access_flags must be in a non-volatile register"); |
| // Type check. |
| // TODO: PPC port: assert(4 == sizeof(AccessFlags), "unexpected field size"); |
| __ lwz(access_flags, method_(access_flags)); |
| |
| // We don't want to reload R19_method and access_flags after calls |
| // to some helper functions. |
| assert(R19_method->is_nonvolatile(), "R19_method must be a non-volatile register"); |
| |
| // Check for synchronized methods. Must happen AFTER invocation counter |
| // check, so method is not locked if counter overflows. |
| |
| { |
| Label method_is_not_synced; |
| // Is_synced is still alive. |
| assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); |
| __ bfalse(is_synced, method_is_not_synced); |
| |
| lock_method(); |
| // Reload method, it may have moved. |
| __ ld(R19_method, state_(_method)); |
| |
| __ BIND(method_is_not_synced); |
| } |
| |
| // jvmti/jvmpi support |
| __ notify_method_entry(); |
| |
| // Reload method, it may have moved. |
| __ ld(R19_method, state_(_method)); |
| |
| //============================================================================= |
| // Get and call the signature handler |
| |
| __ ld(signature_handler_fd, method_(signature_handler)); |
| Label call_signature_handler; |
| |
| __ cmpdi(CCR0, signature_handler_fd, 0); |
| __ bne(CCR0, call_signature_handler); |
| |
| // Method has never been called. Either generate a specialized |
| // handler or point to the slow one. |
| // |
| // Pass parameter 'false' to avoid exception check in call_VM. |
| __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), R19_method, false); |
| |
| // Check for an exception while looking up the target method. If we |
| // incurred one, bail. |
| __ ld(pending_exception, thread_(pending_exception)); |
| __ cmpdi(CCR0, pending_exception, 0); |
| __ bne(CCR0, exception_return_sync_check); // has pending exception |
| |
| // reload method |
| __ ld(R19_method, state_(_method)); |
| |
| // Reload signature handler, it may have been created/assigned in the meanwhile |
| __ ld(signature_handler_fd, method_(signature_handler)); |
| |
| __ BIND(call_signature_handler); |
| |
| // Before we call the signature handler we push a new frame to |
| // protect the interpreter frame volatile registers when we return |
| // from jni but before we can get back to Java. |
| |
| // First set the frame anchor while the SP/FP registers are |
| // convenient and the slow signature handler can use this same frame |
| // anchor. |
| |
| // We have a TOP_IJAVA_FRAME here, which belongs to us. |
| __ set_top_ijava_frame_at_SP_as_last_Java_frame(R1_SP, R12_scratch2/*tmp*/); |
| |
| // Now the interpreter frame (and its call chain) have been |
| // invalidated and flushed. We are now protected against eager |
| // being enabled in native code. Even if it goes eager the |
| // registers will be reloaded as clean and we will invalidate after |
| // the call so no spurious flush should be possible. |
| |
| // Call signature handler and pass locals address. |
| // |
| // Our signature handlers copy required arguments to the C stack |
| // (outgoing C args), R3_ARG1 to R10_ARG8, and F1_ARG1 to |
| // F13_ARG13. |
| __ mr(R3_ARG1, R18_locals); |
| #if !defined(ABI_ELFv2) |
| __ ld(signature_handler_fd, 0, signature_handler_fd); |
| #endif |
| __ call_stub(signature_handler_fd); |
| // reload method |
| __ ld(R19_method, state_(_method)); |
| |
| // Remove the register parameter varargs slots we allocated in |
| // compute_interpreter_state. SP+16 ends up pointing to the ABI |
| // outgoing argument area. |
| // |
| // Not needed on PPC64. |
| //__ add(SP, SP, Argument::n_register_parameters*BytesPerWord); |
| |
| assert(result_handler_addr->is_nonvolatile(), "result_handler_addr must be in a non-volatile register"); |
| // Save across call to native method. |
| __ mr(result_handler_addr, R3_RET); |
| |
| // Set up fixed parameters and call the native method. |
| // If the method is static, get mirror into R4_ARG2. |
| |
| { |
| Label method_is_not_static; |
| // access_flags is non-volatile and still, no need to restore it |
| |
| // restore access flags |
| __ testbitdi(CCR0, R0, access_flags, JVM_ACC_STATIC_BIT); |
| __ bfalse(CCR0, method_is_not_static); |
| |
| // constants = method->constants(); |
| __ ld(R11_scratch1, in_bytes(Method::const_offset()), R19_method); |
| __ ld(R11_scratch1/*constants*/, in_bytes(ConstMethod::constants_offset()), R11_scratch1); |
| // pool_holder = method->constants()->pool_holder(); |
| __ ld(R11_scratch1/*pool_holder*/, ConstantPool::pool_holder_offset_in_bytes(), |
| R11_scratch1/*constants*/); |
| |
| const int mirror_offset = in_bytes(Klass::java_mirror_offset()); |
| |
| // mirror = pool_holder->klass_part()->java_mirror(); |
| __ ld(R0/*mirror*/, mirror_offset, R11_scratch1/*pool_holder*/); |
| // state->_native_mirror = mirror; |
| __ std(R0/*mirror*/, state_(_oop_temp)); |
| // R4_ARG2 = &state->_oop_temp; |
| __ addir(R4_ARG2, state_(_oop_temp)); |
| |
| __ BIND(method_is_not_static); |
| } |
| |
| // At this point, arguments have been copied off the stack into |
| // their JNI positions. Oops are boxed in-place on the stack, with |
| // handles copied to arguments. The result handler address is in a |
| // register. |
| |
| // pass JNIEnv address as first parameter |
| __ addir(R3_ARG1, thread_(jni_environment)); |
| |
| // Load the native_method entry before we change the thread state. |
| __ ld(native_method_fd, method_(native_function)); |
| |
| //============================================================================= |
| // Transition from _thread_in_Java to _thread_in_native. As soon as |
| // we make this change the safepoint code needs to be certain that |
| // the last Java frame we established is good. The pc in that frame |
| // just needs to be near here not an actual return address. |
| |
| // We use release_store_fence to update values like the thread state, where |
| // we don't want the current thread to continue until all our prior memory |
| // accesses (including the new thread state) are visible to other threads. |
| __ li(R0, _thread_in_native); |
| __ release(); |
| |
| // TODO: PPC port: assert(4 == JavaThread::sz_thread_state(), "unexpected field size"); |
| __ stw(R0, thread_(thread_state)); |
| |
| if (UseMembar) { |
| __ fence(); |
| } |
| |
| //============================================================================= |
| // Call the native method. Argument registers must not have been |
| // overwritten since "__ call_stub(signature_handler);" (except for |
| // ARG1 and ARG2 for static methods) |
| __ call_c(native_method_fd); |
| |
| __ std(R3_RET, state_(_native_lresult)); |
| __ stfd(F1_RET, state_(_native_fresult)); |
| |
| // The frame_manager_lr field, which we use for setting the last |
| // java frame, gets overwritten by the signature handler. Restore |
| // it now. |
| __ get_PC_trash_LR(R11_scratch1); |
| __ std(R11_scratch1, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
| |
| // Because of GC R19_method may no longer be valid. |
| |
| // Block, if necessary, before resuming in _thread_in_Java state. |
| // In order for GC to work, don't clear the last_Java_sp until after |
| // blocking. |
| |
| |
| |
| //============================================================================= |
| // Switch thread to "native transition" state before reading the |
| // synchronization state. This additional state is necessary |
| // because reading and testing the synchronization state is not |
| // atomic w.r.t. GC, as this scenario demonstrates: Java thread A, |
| // in _thread_in_native state, loads _not_synchronized and is |
| // preempted. VM thread changes sync state to synchronizing and |
| // suspends threads for GC. Thread A is resumed to finish this |
| // native method, but doesn't block here since it didn't see any |
| // synchronization in progress, and escapes. |
| |
| // We use release_store_fence to update values like the thread state, where |
| // we don't want the current thread to continue until all our prior memory |
| // accesses (including the new thread state) are visible to other threads. |
| __ li(R0/*thread_state*/, _thread_in_native_trans); |
| __ release(); |
| __ stw(R0/*thread_state*/, thread_(thread_state)); |
| if (UseMembar) { |
| __ fence(); |
| } |
| // Write serialization page so that the VM thread can do a pseudo remote |
| // membar. We use the current thread pointer to calculate a thread |
| // specific offset to write to within the page. This minimizes bus |
| // traffic due to cache line collision. |
| else { |
| __ serialize_memory(R16_thread, R11_scratch1, R12_scratch2); |
| } |
| |
| // Now before we return to java we must look for a current safepoint |
| // (a new safepoint can not start since we entered native_trans). |
| // We must check here because a current safepoint could be modifying |
| // the callers registers right this moment. |
| |
| // Acquire isn't strictly necessary here because of the fence, but |
| // sync_state is declared to be volatile, so we do it anyway. |
| __ load_const(sync_state_addr, SafepointSynchronize::address_of_state()); |
| |
| // TODO: PPC port: assert(4 == SafepointSynchronize::sz_state(), "unexpected field size"); |
| __ lwz(sync_state, 0, sync_state_addr); |
| |
| // TODO: PPC port: assert(4 == Thread::sz_suspend_flags(), "unexpected field size"); |
| __ lwz(suspend_flags, thread_(suspend_flags)); |
| |
| __ acquire(); |
| |
| Label sync_check_done; |
| Label do_safepoint; |
| // No synchronization in progress nor yet synchronized |
| __ cmpwi(CCR0, sync_state, SafepointSynchronize::_not_synchronized); |
| // not suspended |
| __ cmpwi(CCR1, suspend_flags, 0); |
| |
| __ bne(CCR0, do_safepoint); |
| __ beq(CCR1, sync_check_done); |
| __ bind(do_safepoint); |
| // Block. We do the call directly and leave the current |
| // last_Java_frame setup undisturbed. We must save any possible |
| // native result acrosss the call. No oop is present |
| |
| __ mr(R3_ARG1, R16_thread); |
| #if defined(ABI_ELFv2) |
| __ call_c(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), |
| relocInfo::none); |
| #else |
| __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, JavaThread::check_special_condition_for_native_trans), |
| relocInfo::none); |
| #endif |
| __ bind(sync_check_done); |
| |
| //============================================================================= |
| // <<<<<< Back in Interpreter Frame >>>>> |
| |
| // We are in thread_in_native_trans here and back in the normal |
| // interpreter frame. We don't have to do anything special about |
| // safepoints and we can switch to Java mode anytime we are ready. |
| |
| // Note: frame::interpreter_frame_result has a dependency on how the |
| // method result is saved across the call to post_method_exit. For |
| // native methods it assumes that the non-FPU/non-void result is |
| // saved in _native_lresult and a FPU result in _native_fresult. If |
| // this changes then the interpreter_frame_result implementation |
| // will need to be updated too. |
| |
| // On PPC64, we have stored the result directly after the native call. |
| |
| //============================================================================= |
| // back in Java |
| |
| // We use release_store_fence to update values like the thread state, where |
| // we don't want the current thread to continue until all our prior memory |
| // accesses (including the new thread state) are visible to other threads. |
| __ li(R0/*thread_state*/, _thread_in_Java); |
| __ release(); |
| __ stw(R0/*thread_state*/, thread_(thread_state)); |
| if (UseMembar) { |
| __ fence(); |
| } |
| |
| __ reset_last_Java_frame(); |
| |
| // Reload GR27_method, call killed it. We can't look at |
| // state->_method until we're back in java state because in java |
| // state gc can't happen until we get to a safepoint. |
| // |
| // We've set thread_state to _thread_in_Java already, so restoring |
| // R19_method from R14_state works; R19_method is invalid, because |
| // GC may have happened. |
| __ ld(R19_method, state_(_method)); // reload method, may have moved |
| |
| // jvmdi/jvmpi support. Whether we've got an exception pending or |
| // not, and whether unlocking throws an exception or not, we notify |
| // on native method exit. If we do have an exception, we'll end up |
| // in the caller's context to handle it, so if we don't do the |
| // notify here, we'll drop it on the floor. |
| |
| __ notify_method_exit(true/*native method*/, |
| ilgl /*illegal state (not used for native methods)*/, |
| InterpreterMacroAssembler::NotifyJVMTI, |
| false /*check_exceptions*/); |
| |
| //============================================================================= |
| // Handle exceptions |
| |
| // See if we must unlock. |
| // |
| { |
| Label method_is_not_synced; |
| // is_synced is still alive |
| assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); |
| __ bfalse(is_synced, method_is_not_synced); |
| |
| unlock_method(); |
| |
| __ bind(method_is_not_synced); |
| } |
| |
| // Reset active handles after returning from native. |
| // thread->active_handles()->clear(); |
| __ ld(active_handles, thread_(active_handles)); |
| // JNIHandleBlock::_top is an int. |
| // TODO: PPC port: assert(4 == JNIHandleBlock::top_size_in_bytes(), "unexpected field size"); |
| __ li(R0, 0); |
| __ stw(R0, JNIHandleBlock::top_offset_in_bytes(), active_handles); |
| |
| Label no_pending_exception_from_native_method; |
| __ ld(R0/*pending_exception*/, thread_(pending_exception)); |
| __ cmpdi(CCR0, R0/*pending_exception*/, 0); |
| __ beq(CCR0, no_pending_exception_from_native_method); |
| |
| |
| //----------------------------------------------------------------------------- |
| // An exception is pending. We call into the runtime only if the |
| // caller was not interpreted. If it was interpreted the |
| // interpreter will do the correct thing. If it isn't interpreted |
| // (call stub/compiled code) we will change our return and continue. |
| __ BIND(exception_return); |
| |
| Label return_to_initial_caller_with_pending_exception; |
| __ cmpdi(CCR0, R15_prev_state, 0); |
| __ beq(CCR0, return_to_initial_caller_with_pending_exception); |
| |
| // We are returning to an interpreter activation, just pop the state, |
| // pop our frame, leave the exception pending, and return. |
| __ pop_interpreter_state(/*prev_state_may_be_0=*/false); |
| __ pop_interpreter_frame(R11_scratch1, R12_scratch2, R21_tmp1 /* set to return pc */, R22_tmp2); |
| __ mtlr(R21_tmp1); |
| __ blr(); |
| |
| __ BIND(exception_return_sync_check); |
| |
| assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); |
| __ bfalse(is_synced, exception_return); |
| unlock_method(); |
| __ b(exception_return); |
| |
| |
| __ BIND(return_to_initial_caller_with_pending_exception); |
| // We are returning to a c2i-adapter / call-stub, get the address of the |
| // exception handler, pop the frame and return to the handler. |
| |
| // First, pop to caller's frame. |
| __ pop_interpreter_frame(R11_scratch1, R12_scratch2, R21_tmp1 /* set to return pc */, R22_tmp2); |
| |
| __ push_frame_reg_args(0, R11_scratch1); |
| // Get the address of the exception handler. |
| __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), |
| R16_thread, |
| R21_tmp1 /* return pc */); |
| __ pop_frame(); |
| |
| // Load the PC of the the exception handler into LR. |
| __ mtlr(R3_RET); |
| |
| // Load exception into R3_ARG1 and clear pending exception in thread. |
| __ ld(R3_ARG1/*exception*/, thread_(pending_exception)); |
| __ li(R4_ARG2, 0); |
| __ std(R4_ARG2, thread_(pending_exception)); |
| |
| // Load the original return pc into R4_ARG2. |
| __ mr(R4_ARG2/*issuing_pc*/, R21_tmp1); |
| |
| // Resize frame to get rid of a potential extension. |
| __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); |
| |
| // Return to exception handler. |
| __ blr(); |
| |
| |
| //----------------------------------------------------------------------------- |
| // No exception pending. |
| __ BIND(no_pending_exception_from_native_method); |
| |
| // Move native method result back into proper registers and return. |
| // Invoke result handler (may unbox/promote). |
| __ ld(R3_RET, state_(_native_lresult)); |
| __ lfd(F1_RET, state_(_native_fresult)); |
| __ call_stub(result_handler_addr); |
| |
| // We have created a new BytecodeInterpreter object, now we must destroy it. |
| // |
| // Restore previous R14_state and caller's SP. R15_prev_state may |
| // be 0 here, because our caller may be the call_stub or compiled |
| // code. |
| __ pop_interpreter_state(/*prev_state_may_be_0=*/true); |
| __ pop_interpreter_frame(R11_scratch1, R12_scratch2, R21_tmp1 /* set to return pc */, R22_tmp2); |
| // Resize frame to get rid of a potential extension. |
| __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); |
| |
| // Must use the return pc which was loaded from the caller's frame |
| // as the VM uses return-pc-patching for deoptimization. |
| __ mtlr(R21_tmp1); |
| __ blr(); |
| |
| |
| |
| //============================================================================= |
| // We encountered an exception while computing the interpreter |
| // state, so R14_state isn't valid. Act as if we just returned from |
| // the callee method with a pending exception. |
| __ BIND(stack_overflow_return); |
| |
| // |
| // Register state: |
| // R14_state invalid; trashed by compute_interpreter_state |
| // R15_prev_state valid, but may be 0 |
| // |
| // R1_SP valid, points to caller's SP; wasn't yet updated by |
| // compute_interpreter_state |
| // |
| |
| // Create exception oop and make it pending. |
| |
| // Throw the exception via RuntimeStub "throw_StackOverflowError_entry". |
| // |
| // Previously, we called C-Code directly. As a consequence, a |
| // possible GC tried to process the argument oops of the top frame |
| // (see RegisterMap::clear, which sets the corresponding flag to |
| // true). This lead to crashes because: |
| // 1. The top register map did not contain locations for the argument registers |
| // 2. The arguments are dead anyway, could be already overwritten in the worst case |
| // Solution: Call via special runtime stub that pushes it's own |
| // frame. This runtime stub has the flag "CodeBlob::caller_must_gc_arguments()" |
| // set to "false", what prevents the dead arguments getting GC'd. |
| // |
| // 2 cases exist: |
| // 1. We were called by the c2i adapter / call stub |
| // 2. We were called by the frame manager |
| // |
| // Both cases are handled by this code: |
| // 1. - initial_caller_sp was saved in both cases on entry, so it's safe to load it back even if it was not changed. |
| // - control flow will be: |
| // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep->excp_blob of caller method |
| // 2. - control flow will be: |
| // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep->rethrow_excp_entry of frame manager->resume_method |
| // Since we restored the caller SP above, the rethrow_excp_entry can restore the original interpreter state |
| // registers using the stack and resume the calling method with a pending excp. |
| |
| // Pop any c2i extension from the stack, restore LR just to be sure |
| __ ld(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
| __ mtlr(R0); |
| // Resize frame to get rid of a potential extension. |
| __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); |
| |
| assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "generated in wrong order"); |
| // Load target address of the runtime stub. |
| __ load_const(R12_scratch2, (StubRoutines::throw_StackOverflowError_entry())); |
| __ mtctr(R12_scratch2); |
| __ bctr(); |
| |
| |
| //============================================================================= |
| // Counter overflow. |
| |
| if (inc_counter) { |
| // Handle invocation counter overflow |
| __ bind(invocation_counter_overflow); |
| |
| generate_counter_overflow(continue_after_compile); |
| } |
| |
| native_entry = entry; |
| return entry; |
| } |
| |
| bool AbstractInterpreter::can_be_compiled(methodHandle m) { |
| // No special entry points that preclude compilation. |
| return true; |
| } |
| |
| // Unlock the current method. |
| // |
| void CppInterpreterGenerator::unlock_method(void) { |
| // Find preallocated monitor and unlock method. Method monitor is |
| // the first one. |
| |
| // Registers alive |
| // R14_state |
| // |
| // Registers updated |
| // volatiles |
| // |
| const Register monitor = R4_ARG2; |
| |
| // Pass address of initial monitor we allocated. |
| // |
| // First monitor. |
| __ addi(monitor, R14_state, -frame::interpreter_frame_monitor_size_in_bytes()); |
| |
| // Unlock method |
| __ unlock_object(monitor); |
| } |
| |
| // Lock the current method. |
| // |
| void CppInterpreterGenerator::lock_method(void) { |
| // Find preallocated monitor and lock method. Method monitor is the |
| // first one. |
| |
| // |
| // Registers alive |
| // R14_state |
| // |
| // Registers updated |
| // volatiles |
| // |
| |
| const Register monitor = R4_ARG2; |
| const Register object = R5_ARG3; |
| |
| // Pass address of initial monitor we allocated. |
| __ addi(monitor, R14_state, -frame::interpreter_frame_monitor_size_in_bytes()); |
| |
| // Pass object address. |
| __ ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); |
| |
| // Lock method. |
| __ lock_object(monitor, object); |
| } |
| |
| // Generate code for handling resuming a deopted method. |
| void CppInterpreterGenerator::generate_deopt_handling(Register result_index) { |
| |
| //============================================================================= |
| // Returning from a compiled method into a deopted method. The |
| // bytecode at the bcp has completed. The result of the bytecode is |
| // in the native abi (the tosca for the template based |
| // interpreter). Any stack space that was used by the bytecode that |
| // has completed has been removed (e.g. parameters for an invoke) so |
| // all that we have to do is place any pending result on the |
| // expression stack and resume execution on the next bytecode. |
| |
| Label return_from_deopt_common; |
| |
| // R3_RET and F1_RET are live here! Load the array index of the |
| // required result stub address and continue at return_from_deopt_common. |
| |
| // Deopt needs to jump to here to enter the interpreter (return a result). |
| deopt_frame_manager_return_atos = __ pc(); |
| __ li(result_index, AbstractInterpreter::BasicType_as_index(T_OBJECT)); |
| __ b(return_from_deopt_common); |
| |
| deopt_frame_manager_return_btos = __ pc(); |
| __ li(result_index, AbstractInterpreter::BasicType_as_index(T_BOOLEAN)); |
| __ b(return_from_deopt_common); |
| |
| deopt_frame_manager_return_itos = __ pc(); |
| __ li(result_index, AbstractInterpreter::BasicType_as_index(T_INT)); |
| __ b(return_from_deopt_common); |
| |
| deopt_frame_manager_return_ltos = __ pc(); |
| __ li(result_index, AbstractInterpreter::BasicType_as_index(T_LONG)); |
| __ b(return_from_deopt_common); |
| |
| deopt_frame_manager_return_ftos = __ pc(); |
| __ li(result_index, AbstractInterpreter::BasicType_as_index(T_FLOAT)); |
| __ b(return_from_deopt_common); |
| |
| deopt_frame_manager_return_dtos = __ pc(); |
| __ li(result_index, AbstractInterpreter::BasicType_as_index(T_DOUBLE)); |
| __ b(return_from_deopt_common); |
| |
| deopt_frame_manager_return_vtos = __ pc(); |
| __ li(result_index, AbstractInterpreter::BasicType_as_index(T_VOID)); |
| // Last one, fall-through to return_from_deopt_common. |
| |
| // Deopt return common. An index is present that lets us move any |
| // possible result being return to the interpreter's stack. |
| // |
| __ BIND(return_from_deopt_common); |
| |
| } |
| |
| // Generate the code to handle a more_monitors message from the c++ interpreter. |
| void CppInterpreterGenerator::generate_more_monitors() { |
| |
| // |
| // Registers alive |
| // R16_thread - JavaThread* |
| // R15_prev_state - previous BytecodeInterpreter or 0 |
| // R14_state - BytecodeInterpreter* address of receiver's interpreter state |
| // R1_SP - old stack pointer |
| // |
| // Registers updated |
| // R1_SP - new stack pointer |
| // |
| |
| // Very-local scratch registers. |
| const Register old_tos = R21_tmp1; |
| const Register new_tos = R22_tmp2; |
| const Register stack_base = R23_tmp3; |
| const Register stack_limit = R24_tmp4; |
| const Register slot = R25_tmp5; |
| const Register n_slots = R25_tmp5; |
| |
| // Interpreter state fields. |
| const Register msg = R24_tmp4; |
| |
| // Load up relevant interpreter state. |
| |
| __ ld(stack_base, state_(_stack_base)); // Old stack_base |
| __ ld(old_tos, state_(_stack)); // Old tos |
| __ ld(stack_limit, state_(_stack_limit)); // Old stack_limit |
| |
| // extracted monitor_size |
| int monitor_size = frame::interpreter_frame_monitor_size_in_bytes(); |
| assert(Assembler::is_aligned((unsigned int)monitor_size, |
| (unsigned int)frame::alignment_in_bytes), |
| "size of a monitor must respect alignment of SP"); |
| |
| // Save and restore top LR |
| __ ld(R12_scratch2, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
| __ resize_frame(-monitor_size, R11_scratch1);// Allocate space for new monitor |
| __ std(R12_scratch2, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
| // Initial_caller_sp is used as unextended_sp for non initial callers. |
| __ std(R1_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); |
| __ addi(stack_base, stack_base, -monitor_size); // New stack_base |
| __ addi(new_tos, old_tos, -monitor_size); // New tos |
| __ addi(stack_limit, stack_limit, -monitor_size); // New stack_limit |
| |
| __ std(R1_SP, state_(_last_Java_sp)); // Update frame_bottom |
| |
| __ std(stack_base, state_(_stack_base)); // Update stack_base |
| __ std(new_tos, state_(_stack)); // Update tos |
| __ std(stack_limit, state_(_stack_limit)); // Update stack_limit |
| |
| __ li(msg, BytecodeInterpreter::got_monitors); // Tell interpreter we allocated the lock |
| __ stw(msg, state_(_msg)); |
| |
| // Shuffle expression stack down. Recall that stack_base points |
| // just above the new expression stack bottom. Old_tos and new_tos |
| // are used to scan thru the old and new expression stacks. |
| |
| Label copy_slot, copy_slot_finished; |
| __ sub(n_slots, stack_base, new_tos); |
| __ srdi_(n_slots, n_slots, LogBytesPerWord); // compute number of slots to copy |
| assert(LogBytesPerWord == 3, "conflicts assembler instructions"); |
| __ beq(CCR0, copy_slot_finished); // nothing to copy |
| |
| __ mtctr(n_slots); |
| |
| // loop |
| __ bind(copy_slot); |
| __ ldu(slot, BytesPerWord, old_tos); // slot = *++old_tos; |
| __ stdu(slot, BytesPerWord, new_tos); // *++new_tos = slot; |
| __ bdnz(copy_slot); |
| |
| __ bind(copy_slot_finished); |
| |
| // Restart interpreter |
| __ li(R0, 0); |
| __ std(R0, BasicObjectLock::obj_offset_in_bytes(), stack_base); // Mark lock as unused |
| } |
| |
| address CppInterpreterGenerator::generate_normal_entry(void) { |
| if (interpreter_frame_manager != NULL) return interpreter_frame_manager; |
| |
| address entry = __ pc(); |
| |
| address return_from_native_pc = (address) NULL; |
| |
| // Initial entry to frame manager (from call_stub or c2i_adapter) |
| |
| // |
| // Registers alive |
| // R16_thread - JavaThread* |
| // R19_method - callee's Method (method to be invoked) |
| // R17_tos - address of sender tos (prepushed) |
| // R1_SP - SP prepared by call stub such that caller's outgoing args are near top |
| // LR - return address to caller (call_stub or c2i_adapter) |
| // R21_sender_SP - initial caller sp |
| // |
| // Registers updated |
| // R15_prev_state - 0 |
| // |
| // Stack layout at this point: |
| // |
| // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP |
| // alignment (optional) |
| // [outgoing Java arguments] <-- R17_tos |
| // ... |
| // PARENT [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| // |
| |
| // Save initial_caller_sp to caller's abi. |
| // The caller frame must be resized before returning to get rid of |
| // the c2i part on top of the calling compiled frame (if any). |
| // R21_tmp1 must match sender_sp in gen_c2i_adapter. |
| // Now override the saved SP with the senderSP so we can pop c2i |
| // arguments (if any) off when we return. |
| __ std(R21_sender_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); |
| |
| // Save LR to caller's frame. We don't use _abi(lr) here, |
| // because it is not safe. |
| __ mflr(R0); |
| __ std(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
| |
| // If we come here, it is the first invocation of the frame manager. |
| // So there is no previous interpreter state. |
| __ li(R15_prev_state, 0); |
| |
| |
| // Fall through to where "recursive" invocations go. |
| |
| //============================================================================= |
| // Dispatch an instance of the interpreter. Recursive activations |
| // come here. |
| |
| Label re_dispatch; |
| __ BIND(re_dispatch); |
| |
| // |
| // Registers alive |
| // R16_thread - JavaThread* |
| // R19_method - callee's Method |
| // R17_tos - address of caller's tos (prepushed) |
| // R15_prev_state - address of caller's BytecodeInterpreter or 0 |
| // R1_SP - caller's SP trimmed such that caller's outgoing args are near top. |
| // |
| // Stack layout at this point: |
| // |
| // 0 [TOP_IJAVA_FRAME_ABI] |
| // alignment (optional) |
| // [outgoing Java arguments] |
| // ... |
| // PARENT [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| |
| // fall through to interpreted execution |
| |
| //============================================================================= |
| // Allocate a new Java frame and initialize the new interpreter state. |
| |
| Label stack_overflow_return; |
| |
| // Create a suitable new Java frame plus a new BytecodeInterpreter instance |
| // in the current (frame manager's) C frame. |
| generate_compute_interpreter_state(stack_overflow_return); |
| |
| // fall through |
| |
| //============================================================================= |
| // Interpreter dispatch. |
| |
| Label call_interpreter; |
| __ BIND(call_interpreter); |
| |
| // |
| // Registers alive |
| // R16_thread - JavaThread* |
| // R15_prev_state - previous BytecodeInterpreter or 0 |
| // R14_state - address of receiver's BytecodeInterpreter |
| // R1_SP - receiver's stack pointer |
| // |
| |
| // Thread fields. |
| const Register pending_exception = R21_tmp1; |
| |
| // Interpreter state fields. |
| const Register msg = R24_tmp4; |
| |
| // Method fields. |
| const Register parameter_count = R25_tmp5; |
| const Register result_index = R26_tmp6; |
| |
| const Register dummy = R28_tmp8; |
| |
| // Address of various interpreter stubs. |
| // R29_tmp9 is reserved. |
| const Register stub_addr = R27_tmp7; |
| |
| // Uncommon trap needs to jump to here to enter the interpreter |
| // (re-execute current bytecode). |
| unctrap_frame_manager_entry = __ pc(); |
| |
| // If we are profiling, store our fp (BSP) in the thread so we can |
| // find it during a tick. |
| if (Arguments::has_profile()) { |
| // On PPC64 we store the pointer to the current BytecodeInterpreter, |
| // instead of the bsp of ia64. This should suffice to be able to |
| // find all interesting information. |
| __ std(R14_state, thread_(last_interpreter_fp)); |
| } |
| |
| // R16_thread, R14_state and R15_prev_state are nonvolatile |
| // registers. There is no need to save these. If we needed to save |
| // some state in the current Java frame, this could be a place to do |
| // so. |
| |
| // Call Java bytecode dispatcher passing "BytecodeInterpreter* istate". |
| __ call_VM_leaf(CAST_FROM_FN_PTR(address, |
| JvmtiExport::can_post_interpreter_events() |
| ? BytecodeInterpreter::runWithChecks |
| : BytecodeInterpreter::run), |
| R14_state); |
| |
| interpreter_return_address = __ last_calls_return_pc(); |
| |
| // R16_thread, R14_state and R15_prev_state have their values preserved. |
| |
| // If we are profiling, clear the fp in the thread to tell |
| // the profiler that we are no longer in the interpreter. |
| if (Arguments::has_profile()) { |
| __ li(R11_scratch1, 0); |
| __ std(R11_scratch1, thread_(last_interpreter_fp)); |
| } |
| |
| // Load message from bytecode dispatcher. |
| // TODO: PPC port: guarantee(4 == BytecodeInterpreter::sz_msg(), "unexpected field size"); |
| __ lwz(msg, state_(_msg)); |
| |
| |
| Label more_monitors; |
| Label return_from_native; |
| Label return_from_native_common; |
| Label return_from_native_no_exception; |
| Label return_from_interpreted_method; |
| Label return_from_recursive_activation; |
| Label unwind_recursive_activation; |
| Label resume_interpreter; |
| Label return_to_initial_caller; |
| Label unwind_initial_activation; |
| Label unwind_initial_activation_pending_exception; |
| Label call_method; |
| Label call_special; |
| Label retry_method; |
| Label retry_method_osr; |
| Label popping_frame; |
| Label throwing_exception; |
| |
| // Branch according to the received message |
| |
| __ cmpwi(CCR1, msg, BytecodeInterpreter::call_method); |
| __ cmpwi(CCR2, msg, BytecodeInterpreter::return_from_method); |
| |
| __ beq(CCR1, call_method); |
| __ beq(CCR2, return_from_interpreted_method); |
| |
| __ cmpwi(CCR3, msg, BytecodeInterpreter::more_monitors); |
| __ cmpwi(CCR4, msg, BytecodeInterpreter::throwing_exception); |
| |
| __ beq(CCR3, more_monitors); |
| __ beq(CCR4, throwing_exception); |
| |
| __ cmpwi(CCR5, msg, BytecodeInterpreter::popping_frame); |
| __ cmpwi(CCR6, msg, BytecodeInterpreter::do_osr); |
| |
| __ beq(CCR5, popping_frame); |
| __ beq(CCR6, retry_method_osr); |
| |
| __ stop("bad message from interpreter"); |
| |
| |
| //============================================================================= |
| // Add a monitor just below the existing one(s). State->_stack_base |
| // points to the lowest existing one, so we insert the new one just |
| // below it and shuffle the expression stack down. Ref. the above |
| // stack layout picture, we must update _stack_base, _stack, _stack_limit |
| // and _last_Java_sp in the interpreter state. |
| |
| __ BIND(more_monitors); |
| |
| generate_more_monitors(); |
| __ b(call_interpreter); |
| |
| generate_deopt_handling(result_index); |
| |
| // Restoring the R14_state is already done by the deopt_blob. |
| |
| // Current tos includes no parameter slots. |
| __ ld(R17_tos, state_(_stack)); |
| __ li(msg, BytecodeInterpreter::deopt_resume); |
| __ b(return_from_native_common); |
| |
| // We are sent here when we are unwinding from a native method or |
| // adapter with an exception pending. We need to notify the interpreter |
| // that there is an exception to process. |
| // We arrive here also if the frame manager called an (interpreted) target |
| // which returns with a StackOverflow exception. |
| // The control flow is in this case is: |
| // frame_manager->throw_excp_stub->forward_excp->rethrow_excp_entry |
| |
| AbstractInterpreter::_rethrow_exception_entry = __ pc(); |
| |
| // Restore R14_state. |
| __ ld(R14_state, 0, R1_SP); |
| __ addi(R14_state, R14_state, |
| -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); |
| |
| // Store exception oop into thread object. |
| __ std(R3_RET, thread_(pending_exception)); |
| __ li(msg, BytecodeInterpreter::method_resume /*rethrow_exception*/); |
| // |
| // NOTE: the interpreter frame as setup be deopt does NOT include |
| // any parameter slots (good thing since we have no callee here |
| // and couldn't remove them) so we don't have to do any calculations |
| // here to figure it out. |
| // |
| __ ld(R17_tos, state_(_stack)); |
| __ b(return_from_native_common); |
| |
| |
| //============================================================================= |
| // Returning from a native method. Result is in the native abi |
| // location so we must move it to the java expression stack. |
| |
| __ BIND(return_from_native); |
| guarantee(return_from_native_pc == (address) NULL, "precondition"); |
| return_from_native_pc = __ pc(); |
| |
| // Restore R14_state. |
| __ ld(R14_state, 0, R1_SP); |
| __ addi(R14_state, R14_state, -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); |
| |
| // |
| // Registers alive |
| // R16_thread |
| // R14_state - address of caller's BytecodeInterpreter. |
| // R3_RET - integer result, if any. |
| // F1_RET - float result, if any. |
| // |
| // Registers updated |
| // R19_method - callee's Method |
| // R17_tos - caller's tos, with outgoing args popped |
| // result_index - index of result handler. |
| // msg - message for resuming interpreter. |
| // |
| |
| // Very-local scratch registers. |
| |
| const ConditionRegister have_pending_exception = CCR0; |
| |
| // Load callee Method, gc may have moved it. |
| __ ld(R19_method, state_(_result._to_call._callee)); |
| |
| // Load address of caller's tos. includes parameter slots. |
| __ ld(R17_tos, state_(_stack)); |
| |
| // Pop callee's parameters. |
| |
| __ ld(parameter_count, in_bytes(Method::const_offset()), R19_method); |
| __ lhz(parameter_count, in_bytes(ConstMethod::size_of_parameters_offset()), parameter_count); |
| __ sldi(parameter_count, parameter_count, Interpreter::logStackElementSize); |
| __ add(R17_tos, R17_tos, parameter_count); |
| |
| // Result stub address array index |
| // TODO: PPC port: assert(4 == sizeof(AccessFlags), "unexpected field size"); |
| __ lwa(result_index, method_(result_index)); |
| |
| __ li(msg, BytecodeInterpreter::method_resume); |
| |
| // |
| // Registers alive |
| // R16_thread |
| // R14_state - address of caller's BytecodeInterpreter. |
| // R17_tos - address of caller's tos with outgoing args already popped |
| // R3_RET - integer return value, if any. |
| // F1_RET - float return value, if any. |
| // result_index - index of result handler. |
| // msg - message for resuming interpreter. |
| // |
| // Registers updated |
| // R3_RET - new address of caller's tos, including result, if any |
| // |
| |
| __ BIND(return_from_native_common); |
| |
| // Check for pending exception |
| __ ld(pending_exception, thread_(pending_exception)); |
| __ cmpdi(CCR0, pending_exception, 0); |
| __ beq(CCR0, return_from_native_no_exception); |
| |
| // If there's a pending exception, we really have no result, so |
| // R3_RET is dead. Resume_interpreter assumes the new tos is in |
| // R3_RET. |
| __ mr(R3_RET, R17_tos); |
| // `resume_interpreter' expects R15_prev_state to be alive. |
| __ ld(R15_prev_state, state_(_prev_link)); |
| __ b(resume_interpreter); |
| |
| __ BIND(return_from_native_no_exception); |
| |
| // No pending exception, copy method result from native ABI register |
| // to tos. |
| |
| // Address of stub descriptor address array. |
| __ load_const(stub_addr, CppInterpreter::tosca_result_to_stack()); |
| |
| // Pass address of tos to stub. |
| __ mr(R4_ARG2, R17_tos); |
| |
| // Address of stub descriptor address. |
| __ sldi(result_index, result_index, LogBytesPerWord); |
| __ add(stub_addr, stub_addr, result_index); |
| |
| // Stub descriptor address. |
| __ ld(stub_addr, 0, stub_addr); |
| |
| // TODO: don't do this via a call, do it in place! |
| // |
| // call stub via descriptor |
| // in R3_ARG1/F1_ARG1: result value (R3_RET or F1_RET) |
| __ call_stub(stub_addr); |
| |
| // new tos = result of call in R3_RET |
| |
| // `resume_interpreter' expects R15_prev_state to be alive. |
| __ ld(R15_prev_state, state_(_prev_link)); |
| __ b(resume_interpreter); |
| |
| //============================================================================= |
| // We encountered an exception while computing the interpreter |
| // state, so R14_state isn't valid. Act as if we just returned from |
| // the callee method with a pending exception. |
| __ BIND(stack_overflow_return); |
| |
| // |
| // Registers alive |
| // R16_thread - JavaThread* |
| // R1_SP - old stack pointer |
| // R19_method - callee's Method |
| // R17_tos - address of caller's tos (prepushed) |
| // R15_prev_state - address of caller's BytecodeInterpreter or 0 |
| // R18_locals - address of callee's locals array |
| // |
| // Registers updated |
| // R3_RET - address of resuming tos, if recursive unwind |
| |
| Label Lskip_unextend_SP; |
| |
| { |
| const ConditionRegister is_initial_call = CCR0; |
| const Register tos_save = R21_tmp1; |
| const Register tmp = R22_tmp2; |
| |
| assert(tos_save->is_nonvolatile(), "need a nonvolatile"); |
| |
| // Is the exception thrown in the initial Java frame of this frame |
| // manager frame? |
| __ cmpdi(is_initial_call, R15_prev_state, 0); |
| __ bne(is_initial_call, Lskip_unextend_SP); |
| |
| // Pop any c2i extension from the stack. This is necessary in the |
| // non-recursive case (that is we were called by the c2i adapter, |
| // meaning we have to prev state). In this case we entered the frame |
| // manager through a special entry which pushes the orignal |
| // unextended SP to the stack. Here we load it back. |
| __ ld(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
| __ mtlr(R0); |
| // Resize frame to get rid of a potential extension. |
| __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); |
| |
| // Fall through |
| |
| __ bind(Lskip_unextend_SP); |
| |
| // Throw the exception via RuntimeStub "throw_StackOverflowError_entry". |
| // |
| // Previously, we called C-Code directly. As a consequence, a |
| // possible GC tried to process the argument oops of the top frame |
| // (see RegisterMap::clear, which sets the corresponding flag to |
| // true). This lead to crashes because: |
| // 1. The top register map did not contain locations for the argument registers |
| // 2. The arguments are dead anyway, could be already overwritten in the worst case |
| // Solution: Call via special runtime stub that pushes it's own frame. This runtime stub has the flag |
| // "CodeBlob::caller_must_gc_arguments()" set to "false", what prevents the dead arguments getting GC'd. |
| // |
| // 2 cases exist: |
| // 1. We were called by the c2i adapter / call stub |
| // 2. We were called by the frame manager |
| // |
| // Both cases are handled by this code: |
| // 1. - initial_caller_sp was saved on stack => Load it back and we're ok |
| // - control flow will be: |
| // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep->excp_blob of calling method |
| // 2. - control flow will be: |
| // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep-> |
| // ->rethrow_excp_entry of frame manager->resume_method |
| // Since we restored the caller SP above, the rethrow_excp_entry can restore the original interpreter state |
| // registers using the stack and resume the calling method with a pending excp. |
| |
| assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "generated in wrong order"); |
| __ load_const(R3_ARG1, (StubRoutines::throw_StackOverflowError_entry())); |
| __ mtctr(R3_ARG1); |
| __ bctr(); |
| } |
| //============================================================================= |
| // We have popped a frame from an interpreted call. We are assured |
| // of returning to an interpreted call by the popframe abi. We have |
| // no return value all we have to do is pop the current frame and |
| // then make sure that the top of stack (of the caller) gets set to |
| // where it was when we entered the callee (i.e. the args are still |
| // in place). Or we are returning to the interpreter. In the first |
| // case we must extract result (if any) from the java expression |
| // stack and store it in the location the native abi would expect |
| // for a call returning this type. In the second case we must simply |
| // do a stack to stack move as we unwind. |
| |
| __ BIND(popping_frame); |
| |
| // Registers alive |
| // R14_state |
| // R15_prev_state |
| // R17_tos |
| // |
| // Registers updated |
| // R19_method |
| // R3_RET |
| // msg |
| { |
| Label L; |
| |
| // Reload callee method, gc may have moved it. |
| __ ld(R19_method, state_(_method)); |
| |
| // We may be returning to a deoptimized frame in which case the |
| // usual assumption of a recursive return is not true. |
| |
| // not equal = is recursive call |
| __ cmpdi(CCR0, R15_prev_state, 0); |
| |
| __ bne(CCR0, L); |
| |
| // Pop_frame capability. |
| // The pop_frame api says that the underlying frame is a Java frame, in this case |
| // (prev_state==null) it must be a compiled frame: |
| // |
| // Stack at this point: I, C2I + C, ... |
| // |
| // The outgoing arguments of the call have just been copied (popframe_preserve_args). |
| // By the pop_frame api, we must end up in an interpreted frame. So the compiled frame |
| // will be deoptimized. Deoptimization will restore the outgoing arguments from |
| // popframe_preserve_args, adjust the tos such that it includes the popframe_preserve_args, |
| // and adjust the bci such that the call will be executed again. |
| // We have no results, just pop the interpreter frame, resize the compiled frame to get rid |
| // of the c2i extension and return to the deopt_handler. |
| __ b(unwind_initial_activation); |
| |
| // is recursive call |
| __ bind(L); |
| |
| // Resume_interpreter expects the original tos in R3_RET. |
| __ ld(R3_RET, prev_state_(_stack)); |
| |
| // We're done. |
| __ li(msg, BytecodeInterpreter::popping_frame); |
| |
| __ b(unwind_recursive_activation); |
| } |
| |
| |
| //============================================================================= |
| |
| // We have finished an interpreted call. We are either returning to |
| // native (call_stub/c2) or we are returning to the interpreter. |
| // When returning to native, we must extract the result (if any) |
| // from the java expression stack and store it in the location the |
| // native abi expects. When returning to the interpreter we must |
| // simply do a stack to stack move as we unwind. |
| |
| __ BIND(return_from_interpreted_method); |
| |
| // |
| // Registers alive |
| // R16_thread - JavaThread* |
| // R15_prev_state - address of caller's BytecodeInterpreter or 0 |
| // R14_state - address of callee's interpreter state |
| // R1_SP - callee's stack pointer |
| // |
| // Registers updated |
| // R19_method - callee's method |
| // R3_RET - address of result (new caller's tos), |
| // |
| // if returning to interpreted |
| // msg - message for interpreter, |
| // if returning to interpreted |
| // |
| |
| // Check if this is the initial invocation of the frame manager. |
| // If so, R15_prev_state will be null. |
| __ cmpdi(CCR0, R15_prev_state, 0); |
| |
| // Reload callee method, gc may have moved it. |
| __ ld(R19_method, state_(_method)); |
| |
| // Load the method's result type. |
| __ lwz(result_index, method_(result_index)); |
| |
| // Go to return_to_initial_caller if R15_prev_state is null. |
| __ beq(CCR0, return_to_initial_caller); |
| |
| // Copy callee's result to caller's expression stack via inline stack-to-stack |
| // converters. |
| { |
| Register new_tos = R3_RET; |
| Register from_temp = R4_ARG2; |
| Register from = R5_ARG3; |
| Register tos = R6_ARG4; |
| Register tmp1 = R7_ARG5; |
| Register tmp2 = R8_ARG6; |
| |
| ConditionRegister result_type_is_void = CCR1; |
| ConditionRegister result_type_is_long = CCR2; |
| ConditionRegister result_type_is_double = CCR3; |
| |
| Label stack_to_stack_void; |
| Label stack_to_stack_double_slot; // T_LONG, T_DOUBLE |
| Label stack_to_stack_single_slot; // T_BOOLEAN, T_BYTE, T_CHAR, T_SHORT, T_INT, T_FLOAT, T_OBJECT |
| Label stack_to_stack_done; |
| |
| // Pass callee's address of tos + BytesPerWord |
| __ ld(from_temp, state_(_stack)); |
| |
| // result type: void |
| __ cmpwi(result_type_is_void, result_index, AbstractInterpreter::BasicType_as_index(T_VOID)); |
| |
| // Pass caller's tos == callee's locals address |
| __ ld(tos, state_(_locals)); |
| |
| // result type: long |
| __ cmpwi(result_type_is_long, result_index, AbstractInterpreter::BasicType_as_index(T_LONG)); |
| |
| __ addi(from, from_temp, Interpreter::stackElementSize); |
| |
| // !! don't branch above this line !! |
| |
| // handle void |
| __ beq(result_type_is_void, stack_to_stack_void); |
| |
| // result type: double |
| __ cmpwi(result_type_is_double, result_index, AbstractInterpreter::BasicType_as_index(T_DOUBLE)); |
| |
| // handle long or double |
| __ beq(result_type_is_long, stack_to_stack_double_slot); |
| __ beq(result_type_is_double, stack_to_stack_double_slot); |
| |
| // fall through to single slot types (incl. object) |
| |
| { |
| __ BIND(stack_to_stack_single_slot); |
| // T_BOOLEAN, T_BYTE, T_CHAR, T_SHORT, T_INT, T_FLOAT, T_OBJECT |
| |
| __ ld(tmp1, 0, from); |
| __ std(tmp1, 0, tos); |
| // New expression stack top |
| __ addi(new_tos, tos, - BytesPerWord); |
| |
| __ b(stack_to_stack_done); |
| } |
| |
| { |
| __ BIND(stack_to_stack_double_slot); |
| // T_LONG, T_DOUBLE |
| |
| // Move both entries for debug purposes even though only one is live |
| __ ld(tmp1, BytesPerWord, from); |
| __ ld(tmp2, 0, from); |
| __ std(tmp1, 0, tos); |
| __ std(tmp2, -BytesPerWord, tos); |
| |
| // new expression stack top |
| __ addi(new_tos, tos, - 2 * BytesPerWord); // two slots |
| __ b(stack_to_stack_done); |
| } |
| |
| { |
| __ BIND(stack_to_stack_void); |
| // T_VOID |
| |
| // new expression stack top |
| __ mr(new_tos, tos); |
| // fall through to stack_to_stack_done |
| } |
| |
| __ BIND(stack_to_stack_done); |
| } |
| |
| // new tos = R3_RET |
| |
| // Get the message for the interpreter |
| __ li(msg, BytecodeInterpreter::method_resume); |
| |
| // And fall thru |
| |
| |
| //============================================================================= |
| // Restore caller's interpreter state and pass pointer to caller's |
| // new tos to caller. |
| |
| __ BIND(unwind_recursive_activation); |
| |
| // |
| // Registers alive |
| // R15_prev_state - address of caller's BytecodeInterpreter |
| // R3_RET - address of caller's tos |
| // msg - message for caller's BytecodeInterpreter |
| // R1_SP - callee's stack pointer |
| // |
| // Registers updated |
| // R14_state - address of caller's BytecodeInterpreter |
| // R15_prev_state - address of its parent or 0 |
| // |
| |
| // Pop callee's interpreter and set R14_state to caller's interpreter. |
| __ pop_interpreter_state(/*prev_state_may_be_0=*/false); |
| |
| // And fall thru |
| |
| |
| //============================================================================= |
| // Resume the (calling) interpreter after a call. |
| |
| __ BIND(resume_interpreter); |
| |
| // |
| // Registers alive |
| // R14_state - address of resuming BytecodeInterpreter |
| // R15_prev_state - address of its parent or 0 |
| // R3_RET - address of resuming tos |
| // msg - message for resuming interpreter |
| // R1_SP - callee's stack pointer |
| // |
| // Registers updated |
| // R1_SP - caller's stack pointer |
| // |
| |
| // Restore C stack pointer of caller (resuming interpreter), |
| // R14_state already points to the resuming BytecodeInterpreter. |
| __ pop_interpreter_frame_to_state(R14_state, R21_tmp1, R11_scratch1, R12_scratch2); |
| |
| // Store new address of tos (holding return value) in interpreter state. |
| __ std(R3_RET, state_(_stack)); |
| |
| // Store message for interpreter. |
| __ stw(msg, state_(_msg)); |
| |
| __ b(call_interpreter); |
| |
| //============================================================================= |
| // Interpreter returning to native code (call_stub/c1/c2) from |
| // initial activation. Convert stack result and unwind activation. |
| |
| __ BIND(return_to_initial_caller); |
| |
| // |
| // Registers alive |
| // R19_method - callee's Method |
| // R14_state - address of callee's interpreter state |
| // R16_thread - JavaThread |
| // R1_SP - callee's stack pointer |
| // |
| // Registers updated |
| // R3_RET/F1_RET - result in expected output register |
| // |
| |
| // If we have an exception pending we have no result and we |
| // must figure out where to really return to. |
| // |
| __ ld(pending_exception, thread_(pending_exception)); |
| __ cmpdi(CCR0, pending_exception, 0); |
| __ bne(CCR0, unwind_initial_activation_pending_exception); |
| |
| __ lwa(result_index, method_(result_index)); |
| |
| // Address of stub descriptor address array. |
| __ load_const(stub_addr, CppInterpreter::stack_result_to_native()); |
| |
| // Pass address of callee's tos + BytesPerWord. |
| // Will then point directly to result. |
| __ ld(R3_ARG1, state_(_stack)); |
| __ addi(R3_ARG1, R3_ARG1, Interpreter::stackElementSize); |
| |
| // Address of stub descriptor address |
| __ sldi(result_index, result_index, LogBytesPerWord); |
| __ add(stub_addr, stub_addr, result_index); |
| |
| // Stub descriptor address |
| __ ld(stub_addr, 0, stub_addr); |
| |
| // TODO: don't do this via a call, do it in place! |
| // |
| // call stub via descriptor |
| __ call_stub(stub_addr); |
| |
| __ BIND(unwind_initial_activation); |
| |
| // Unwind from initial activation. No exception is pending. |
| |
| // |
| // Stack layout at this point: |
| // |
| // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP |
| // ... |
| // CALLER [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| // CALLER [unextended ABI] |
| // ... |
| // |
| // The CALLER frame has a C2I adapter or is an entry-frame. |
| // |
| |
| // An interpreter frame exists, we may pop the TOP_IJAVA_FRAME and |
| // turn the caller's PARENT_IJAVA_FRAME back into a TOP_IJAVA_FRAME. |
| // But, we simply restore the return pc from the caller's frame and |
| // use the caller's initial_caller_sp as the new SP which pops the |
| // interpreter frame and "resizes" the caller's frame to its "unextended" |
| // size. |
| |
| // get rid of top frame |
| __ pop_frame(); |
| |
| // Load return PC from parent frame. |
| __ ld(R21_tmp1, _parent_ijava_frame_abi(lr), R1_SP); |
| |
| // Resize frame to get rid of a potential extension. |
| __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); |
| |
| // update LR |
| __ mtlr(R21_tmp1); |
| |
| // return |
| __ blr(); |
| |
| //============================================================================= |
| // Unwind from initial activation. An exception is pending |
| |
| __ BIND(unwind_initial_activation_pending_exception); |
| |
| // |
| // Stack layout at this point: |
| // |
| // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP |
| // ... |
| // CALLER [PARENT_IJAVA_FRAME_ABI] |
| // ... |
| // CALLER [unextended ABI] |
| // ... |
| // |
| // The CALLER frame has a C2I adapter or is an entry-frame. |
| // |
| |
| // An interpreter frame exists, we may pop the TOP_IJAVA_FRAME and |
| // turn the caller's PARENT_IJAVA_FRAME back into a TOP_IJAVA_FRAME. |
| // But, we just pop the current TOP_IJAVA_FRAME and fall through |
| |
| __ pop_frame(); |
| __ ld(R3_ARG1, _top_ijava_frame_abi(lr), R1_SP); |
| |
| // |
| // Stack layout at this point: |
| // |
| // CALLER [PARENT_IJAVA_FRAME_ABI] <-- R1_SP |
| // ... |
| // CALLER [unextended ABI] |
| // ... |
| // |
| // The CALLER frame has a C2I adapter or is an entry-frame. |
| // |
| // Registers alive |
| // R16_thread |
| // R3_ARG1 - return address to caller |
| // |
| // Registers updated |
| // R3_ARG1 - address of pending exception |
| // R4_ARG2 - issuing pc = return address to caller |
| // LR - address of exception handler stub |
| // |
| |
| // Resize frame to get rid of a potential extension. |
| __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); |
| |
| __ mr(R14, R3_ARG1); // R14 := ARG1 |
| __ mr(R4_ARG2, R3_ARG1); // ARG2 := ARG1 |
| |
| // Find the address of the "catch_exception" stub. |
| __ push_frame_reg_args(0, R11_scratch1); |
| __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), |
| R16_thread, |
| R4_ARG2); |
| __ pop_frame(); |
| |
| // Load continuation address into LR. |
| __ mtlr(R3_RET); |
| |
| // Load address of pending exception and clear it in thread object. |
| __ ld(R3_ARG1/*R3_RET*/, thread_(pending_exception)); |
| __ li(R4_ARG2, 0); |
| __ std(R4_ARG2, thread_(pending_exception)); |
| |
| // re-load issuing pc |
| __ mr(R4_ARG2, R14); |
| |
| // Branch to found exception handler. |
| __ blr(); |
| |
| //============================================================================= |
| // Call a new method. Compute new args and trim the expression stack |
| // to only what we are currently using and then recurse. |
| |
| __ BIND(call_method); |
| |
| // |
| // Registers alive |
| // R16_thread |
| // R14_state - address of caller's BytecodeInterpreter |
| // R1_SP - caller's stack pointer |
| // |
| // Registers updated |
| // R15_prev_state - address of caller's BytecodeInterpreter |
| // R17_tos - address of caller's tos |
| // R19_method - callee's Method |
| // R1_SP - trimmed back |
| // |
| |
| // Very-local scratch registers. |
| |
| const Register offset = R21_tmp1; |
| const Register tmp = R22_tmp2; |
| const Register self_entry = R23_tmp3; |
| const Register stub_entry = R24_tmp4; |
| |
| const ConditionRegister cr = CCR0; |
| |
| // Load the address of the frame manager. |
| __ load_const(self_entry, &interpreter_frame_manager); |
| __ ld(self_entry, 0, self_entry); |
| |
| // Load BytecodeInterpreter._result._to_call._callee (callee's Method). |
| __ ld(R19_method, state_(_result._to_call._callee)); |
| // Load BytecodeInterpreter._stack (outgoing tos). |
| __ ld(R17_tos, state_(_stack)); |
| |
| // Save address of caller's BytecodeInterpreter. |
| __ mr(R15_prev_state, R14_state); |
| |
| // Load the callee's entry point. |
| // Load BytecodeInterpreter._result._to_call._callee_entry_point. |
| __ ld(stub_entry, state_(_result._to_call._callee_entry_point)); |
| |
| // Check whether stub_entry is equal to self_entry. |
| __ cmpd(cr, self_entry, stub_entry); |
| // if (self_entry == stub_entry) |
| // do a re-dispatch |
| __ beq(cr, re_dispatch); |
| // else |
| // call the specialized entry (adapter for jni or compiled code) |
| __ BIND(call_special); |
| |
| // |
| // Call the entry generated by `InterpreterGenerator::generate_native_entry'. |
| // |
| // Registers alive |
| // R16_thread |
| // R15_prev_state - address of caller's BytecodeInterpreter |
| // R19_method - callee's Method |
| // R17_tos - address of caller's tos |
| // R1_SP - caller's stack pointer |
| // |
| |
| // Mark return from specialized entry for generate_native_entry. |
| guarantee(return_from_native_pc != (address) NULL, "precondition"); |
| frame_manager_specialized_return = return_from_native_pc; |
| |
| // Set sender_SP in case we call interpreter native wrapper which |
| // will expect it. Compiled code should not care. |
| __ mr(R21_sender_SP, R1_SP); |
| |
| // Do a tail call here, and let the link register point to |
| // frame_manager_specialized_return which is return_from_native_pc. |
| __ load_const(tmp, frame_manager_specialized_return); |
| __ call_stub_and_return_to(stub_entry, tmp /* return_pc=tmp */); |
| |
| |
| //============================================================================= |
| // |
| // InterpretMethod triggered OSR compilation of some Java method M |
| // and now asks to run the compiled code. We call this code the |
| // `callee'. |
| // |
| // This is our current idea on how OSR should look like on PPC64: |
| // |
| // While interpreting a Java method M the stack is: |
| // |
| // (InterpretMethod (M), IJAVA_FRAME (M), ANY_FRAME, ...). |
| // |
| // After having OSR compiled M, `InterpretMethod' returns to the |
| // frame manager, sending the message `retry_method_osr'. The stack |
| // is: |
| // |
| // (IJAVA_FRAME (M), ANY_FRAME, ...). |
| // |
| // The compiler will have generated an `nmethod' suitable for |
| // continuing execution of M at the bytecode index at which OSR took |
| // place. So now the frame manager calls the OSR entry. The OSR |
| // entry sets up a JIT_FRAME for M and continues execution of M with |
| // initial state determined by the IJAVA_FRAME. |
| // |
| // (JIT_FRAME (M), IJAVA_FRAME (M), ANY_FRAME, ...). |
| // |
| |
| __ BIND(retry_method_osr); |
| { |
| // |
| // Registers alive |
| // R16_thread |
| // R15_prev_state - address of caller's BytecodeInterpreter |
| // R14_state - address of callee's BytecodeInterpreter |
| // R1_SP - callee's SP before call to InterpretMethod |
| // |
| // Registers updated |
| // R17 - pointer to callee's locals array |
| // (declared via `interpreter_arg_ptr_reg' in the AD file) |
| // R19_method - callee's Method |
| // R1_SP - callee's SP (will become SP of OSR adapter frame) |
| // |
| |
| // Provide a debugger breakpoint in the frame manager if breakpoints |
| // in osr'd methods are requested. |
| #ifdef COMPILER2 |
| NOT_PRODUCT( if (OptoBreakpointOSR) { __ illtrap(); } ) |
| #endif |
| |
| // Load callee's pointer to locals array from callee's state. |
| // __ ld(R17, state_(_locals)); |
| |
| // Load osr entry. |
| __ ld(R12_scratch2, state_(_result._osr._osr_entry)); |
| |
| // Load address of temporary osr buffer to arg1. |
| __ ld(R3_ARG1, state_(_result._osr._osr_buf)); |
| __ mtctr(R12_scratch2); |
| |
| // Load method, gc may move it during execution of osr'd method. |
| __ ld(R22_tmp2, state_(_method)); |
| // Load message 'call_method'. |
| __ li(R23_tmp3, BytecodeInterpreter::call_method); |
| |
| { |
| // Pop the IJAVA frame of the method which we are going to call osr'd. |
| Label no_state, skip_no_state; |
| __ pop_interpreter_state(/*prev_state_may_be_0=*/true); |
| __ cmpdi(CCR0, R14_state,0); |
| __ beq(CCR0, no_state); |
| // return to interpreter |
| __ pop_interpreter_frame_to_state(R14_state, R11_scratch1, R12_scratch2, R21_tmp1); |
| |
| // Init _result._to_call._callee and tell gc that it contains a valid oop |
| // by setting _msg to 'call_method'. |
| __ std(R22_tmp2, state_(_result._to_call._callee)); |
| // TODO: PPC port: assert(4 == BytecodeInterpreter::sz_msg(), "unexpected field size"); |
| __ stw(R23_tmp3, state_(_msg)); |
| |
| __ load_const(R21_tmp1, frame_manager_specialized_return); |
| __ b(skip_no_state); |
| __ bind(no_state); |
| |
| // Return to initial caller. |
| |
| // Get rid of top frame. |
| __ pop_frame(); |
| |
| // Load return PC from parent frame. |
| __ ld(R21_tmp1, _parent_ijava_frame_abi(lr), R1_SP); |
| |
| // Resize frame to get rid of a potential extension. |
| __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); |
| |
| __ bind(skip_no_state); |
| |
| // Update LR with return pc. |
| __ mtlr(R21_tmp1); |
| } |
| // Jump to the osr entry point. |
| __ bctr(); |
| |
| } |
| |
| //============================================================================= |
| // Interpreted method "returned" with an exception, pass it on. |
| // Pass no result, unwind activation and continue/return to |
| // interpreter/call_stub/c2. |
| |
| __ BIND(throwing_exception); |
| |
| // Check if this is the initial invocation of the frame manager. If |
| // so, previous interpreter state in R15_prev_state will be null. |
| |
| // New tos of caller is callee's first parameter address, that is |
| // callee's incoming arguments are popped. |
| __ ld(R3_RET, state_(_locals)); |
| |
| // Check whether this is an initial call. |
| __ cmpdi(CCR0, R15_prev_state, 0); |
| // Yes, called from the call stub or from generated code via a c2i frame. |
| __ beq(CCR0, unwind_initial_activation_pending_exception); |
| |
| // Send resume message, interpreter will see the exception first. |
| |
| __ li(msg, BytecodeInterpreter::method_resume); |
| __ b(unwind_recursive_activation); |
| |
| |
| //============================================================================= |
| // Push the last instruction out to the code buffer. |
| |
| { |
| __ unimplemented("end of InterpreterGenerator::generate_normal_entry", 128); |
| } |
| |
| interpreter_frame_manager = entry; |
| return interpreter_frame_manager; |
| } |
| |
| // Generate code for various sorts of method entries |
| // |
| address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) { |
| address entry_point = NULL; |
| |
| switch (kind) { |
| case Interpreter::zerolocals : break; |
| case Interpreter::zerolocals_synchronized : break; |
| case Interpreter::native : // Fall thru |
| case Interpreter::native_synchronized : entry_point = ((CppInterpreterGenerator*)this)->generate_native_entry(); break; |
| case Interpreter::empty : break; |
| case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; |
| case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; |
| // These are special interpreter intrinsics which we don't support so far. |
| case Interpreter::java_lang_math_sin : break; |
| case Interpreter::java_lang_math_cos : break; |
| case Interpreter::java_lang_math_tan : break; |
| case Interpreter::java_lang_math_abs : break; |
| case Interpreter::java_lang_math_log : break; |
| case Interpreter::java_lang_math_log10 : break; |
| case Interpreter::java_lang_math_sqrt : break; |
| case Interpreter::java_lang_math_pow : break; |
| case Interpreter::java_lang_math_exp : break; |
| case Interpreter::java_lang_ref_reference_get: entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; |
| default : ShouldNotReachHere(); break; |
| } |
| |
| if (entry_point) { |
| return entry_point; |
| } |
| return ((InterpreterGenerator*)this)->generate_normal_entry(); |
| } |
| |
| InterpreterGenerator::InterpreterGenerator(StubQueue* code) |
| : CppInterpreterGenerator(code) { |
| generate_all(); // down here so it can be "virtual" |
| } |
| |
| // How much stack a topmost interpreter method activation needs in words. |
| int AbstractInterpreter::size_top_interpreter_activation(Method* method) { |
| // Computation is in bytes not words to match layout_activation_impl |
| // below, but the return is in words. |
| |
| // |
| // 0 [TOP_IJAVA_FRAME_ABI] \ |
| // alignment (optional) \ | |
| // [operand stack / Java parameters] > stack | | |
| // [monitors] (optional) > monitors | | |
| // [PARENT_IJAVA_FRAME_ABI] \ | | |
| // [BytecodeInterpreter object] > interpreter \ | | | |
| // alignment (optional) | round | parent | round | top |
| // [Java result] (2 slots) > result | | | | |
| // [Java non-arg locals] \ locals | | | | |
| // [arg locals] / / / / / |
| // |
| |
| int locals = method->max_locals() * BytesPerWord; |
| int interpreter = frame::interpreter_frame_cinterpreterstate_size_in_bytes(); |
| int result = 2 * BytesPerWord; |
| |
| int parent = round_to(interpreter + result + locals, 16) + frame::parent_ijava_frame_abi_size; |
| |
| int stack = method->max_stack() * BytesPerWord; |
| int monitors = method->is_synchronized() ? frame::interpreter_frame_monitor_size_in_bytes() : 0; |
| int top = round_to(parent + monitors + stack, 16) + frame::top_ijava_frame_abi_size; |
| |
| return (top / BytesPerWord); |
| } |
| |
| void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill, |
| frame* caller, |
| frame* current, |
| Method* method, |
| intptr_t* locals, |
| intptr_t* stack, |
| intptr_t* stack_base, |
| intptr_t* monitor_base, |
| intptr_t* frame_sp, |
| bool is_top_frame) { |
| // What about any vtable? |
| // |
| to_fill->_thread = JavaThread::current(); |
| // This gets filled in later but make it something recognizable for now. |
| to_fill->_bcp = method->code_base(); |
| to_fill->_locals = locals; |
| to_fill->_constants = method->constants()->cache(); |
| to_fill->_method = method; |
| to_fill->_mdx = NULL; |
| to_fill->_stack = stack; |
| |
| if (is_top_frame && JavaThread::current()->popframe_forcing_deopt_reexecution()) { |
| to_fill->_msg = deopt_resume2; |
| } else { |
| to_fill->_msg = method_resume; |
| } |
| to_fill->_result._to_call._bcp_advance = 0; |
| to_fill->_result._to_call._callee_entry_point = NULL; // doesn't matter to anyone |
| to_fill->_result._to_call._callee = NULL; // doesn't matter to anyone |
| to_fill->_prev_link = NULL; |
| |
| if (caller->is_interpreted_frame()) { |
| interpreterState prev = caller->get_interpreterState(); |
| |
| // Support MH calls. Make sure the interpreter will return the right address: |
| // 1. Caller did ordinary interpreted->compiled call call: Set a prev_state |
| // which makes the CPP interpreter return to frame manager "return_from_interpreted_method" |
| // entry after finishing execution. |
| // 2. Caller did a MH call: If the caller has a MethodHandleInvoke in it's |
| // state (invariant: must be the caller of the bottom vframe) we used the |
| // "call_special" entry to do the call, meaning the arguments have not been |
| // popped from the stack. Therefore, don't enter a prev state in this case |
| // in order to return to "return_from_native" frame manager entry which takes |
| // care of popping arguments. Also, don't overwrite the MH.invoke Method in |
| // the prev_state in order to be able to figure out the number of arguments to |
| // pop. |
| // The parameter method can represent MethodHandle.invokeExact(...). |
| // The MethodHandleCompiler generates these synthetic Methods, |
| // including bytecodes, if an invokedynamic call gets inlined. In |
| // this case we want to return like from any other interpreted |
| // Java call, so we set _prev_link. |
| to_fill->_prev_link = prev; |
| |
| if (*prev->_bcp == Bytecodes::_invokeinterface || *prev->_bcp == Bytecodes::_invokedynamic) { |
| prev->_result._to_call._bcp_advance = 5; |
| } else { |
| prev->_result._to_call._bcp_advance = 3; |
| } |
| } |
| to_fill->_oop_temp = NULL; |
| to_fill->_stack_base = stack_base; |
| // Need +1 here because stack_base points to the word just above the |
| // first expr stack entry and stack_limit is supposed to point to |
| // the word just below the last expr stack entry. See |
| // generate_compute_interpreter_state. |
| to_fill->_stack_limit = stack_base - (method->max_stack() + 1); |
| to_fill->_monitor_base = (BasicObjectLock*) monitor_base; |
| |
| to_fill->_frame_bottom = frame_sp; |
| |
| // PPC64 specific |
| to_fill->_last_Java_pc = NULL; |
| to_fill->_last_Java_fp = NULL; |
| to_fill->_last_Java_sp = frame_sp; |
| #ifdef ASSERT |
| to_fill->_self_link = to_fill; |
| to_fill->_native_fresult = 123456.789; |
| to_fill->_native_lresult = CONST64(0xdeafcafedeadc0de); |
| #endif |
| } |
| |
| void BytecodeInterpreter::pd_layout_interpreterState(interpreterState istate, |
| address last_Java_pc, |
| intptr_t* last_Java_fp) { |
| istate->_last_Java_pc = last_Java_pc; |
| istate->_last_Java_fp = last_Java_fp; |
| } |
| |
| // Computes monitor_size and top_frame_size in bytes. |
| static void frame_size_helper(int max_stack, |
| int monitors, |
| int& monitor_size, |
| int& top_frame_size) { |
| monitor_size = frame::interpreter_frame_monitor_size_in_bytes() * monitors; |
| top_frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() |
| + monitor_size |
| + max_stack * Interpreter::stackElementSize |
| + 2 * Interpreter::stackElementSize, |
| frame::alignment_in_bytes) |
| + frame::top_ijava_frame_abi_size; |
| } |
| |
| // Returns number of stackElementWords needed for the interpreter frame with the |
| // given sections. |
| int AbstractInterpreter::size_activation(int max_stack, |
| int temps, |
| int extra_args, |
| int monitors, |
| int callee_params, |
| int callee_locals, |
| bool is_top_frame) { |
| int monitor_size = 0; |
| int top_frame_size = 0; |
| frame_size_helper(max_stack, monitors, monitor_size, top_frame_size); |
| |
| int frame_size; |
| if (is_top_frame) { |
| frame_size = top_frame_size; |
| } else { |
| frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() |
| + monitor_size |
| + (temps - callee_params + callee_locals) * Interpreter::stackElementSize |
| + 2 * Interpreter::stackElementSize, |
| frame::alignment_in_bytes) |
| + frame::parent_ijava_frame_abi_size; |
| assert(extra_args == 0, "non-zero for top_frame only"); |
| } |
| |
| return frame_size / Interpreter::stackElementSize; |
| } |
| |
| void AbstractInterpreter::layout_activation(Method* method, |
| int temps, // Number of slots on java expression stack in use. |
| int popframe_args, |
| int monitors, // Number of active monitors. |
| int caller_actual_parameters, |
| int callee_params,// Number of slots for callee parameters. |
| int callee_locals,// Number of slots for locals. |
| frame* caller, |
| frame* interpreter_frame, |
| bool is_top_frame, |
| bool is_bottom_frame) { |
| |
| // NOTE this code must exactly mimic what |
| // InterpreterGenerator::generate_compute_interpreter_state() does |
| // as far as allocating an interpreter frame. However there is an |
| // exception. With the C++ based interpreter only the top most frame |
| // has a full sized expression stack. The 16 byte slop factor is |
| // both the abi scratch area and a place to hold a result from a |
| // callee on its way to the callers stack. |
| |
| int monitor_size = 0; |
| int top_frame_size = 0; |
| frame_size_helper(method->max_stack(), monitors, monitor_size, top_frame_size); |
| |
| intptr_t sp = (intptr_t)interpreter_frame->sp(); |
| intptr_t fp = *(intptr_t *)sp; |
| assert(fp == (intptr_t)caller->sp(), "fp must match"); |
| interpreterState cur_state = |
| (interpreterState)(fp - frame::interpreter_frame_cinterpreterstate_size_in_bytes()); |
| |
| // Now fill in the interpreterState object. |
| |
| intptr_t* locals; |
| if (caller->is_interpreted_frame()) { |
| // Locals must agree with the caller because it will be used to set the |
| // caller's tos when we return. |
| interpreterState prev = caller->get_interpreterState(); |
| // Calculate start of "locals" for MH calls. For MH calls, the |
| // current method() (= MH target) and prev->callee() (= |
| // MH.invoke*()) are different and especially have different |
| // signatures. To pop the argumentsof the caller, we must use |
| // the prev->callee()->size_of_arguments() because that's what |
| // the caller actually pushed. Currently, for synthetic MH |
| // calls (deoptimized from inlined MH calls), detected by |
| // is_method_handle_invoke(), we use the callee's arguments |
| // because here, the caller's and callee's signature match. |
| if (true /*!caller->is_at_mh_callsite()*/) { |
| locals = prev->stack() + method->size_of_parameters(); |
| } else { |
| // Normal MH call. |
| locals = prev->stack() + prev->callee()->size_of_parameters(); |
| } |
| } else { |
| bool is_deopted; |
| locals = (intptr_t*) (fp + ((method->max_locals() - 1) * BytesPerWord) + |
| frame::parent_ijava_frame_abi_size); |
| } |
| |
| intptr_t* monitor_base = (intptr_t*) cur_state; |
| intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); |
| |
| // Provide pop_frame capability on PPC64, add popframe_args. |
| // +1 because stack is always prepushed. |
| intptr_t* stack = (intptr_t*) ((intptr_t) stack_base - (temps + popframe_args + 1) * BytesPerWord); |
| |
| BytecodeInterpreter::layout_interpreterState(cur_state, |
| caller, |
| interpreter_frame, |
| method, |
| locals, |
| stack, |
| stack_base, |
| monitor_base, |
| (intptr_t*)(((intptr_t)fp) - top_frame_size), |
| is_top_frame); |
| |
| BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, |
| interpreter_frame->fp()); |
| } |
| |
| #endif // CC_INTERP |