Tue, 17 Oct 2017 12:58:25 +0800
merge
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * Copyright 2012, 2014 SAP AG. All rights reserved. |
aoqi@0 | 4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 5 | * |
aoqi@0 | 6 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 7 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 8 | * published by the Free Software Foundation. |
aoqi@0 | 9 | * |
aoqi@0 | 10 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 13 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 14 | * accompanied this code). |
aoqi@0 | 15 | * |
aoqi@0 | 16 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 17 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 19 | * |
aoqi@0 | 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 21 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 22 | * questions. |
aoqi@0 | 23 | * |
aoqi@0 | 24 | */ |
aoqi@0 | 25 | |
aoqi@0 | 26 | |
aoqi@0 | 27 | #include "precompiled.hpp" |
aoqi@0 | 28 | #include "asm/macroAssembler.inline.hpp" |
aoqi@0 | 29 | #include "interp_masm_ppc_64.hpp" |
aoqi@0 | 30 | #include "interpreter/interpreterRuntime.hpp" |
aoqi@0 | 31 | #include "prims/jvmtiThreadState.hpp" |
aoqi@0 | 32 | |
aoqi@0 | 33 | #ifdef PRODUCT |
aoqi@0 | 34 | #define BLOCK_COMMENT(str) // nothing |
aoqi@0 | 35 | #else |
aoqi@0 | 36 | #define BLOCK_COMMENT(str) block_comment(str) |
aoqi@0 | 37 | #endif |
aoqi@0 | 38 | |
aoqi@0 | 39 | void InterpreterMacroAssembler::null_check_throw(Register a, int offset, Register temp_reg) { |
aoqi@0 | 40 | #ifdef CC_INTERP |
aoqi@0 | 41 | address exception_entry = StubRoutines::throw_NullPointerException_at_call_entry(); |
aoqi@0 | 42 | #else |
aoqi@0 | 43 | address exception_entry = Interpreter::throw_NullPointerException_entry(); |
aoqi@0 | 44 | #endif |
aoqi@0 | 45 | MacroAssembler::null_check_throw(a, offset, temp_reg, exception_entry); |
aoqi@0 | 46 | } |
aoqi@0 | 47 | |
aoqi@0 | 48 | void InterpreterMacroAssembler::branch_to_entry(address entry, Register Rscratch) { |
aoqi@0 | 49 | assert(entry, "Entry must have been generated by now"); |
aoqi@0 | 50 | if (is_within_range_of_b(entry, pc())) { |
aoqi@0 | 51 | b(entry); |
aoqi@0 | 52 | } else { |
aoqi@0 | 53 | load_const_optimized(Rscratch, entry, R0); |
aoqi@0 | 54 | mtctr(Rscratch); |
aoqi@0 | 55 | bctr(); |
aoqi@0 | 56 | } |
aoqi@0 | 57 | } |
aoqi@0 | 58 | |
aoqi@0 | 59 | #ifndef CC_INTERP |
aoqi@0 | 60 | |
aoqi@0 | 61 | void InterpreterMacroAssembler::dispatch_next(TosState state, int bcp_incr) { |
aoqi@0 | 62 | Register bytecode = R12_scratch2; |
aoqi@0 | 63 | if (bcp_incr != 0) { |
aoqi@0 | 64 | lbzu(bytecode, bcp_incr, R14_bcp); |
aoqi@0 | 65 | } else { |
aoqi@0 | 66 | lbz(bytecode, 0, R14_bcp); |
aoqi@0 | 67 | } |
aoqi@0 | 68 | |
aoqi@0 | 69 | dispatch_Lbyte_code(state, bytecode, Interpreter::dispatch_table(state)); |
aoqi@0 | 70 | } |
aoqi@0 | 71 | |
aoqi@0 | 72 | void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { |
aoqi@0 | 73 | // Load current bytecode. |
aoqi@0 | 74 | Register bytecode = R12_scratch2; |
aoqi@0 | 75 | lbz(bytecode, 0, R14_bcp); |
aoqi@0 | 76 | dispatch_Lbyte_code(state, bytecode, table); |
aoqi@0 | 77 | } |
aoqi@0 | 78 | |
aoqi@0 | 79 | // Dispatch code executed in the prolog of a bytecode which does not do it's |
aoqi@0 | 80 | // own dispatch. The dispatch address is computed and placed in R24_dispatch_addr. |
aoqi@0 | 81 | void InterpreterMacroAssembler::dispatch_prolog(TosState state, int bcp_incr) { |
aoqi@0 | 82 | Register bytecode = R12_scratch2; |
aoqi@0 | 83 | lbz(bytecode, bcp_incr, R14_bcp); |
aoqi@0 | 84 | |
aoqi@0 | 85 | load_dispatch_table(R24_dispatch_addr, Interpreter::dispatch_table(state)); |
aoqi@0 | 86 | |
aoqi@0 | 87 | sldi(bytecode, bytecode, LogBytesPerWord); |
aoqi@0 | 88 | ldx(R24_dispatch_addr, R24_dispatch_addr, bytecode); |
aoqi@0 | 89 | } |
aoqi@0 | 90 | |
aoqi@0 | 91 | // Dispatch code executed in the epilog of a bytecode which does not do it's |
aoqi@0 | 92 | // own dispatch. The dispatch address in R24_dispatch_addr is used for the |
aoqi@0 | 93 | // dispatch. |
aoqi@0 | 94 | void InterpreterMacroAssembler::dispatch_epilog(TosState state, int bcp_incr) { |
aoqi@0 | 95 | mtctr(R24_dispatch_addr); |
aoqi@0 | 96 | addi(R14_bcp, R14_bcp, bcp_incr); |
aoqi@0 | 97 | bctr(); |
aoqi@0 | 98 | } |
aoqi@0 | 99 | |
aoqi@0 | 100 | void InterpreterMacroAssembler::check_and_handle_popframe(Register scratch_reg) { |
aoqi@0 | 101 | assert(scratch_reg != R0, "can't use R0 as scratch_reg here"); |
aoqi@0 | 102 | if (JvmtiExport::can_pop_frame()) { |
aoqi@0 | 103 | Label L; |
aoqi@0 | 104 | |
aoqi@0 | 105 | // Check the "pending popframe condition" flag in the current thread. |
aoqi@0 | 106 | lwz(scratch_reg, in_bytes(JavaThread::popframe_condition_offset()), R16_thread); |
aoqi@0 | 107 | |
aoqi@0 | 108 | // Initiate popframe handling only if it is not already being |
aoqi@0 | 109 | // processed. If the flag has the popframe_processing bit set, it |
aoqi@0 | 110 | // means that this code is called *during* popframe handling - we |
aoqi@0 | 111 | // don't want to reenter. |
aoqi@0 | 112 | andi_(R0, scratch_reg, JavaThread::popframe_pending_bit); |
aoqi@0 | 113 | beq(CCR0, L); |
aoqi@0 | 114 | |
aoqi@0 | 115 | andi_(R0, scratch_reg, JavaThread::popframe_processing_bit); |
aoqi@0 | 116 | bne(CCR0, L); |
aoqi@0 | 117 | |
aoqi@0 | 118 | // Call the Interpreter::remove_activation_preserving_args_entry() |
aoqi@0 | 119 | // func to get the address of the same-named entrypoint in the |
aoqi@0 | 120 | // generated interpreter code. |
kvn@7132 | 121 | #if defined(ABI_ELFv2) |
kvn@7132 | 122 | call_c(CAST_FROM_FN_PTR(address, |
kvn@7132 | 123 | Interpreter::remove_activation_preserving_args_entry), |
kvn@7132 | 124 | relocInfo::none); |
kvn@7132 | 125 | #else |
aoqi@0 | 126 | call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, |
aoqi@0 | 127 | Interpreter::remove_activation_preserving_args_entry), |
aoqi@0 | 128 | relocInfo::none); |
kvn@7132 | 129 | #endif |
aoqi@0 | 130 | |
aoqi@0 | 131 | // Jump to Interpreter::_remove_activation_preserving_args_entry. |
aoqi@0 | 132 | mtctr(R3_RET); |
aoqi@0 | 133 | bctr(); |
aoqi@0 | 134 | |
aoqi@0 | 135 | align(32, 12); |
aoqi@0 | 136 | bind(L); |
aoqi@0 | 137 | } |
aoqi@0 | 138 | } |
aoqi@0 | 139 | |
aoqi@0 | 140 | void InterpreterMacroAssembler::check_and_handle_earlyret(Register scratch_reg) { |
aoqi@0 | 141 | const Register Rthr_state_addr = scratch_reg; |
aoqi@0 | 142 | if (JvmtiExport::can_force_early_return()) { |
aoqi@0 | 143 | Label Lno_early_ret; |
aoqi@0 | 144 | ld(Rthr_state_addr, in_bytes(JavaThread::jvmti_thread_state_offset()), R16_thread); |
aoqi@0 | 145 | cmpdi(CCR0, Rthr_state_addr, 0); |
aoqi@0 | 146 | beq(CCR0, Lno_early_ret); |
aoqi@0 | 147 | |
aoqi@0 | 148 | lwz(R0, in_bytes(JvmtiThreadState::earlyret_state_offset()), Rthr_state_addr); |
aoqi@0 | 149 | cmpwi(CCR0, R0, JvmtiThreadState::earlyret_pending); |
aoqi@0 | 150 | bne(CCR0, Lno_early_ret); |
aoqi@0 | 151 | |
aoqi@0 | 152 | // Jump to Interpreter::_earlyret_entry. |
aoqi@0 | 153 | lwz(R3_ARG1, in_bytes(JvmtiThreadState::earlyret_tos_offset()), Rthr_state_addr); |
aoqi@0 | 154 | call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry)); |
aoqi@0 | 155 | mtlr(R3_RET); |
aoqi@0 | 156 | blr(); |
aoqi@0 | 157 | |
aoqi@0 | 158 | align(32, 12); |
aoqi@0 | 159 | bind(Lno_early_ret); |
aoqi@0 | 160 | } |
aoqi@0 | 161 | } |
aoqi@0 | 162 | |
aoqi@0 | 163 | void InterpreterMacroAssembler::load_earlyret_value(TosState state, Register Rscratch1) { |
aoqi@0 | 164 | const Register RjvmtiState = Rscratch1; |
aoqi@0 | 165 | const Register Rscratch2 = R0; |
aoqi@0 | 166 | |
aoqi@0 | 167 | ld(RjvmtiState, in_bytes(JavaThread::jvmti_thread_state_offset()), R16_thread); |
aoqi@0 | 168 | li(Rscratch2, 0); |
aoqi@0 | 169 | |
aoqi@0 | 170 | switch (state) { |
aoqi@0 | 171 | case atos: ld(R17_tos, in_bytes(JvmtiThreadState::earlyret_oop_offset()), RjvmtiState); |
aoqi@0 | 172 | std(Rscratch2, in_bytes(JvmtiThreadState::earlyret_oop_offset()), RjvmtiState); |
aoqi@0 | 173 | break; |
aoqi@0 | 174 | case ltos: ld(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); |
aoqi@0 | 175 | break; |
aoqi@0 | 176 | case btos: // fall through |
aoqi@0 | 177 | case ctos: // fall through |
aoqi@0 | 178 | case stos: // fall through |
aoqi@0 | 179 | case itos: lwz(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); |
aoqi@0 | 180 | break; |
aoqi@0 | 181 | case ftos: lfs(F15_ftos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); |
aoqi@0 | 182 | break; |
aoqi@0 | 183 | case dtos: lfd(F15_ftos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); |
aoqi@0 | 184 | break; |
aoqi@0 | 185 | case vtos: break; |
aoqi@0 | 186 | default : ShouldNotReachHere(); |
aoqi@0 | 187 | } |
aoqi@0 | 188 | |
aoqi@0 | 189 | // Clean up tos value in the jvmti thread state. |
aoqi@0 | 190 | std(Rscratch2, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); |
aoqi@0 | 191 | // Set tos state field to illegal value. |
aoqi@0 | 192 | li(Rscratch2, ilgl); |
aoqi@0 | 193 | stw(Rscratch2, in_bytes(JvmtiThreadState::earlyret_tos_offset()), RjvmtiState); |
aoqi@0 | 194 | } |
aoqi@0 | 195 | |
aoqi@0 | 196 | // Common code to dispatch and dispatch_only. |
aoqi@0 | 197 | // Dispatch value in Lbyte_code and increment Lbcp. |
aoqi@0 | 198 | |
aoqi@0 | 199 | void InterpreterMacroAssembler::load_dispatch_table(Register dst, address* table) { |
aoqi@0 | 200 | address table_base = (address)Interpreter::dispatch_table((TosState)0); |
aoqi@0 | 201 | intptr_t table_offs = (intptr_t)table - (intptr_t)table_base; |
aoqi@0 | 202 | if (is_simm16(table_offs)) { |
aoqi@0 | 203 | addi(dst, R25_templateTableBase, (int)table_offs); |
aoqi@0 | 204 | } else { |
aoqi@0 | 205 | load_const_optimized(dst, table, R0); |
aoqi@0 | 206 | } |
aoqi@0 | 207 | } |
aoqi@0 | 208 | |
aoqi@0 | 209 | void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, Register bytecode, address* table, bool verify) { |
aoqi@0 | 210 | if (verify) { |
aoqi@0 | 211 | unimplemented("dispatch_Lbyte_code: verify"); // See Sparc Implementation to implement this |
aoqi@0 | 212 | } |
aoqi@0 | 213 | |
aoqi@0 | 214 | #ifdef FAST_DISPATCH |
aoqi@0 | 215 | unimplemented("dispatch_Lbyte_code FAST_DISPATCH"); |
aoqi@0 | 216 | #else |
aoqi@0 | 217 | assert_different_registers(bytecode, R11_scratch1); |
aoqi@0 | 218 | |
aoqi@0 | 219 | // Calc dispatch table address. |
aoqi@0 | 220 | load_dispatch_table(R11_scratch1, table); |
aoqi@0 | 221 | |
aoqi@0 | 222 | sldi(R12_scratch2, bytecode, LogBytesPerWord); |
aoqi@0 | 223 | ldx(R11_scratch1, R11_scratch1, R12_scratch2); |
aoqi@0 | 224 | |
aoqi@0 | 225 | // Jump off! |
aoqi@0 | 226 | mtctr(R11_scratch1); |
aoqi@0 | 227 | bctr(); |
aoqi@0 | 228 | #endif |
aoqi@0 | 229 | } |
aoqi@0 | 230 | |
aoqi@0 | 231 | void InterpreterMacroAssembler::load_receiver(Register Rparam_count, Register Rrecv_dst) { |
aoqi@0 | 232 | sldi(Rrecv_dst, Rparam_count, Interpreter::logStackElementSize); |
aoqi@0 | 233 | ldx(Rrecv_dst, Rrecv_dst, R15_esp); |
aoqi@0 | 234 | } |
aoqi@0 | 235 | |
aoqi@0 | 236 | // helpers for expression stack |
aoqi@0 | 237 | |
aoqi@0 | 238 | void InterpreterMacroAssembler::pop_i(Register r) { |
aoqi@0 | 239 | lwzu(r, Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 240 | } |
aoqi@0 | 241 | |
aoqi@0 | 242 | void InterpreterMacroAssembler::pop_ptr(Register r) { |
aoqi@0 | 243 | ldu(r, Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 244 | } |
aoqi@0 | 245 | |
aoqi@0 | 246 | void InterpreterMacroAssembler::pop_l(Register r) { |
aoqi@0 | 247 | ld(r, Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 248 | addi(R15_esp, R15_esp, 2 * Interpreter::stackElementSize); |
aoqi@0 | 249 | } |
aoqi@0 | 250 | |
aoqi@0 | 251 | void InterpreterMacroAssembler::pop_f(FloatRegister f) { |
aoqi@0 | 252 | lfsu(f, Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 253 | } |
aoqi@0 | 254 | |
aoqi@0 | 255 | void InterpreterMacroAssembler::pop_d(FloatRegister f) { |
aoqi@0 | 256 | lfd(f, Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 257 | addi(R15_esp, R15_esp, 2 * Interpreter::stackElementSize); |
aoqi@0 | 258 | } |
aoqi@0 | 259 | |
aoqi@0 | 260 | void InterpreterMacroAssembler::push_i(Register r) { |
aoqi@0 | 261 | stw(r, 0, R15_esp); |
aoqi@0 | 262 | addi(R15_esp, R15_esp, - Interpreter::stackElementSize ); |
aoqi@0 | 263 | } |
aoqi@0 | 264 | |
aoqi@0 | 265 | void InterpreterMacroAssembler::push_ptr(Register r) { |
aoqi@0 | 266 | std(r, 0, R15_esp); |
aoqi@0 | 267 | addi(R15_esp, R15_esp, - Interpreter::stackElementSize ); |
aoqi@0 | 268 | } |
aoqi@0 | 269 | |
aoqi@0 | 270 | void InterpreterMacroAssembler::push_l(Register r) { |
aoqi@0 | 271 | std(r, - Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 272 | addi(R15_esp, R15_esp, - 2 * Interpreter::stackElementSize ); |
aoqi@0 | 273 | } |
aoqi@0 | 274 | |
aoqi@0 | 275 | void InterpreterMacroAssembler::push_f(FloatRegister f) { |
aoqi@0 | 276 | stfs(f, 0, R15_esp); |
aoqi@0 | 277 | addi(R15_esp, R15_esp, - Interpreter::stackElementSize ); |
aoqi@0 | 278 | } |
aoqi@0 | 279 | |
aoqi@0 | 280 | void InterpreterMacroAssembler::push_d(FloatRegister f) { |
aoqi@0 | 281 | stfd(f, - Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 282 | addi(R15_esp, R15_esp, - 2 * Interpreter::stackElementSize ); |
aoqi@0 | 283 | } |
aoqi@0 | 284 | |
aoqi@0 | 285 | void InterpreterMacroAssembler::push_2ptrs(Register first, Register second) { |
aoqi@0 | 286 | std(first, 0, R15_esp); |
aoqi@0 | 287 | std(second, -Interpreter::stackElementSize, R15_esp); |
aoqi@0 | 288 | addi(R15_esp, R15_esp, - 2 * Interpreter::stackElementSize ); |
aoqi@0 | 289 | } |
aoqi@0 | 290 | |
aoqi@0 | 291 | void InterpreterMacroAssembler::push_l_pop_d(Register l, FloatRegister d) { |
aoqi@0 | 292 | std(l, 0, R15_esp); |
aoqi@0 | 293 | lfd(d, 0, R15_esp); |
aoqi@0 | 294 | } |
aoqi@0 | 295 | |
aoqi@0 | 296 | void InterpreterMacroAssembler::push_d_pop_l(FloatRegister d, Register l) { |
aoqi@0 | 297 | stfd(d, 0, R15_esp); |
aoqi@0 | 298 | ld(l, 0, R15_esp); |
aoqi@0 | 299 | } |
aoqi@0 | 300 | |
aoqi@0 | 301 | void InterpreterMacroAssembler::push(TosState state) { |
aoqi@0 | 302 | switch (state) { |
aoqi@0 | 303 | case atos: push_ptr(); break; |
aoqi@0 | 304 | case btos: |
aoqi@0 | 305 | case ctos: |
aoqi@0 | 306 | case stos: |
aoqi@0 | 307 | case itos: push_i(); break; |
aoqi@0 | 308 | case ltos: push_l(); break; |
aoqi@0 | 309 | case ftos: push_f(); break; |
aoqi@0 | 310 | case dtos: push_d(); break; |
aoqi@0 | 311 | case vtos: /* nothing to do */ break; |
aoqi@0 | 312 | default : ShouldNotReachHere(); |
aoqi@0 | 313 | } |
aoqi@0 | 314 | } |
aoqi@0 | 315 | |
aoqi@0 | 316 | void InterpreterMacroAssembler::pop(TosState state) { |
aoqi@0 | 317 | switch (state) { |
aoqi@0 | 318 | case atos: pop_ptr(); break; |
aoqi@0 | 319 | case btos: |
aoqi@0 | 320 | case ctos: |
aoqi@0 | 321 | case stos: |
aoqi@0 | 322 | case itos: pop_i(); break; |
aoqi@0 | 323 | case ltos: pop_l(); break; |
aoqi@0 | 324 | case ftos: pop_f(); break; |
aoqi@0 | 325 | case dtos: pop_d(); break; |
aoqi@0 | 326 | case vtos: /* nothing to do */ break; |
aoqi@0 | 327 | default : ShouldNotReachHere(); |
aoqi@0 | 328 | } |
aoqi@0 | 329 | verify_oop(R17_tos, state); |
aoqi@0 | 330 | } |
aoqi@0 | 331 | |
aoqi@0 | 332 | void InterpreterMacroAssembler::empty_expression_stack() { |
aoqi@0 | 333 | addi(R15_esp, R26_monitor, - Interpreter::stackElementSize); |
aoqi@0 | 334 | } |
aoqi@0 | 335 | |
aoqi@0 | 336 | void InterpreterMacroAssembler::get_2_byte_integer_at_bcp(int bcp_offset, |
aoqi@0 | 337 | Register Rdst, |
aoqi@0 | 338 | signedOrNot is_signed) { |
kvn@7132 | 339 | #if defined(VM_LITTLE_ENDIAN) |
kvn@7132 | 340 | if (bcp_offset) { |
kvn@7132 | 341 | load_const_optimized(Rdst, bcp_offset); |
kvn@7132 | 342 | lhbrx(Rdst, R14_bcp, Rdst); |
kvn@7132 | 343 | } else { |
kvn@7132 | 344 | lhbrx(Rdst, R14_bcp); |
kvn@7132 | 345 | } |
kvn@7132 | 346 | if (is_signed == Signed) { |
kvn@7132 | 347 | extsh(Rdst, Rdst); |
kvn@7132 | 348 | } |
kvn@7132 | 349 | #else |
aoqi@0 | 350 | // Read Java big endian format. |
aoqi@0 | 351 | if (is_signed == Signed) { |
aoqi@0 | 352 | lha(Rdst, bcp_offset, R14_bcp); |
aoqi@0 | 353 | } else { |
aoqi@0 | 354 | lhz(Rdst, bcp_offset, R14_bcp); |
aoqi@0 | 355 | } |
aoqi@0 | 356 | #endif |
aoqi@0 | 357 | } |
aoqi@0 | 358 | |
aoqi@0 | 359 | void InterpreterMacroAssembler::get_4_byte_integer_at_bcp(int bcp_offset, |
aoqi@0 | 360 | Register Rdst, |
aoqi@0 | 361 | signedOrNot is_signed) { |
kvn@7132 | 362 | #if defined(VM_LITTLE_ENDIAN) |
kvn@7132 | 363 | if (bcp_offset) { |
kvn@7132 | 364 | load_const_optimized(Rdst, bcp_offset); |
kvn@7132 | 365 | lwbrx(Rdst, R14_bcp, Rdst); |
kvn@7132 | 366 | } else { |
kvn@7132 | 367 | lwbrx(Rdst, R14_bcp); |
kvn@7132 | 368 | } |
kvn@7132 | 369 | if (is_signed == Signed) { |
kvn@7132 | 370 | extsw(Rdst, Rdst); |
kvn@7132 | 371 | } |
kvn@7132 | 372 | #else |
aoqi@0 | 373 | // Read Java big endian format. |
aoqi@0 | 374 | if (bcp_offset & 3) { // Offset unaligned? |
aoqi@0 | 375 | load_const_optimized(Rdst, bcp_offset); |
aoqi@0 | 376 | if (is_signed == Signed) { |
aoqi@0 | 377 | lwax(Rdst, R14_bcp, Rdst); |
aoqi@0 | 378 | } else { |
aoqi@0 | 379 | lwzx(Rdst, R14_bcp, Rdst); |
aoqi@0 | 380 | } |
aoqi@0 | 381 | } else { |
aoqi@0 | 382 | if (is_signed == Signed) { |
aoqi@0 | 383 | lwa(Rdst, bcp_offset, R14_bcp); |
aoqi@0 | 384 | } else { |
aoqi@0 | 385 | lwz(Rdst, bcp_offset, R14_bcp); |
aoqi@0 | 386 | } |
aoqi@0 | 387 | } |
kvn@7132 | 388 | #endif |
aoqi@0 | 389 | } |
aoqi@0 | 390 | |
kvn@7132 | 391 | |
aoqi@0 | 392 | // Load the constant pool cache index from the bytecode stream. |
aoqi@0 | 393 | // |
aoqi@0 | 394 | // Kills / writes: |
aoqi@0 | 395 | // - Rdst, Rscratch |
aoqi@0 | 396 | void InterpreterMacroAssembler::get_cache_index_at_bcp(Register Rdst, int bcp_offset, size_t index_size) { |
aoqi@0 | 397 | assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); |
kvn@7132 | 398 | // Cache index is always in the native format, courtesy of Rewriter. |
aoqi@0 | 399 | if (index_size == sizeof(u2)) { |
kvn@7132 | 400 | lhz(Rdst, bcp_offset, R14_bcp); |
aoqi@0 | 401 | } else if (index_size == sizeof(u4)) { |
aoqi@0 | 402 | assert(EnableInvokeDynamic, "giant index used only for JSR 292"); |
kvn@7132 | 403 | if (bcp_offset & 3) { |
kvn@7132 | 404 | load_const_optimized(Rdst, bcp_offset); |
kvn@7132 | 405 | lwax(Rdst, R14_bcp, Rdst); |
kvn@7132 | 406 | } else { |
kvn@7132 | 407 | lwa(Rdst, bcp_offset, R14_bcp); |
kvn@7132 | 408 | } |
aoqi@0 | 409 | assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); |
aoqi@0 | 410 | nand(Rdst, Rdst, Rdst); // convert to plain index |
aoqi@0 | 411 | } else if (index_size == sizeof(u1)) { |
aoqi@0 | 412 | lbz(Rdst, bcp_offset, R14_bcp); |
aoqi@0 | 413 | } else { |
aoqi@0 | 414 | ShouldNotReachHere(); |
aoqi@0 | 415 | } |
aoqi@0 | 416 | // Rdst now contains cp cache index. |
aoqi@0 | 417 | } |
aoqi@0 | 418 | |
aoqi@0 | 419 | void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, int bcp_offset, size_t index_size) { |
aoqi@0 | 420 | get_cache_index_at_bcp(cache, bcp_offset, index_size); |
aoqi@0 | 421 | sldi(cache, cache, exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord)); |
aoqi@0 | 422 | add(cache, R27_constPoolCache, cache); |
aoqi@0 | 423 | } |
aoqi@0 | 424 | |
kvn@7132 | 425 | // Load 4-byte signed or unsigned integer in Java format (that is, big-endian format) |
kvn@7132 | 426 | // from (Rsrc)+offset. |
kvn@7132 | 427 | void InterpreterMacroAssembler::get_u4(Register Rdst, Register Rsrc, int offset, |
kvn@7132 | 428 | signedOrNot is_signed) { |
kvn@7132 | 429 | #if defined(VM_LITTLE_ENDIAN) |
kvn@7132 | 430 | if (offset) { |
kvn@7132 | 431 | load_const_optimized(Rdst, offset); |
kvn@7132 | 432 | lwbrx(Rdst, Rdst, Rsrc); |
kvn@7132 | 433 | } else { |
kvn@7132 | 434 | lwbrx(Rdst, Rsrc); |
kvn@7132 | 435 | } |
kvn@7132 | 436 | if (is_signed == Signed) { |
kvn@7132 | 437 | extsw(Rdst, Rdst); |
kvn@7132 | 438 | } |
kvn@7132 | 439 | #else |
kvn@7132 | 440 | if (is_signed == Signed) { |
kvn@7132 | 441 | lwa(Rdst, offset, Rsrc); |
kvn@7132 | 442 | } else { |
kvn@7132 | 443 | lwz(Rdst, offset, Rsrc); |
kvn@7132 | 444 | } |
kvn@7132 | 445 | #endif |
kvn@7132 | 446 | } |
kvn@7132 | 447 | |
aoqi@0 | 448 | // Load object from cpool->resolved_references(index). |
aoqi@0 | 449 | void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index) { |
aoqi@0 | 450 | assert_different_registers(result, index); |
aoqi@0 | 451 | get_constant_pool(result); |
aoqi@0 | 452 | |
aoqi@0 | 453 | // Convert from field index to resolved_references() index and from |
aoqi@0 | 454 | // word index to byte offset. Since this is a java object, it can be compressed. |
aoqi@0 | 455 | Register tmp = index; // reuse |
aoqi@0 | 456 | sldi(tmp, index, LogBytesPerHeapOop); |
aoqi@0 | 457 | // Load pointer for resolved_references[] objArray. |
aoqi@0 | 458 | ld(result, ConstantPool::resolved_references_offset_in_bytes(), result); |
aoqi@0 | 459 | // JNIHandles::resolve(result) |
aoqi@0 | 460 | ld(result, 0, result); |
aoqi@0 | 461 | #ifdef ASSERT |
aoqi@0 | 462 | Label index_ok; |
aoqi@0 | 463 | lwa(R0, arrayOopDesc::length_offset_in_bytes(), result); |
aoqi@0 | 464 | sldi(R0, R0, LogBytesPerHeapOop); |
aoqi@0 | 465 | cmpd(CCR0, tmp, R0); |
aoqi@0 | 466 | blt(CCR0, index_ok); |
aoqi@0 | 467 | stop("resolved reference index out of bounds", 0x09256); |
aoqi@0 | 468 | bind(index_ok); |
aoqi@0 | 469 | #endif |
aoqi@0 | 470 | // Add in the index. |
aoqi@0 | 471 | add(result, tmp, result); |
aoqi@0 | 472 | load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result); |
aoqi@0 | 473 | } |
aoqi@0 | 474 | |
aoqi@0 | 475 | // Generate a subtype check: branch to ok_is_subtype if sub_klass is |
aoqi@0 | 476 | // a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2. |
aoqi@0 | 477 | void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1, |
aoqi@0 | 478 | Register Rtmp2, Register Rtmp3, Label &ok_is_subtype) { |
aoqi@0 | 479 | // Profile the not-null value's klass. |
aoqi@0 | 480 | profile_typecheck(Rsub_klass, Rtmp1, Rtmp2); |
aoqi@0 | 481 | check_klass_subtype(Rsub_klass, Rsuper_klass, Rtmp1, Rtmp2, ok_is_subtype); |
aoqi@0 | 482 | profile_typecheck_failed(Rtmp1, Rtmp2); |
aoqi@0 | 483 | } |
aoqi@0 | 484 | |
aoqi@0 | 485 | void InterpreterMacroAssembler::generate_stack_overflow_check_with_compare_and_throw(Register Rmem_frame_size, Register Rscratch1) { |
aoqi@0 | 486 | Label done; |
aoqi@0 | 487 | sub(Rmem_frame_size, R1_SP, Rmem_frame_size); |
aoqi@0 | 488 | ld(Rscratch1, thread_(stack_overflow_limit)); |
aoqi@0 | 489 | cmpld(CCR0/*is_stack_overflow*/, Rmem_frame_size, Rscratch1); |
aoqi@0 | 490 | bgt(CCR0/*is_stack_overflow*/, done); |
aoqi@0 | 491 | |
aoqi@0 | 492 | // Load target address of the runtime stub. |
aoqi@0 | 493 | assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "generated in wrong order"); |
aoqi@0 | 494 | load_const_optimized(Rscratch1, (StubRoutines::throw_StackOverflowError_entry()), R0); |
aoqi@0 | 495 | mtctr(Rscratch1); |
aoqi@0 | 496 | // Restore caller_sp. |
aoqi@0 | 497 | #ifdef ASSERT |
aoqi@0 | 498 | ld(Rscratch1, 0, R1_SP); |
aoqi@0 | 499 | ld(R0, 0, R21_sender_SP); |
aoqi@0 | 500 | cmpd(CCR0, R0, Rscratch1); |
aoqi@0 | 501 | asm_assert_eq("backlink", 0x547); |
aoqi@0 | 502 | #endif // ASSERT |
aoqi@0 | 503 | mr(R1_SP, R21_sender_SP); |
aoqi@0 | 504 | bctr(); |
aoqi@0 | 505 | |
aoqi@0 | 506 | align(32, 12); |
aoqi@0 | 507 | bind(done); |
aoqi@0 | 508 | } |
aoqi@0 | 509 | |
aoqi@0 | 510 | // Separate these two to allow for delay slot in middle. |
aoqi@0 | 511 | // These are used to do a test and full jump to exception-throwing code. |
aoqi@0 | 512 | |
aoqi@0 | 513 | // Check that index is in range for array, then shift index by index_shift, |
aoqi@0 | 514 | // and put arrayOop + shifted_index into res. |
aoqi@0 | 515 | // Note: res is still shy of address by array offset into object. |
aoqi@0 | 516 | |
aoqi@0 | 517 | void InterpreterMacroAssembler::index_check_without_pop(Register Rarray, Register Rindex, int index_shift, Register Rtmp, Register Rres) { |
aoqi@0 | 518 | // Check that index is in range for array, then shift index by index_shift, |
aoqi@0 | 519 | // and put arrayOop + shifted_index into res. |
aoqi@0 | 520 | // Note: res is still shy of address by array offset into object. |
aoqi@0 | 521 | // Kills: |
aoqi@0 | 522 | // - Rindex |
aoqi@0 | 523 | // Writes: |
aoqi@0 | 524 | // - Rres: Address that corresponds to the array index if check was successful. |
aoqi@0 | 525 | verify_oop(Rarray); |
aoqi@0 | 526 | const Register Rlength = R0; |
aoqi@0 | 527 | const Register RsxtIndex = Rtmp; |
aoqi@0 | 528 | Label LisNull, LnotOOR; |
aoqi@0 | 529 | |
aoqi@0 | 530 | // Array nullcheck |
aoqi@0 | 531 | if (!ImplicitNullChecks) { |
aoqi@0 | 532 | cmpdi(CCR0, Rarray, 0); |
aoqi@0 | 533 | beq(CCR0, LisNull); |
aoqi@0 | 534 | } else { |
aoqi@0 | 535 | null_check_throw(Rarray, arrayOopDesc::length_offset_in_bytes(), /*temp*/RsxtIndex); |
aoqi@0 | 536 | } |
aoqi@0 | 537 | |
aoqi@0 | 538 | // Rindex might contain garbage in upper bits (remember that we don't sign extend |
aoqi@0 | 539 | // during integer arithmetic operations). So kill them and put value into same register |
aoqi@0 | 540 | // where ArrayIndexOutOfBounds would expect the index in. |
aoqi@0 | 541 | rldicl(RsxtIndex, Rindex, 0, 32); // zero extend 32 bit -> 64 bit |
aoqi@0 | 542 | |
aoqi@0 | 543 | // Index check |
aoqi@0 | 544 | lwz(Rlength, arrayOopDesc::length_offset_in_bytes(), Rarray); |
aoqi@0 | 545 | cmplw(CCR0, Rindex, Rlength); |
aoqi@0 | 546 | sldi(RsxtIndex, RsxtIndex, index_shift); |
aoqi@0 | 547 | blt(CCR0, LnotOOR); |
goetz@7424 | 548 | // Index should be in R17_tos, array should be in R4_ARG2. |
goetz@7424 | 549 | mr(R17_tos, Rindex); |
goetz@7424 | 550 | mr(R4_ARG2, Rarray); |
aoqi@0 | 551 | load_dispatch_table(Rtmp, (address*)Interpreter::_throw_ArrayIndexOutOfBoundsException_entry); |
aoqi@0 | 552 | mtctr(Rtmp); |
aoqi@0 | 553 | bctr(); |
aoqi@0 | 554 | |
aoqi@0 | 555 | if (!ImplicitNullChecks) { |
aoqi@0 | 556 | bind(LisNull); |
aoqi@0 | 557 | load_dispatch_table(Rtmp, (address*)Interpreter::_throw_NullPointerException_entry); |
aoqi@0 | 558 | mtctr(Rtmp); |
aoqi@0 | 559 | bctr(); |
aoqi@0 | 560 | } |
aoqi@0 | 561 | |
aoqi@0 | 562 | align(32, 16); |
aoqi@0 | 563 | bind(LnotOOR); |
aoqi@0 | 564 | |
aoqi@0 | 565 | // Calc address |
aoqi@0 | 566 | add(Rres, RsxtIndex, Rarray); |
aoqi@0 | 567 | } |
aoqi@0 | 568 | |
aoqi@0 | 569 | void InterpreterMacroAssembler::index_check(Register array, Register index, int index_shift, Register tmp, Register res) { |
aoqi@0 | 570 | // pop array |
aoqi@0 | 571 | pop_ptr(array); |
aoqi@0 | 572 | |
aoqi@0 | 573 | // check array |
aoqi@0 | 574 | index_check_without_pop(array, index, index_shift, tmp, res); |
aoqi@0 | 575 | } |
aoqi@0 | 576 | |
aoqi@0 | 577 | void InterpreterMacroAssembler::get_const(Register Rdst) { |
aoqi@0 | 578 | ld(Rdst, in_bytes(Method::const_offset()), R19_method); |
aoqi@0 | 579 | } |
aoqi@0 | 580 | |
aoqi@0 | 581 | void InterpreterMacroAssembler::get_constant_pool(Register Rdst) { |
aoqi@0 | 582 | get_const(Rdst); |
aoqi@0 | 583 | ld(Rdst, in_bytes(ConstMethod::constants_offset()), Rdst); |
aoqi@0 | 584 | } |
aoqi@0 | 585 | |
aoqi@0 | 586 | void InterpreterMacroAssembler::get_constant_pool_cache(Register Rdst) { |
aoqi@0 | 587 | get_constant_pool(Rdst); |
aoqi@0 | 588 | ld(Rdst, ConstantPool::cache_offset_in_bytes(), Rdst); |
aoqi@0 | 589 | } |
aoqi@0 | 590 | |
aoqi@0 | 591 | void InterpreterMacroAssembler::get_cpool_and_tags(Register Rcpool, Register Rtags) { |
aoqi@0 | 592 | get_constant_pool(Rcpool); |
aoqi@0 | 593 | ld(Rtags, ConstantPool::tags_offset_in_bytes(), Rcpool); |
aoqi@0 | 594 | } |
aoqi@0 | 595 | |
aoqi@0 | 596 | // Unlock if synchronized method. |
aoqi@0 | 597 | // |
aoqi@0 | 598 | // Unlock the receiver if this is a synchronized method. |
aoqi@0 | 599 | // Unlock any Java monitors from synchronized blocks. |
aoqi@0 | 600 | // |
aoqi@0 | 601 | // If there are locked Java monitors |
aoqi@0 | 602 | // If throw_monitor_exception |
aoqi@0 | 603 | // throws IllegalMonitorStateException |
aoqi@0 | 604 | // Else if install_monitor_exception |
aoqi@0 | 605 | // installs IllegalMonitorStateException |
aoqi@0 | 606 | // Else |
aoqi@0 | 607 | // no error processing |
aoqi@0 | 608 | void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, |
aoqi@0 | 609 | bool throw_monitor_exception, |
aoqi@0 | 610 | bool install_monitor_exception) { |
aoqi@0 | 611 | Label Lunlocked, Lno_unlock; |
aoqi@0 | 612 | { |
aoqi@0 | 613 | Register Rdo_not_unlock_flag = R11_scratch1; |
aoqi@0 | 614 | Register Raccess_flags = R12_scratch2; |
aoqi@0 | 615 | |
aoqi@0 | 616 | // Check if synchronized method or unlocking prevented by |
aoqi@0 | 617 | // JavaThread::do_not_unlock_if_synchronized flag. |
aoqi@0 | 618 | lbz(Rdo_not_unlock_flag, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()), R16_thread); |
aoqi@0 | 619 | lwz(Raccess_flags, in_bytes(Method::access_flags_offset()), R19_method); |
aoqi@0 | 620 | li(R0, 0); |
aoqi@0 | 621 | stb(R0, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()), R16_thread); // reset flag |
aoqi@0 | 622 | |
aoqi@0 | 623 | push(state); |
aoqi@0 | 624 | |
aoqi@0 | 625 | // Skip if we don't have to unlock. |
aoqi@0 | 626 | rldicl_(R0, Raccess_flags, 64-JVM_ACC_SYNCHRONIZED_BIT, 63); // Extract bit and compare to 0. |
aoqi@0 | 627 | beq(CCR0, Lunlocked); |
aoqi@0 | 628 | |
aoqi@0 | 629 | cmpwi(CCR0, Rdo_not_unlock_flag, 0); |
aoqi@0 | 630 | bne(CCR0, Lno_unlock); |
aoqi@0 | 631 | } |
aoqi@0 | 632 | |
aoqi@0 | 633 | // Unlock |
aoqi@0 | 634 | { |
aoqi@0 | 635 | Register Rmonitor_base = R11_scratch1; |
aoqi@0 | 636 | |
aoqi@0 | 637 | Label Lunlock; |
aoqi@0 | 638 | // If it's still locked, everything is ok, unlock it. |
aoqi@0 | 639 | ld(Rmonitor_base, 0, R1_SP); |
aoqi@0 | 640 | addi(Rmonitor_base, Rmonitor_base, - (frame::ijava_state_size + frame::interpreter_frame_monitor_size_in_bytes())); // Monitor base |
aoqi@0 | 641 | |
aoqi@0 | 642 | ld(R0, BasicObjectLock::obj_offset_in_bytes(), Rmonitor_base); |
aoqi@0 | 643 | cmpdi(CCR0, R0, 0); |
aoqi@0 | 644 | bne(CCR0, Lunlock); |
aoqi@0 | 645 | |
aoqi@0 | 646 | // If it's already unlocked, throw exception. |
aoqi@0 | 647 | if (throw_monitor_exception) { |
aoqi@0 | 648 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); |
aoqi@0 | 649 | should_not_reach_here(); |
aoqi@0 | 650 | } else { |
aoqi@0 | 651 | if (install_monitor_exception) { |
aoqi@0 | 652 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); |
aoqi@0 | 653 | b(Lunlocked); |
aoqi@0 | 654 | } |
aoqi@0 | 655 | } |
aoqi@0 | 656 | |
aoqi@0 | 657 | bind(Lunlock); |
aoqi@0 | 658 | unlock_object(Rmonitor_base); |
aoqi@0 | 659 | } |
aoqi@0 | 660 | |
aoqi@0 | 661 | // Check that all other monitors are unlocked. Throw IllegelMonitorState exception if not. |
aoqi@0 | 662 | bind(Lunlocked); |
aoqi@0 | 663 | { |
aoqi@0 | 664 | Label Lexception, Lrestart; |
aoqi@0 | 665 | Register Rcurrent_obj_addr = R11_scratch1; |
aoqi@0 | 666 | const int delta = frame::interpreter_frame_monitor_size_in_bytes(); |
aoqi@0 | 667 | assert((delta & LongAlignmentMask) == 0, "sizeof BasicObjectLock must be even number of doublewords"); |
aoqi@0 | 668 | |
aoqi@0 | 669 | bind(Lrestart); |
aoqi@0 | 670 | // Set up search loop: Calc num of iterations. |
aoqi@0 | 671 | { |
aoqi@0 | 672 | Register Riterations = R12_scratch2; |
aoqi@0 | 673 | Register Rmonitor_base = Rcurrent_obj_addr; |
aoqi@0 | 674 | ld(Rmonitor_base, 0, R1_SP); |
aoqi@0 | 675 | addi(Rmonitor_base, Rmonitor_base, - frame::ijava_state_size); // Monitor base |
aoqi@0 | 676 | |
aoqi@0 | 677 | subf_(Riterations, R26_monitor, Rmonitor_base); |
aoqi@0 | 678 | ble(CCR0, Lno_unlock); |
aoqi@0 | 679 | |
aoqi@0 | 680 | addi(Rcurrent_obj_addr, Rmonitor_base, BasicObjectLock::obj_offset_in_bytes() - frame::interpreter_frame_monitor_size_in_bytes()); |
aoqi@0 | 681 | // Check if any monitor is on stack, bail out if not |
aoqi@0 | 682 | srdi(Riterations, Riterations, exact_log2(delta)); |
aoqi@0 | 683 | mtctr(Riterations); |
aoqi@0 | 684 | } |
aoqi@0 | 685 | |
aoqi@0 | 686 | // The search loop: Look for locked monitors. |
aoqi@0 | 687 | { |
aoqi@0 | 688 | const Register Rcurrent_obj = R0; |
aoqi@0 | 689 | Label Lloop; |
aoqi@0 | 690 | |
aoqi@0 | 691 | ld(Rcurrent_obj, 0, Rcurrent_obj_addr); |
aoqi@0 | 692 | addi(Rcurrent_obj_addr, Rcurrent_obj_addr, -delta); |
aoqi@0 | 693 | bind(Lloop); |
aoqi@0 | 694 | |
aoqi@0 | 695 | // Check if current entry is used. |
aoqi@0 | 696 | cmpdi(CCR0, Rcurrent_obj, 0); |
aoqi@0 | 697 | bne(CCR0, Lexception); |
aoqi@0 | 698 | // Preload next iteration's compare value. |
aoqi@0 | 699 | ld(Rcurrent_obj, 0, Rcurrent_obj_addr); |
aoqi@0 | 700 | addi(Rcurrent_obj_addr, Rcurrent_obj_addr, -delta); |
aoqi@0 | 701 | bdnz(Lloop); |
aoqi@0 | 702 | } |
aoqi@0 | 703 | // Fell through: Everything's unlocked => finish. |
aoqi@0 | 704 | b(Lno_unlock); |
aoqi@0 | 705 | |
aoqi@0 | 706 | // An object is still locked => need to throw exception. |
aoqi@0 | 707 | bind(Lexception); |
aoqi@0 | 708 | if (throw_monitor_exception) { |
aoqi@0 | 709 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); |
aoqi@0 | 710 | should_not_reach_here(); |
aoqi@0 | 711 | } else { |
aoqi@0 | 712 | // Stack unrolling. Unlock object and if requested, install illegal_monitor_exception. |
aoqi@0 | 713 | // Unlock does not block, so don't have to worry about the frame. |
aoqi@0 | 714 | Register Rmonitor_addr = R11_scratch1; |
aoqi@0 | 715 | addi(Rmonitor_addr, Rcurrent_obj_addr, -BasicObjectLock::obj_offset_in_bytes() + delta); |
aoqi@0 | 716 | unlock_object(Rmonitor_addr); |
aoqi@0 | 717 | if (install_monitor_exception) { |
aoqi@0 | 718 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); |
aoqi@0 | 719 | } |
aoqi@0 | 720 | b(Lrestart); |
aoqi@0 | 721 | } |
aoqi@0 | 722 | } |
aoqi@0 | 723 | |
aoqi@0 | 724 | align(32, 12); |
aoqi@0 | 725 | bind(Lno_unlock); |
aoqi@0 | 726 | pop(state); |
aoqi@0 | 727 | } |
aoqi@0 | 728 | |
aoqi@0 | 729 | // Support function for remove_activation & Co. |
aoqi@0 | 730 | void InterpreterMacroAssembler::merge_frames(Register Rsender_sp, Register return_pc, Register Rscratch1, Register Rscratch2) { |
aoqi@0 | 731 | // Pop interpreter frame. |
aoqi@0 | 732 | ld(Rscratch1, 0, R1_SP); // *SP |
aoqi@0 | 733 | ld(Rsender_sp, _ijava_state_neg(sender_sp), Rscratch1); // top_frame_sp |
aoqi@0 | 734 | ld(Rscratch2, 0, Rscratch1); // **SP |
aoqi@0 | 735 | #ifdef ASSERT |
aoqi@0 | 736 | { |
aoqi@0 | 737 | Label Lok; |
aoqi@0 | 738 | ld(R0, _ijava_state_neg(ijava_reserved), Rscratch1); |
aoqi@0 | 739 | cmpdi(CCR0, R0, 0x5afe); |
aoqi@0 | 740 | beq(CCR0, Lok); |
aoqi@0 | 741 | stop("frame corrupted (remove activation)", 0x5afe); |
aoqi@0 | 742 | bind(Lok); |
aoqi@0 | 743 | } |
aoqi@0 | 744 | #endif |
aoqi@0 | 745 | if (return_pc!=noreg) { |
aoqi@0 | 746 | ld(return_pc, _abi(lr), Rscratch1); // LR |
aoqi@0 | 747 | } |
aoqi@0 | 748 | |
aoqi@0 | 749 | // Merge top frames. |
aoqi@0 | 750 | subf(Rscratch1, R1_SP, Rsender_sp); // top_frame_sp - SP |
aoqi@0 | 751 | stdux(Rscratch2, R1_SP, Rscratch1); // atomically set *(SP = top_frame_sp) = **SP |
aoqi@0 | 752 | } |
aoqi@0 | 753 | |
aoqi@0 | 754 | // Remove activation. |
aoqi@0 | 755 | // |
aoqi@0 | 756 | // Unlock the receiver if this is a synchronized method. |
aoqi@0 | 757 | // Unlock any Java monitors from synchronized blocks. |
aoqi@0 | 758 | // Remove the activation from the stack. |
aoqi@0 | 759 | // |
aoqi@0 | 760 | // If there are locked Java monitors |
aoqi@0 | 761 | // If throw_monitor_exception |
aoqi@0 | 762 | // throws IllegalMonitorStateException |
aoqi@0 | 763 | // Else if install_monitor_exception |
aoqi@0 | 764 | // installs IllegalMonitorStateException |
aoqi@0 | 765 | // Else |
aoqi@0 | 766 | // no error processing |
aoqi@0 | 767 | void InterpreterMacroAssembler::remove_activation(TosState state, |
aoqi@0 | 768 | bool throw_monitor_exception, |
aoqi@0 | 769 | bool install_monitor_exception) { |
aoqi@0 | 770 | unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception); |
aoqi@0 | 771 | |
aoqi@0 | 772 | // Save result (push state before jvmti call and pop it afterwards) and notify jvmti. |
aoqi@0 | 773 | notify_method_exit(false, state, NotifyJVMTI, true); |
aoqi@0 | 774 | |
aoqi@0 | 775 | verify_oop(R17_tos, state); |
aoqi@0 | 776 | verify_thread(); |
aoqi@0 | 777 | |
aoqi@0 | 778 | merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R0, R11_scratch1, R12_scratch2); |
aoqi@0 | 779 | mtlr(R0); |
aoqi@0 | 780 | } |
aoqi@0 | 781 | |
aoqi@0 | 782 | #endif // !CC_INTERP |
aoqi@0 | 783 | |
aoqi@0 | 784 | // Lock object |
aoqi@0 | 785 | // |
aoqi@0 | 786 | // Registers alive |
aoqi@0 | 787 | // monitor - Address of the BasicObjectLock to be used for locking, |
aoqi@0 | 788 | // which must be initialized with the object to lock. |
aoqi@0 | 789 | // object - Address of the object to be locked. |
aoqi@0 | 790 | // |
aoqi@0 | 791 | void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { |
aoqi@0 | 792 | if (UseHeavyMonitors) { |
aoqi@0 | 793 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), |
aoqi@0 | 794 | monitor, /*check_for_exceptions=*/true CC_INTERP_ONLY(&& false)); |
aoqi@0 | 795 | } else { |
aoqi@0 | 796 | // template code: |
aoqi@0 | 797 | // |
aoqi@0 | 798 | // markOop displaced_header = obj->mark().set_unlocked(); |
aoqi@0 | 799 | // monitor->lock()->set_displaced_header(displaced_header); |
aoqi@0 | 800 | // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) { |
aoqi@0 | 801 | // // We stored the monitor address into the object's mark word. |
aoqi@0 | 802 | // } else if (THREAD->is_lock_owned((address)displaced_header)) |
aoqi@0 | 803 | // // Simple recursive case. |
aoqi@0 | 804 | // monitor->lock()->set_displaced_header(NULL); |
aoqi@0 | 805 | // } else { |
aoqi@0 | 806 | // // Slow path. |
aoqi@0 | 807 | // InterpreterRuntime::monitorenter(THREAD, monitor); |
aoqi@0 | 808 | // } |
aoqi@0 | 809 | |
aoqi@0 | 810 | const Register displaced_header = R7_ARG5; |
aoqi@0 | 811 | const Register object_mark_addr = R8_ARG6; |
aoqi@0 | 812 | const Register current_header = R9_ARG7; |
aoqi@0 | 813 | const Register tmp = R10_ARG8; |
aoqi@0 | 814 | |
aoqi@0 | 815 | Label done; |
aoqi@0 | 816 | Label cas_failed, slow_case; |
aoqi@0 | 817 | |
aoqi@0 | 818 | assert_different_registers(displaced_header, object_mark_addr, current_header, tmp); |
aoqi@0 | 819 | |
aoqi@0 | 820 | // markOop displaced_header = obj->mark().set_unlocked(); |
aoqi@0 | 821 | |
aoqi@0 | 822 | // Load markOop from object into displaced_header. |
aoqi@0 | 823 | ld(displaced_header, oopDesc::mark_offset_in_bytes(), object); |
aoqi@0 | 824 | |
aoqi@0 | 825 | if (UseBiasedLocking) { |
aoqi@0 | 826 | biased_locking_enter(CCR0, object, displaced_header, tmp, current_header, done, &slow_case); |
aoqi@0 | 827 | } |
aoqi@0 | 828 | |
aoqi@0 | 829 | // Set displaced_header to be (markOop of object | UNLOCK_VALUE). |
aoqi@0 | 830 | ori(displaced_header, displaced_header, markOopDesc::unlocked_value); |
aoqi@0 | 831 | |
aoqi@0 | 832 | // monitor->lock()->set_displaced_header(displaced_header); |
aoqi@0 | 833 | |
aoqi@0 | 834 | // Initialize the box (Must happen before we update the object mark!). |
aoqi@0 | 835 | std(displaced_header, BasicObjectLock::lock_offset_in_bytes() + |
aoqi@0 | 836 | BasicLock::displaced_header_offset_in_bytes(), monitor); |
aoqi@0 | 837 | |
aoqi@0 | 838 | // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) { |
aoqi@0 | 839 | |
aoqi@0 | 840 | // Store stack address of the BasicObjectLock (this is monitor) into object. |
aoqi@0 | 841 | addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes()); |
aoqi@0 | 842 | |
aoqi@0 | 843 | // Must fence, otherwise, preceding store(s) may float below cmpxchg. |
aoqi@0 | 844 | // CmpxchgX sets CCR0 to cmpX(current, displaced). |
aoqi@0 | 845 | fence(); // TODO: replace by MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq ? |
aoqi@0 | 846 | cmpxchgd(/*flag=*/CCR0, |
aoqi@0 | 847 | /*current_value=*/current_header, |
aoqi@0 | 848 | /*compare_value=*/displaced_header, /*exchange_value=*/monitor, |
aoqi@0 | 849 | /*where=*/object_mark_addr, |
aoqi@0 | 850 | MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, |
aoqi@0 | 851 | MacroAssembler::cmpxchgx_hint_acquire_lock(), |
aoqi@0 | 852 | noreg, |
aoqi@0 | 853 | &cas_failed); |
aoqi@0 | 854 | |
aoqi@0 | 855 | // If the compare-and-exchange succeeded, then we found an unlocked |
aoqi@0 | 856 | // object and we have now locked it. |
aoqi@0 | 857 | b(done); |
aoqi@0 | 858 | bind(cas_failed); |
aoqi@0 | 859 | |
aoqi@0 | 860 | // } else if (THREAD->is_lock_owned((address)displaced_header)) |
aoqi@0 | 861 | // // Simple recursive case. |
aoqi@0 | 862 | // monitor->lock()->set_displaced_header(NULL); |
aoqi@0 | 863 | |
aoqi@0 | 864 | // We did not see an unlocked object so try the fast recursive case. |
aoqi@0 | 865 | |
aoqi@0 | 866 | // Check if owner is self by comparing the value in the markOop of object |
aoqi@0 | 867 | // (current_header) with the stack pointer. |
aoqi@0 | 868 | sub(current_header, current_header, R1_SP); |
aoqi@0 | 869 | |
aoqi@0 | 870 | assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); |
aoqi@0 | 871 | load_const_optimized(tmp, |
aoqi@0 | 872 | (address) (~(os::vm_page_size()-1) | |
aoqi@0 | 873 | markOopDesc::lock_mask_in_place)); |
aoqi@0 | 874 | |
aoqi@0 | 875 | and_(R0/*==0?*/, current_header, tmp); |
aoqi@0 | 876 | // If condition is true we are done and hence we can store 0 in the displaced |
aoqi@0 | 877 | // header indicating it is a recursive lock. |
aoqi@0 | 878 | bne(CCR0, slow_case); |
aoqi@0 | 879 | release(); |
aoqi@0 | 880 | std(R0/*==0!*/, BasicObjectLock::lock_offset_in_bytes() + |
aoqi@0 | 881 | BasicLock::displaced_header_offset_in_bytes(), monitor); |
aoqi@0 | 882 | b(done); |
aoqi@0 | 883 | |
aoqi@0 | 884 | // } else { |
aoqi@0 | 885 | // // Slow path. |
aoqi@0 | 886 | // InterpreterRuntime::monitorenter(THREAD, monitor); |
aoqi@0 | 887 | |
aoqi@0 | 888 | // None of the above fast optimizations worked so we have to get into the |
aoqi@0 | 889 | // slow case of monitor enter. |
aoqi@0 | 890 | bind(slow_case); |
aoqi@0 | 891 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), |
aoqi@0 | 892 | monitor, /*check_for_exceptions=*/true CC_INTERP_ONLY(&& false)); |
aoqi@0 | 893 | // } |
aoqi@0 | 894 | align(32, 12); |
aoqi@0 | 895 | bind(done); |
aoqi@0 | 896 | } |
aoqi@0 | 897 | } |
aoqi@0 | 898 | |
aoqi@0 | 899 | // Unlocks an object. Used in monitorexit bytecode and remove_activation. |
aoqi@0 | 900 | // |
aoqi@0 | 901 | // Registers alive |
aoqi@0 | 902 | // monitor - Address of the BasicObjectLock to be used for locking, |
aoqi@0 | 903 | // which must be initialized with the object to lock. |
aoqi@0 | 904 | // |
aoqi@0 | 905 | // Throw IllegalMonitorException if object is not locked by current thread. |
aoqi@0 | 906 | void InterpreterMacroAssembler::unlock_object(Register monitor, bool check_for_exceptions) { |
aoqi@0 | 907 | if (UseHeavyMonitors) { |
aoqi@0 | 908 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), |
aoqi@0 | 909 | monitor, check_for_exceptions CC_INTERP_ONLY(&& false)); |
aoqi@0 | 910 | } else { |
aoqi@0 | 911 | |
aoqi@0 | 912 | // template code: |
aoqi@0 | 913 | // |
aoqi@0 | 914 | // if ((displaced_header = monitor->displaced_header()) == NULL) { |
aoqi@0 | 915 | // // Recursive unlock. Mark the monitor unlocked by setting the object field to NULL. |
aoqi@0 | 916 | // monitor->set_obj(NULL); |
aoqi@0 | 917 | // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) { |
aoqi@0 | 918 | // // We swapped the unlocked mark in displaced_header into the object's mark word. |
aoqi@0 | 919 | // monitor->set_obj(NULL); |
aoqi@0 | 920 | // } else { |
aoqi@0 | 921 | // // Slow path. |
aoqi@0 | 922 | // InterpreterRuntime::monitorexit(THREAD, monitor); |
aoqi@0 | 923 | // } |
aoqi@0 | 924 | |
aoqi@0 | 925 | const Register object = R7_ARG5; |
aoqi@0 | 926 | const Register displaced_header = R8_ARG6; |
aoqi@0 | 927 | const Register object_mark_addr = R9_ARG7; |
aoqi@0 | 928 | const Register current_header = R10_ARG8; |
aoqi@0 | 929 | |
aoqi@0 | 930 | Label free_slot; |
aoqi@0 | 931 | Label slow_case; |
aoqi@0 | 932 | |
aoqi@0 | 933 | assert_different_registers(object, displaced_header, object_mark_addr, current_header); |
aoqi@0 | 934 | |
aoqi@0 | 935 | if (UseBiasedLocking) { |
aoqi@0 | 936 | // The object address from the monitor is in object. |
aoqi@0 | 937 | ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); |
aoqi@0 | 938 | assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); |
aoqi@0 | 939 | biased_locking_exit(CCR0, object, displaced_header, free_slot); |
aoqi@0 | 940 | } |
aoqi@0 | 941 | |
aoqi@0 | 942 | // Test first if we are in the fast recursive case. |
aoqi@0 | 943 | ld(displaced_header, BasicObjectLock::lock_offset_in_bytes() + |
aoqi@0 | 944 | BasicLock::displaced_header_offset_in_bytes(), monitor); |
aoqi@0 | 945 | |
aoqi@0 | 946 | // If the displaced header is zero, we have a recursive unlock. |
aoqi@0 | 947 | cmpdi(CCR0, displaced_header, 0); |
aoqi@0 | 948 | beq(CCR0, free_slot); // recursive unlock |
aoqi@0 | 949 | |
aoqi@0 | 950 | // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) { |
aoqi@0 | 951 | // // We swapped the unlocked mark in displaced_header into the object's mark word. |
aoqi@0 | 952 | // monitor->set_obj(NULL); |
aoqi@0 | 953 | |
aoqi@0 | 954 | // If we still have a lightweight lock, unlock the object and be done. |
aoqi@0 | 955 | |
aoqi@0 | 956 | // The object address from the monitor is in object. |
aoqi@0 | 957 | if (!UseBiasedLocking) { ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); } |
aoqi@0 | 958 | addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes()); |
aoqi@0 | 959 | |
aoqi@0 | 960 | // We have the displaced header in displaced_header. If the lock is still |
aoqi@0 | 961 | // lightweight, it will contain the monitor address and we'll store the |
aoqi@0 | 962 | // displaced header back into the object's mark word. |
aoqi@0 | 963 | // CmpxchgX sets CCR0 to cmpX(current, monitor). |
aoqi@0 | 964 | cmpxchgd(/*flag=*/CCR0, |
aoqi@0 | 965 | /*current_value=*/current_header, |
aoqi@0 | 966 | /*compare_value=*/monitor, /*exchange_value=*/displaced_header, |
aoqi@0 | 967 | /*where=*/object_mark_addr, |
aoqi@0 | 968 | MacroAssembler::MemBarRel, |
aoqi@0 | 969 | MacroAssembler::cmpxchgx_hint_release_lock(), |
aoqi@0 | 970 | noreg, |
aoqi@0 | 971 | &slow_case); |
aoqi@0 | 972 | b(free_slot); |
aoqi@0 | 973 | |
aoqi@0 | 974 | // } else { |
aoqi@0 | 975 | // // Slow path. |
aoqi@0 | 976 | // InterpreterRuntime::monitorexit(THREAD, monitor); |
aoqi@0 | 977 | |
aoqi@0 | 978 | // The lock has been converted into a heavy lock and hence |
aoqi@0 | 979 | // we need to get into the slow case. |
aoqi@0 | 980 | bind(slow_case); |
aoqi@0 | 981 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), |
aoqi@0 | 982 | monitor, check_for_exceptions CC_INTERP_ONLY(&& false)); |
aoqi@0 | 983 | // } |
aoqi@0 | 984 | |
aoqi@0 | 985 | Label done; |
aoqi@0 | 986 | b(done); // Monitor register may be overwritten! Runtime has already freed the slot. |
aoqi@0 | 987 | |
aoqi@0 | 988 | // Exchange worked, do monitor->set_obj(NULL); |
aoqi@0 | 989 | align(32, 12); |
aoqi@0 | 990 | bind(free_slot); |
aoqi@0 | 991 | li(R0, 0); |
aoqi@0 | 992 | std(R0, BasicObjectLock::obj_offset_in_bytes(), monitor); |
aoqi@0 | 993 | bind(done); |
aoqi@0 | 994 | } |
aoqi@0 | 995 | } |
aoqi@0 | 996 | |
aoqi@0 | 997 | #ifndef CC_INTERP |
aoqi@0 | 998 | |
aoqi@0 | 999 | // Load compiled (i2c) or interpreter entry when calling from interpreted and |
aoqi@0 | 1000 | // do the call. Centralized so that all interpreter calls will do the same actions. |
aoqi@0 | 1001 | // If jvmti single stepping is on for a thread we must not call compiled code. |
aoqi@0 | 1002 | // |
aoqi@0 | 1003 | // Input: |
aoqi@0 | 1004 | // - Rtarget_method: method to call |
aoqi@0 | 1005 | // - Rret_addr: return address |
aoqi@0 | 1006 | // - 2 scratch regs |
aoqi@0 | 1007 | // |
aoqi@0 | 1008 | void InterpreterMacroAssembler::call_from_interpreter(Register Rtarget_method, Register Rret_addr, Register Rscratch1, Register Rscratch2) { |
aoqi@0 | 1009 | assert_different_registers(Rscratch1, Rscratch2, Rtarget_method, Rret_addr); |
aoqi@0 | 1010 | // Assume we want to go compiled if available. |
aoqi@0 | 1011 | const Register Rtarget_addr = Rscratch1; |
aoqi@0 | 1012 | const Register Rinterp_only = Rscratch2; |
aoqi@0 | 1013 | |
aoqi@0 | 1014 | ld(Rtarget_addr, in_bytes(Method::from_interpreted_offset()), Rtarget_method); |
aoqi@0 | 1015 | |
aoqi@0 | 1016 | if (JvmtiExport::can_post_interpreter_events()) { |
aoqi@0 | 1017 | lwz(Rinterp_only, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread); |
aoqi@0 | 1018 | |
aoqi@0 | 1019 | // JVMTI events, such as single-stepping, are implemented partly by avoiding running |
aoqi@0 | 1020 | // compiled code in threads for which the event is enabled. Check here for |
aoqi@0 | 1021 | // interp_only_mode if these events CAN be enabled. |
aoqi@0 | 1022 | Label done; |
aoqi@0 | 1023 | verify_thread(); |
aoqi@0 | 1024 | cmpwi(CCR0, Rinterp_only, 0); |
aoqi@0 | 1025 | beq(CCR0, done); |
aoqi@0 | 1026 | ld(Rtarget_addr, in_bytes(Method::interpreter_entry_offset()), Rtarget_method); |
aoqi@0 | 1027 | align(32, 12); |
aoqi@0 | 1028 | bind(done); |
aoqi@0 | 1029 | } |
aoqi@0 | 1030 | |
aoqi@0 | 1031 | #ifdef ASSERT |
aoqi@0 | 1032 | { |
aoqi@0 | 1033 | Label Lok; |
aoqi@0 | 1034 | cmpdi(CCR0, Rtarget_addr, 0); |
aoqi@0 | 1035 | bne(CCR0, Lok); |
aoqi@0 | 1036 | stop("null entry point"); |
aoqi@0 | 1037 | bind(Lok); |
aoqi@0 | 1038 | } |
aoqi@0 | 1039 | #endif // ASSERT |
aoqi@0 | 1040 | |
aoqi@0 | 1041 | mr(R21_sender_SP, R1_SP); |
aoqi@0 | 1042 | |
aoqi@0 | 1043 | // Calc a precise SP for the call. The SP value we calculated in |
aoqi@0 | 1044 | // generate_fixed_frame() is based on the max_stack() value, so we would waste stack space |
aoqi@0 | 1045 | // if esp is not max. Also, the i2c adapter extends the stack space without restoring |
aoqi@0 | 1046 | // our pre-calced value, so repeating calls via i2c would result in stack overflow. |
aoqi@0 | 1047 | // Since esp already points to an empty slot, we just have to sub 1 additional slot |
aoqi@0 | 1048 | // to meet the abi scratch requirements. |
aoqi@0 | 1049 | // The max_stack pointer will get restored by means of the GR_Lmax_stack local in |
aoqi@0 | 1050 | // the return entry of the interpreter. |
aoqi@0 | 1051 | addi(Rscratch2, R15_esp, Interpreter::stackElementSize - frame::abi_reg_args_size); |
aoqi@0 | 1052 | clrrdi(Rscratch2, Rscratch2, exact_log2(frame::alignment_in_bytes)); // round towards smaller address |
aoqi@0 | 1053 | resize_frame_absolute(Rscratch2, Rscratch2, R0); |
aoqi@0 | 1054 | |
aoqi@0 | 1055 | mr_if_needed(R19_method, Rtarget_method); |
aoqi@0 | 1056 | mtctr(Rtarget_addr); |
aoqi@0 | 1057 | mtlr(Rret_addr); |
aoqi@0 | 1058 | |
aoqi@0 | 1059 | save_interpreter_state(Rscratch2); |
aoqi@0 | 1060 | #ifdef ASSERT |
aoqi@0 | 1061 | ld(Rscratch1, _ijava_state_neg(top_frame_sp), Rscratch2); // Rscratch2 contains fp |
aoqi@0 | 1062 | cmpd(CCR0, R21_sender_SP, Rscratch1); |
aoqi@0 | 1063 | asm_assert_eq("top_frame_sp incorrect", 0x951); |
aoqi@0 | 1064 | #endif |
aoqi@0 | 1065 | |
aoqi@0 | 1066 | bctr(); |
aoqi@0 | 1067 | } |
aoqi@0 | 1068 | |
aoqi@0 | 1069 | // Set the method data pointer for the current bcp. |
aoqi@0 | 1070 | void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { |
aoqi@0 | 1071 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1072 | Label get_continue; |
aoqi@0 | 1073 | ld(R28_mdx, in_bytes(Method::method_data_offset()), R19_method); |
aoqi@0 | 1074 | test_method_data_pointer(get_continue); |
aoqi@0 | 1075 | call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), R19_method, R14_bcp); |
aoqi@0 | 1076 | |
aoqi@0 | 1077 | addi(R28_mdx, R28_mdx, in_bytes(MethodData::data_offset())); |
aoqi@0 | 1078 | add(R28_mdx, R28_mdx, R3_RET); |
aoqi@0 | 1079 | bind(get_continue); |
aoqi@0 | 1080 | } |
aoqi@0 | 1081 | |
aoqi@0 | 1082 | // Test ImethodDataPtr. If it is null, continue at the specified label. |
aoqi@0 | 1083 | void InterpreterMacroAssembler::test_method_data_pointer(Label& zero_continue) { |
aoqi@0 | 1084 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1085 | cmpdi(CCR0, R28_mdx, 0); |
aoqi@0 | 1086 | beq(CCR0, zero_continue); |
aoqi@0 | 1087 | } |
aoqi@0 | 1088 | |
aoqi@0 | 1089 | void InterpreterMacroAssembler::verify_method_data_pointer() { |
aoqi@0 | 1090 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1091 | #ifdef ASSERT |
aoqi@0 | 1092 | Label verify_continue; |
aoqi@0 | 1093 | test_method_data_pointer(verify_continue); |
aoqi@0 | 1094 | |
aoqi@0 | 1095 | // If the mdp is valid, it will point to a DataLayout header which is |
aoqi@0 | 1096 | // consistent with the bcp. The converse is highly probable also. |
aoqi@0 | 1097 | lhz(R11_scratch1, in_bytes(DataLayout::bci_offset()), R28_mdx); |
aoqi@0 | 1098 | ld(R12_scratch2, in_bytes(Method::const_offset()), R19_method); |
aoqi@0 | 1099 | addi(R11_scratch1, R11_scratch1, in_bytes(ConstMethod::codes_offset())); |
aoqi@0 | 1100 | add(R11_scratch1, R12_scratch2, R12_scratch2); |
aoqi@0 | 1101 | cmpd(CCR0, R11_scratch1, R14_bcp); |
aoqi@0 | 1102 | beq(CCR0, verify_continue); |
aoqi@0 | 1103 | |
aoqi@0 | 1104 | call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp ), R19_method, R14_bcp, R28_mdx); |
aoqi@0 | 1105 | |
aoqi@0 | 1106 | bind(verify_continue); |
aoqi@0 | 1107 | #endif |
aoqi@0 | 1108 | } |
aoqi@0 | 1109 | |
aoqi@0 | 1110 | void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count, |
aoqi@0 | 1111 | Register Rscratch, |
aoqi@0 | 1112 | Label &profile_continue) { |
aoqi@0 | 1113 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1114 | // Control will flow to "profile_continue" if the counter is less than the |
aoqi@0 | 1115 | // limit or if we call profile_method(). |
aoqi@0 | 1116 | Label done; |
aoqi@0 | 1117 | |
aoqi@0 | 1118 | // If no method data exists, and the counter is high enough, make one. |
aoqi@0 | 1119 | int ipl_offs = load_const_optimized(Rscratch, &InvocationCounter::InterpreterProfileLimit, R0, true); |
aoqi@0 | 1120 | lwz(Rscratch, ipl_offs, Rscratch); |
aoqi@0 | 1121 | |
aoqi@0 | 1122 | cmpdi(CCR0, R28_mdx, 0); |
aoqi@0 | 1123 | // Test to see if we should create a method data oop. |
aoqi@0 | 1124 | cmpd(CCR1, Rscratch /* InterpreterProfileLimit */, invocation_count); |
aoqi@0 | 1125 | bne(CCR0, done); |
aoqi@0 | 1126 | bge(CCR1, profile_continue); |
aoqi@0 | 1127 | |
aoqi@0 | 1128 | // Build it now. |
aoqi@0 | 1129 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); |
aoqi@0 | 1130 | set_method_data_pointer_for_bcp(); |
aoqi@0 | 1131 | b(profile_continue); |
aoqi@0 | 1132 | |
aoqi@0 | 1133 | align(32, 12); |
aoqi@0 | 1134 | bind(done); |
aoqi@0 | 1135 | } |
aoqi@0 | 1136 | |
aoqi@0 | 1137 | void InterpreterMacroAssembler::test_backedge_count_for_osr(Register backedge_count, Register branch_bcp, Register Rtmp) { |
aoqi@0 | 1138 | assert_different_registers(backedge_count, Rtmp, branch_bcp); |
aoqi@0 | 1139 | assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr"); |
aoqi@0 | 1140 | |
aoqi@0 | 1141 | Label did_not_overflow; |
aoqi@0 | 1142 | Label overflow_with_error; |
aoqi@0 | 1143 | |
aoqi@0 | 1144 | int ibbl_offs = load_const_optimized(Rtmp, &InvocationCounter::InterpreterBackwardBranchLimit, R0, true); |
aoqi@0 | 1145 | lwz(Rtmp, ibbl_offs, Rtmp); |
aoqi@0 | 1146 | cmpw(CCR0, backedge_count, Rtmp); |
aoqi@0 | 1147 | |
aoqi@0 | 1148 | blt(CCR0, did_not_overflow); |
aoqi@0 | 1149 | |
aoqi@0 | 1150 | // When ProfileInterpreter is on, the backedge_count comes from the |
aoqi@0 | 1151 | // methodDataOop, which value does not get reset on the call to |
aoqi@0 | 1152 | // frequency_counter_overflow(). To avoid excessive calls to the overflow |
aoqi@0 | 1153 | // routine while the method is being compiled, add a second test to make sure |
aoqi@0 | 1154 | // the overflow function is called only once every overflow_frequency. |
aoqi@0 | 1155 | if (ProfileInterpreter) { |
aoqi@0 | 1156 | const int overflow_frequency = 1024; |
aoqi@0 | 1157 | li(Rtmp, overflow_frequency-1); |
aoqi@0 | 1158 | andr(Rtmp, Rtmp, backedge_count); |
aoqi@0 | 1159 | cmpwi(CCR0, Rtmp, 0); |
aoqi@0 | 1160 | bne(CCR0, did_not_overflow); |
aoqi@0 | 1161 | } |
aoqi@0 | 1162 | |
aoqi@0 | 1163 | // Overflow in loop, pass branch bytecode. |
aoqi@0 | 1164 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), branch_bcp, true); |
aoqi@0 | 1165 | |
aoqi@0 | 1166 | // Was an OSR adapter generated? |
aoqi@0 | 1167 | // O0 = osr nmethod |
aoqi@0 | 1168 | cmpdi(CCR0, R3_RET, 0); |
aoqi@0 | 1169 | beq(CCR0, overflow_with_error); |
aoqi@0 | 1170 | |
aoqi@0 | 1171 | // Has the nmethod been invalidated already? |
aoqi@0 | 1172 | lwz(Rtmp, nmethod::entry_bci_offset(), R3_RET); |
aoqi@0 | 1173 | cmpwi(CCR0, Rtmp, InvalidOSREntryBci); |
aoqi@0 | 1174 | beq(CCR0, overflow_with_error); |
aoqi@0 | 1175 | |
aoqi@0 | 1176 | // Migrate the interpreter frame off of the stack. |
aoqi@0 | 1177 | // We can use all registers because we will not return to interpreter from this point. |
aoqi@0 | 1178 | |
aoqi@0 | 1179 | // Save nmethod. |
aoqi@0 | 1180 | const Register osr_nmethod = R31; |
aoqi@0 | 1181 | mr(osr_nmethod, R3_RET); |
aoqi@0 | 1182 | set_top_ijava_frame_at_SP_as_last_Java_frame(R1_SP, R11_scratch1); |
aoqi@0 | 1183 | call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin), R16_thread); |
aoqi@0 | 1184 | reset_last_Java_frame(); |
aoqi@0 | 1185 | // OSR buffer is in ARG1 |
aoqi@0 | 1186 | |
aoqi@0 | 1187 | // Remove the interpreter frame. |
aoqi@0 | 1188 | merge_frames(/*top_frame_sp*/ R21_sender_SP, /*return_pc*/ R0, R11_scratch1, R12_scratch2); |
aoqi@0 | 1189 | |
aoqi@0 | 1190 | // Jump to the osr code. |
aoqi@0 | 1191 | ld(R11_scratch1, nmethod::osr_entry_point_offset(), osr_nmethod); |
aoqi@0 | 1192 | mtlr(R0); |
aoqi@0 | 1193 | mtctr(R11_scratch1); |
aoqi@0 | 1194 | bctr(); |
aoqi@0 | 1195 | |
aoqi@0 | 1196 | align(32, 12); |
aoqi@0 | 1197 | bind(overflow_with_error); |
aoqi@0 | 1198 | bind(did_not_overflow); |
aoqi@0 | 1199 | } |
aoqi@0 | 1200 | |
aoqi@0 | 1201 | // Store a value at some constant offset from the method data pointer. |
aoqi@0 | 1202 | void InterpreterMacroAssembler::set_mdp_data_at(int constant, Register value) { |
aoqi@0 | 1203 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1204 | |
aoqi@0 | 1205 | std(value, constant, R28_mdx); |
aoqi@0 | 1206 | } |
aoqi@0 | 1207 | |
aoqi@0 | 1208 | // Increment the value at some constant offset from the method data pointer. |
aoqi@0 | 1209 | void InterpreterMacroAssembler::increment_mdp_data_at(int constant, |
aoqi@0 | 1210 | Register counter_addr, |
aoqi@0 | 1211 | Register Rbumped_count, |
aoqi@0 | 1212 | bool decrement) { |
aoqi@0 | 1213 | // Locate the counter at a fixed offset from the mdp: |
aoqi@0 | 1214 | addi(counter_addr, R28_mdx, constant); |
aoqi@0 | 1215 | increment_mdp_data_at(counter_addr, Rbumped_count, decrement); |
aoqi@0 | 1216 | } |
aoqi@0 | 1217 | |
aoqi@0 | 1218 | // Increment the value at some non-fixed (reg + constant) offset from |
aoqi@0 | 1219 | // the method data pointer. |
aoqi@0 | 1220 | void InterpreterMacroAssembler::increment_mdp_data_at(Register reg, |
aoqi@0 | 1221 | int constant, |
aoqi@0 | 1222 | Register scratch, |
aoqi@0 | 1223 | Register Rbumped_count, |
aoqi@0 | 1224 | bool decrement) { |
aoqi@0 | 1225 | // Add the constant to reg to get the offset. |
aoqi@0 | 1226 | add(scratch, R28_mdx, reg); |
aoqi@0 | 1227 | // Then calculate the counter address. |
aoqi@0 | 1228 | addi(scratch, scratch, constant); |
aoqi@0 | 1229 | increment_mdp_data_at(scratch, Rbumped_count, decrement); |
aoqi@0 | 1230 | } |
aoqi@0 | 1231 | |
aoqi@0 | 1232 | void InterpreterMacroAssembler::increment_mdp_data_at(Register counter_addr, |
aoqi@0 | 1233 | Register Rbumped_count, |
aoqi@0 | 1234 | bool decrement) { |
aoqi@0 | 1235 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1236 | |
aoqi@0 | 1237 | // Load the counter. |
aoqi@0 | 1238 | ld(Rbumped_count, 0, counter_addr); |
aoqi@0 | 1239 | |
aoqi@0 | 1240 | if (decrement) { |
aoqi@0 | 1241 | // Decrement the register. Set condition codes. |
aoqi@0 | 1242 | addi(Rbumped_count, Rbumped_count, - DataLayout::counter_increment); |
aoqi@0 | 1243 | // Store the decremented counter, if it is still negative. |
aoqi@0 | 1244 | std(Rbumped_count, 0, counter_addr); |
aoqi@0 | 1245 | // Note: add/sub overflow check are not ported, since 64 bit |
aoqi@0 | 1246 | // calculation should never overflow. |
aoqi@0 | 1247 | } else { |
aoqi@0 | 1248 | // Increment the register. Set carry flag. |
aoqi@0 | 1249 | addi(Rbumped_count, Rbumped_count, DataLayout::counter_increment); |
aoqi@0 | 1250 | // Store the incremented counter. |
aoqi@0 | 1251 | std(Rbumped_count, 0, counter_addr); |
aoqi@0 | 1252 | } |
aoqi@0 | 1253 | } |
aoqi@0 | 1254 | |
aoqi@0 | 1255 | // Set a flag value at the current method data pointer position. |
aoqi@0 | 1256 | void InterpreterMacroAssembler::set_mdp_flag_at(int flag_constant, |
aoqi@0 | 1257 | Register scratch) { |
aoqi@0 | 1258 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1259 | // Load the data header. |
aoqi@0 | 1260 | lbz(scratch, in_bytes(DataLayout::flags_offset()), R28_mdx); |
aoqi@0 | 1261 | // Set the flag. |
aoqi@0 | 1262 | ori(scratch, scratch, flag_constant); |
aoqi@0 | 1263 | // Store the modified header. |
aoqi@0 | 1264 | stb(scratch, in_bytes(DataLayout::flags_offset()), R28_mdx); |
aoqi@0 | 1265 | } |
aoqi@0 | 1266 | |
aoqi@0 | 1267 | // Test the location at some offset from the method data pointer. |
aoqi@0 | 1268 | // If it is not equal to value, branch to the not_equal_continue Label. |
aoqi@0 | 1269 | void InterpreterMacroAssembler::test_mdp_data_at(int offset, |
aoqi@0 | 1270 | Register value, |
aoqi@0 | 1271 | Label& not_equal_continue, |
aoqi@0 | 1272 | Register test_out) { |
aoqi@0 | 1273 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1274 | |
aoqi@0 | 1275 | ld(test_out, offset, R28_mdx); |
aoqi@0 | 1276 | cmpd(CCR0, value, test_out); |
aoqi@0 | 1277 | bne(CCR0, not_equal_continue); |
aoqi@0 | 1278 | } |
aoqi@0 | 1279 | |
aoqi@0 | 1280 | // Update the method data pointer by the displacement located at some fixed |
aoqi@0 | 1281 | // offset from the method data pointer. |
aoqi@0 | 1282 | void InterpreterMacroAssembler::update_mdp_by_offset(int offset_of_disp, |
aoqi@0 | 1283 | Register scratch) { |
aoqi@0 | 1284 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1285 | |
aoqi@0 | 1286 | ld(scratch, offset_of_disp, R28_mdx); |
aoqi@0 | 1287 | add(R28_mdx, scratch, R28_mdx); |
aoqi@0 | 1288 | } |
aoqi@0 | 1289 | |
aoqi@0 | 1290 | // Update the method data pointer by the displacement located at the |
aoqi@0 | 1291 | // offset (reg + offset_of_disp). |
aoqi@0 | 1292 | void InterpreterMacroAssembler::update_mdp_by_offset(Register reg, |
aoqi@0 | 1293 | int offset_of_disp, |
aoqi@0 | 1294 | Register scratch) { |
aoqi@0 | 1295 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1296 | |
aoqi@0 | 1297 | add(scratch, reg, R28_mdx); |
aoqi@0 | 1298 | ld(scratch, offset_of_disp, scratch); |
aoqi@0 | 1299 | add(R28_mdx, scratch, R28_mdx); |
aoqi@0 | 1300 | } |
aoqi@0 | 1301 | |
aoqi@0 | 1302 | // Update the method data pointer by a simple constant displacement. |
aoqi@0 | 1303 | void InterpreterMacroAssembler::update_mdp_by_constant(int constant) { |
aoqi@0 | 1304 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1305 | addi(R28_mdx, R28_mdx, constant); |
aoqi@0 | 1306 | } |
aoqi@0 | 1307 | |
aoqi@0 | 1308 | // Update the method data pointer for a _ret bytecode whose target |
aoqi@0 | 1309 | // was not among our cached targets. |
aoqi@0 | 1310 | void InterpreterMacroAssembler::update_mdp_for_ret(TosState state, |
aoqi@0 | 1311 | Register return_bci) { |
aoqi@0 | 1312 | assert(ProfileInterpreter, "must be profiling interpreter"); |
aoqi@0 | 1313 | |
aoqi@0 | 1314 | push(state); |
aoqi@0 | 1315 | assert(return_bci->is_nonvolatile(), "need to protect return_bci"); |
aoqi@0 | 1316 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); |
aoqi@0 | 1317 | pop(state); |
aoqi@0 | 1318 | } |
aoqi@0 | 1319 | |
aoqi@0 | 1320 | // Increments the backedge counter. |
aoqi@0 | 1321 | // Returns backedge counter + invocation counter in Rdst. |
aoqi@0 | 1322 | void InterpreterMacroAssembler::increment_backedge_counter(const Register Rcounters, const Register Rdst, |
aoqi@0 | 1323 | const Register Rtmp1, Register Rscratch) { |
aoqi@0 | 1324 | assert(UseCompiler, "incrementing must be useful"); |
aoqi@0 | 1325 | assert_different_registers(Rdst, Rtmp1); |
aoqi@0 | 1326 | const Register invocation_counter = Rtmp1; |
aoqi@0 | 1327 | const Register counter = Rdst; |
aoqi@0 | 1328 | // TODO ppc port assert(4 == InvocationCounter::sz_counter(), "unexpected field size."); |
aoqi@0 | 1329 | |
aoqi@0 | 1330 | // Load backedge counter. |
aoqi@0 | 1331 | lwz(counter, in_bytes(MethodCounters::backedge_counter_offset()) + |
aoqi@0 | 1332 | in_bytes(InvocationCounter::counter_offset()), Rcounters); |
aoqi@0 | 1333 | // Load invocation counter. |
aoqi@0 | 1334 | lwz(invocation_counter, in_bytes(MethodCounters::invocation_counter_offset()) + |
aoqi@0 | 1335 | in_bytes(InvocationCounter::counter_offset()), Rcounters); |
aoqi@0 | 1336 | |
aoqi@0 | 1337 | // Add the delta to the backedge counter. |
aoqi@0 | 1338 | addi(counter, counter, InvocationCounter::count_increment); |
aoqi@0 | 1339 | |
aoqi@0 | 1340 | // Mask the invocation counter. |
aoqi@0 | 1341 | li(Rscratch, InvocationCounter::count_mask_value); |
aoqi@0 | 1342 | andr(invocation_counter, invocation_counter, Rscratch); |
aoqi@0 | 1343 | |
aoqi@0 | 1344 | // Store new counter value. |
aoqi@0 | 1345 | stw(counter, in_bytes(MethodCounters::backedge_counter_offset()) + |
aoqi@0 | 1346 | in_bytes(InvocationCounter::counter_offset()), Rcounters); |
aoqi@0 | 1347 | // Return invocation counter + backedge counter. |
aoqi@0 | 1348 | add(counter, counter, invocation_counter); |
aoqi@0 | 1349 | } |
aoqi@0 | 1350 | |
aoqi@0 | 1351 | // Count a taken branch in the bytecodes. |
aoqi@0 | 1352 | void InterpreterMacroAssembler::profile_taken_branch(Register scratch, Register bumped_count) { |
aoqi@0 | 1353 | if (ProfileInterpreter) { |
aoqi@0 | 1354 | Label profile_continue; |
aoqi@0 | 1355 | |
aoqi@0 | 1356 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1357 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1358 | |
aoqi@0 | 1359 | // We are taking a branch. Increment the taken count. |
aoqi@0 | 1360 | increment_mdp_data_at(in_bytes(JumpData::taken_offset()), scratch, bumped_count); |
aoqi@0 | 1361 | |
aoqi@0 | 1362 | // The method data pointer needs to be updated to reflect the new target. |
aoqi@0 | 1363 | update_mdp_by_offset(in_bytes(JumpData::displacement_offset()), scratch); |
aoqi@0 | 1364 | bind (profile_continue); |
aoqi@0 | 1365 | } |
aoqi@0 | 1366 | } |
aoqi@0 | 1367 | |
aoqi@0 | 1368 | // Count a not-taken branch in the bytecodes. |
aoqi@0 | 1369 | void InterpreterMacroAssembler::profile_not_taken_branch(Register scratch1, Register scratch2) { |
aoqi@0 | 1370 | if (ProfileInterpreter) { |
aoqi@0 | 1371 | Label profile_continue; |
aoqi@0 | 1372 | |
aoqi@0 | 1373 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1374 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1375 | |
aoqi@0 | 1376 | // We are taking a branch. Increment the not taken count. |
aoqi@0 | 1377 | increment_mdp_data_at(in_bytes(BranchData::not_taken_offset()), scratch1, scratch2); |
aoqi@0 | 1378 | |
aoqi@0 | 1379 | // The method data pointer needs to be updated to correspond to the |
aoqi@0 | 1380 | // next bytecode. |
aoqi@0 | 1381 | update_mdp_by_constant(in_bytes(BranchData::branch_data_size())); |
aoqi@0 | 1382 | bind (profile_continue); |
aoqi@0 | 1383 | } |
aoqi@0 | 1384 | } |
aoqi@0 | 1385 | |
aoqi@0 | 1386 | // Count a non-virtual call in the bytecodes. |
aoqi@0 | 1387 | void InterpreterMacroAssembler::profile_call(Register scratch1, Register scratch2) { |
aoqi@0 | 1388 | if (ProfileInterpreter) { |
aoqi@0 | 1389 | Label profile_continue; |
aoqi@0 | 1390 | |
aoqi@0 | 1391 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1392 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1393 | |
aoqi@0 | 1394 | // We are making a call. Increment the count. |
aoqi@0 | 1395 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch1, scratch2); |
aoqi@0 | 1396 | |
aoqi@0 | 1397 | // The method data pointer needs to be updated to reflect the new target. |
aoqi@0 | 1398 | update_mdp_by_constant(in_bytes(CounterData::counter_data_size())); |
aoqi@0 | 1399 | bind (profile_continue); |
aoqi@0 | 1400 | } |
aoqi@0 | 1401 | } |
aoqi@0 | 1402 | |
aoqi@0 | 1403 | // Count a final call in the bytecodes. |
aoqi@0 | 1404 | void InterpreterMacroAssembler::profile_final_call(Register scratch1, Register scratch2) { |
aoqi@0 | 1405 | if (ProfileInterpreter) { |
aoqi@0 | 1406 | Label profile_continue; |
aoqi@0 | 1407 | |
aoqi@0 | 1408 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1409 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1410 | |
aoqi@0 | 1411 | // We are making a call. Increment the count. |
aoqi@0 | 1412 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch1, scratch2); |
aoqi@0 | 1413 | |
aoqi@0 | 1414 | // The method data pointer needs to be updated to reflect the new target. |
aoqi@0 | 1415 | update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); |
aoqi@0 | 1416 | bind (profile_continue); |
aoqi@0 | 1417 | } |
aoqi@0 | 1418 | } |
aoqi@0 | 1419 | |
aoqi@0 | 1420 | // Count a virtual call in the bytecodes. |
aoqi@0 | 1421 | void InterpreterMacroAssembler::profile_virtual_call(Register Rreceiver, |
aoqi@0 | 1422 | Register Rscratch1, |
aoqi@0 | 1423 | Register Rscratch2, |
aoqi@0 | 1424 | bool receiver_can_be_null) { |
aoqi@0 | 1425 | if (!ProfileInterpreter) { return; } |
aoqi@0 | 1426 | Label profile_continue; |
aoqi@0 | 1427 | |
aoqi@0 | 1428 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1429 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1430 | |
aoqi@0 | 1431 | Label skip_receiver_profile; |
aoqi@0 | 1432 | if (receiver_can_be_null) { |
aoqi@0 | 1433 | Label not_null; |
aoqi@0 | 1434 | cmpdi(CCR0, Rreceiver, 0); |
aoqi@0 | 1435 | bne(CCR0, not_null); |
aoqi@0 | 1436 | // We are making a call. Increment the count for null receiver. |
aoqi@0 | 1437 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), Rscratch1, Rscratch2); |
aoqi@0 | 1438 | b(skip_receiver_profile); |
aoqi@0 | 1439 | bind(not_null); |
aoqi@0 | 1440 | } |
aoqi@0 | 1441 | |
aoqi@0 | 1442 | // Record the receiver type. |
aoqi@0 | 1443 | record_klass_in_profile(Rreceiver, Rscratch1, Rscratch2, true); |
aoqi@0 | 1444 | bind(skip_receiver_profile); |
aoqi@0 | 1445 | |
aoqi@0 | 1446 | // The method data pointer needs to be updated to reflect the new target. |
aoqi@0 | 1447 | update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); |
aoqi@0 | 1448 | bind (profile_continue); |
aoqi@0 | 1449 | } |
aoqi@0 | 1450 | |
aoqi@0 | 1451 | void InterpreterMacroAssembler::profile_typecheck(Register Rklass, Register Rscratch1, Register Rscratch2) { |
aoqi@0 | 1452 | if (ProfileInterpreter) { |
aoqi@0 | 1453 | Label profile_continue; |
aoqi@0 | 1454 | |
aoqi@0 | 1455 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1456 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1457 | |
aoqi@0 | 1458 | int mdp_delta = in_bytes(BitData::bit_data_size()); |
aoqi@0 | 1459 | if (TypeProfileCasts) { |
aoqi@0 | 1460 | mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); |
aoqi@0 | 1461 | |
aoqi@0 | 1462 | // Record the object type. |
aoqi@0 | 1463 | record_klass_in_profile(Rklass, Rscratch1, Rscratch2, false); |
aoqi@0 | 1464 | } |
aoqi@0 | 1465 | |
aoqi@0 | 1466 | // The method data pointer needs to be updated. |
aoqi@0 | 1467 | update_mdp_by_constant(mdp_delta); |
aoqi@0 | 1468 | |
aoqi@0 | 1469 | bind (profile_continue); |
aoqi@0 | 1470 | } |
aoqi@0 | 1471 | } |
aoqi@0 | 1472 | |
aoqi@0 | 1473 | void InterpreterMacroAssembler::profile_typecheck_failed(Register Rscratch1, Register Rscratch2) { |
aoqi@0 | 1474 | if (ProfileInterpreter && TypeProfileCasts) { |
aoqi@0 | 1475 | Label profile_continue; |
aoqi@0 | 1476 | |
aoqi@0 | 1477 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1478 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1479 | |
aoqi@0 | 1480 | int count_offset = in_bytes(CounterData::count_offset()); |
aoqi@0 | 1481 | // Back up the address, since we have already bumped the mdp. |
aoqi@0 | 1482 | count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); |
aoqi@0 | 1483 | |
aoqi@0 | 1484 | // *Decrement* the counter. We expect to see zero or small negatives. |
aoqi@0 | 1485 | increment_mdp_data_at(count_offset, Rscratch1, Rscratch2, true); |
aoqi@0 | 1486 | |
aoqi@0 | 1487 | bind (profile_continue); |
aoqi@0 | 1488 | } |
aoqi@0 | 1489 | } |
aoqi@0 | 1490 | |
aoqi@0 | 1491 | // Count a ret in the bytecodes. |
aoqi@0 | 1492 | void InterpreterMacroAssembler::profile_ret(TosState state, Register return_bci, Register scratch1, Register scratch2) { |
aoqi@0 | 1493 | if (ProfileInterpreter) { |
aoqi@0 | 1494 | Label profile_continue; |
aoqi@0 | 1495 | uint row; |
aoqi@0 | 1496 | |
aoqi@0 | 1497 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1498 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1499 | |
aoqi@0 | 1500 | // Update the total ret count. |
aoqi@0 | 1501 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch1, scratch2 ); |
aoqi@0 | 1502 | |
aoqi@0 | 1503 | for (row = 0; row < RetData::row_limit(); row++) { |
aoqi@0 | 1504 | Label next_test; |
aoqi@0 | 1505 | |
aoqi@0 | 1506 | // See if return_bci is equal to bci[n]: |
aoqi@0 | 1507 | test_mdp_data_at(in_bytes(RetData::bci_offset(row)), return_bci, next_test, scratch1); |
aoqi@0 | 1508 | |
aoqi@0 | 1509 | // return_bci is equal to bci[n]. Increment the count. |
aoqi@0 | 1510 | increment_mdp_data_at(in_bytes(RetData::bci_count_offset(row)), scratch1, scratch2); |
aoqi@0 | 1511 | |
aoqi@0 | 1512 | // The method data pointer needs to be updated to reflect the new target. |
aoqi@0 | 1513 | update_mdp_by_offset(in_bytes(RetData::bci_displacement_offset(row)), scratch1); |
aoqi@0 | 1514 | b(profile_continue); |
aoqi@0 | 1515 | bind(next_test); |
aoqi@0 | 1516 | } |
aoqi@0 | 1517 | |
aoqi@0 | 1518 | update_mdp_for_ret(state, return_bci); |
aoqi@0 | 1519 | |
aoqi@0 | 1520 | bind (profile_continue); |
aoqi@0 | 1521 | } |
aoqi@0 | 1522 | } |
aoqi@0 | 1523 | |
aoqi@0 | 1524 | // Count the default case of a switch construct. |
aoqi@0 | 1525 | void InterpreterMacroAssembler::profile_switch_default(Register scratch1, Register scratch2) { |
aoqi@0 | 1526 | if (ProfileInterpreter) { |
aoqi@0 | 1527 | Label profile_continue; |
aoqi@0 | 1528 | |
aoqi@0 | 1529 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1530 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1531 | |
aoqi@0 | 1532 | // Update the default case count |
aoqi@0 | 1533 | increment_mdp_data_at(in_bytes(MultiBranchData::default_count_offset()), |
aoqi@0 | 1534 | scratch1, scratch2); |
aoqi@0 | 1535 | |
aoqi@0 | 1536 | // The method data pointer needs to be updated. |
aoqi@0 | 1537 | update_mdp_by_offset(in_bytes(MultiBranchData::default_displacement_offset()), |
aoqi@0 | 1538 | scratch1); |
aoqi@0 | 1539 | |
aoqi@0 | 1540 | bind (profile_continue); |
aoqi@0 | 1541 | } |
aoqi@0 | 1542 | } |
aoqi@0 | 1543 | |
aoqi@0 | 1544 | // Count the index'th case of a switch construct. |
aoqi@0 | 1545 | void InterpreterMacroAssembler::profile_switch_case(Register index, |
aoqi@0 | 1546 | Register scratch1, |
aoqi@0 | 1547 | Register scratch2, |
aoqi@0 | 1548 | Register scratch3) { |
aoqi@0 | 1549 | if (ProfileInterpreter) { |
aoqi@0 | 1550 | assert_different_registers(index, scratch1, scratch2, scratch3); |
aoqi@0 | 1551 | Label profile_continue; |
aoqi@0 | 1552 | |
aoqi@0 | 1553 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1554 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1555 | |
aoqi@0 | 1556 | // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes(). |
aoqi@0 | 1557 | li(scratch3, in_bytes(MultiBranchData::case_array_offset())); |
aoqi@0 | 1558 | |
aoqi@0 | 1559 | assert (in_bytes(MultiBranchData::per_case_size()) == 16, "so that shladd works"); |
aoqi@0 | 1560 | sldi(scratch1, index, exact_log2(in_bytes(MultiBranchData::per_case_size()))); |
aoqi@0 | 1561 | add(scratch1, scratch1, scratch3); |
aoqi@0 | 1562 | |
aoqi@0 | 1563 | // Update the case count. |
aoqi@0 | 1564 | increment_mdp_data_at(scratch1, in_bytes(MultiBranchData::relative_count_offset()), scratch2, scratch3); |
aoqi@0 | 1565 | |
aoqi@0 | 1566 | // The method data pointer needs to be updated. |
aoqi@0 | 1567 | update_mdp_by_offset(scratch1, in_bytes(MultiBranchData::relative_displacement_offset()), scratch2); |
aoqi@0 | 1568 | |
aoqi@0 | 1569 | bind (profile_continue); |
aoqi@0 | 1570 | } |
aoqi@0 | 1571 | } |
aoqi@0 | 1572 | |
aoqi@0 | 1573 | void InterpreterMacroAssembler::profile_null_seen(Register Rscratch1, Register Rscratch2) { |
aoqi@0 | 1574 | if (ProfileInterpreter) { |
aoqi@0 | 1575 | assert_different_registers(Rscratch1, Rscratch2); |
aoqi@0 | 1576 | Label profile_continue; |
aoqi@0 | 1577 | |
aoqi@0 | 1578 | // If no method data exists, go to profile_continue. |
aoqi@0 | 1579 | test_method_data_pointer(profile_continue); |
aoqi@0 | 1580 | |
aoqi@0 | 1581 | set_mdp_flag_at(BitData::null_seen_byte_constant(), Rscratch1); |
aoqi@0 | 1582 | |
aoqi@0 | 1583 | // The method data pointer needs to be updated. |
aoqi@0 | 1584 | int mdp_delta = in_bytes(BitData::bit_data_size()); |
aoqi@0 | 1585 | if (TypeProfileCasts) { |
aoqi@0 | 1586 | mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); |
aoqi@0 | 1587 | } |
aoqi@0 | 1588 | update_mdp_by_constant(mdp_delta); |
aoqi@0 | 1589 | |
aoqi@0 | 1590 | bind (profile_continue); |
aoqi@0 | 1591 | } |
aoqi@0 | 1592 | } |
aoqi@0 | 1593 | |
aoqi@0 | 1594 | void InterpreterMacroAssembler::record_klass_in_profile(Register Rreceiver, |
aoqi@0 | 1595 | Register Rscratch1, Register Rscratch2, |
aoqi@0 | 1596 | bool is_virtual_call) { |
aoqi@0 | 1597 | assert(ProfileInterpreter, "must be profiling"); |
aoqi@0 | 1598 | assert_different_registers(Rreceiver, Rscratch1, Rscratch2); |
aoqi@0 | 1599 | |
aoqi@0 | 1600 | Label done; |
aoqi@0 | 1601 | record_klass_in_profile_helper(Rreceiver, Rscratch1, Rscratch2, 0, done, is_virtual_call); |
aoqi@0 | 1602 | bind (done); |
aoqi@0 | 1603 | } |
aoqi@0 | 1604 | |
aoqi@0 | 1605 | void InterpreterMacroAssembler::record_klass_in_profile_helper( |
aoqi@0 | 1606 | Register receiver, Register scratch1, Register scratch2, |
aoqi@0 | 1607 | int start_row, Label& done, bool is_virtual_call) { |
aoqi@0 | 1608 | if (TypeProfileWidth == 0) { |
aoqi@0 | 1609 | if (is_virtual_call) { |
aoqi@0 | 1610 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch1, scratch2); |
aoqi@0 | 1611 | } |
aoqi@0 | 1612 | return; |
aoqi@0 | 1613 | } |
aoqi@0 | 1614 | |
aoqi@0 | 1615 | int last_row = VirtualCallData::row_limit() - 1; |
aoqi@0 | 1616 | assert(start_row <= last_row, "must be work left to do"); |
aoqi@0 | 1617 | // Test this row for both the receiver and for null. |
aoqi@0 | 1618 | // Take any of three different outcomes: |
aoqi@0 | 1619 | // 1. found receiver => increment count and goto done |
aoqi@0 | 1620 | // 2. found null => keep looking for case 1, maybe allocate this cell |
aoqi@0 | 1621 | // 3. found something else => keep looking for cases 1 and 2 |
aoqi@0 | 1622 | // Case 3 is handled by a recursive call. |
aoqi@0 | 1623 | for (int row = start_row; row <= last_row; row++) { |
aoqi@0 | 1624 | Label next_test; |
aoqi@0 | 1625 | bool test_for_null_also = (row == start_row); |
aoqi@0 | 1626 | |
aoqi@0 | 1627 | // See if the receiver is receiver[n]. |
aoqi@0 | 1628 | int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); |
aoqi@0 | 1629 | test_mdp_data_at(recvr_offset, receiver, next_test, scratch1); |
aoqi@0 | 1630 | // delayed()->tst(scratch); |
aoqi@0 | 1631 | |
aoqi@0 | 1632 | // The receiver is receiver[n]. Increment count[n]. |
aoqi@0 | 1633 | int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); |
aoqi@0 | 1634 | increment_mdp_data_at(count_offset, scratch1, scratch2); |
aoqi@0 | 1635 | b(done); |
aoqi@0 | 1636 | bind(next_test); |
aoqi@0 | 1637 | |
aoqi@0 | 1638 | if (test_for_null_also) { |
aoqi@0 | 1639 | Label found_null; |
aoqi@0 | 1640 | // Failed the equality check on receiver[n]... Test for null. |
aoqi@0 | 1641 | if (start_row == last_row) { |
aoqi@0 | 1642 | // The only thing left to do is handle the null case. |
aoqi@0 | 1643 | if (is_virtual_call) { |
aoqi@0 | 1644 | // Scratch1 contains test_out from test_mdp_data_at. |
aoqi@0 | 1645 | cmpdi(CCR0, scratch1, 0); |
aoqi@0 | 1646 | beq(CCR0, found_null); |
aoqi@0 | 1647 | // Receiver did not match any saved receiver and there is no empty row for it. |
aoqi@0 | 1648 | // Increment total counter to indicate polymorphic case. |
aoqi@0 | 1649 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch1, scratch2); |
aoqi@0 | 1650 | b(done); |
aoqi@0 | 1651 | bind(found_null); |
aoqi@0 | 1652 | } else { |
aoqi@0 | 1653 | cmpdi(CCR0, scratch1, 0); |
aoqi@0 | 1654 | bne(CCR0, done); |
aoqi@0 | 1655 | } |
aoqi@0 | 1656 | break; |
aoqi@0 | 1657 | } |
aoqi@0 | 1658 | // Since null is rare, make it be the branch-taken case. |
aoqi@0 | 1659 | cmpdi(CCR0, scratch1, 0); |
aoqi@0 | 1660 | beq(CCR0, found_null); |
aoqi@0 | 1661 | |
aoqi@0 | 1662 | // Put all the "Case 3" tests here. |
aoqi@0 | 1663 | record_klass_in_profile_helper(receiver, scratch1, scratch2, start_row + 1, done, is_virtual_call); |
aoqi@0 | 1664 | |
aoqi@0 | 1665 | // Found a null. Keep searching for a matching receiver, |
aoqi@0 | 1666 | // but remember that this is an empty (unused) slot. |
aoqi@0 | 1667 | bind(found_null); |
aoqi@0 | 1668 | } |
aoqi@0 | 1669 | } |
aoqi@0 | 1670 | |
aoqi@0 | 1671 | // In the fall-through case, we found no matching receiver, but we |
aoqi@0 | 1672 | // observed the receiver[start_row] is NULL. |
aoqi@0 | 1673 | |
aoqi@0 | 1674 | // Fill in the receiver field and increment the count. |
aoqi@0 | 1675 | int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); |
aoqi@0 | 1676 | set_mdp_data_at(recvr_offset, receiver); |
aoqi@0 | 1677 | int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); |
aoqi@0 | 1678 | li(scratch1, DataLayout::counter_increment); |
aoqi@0 | 1679 | set_mdp_data_at(count_offset, scratch1); |
aoqi@0 | 1680 | if (start_row > 0) { |
aoqi@0 | 1681 | b(done); |
aoqi@0 | 1682 | } |
aoqi@0 | 1683 | } |
aoqi@0 | 1684 | |
goetz@7424 | 1685 | // Argument and return type profilig. |
goetz@7424 | 1686 | // kills: tmp, tmp2, R0, CR0, CR1 |
goetz@7424 | 1687 | void InterpreterMacroAssembler::profile_obj_type(Register obj, Register mdo_addr_base, |
goetz@7424 | 1688 | RegisterOrConstant mdo_addr_offs, Register tmp, Register tmp2) { |
goetz@7424 | 1689 | Label do_nothing, do_update; |
goetz@7424 | 1690 | |
goetz@7424 | 1691 | // tmp2 = obj is allowed |
goetz@7424 | 1692 | assert_different_registers(obj, mdo_addr_base, tmp, R0); |
goetz@7424 | 1693 | assert_different_registers(tmp2, mdo_addr_base, tmp, R0); |
goetz@7424 | 1694 | const Register klass = tmp2; |
goetz@7424 | 1695 | |
goetz@7424 | 1696 | verify_oop(obj); |
goetz@7424 | 1697 | |
goetz@7424 | 1698 | ld(tmp, mdo_addr_offs, mdo_addr_base); |
goetz@7424 | 1699 | |
goetz@7424 | 1700 | // Set null_seen if obj is 0. |
goetz@7424 | 1701 | cmpdi(CCR0, obj, 0); |
goetz@7424 | 1702 | ori(R0, tmp, TypeEntries::null_seen); |
goetz@7424 | 1703 | beq(CCR0, do_update); |
goetz@7424 | 1704 | |
goetz@7424 | 1705 | load_klass(klass, obj); |
goetz@7424 | 1706 | |
goetz@7424 | 1707 | clrrdi(R0, tmp, exact_log2(-TypeEntries::type_klass_mask)); |
goetz@7424 | 1708 | // Basically same as andi(R0, tmp, TypeEntries::type_klass_mask); |
goetz@7424 | 1709 | cmpd(CCR1, R0, klass); |
goetz@7424 | 1710 | // Klass seen before, nothing to do (regardless of unknown bit). |
goetz@7424 | 1711 | //beq(CCR1, do_nothing); |
goetz@7424 | 1712 | |
goetz@7424 | 1713 | andi_(R0, klass, TypeEntries::type_unknown); |
goetz@7424 | 1714 | // Already unknown. Nothing to do anymore. |
goetz@7424 | 1715 | //bne(CCR0, do_nothing); |
goetz@7424 | 1716 | crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); // cr0 eq = cr1 eq or cr0 ne |
goetz@7424 | 1717 | beq(CCR0, do_nothing); |
goetz@7424 | 1718 | |
goetz@7424 | 1719 | clrrdi_(R0, tmp, exact_log2(-TypeEntries::type_mask)); |
goetz@7424 | 1720 | orr(R0, klass, tmp); // Combine klass and null_seen bit (only used if (tmp & type_mask)==0). |
goetz@7424 | 1721 | beq(CCR0, do_update); // First time here. Set profile type. |
goetz@7424 | 1722 | |
goetz@7424 | 1723 | // Different than before. Cannot keep accurate profile. |
goetz@7424 | 1724 | ori(R0, tmp, TypeEntries::type_unknown); |
goetz@7424 | 1725 | |
goetz@7424 | 1726 | bind(do_update); |
goetz@7424 | 1727 | // update profile |
goetz@7424 | 1728 | std(R0, mdo_addr_offs, mdo_addr_base); |
goetz@7424 | 1729 | |
goetz@7424 | 1730 | align(32, 12); |
goetz@7424 | 1731 | bind(do_nothing); |
goetz@7424 | 1732 | } |
goetz@7424 | 1733 | |
goetz@7424 | 1734 | void InterpreterMacroAssembler::profile_arguments_type(Register callee, Register tmp1, Register tmp2, bool is_virtual) { |
goetz@7424 | 1735 | if (!ProfileInterpreter) { |
goetz@7424 | 1736 | return; |
goetz@7424 | 1737 | } |
goetz@7424 | 1738 | |
goetz@7424 | 1739 | assert_different_registers(callee, tmp1, tmp2, R28_mdx); |
goetz@7424 | 1740 | |
goetz@7424 | 1741 | if (MethodData::profile_arguments() || MethodData::profile_return()) { |
goetz@7424 | 1742 | Label profile_continue; |
goetz@7424 | 1743 | |
goetz@7424 | 1744 | test_method_data_pointer(profile_continue); |
goetz@7424 | 1745 | |
goetz@7424 | 1746 | int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size()); |
goetz@7424 | 1747 | |
goetz@7424 | 1748 | lbz(tmp1, in_bytes(DataLayout::tag_offset()) - off_to_start, R28_mdx); |
goetz@7424 | 1749 | cmpwi(CCR0, tmp1, is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag); |
goetz@7424 | 1750 | bne(CCR0, profile_continue); |
goetz@7424 | 1751 | |
goetz@7424 | 1752 | if (MethodData::profile_arguments()) { |
goetz@7424 | 1753 | Label done; |
goetz@7424 | 1754 | int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset()); |
goetz@7424 | 1755 | add(R28_mdx, off_to_args, R28_mdx); |
goetz@7424 | 1756 | |
goetz@7424 | 1757 | for (int i = 0; i < TypeProfileArgsLimit; i++) { |
goetz@7424 | 1758 | if (i > 0 || MethodData::profile_return()) { |
goetz@7424 | 1759 | // If return value type is profiled we may have no argument to profile. |
goetz@7424 | 1760 | ld(tmp1, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args, R28_mdx); |
goetz@7424 | 1761 | cmpdi(CCR0, tmp1, (i+1)*TypeStackSlotEntries::per_arg_count()); |
goetz@7424 | 1762 | addi(tmp1, tmp1, -i*TypeStackSlotEntries::per_arg_count()); |
goetz@7424 | 1763 | blt(CCR0, done); |
goetz@7424 | 1764 | } |
goetz@7424 | 1765 | ld(tmp1, in_bytes(Method::const_offset()), callee); |
goetz@7424 | 1766 | lhz(tmp1, in_bytes(ConstMethod::size_of_parameters_offset()), tmp1); |
goetz@7424 | 1767 | // Stack offset o (zero based) from the start of the argument |
goetz@7424 | 1768 | // list, for n arguments translates into offset n - o - 1 from |
goetz@7424 | 1769 | // the end of the argument list. But there's an extra slot at |
goetz@7424 | 1770 | // the top of the stack. So the offset is n - o from Lesp. |
goetz@7424 | 1771 | ld(tmp2, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args, R28_mdx); |
goetz@7424 | 1772 | subf(tmp1, tmp2, tmp1); |
goetz@7424 | 1773 | |
goetz@7424 | 1774 | sldi(tmp1, tmp1, Interpreter::logStackElementSize); |
goetz@7424 | 1775 | ldx(tmp1, tmp1, R15_esp); |
goetz@7424 | 1776 | |
goetz@7424 | 1777 | profile_obj_type(tmp1, R28_mdx, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args, tmp2, tmp1); |
goetz@7424 | 1778 | |
goetz@7424 | 1779 | int to_add = in_bytes(TypeStackSlotEntries::per_arg_size()); |
goetz@7424 | 1780 | addi(R28_mdx, R28_mdx, to_add); |
goetz@7424 | 1781 | off_to_args += to_add; |
goetz@7424 | 1782 | } |
goetz@7424 | 1783 | |
goetz@7424 | 1784 | if (MethodData::profile_return()) { |
goetz@7424 | 1785 | ld(tmp1, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args, R28_mdx); |
goetz@7424 | 1786 | addi(tmp1, tmp1, -TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count()); |
goetz@7424 | 1787 | } |
goetz@7424 | 1788 | |
goetz@7424 | 1789 | bind(done); |
goetz@7424 | 1790 | |
goetz@7424 | 1791 | if (MethodData::profile_return()) { |
goetz@7424 | 1792 | // We're right after the type profile for the last |
goetz@7424 | 1793 | // argument. tmp1 is the number of cells left in the |
goetz@7424 | 1794 | // CallTypeData/VirtualCallTypeData to reach its end. Non null |
goetz@7424 | 1795 | // if there's a return to profile. |
goetz@7424 | 1796 | assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type"); |
goetz@7424 | 1797 | sldi(tmp1, tmp1, exact_log2(DataLayout::cell_size)); |
goetz@7424 | 1798 | add(R28_mdx, tmp1, R28_mdx); |
goetz@7424 | 1799 | } |
goetz@7424 | 1800 | } else { |
goetz@7424 | 1801 | assert(MethodData::profile_return(), "either profile call args or call ret"); |
goetz@7424 | 1802 | update_mdp_by_constant(in_bytes(TypeEntriesAtCall::return_only_size())); |
goetz@7424 | 1803 | } |
goetz@7424 | 1804 | |
goetz@7424 | 1805 | // Mdp points right after the end of the |
goetz@7424 | 1806 | // CallTypeData/VirtualCallTypeData, right after the cells for the |
goetz@7424 | 1807 | // return value type if there's one. |
goetz@7424 | 1808 | align(32, 12); |
goetz@7424 | 1809 | bind(profile_continue); |
goetz@7424 | 1810 | } |
goetz@7424 | 1811 | } |
goetz@7424 | 1812 | |
goetz@7424 | 1813 | void InterpreterMacroAssembler::profile_return_type(Register ret, Register tmp1, Register tmp2) { |
goetz@7424 | 1814 | assert_different_registers(ret, tmp1, tmp2); |
goetz@7424 | 1815 | if (ProfileInterpreter && MethodData::profile_return()) { |
goetz@7424 | 1816 | Label profile_continue; |
goetz@7424 | 1817 | |
goetz@7424 | 1818 | test_method_data_pointer(profile_continue); |
goetz@7424 | 1819 | |
goetz@7424 | 1820 | if (MethodData::profile_return_jsr292_only()) { |
goetz@7424 | 1821 | // If we don't profile all invoke bytecodes we must make sure |
goetz@7424 | 1822 | // it's a bytecode we indeed profile. We can't go back to the |
goetz@7424 | 1823 | // begining of the ProfileData we intend to update to check its |
goetz@7424 | 1824 | // type because we're right after it and we don't known its |
goetz@7424 | 1825 | // length. |
goetz@7424 | 1826 | lbz(tmp1, 0, R14_bcp); |
goetz@7424 | 1827 | lbz(tmp2, Method::intrinsic_id_offset_in_bytes(), R19_method); |
goetz@7424 | 1828 | cmpwi(CCR0, tmp1, Bytecodes::_invokedynamic); |
goetz@7424 | 1829 | cmpwi(CCR1, tmp1, Bytecodes::_invokehandle); |
goetz@7424 | 1830 | cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); |
goetz@7424 | 1831 | cmpwi(CCR1, tmp2, vmIntrinsics::_compiledLambdaForm); |
goetz@7424 | 1832 | cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); |
goetz@7424 | 1833 | bne(CCR0, profile_continue); |
goetz@7424 | 1834 | } |
goetz@7424 | 1835 | |
goetz@7424 | 1836 | profile_obj_type(ret, R28_mdx, -in_bytes(ReturnTypeEntry::size()), tmp1, tmp2); |
goetz@7424 | 1837 | |
goetz@7424 | 1838 | align(32, 12); |
goetz@7424 | 1839 | bind(profile_continue); |
goetz@7424 | 1840 | } |
goetz@7424 | 1841 | } |
goetz@7424 | 1842 | |
goetz@7424 | 1843 | void InterpreterMacroAssembler::profile_parameters_type(Register tmp1, Register tmp2, Register tmp3, Register tmp4) { |
goetz@7424 | 1844 | if (ProfileInterpreter && MethodData::profile_parameters()) { |
goetz@7424 | 1845 | Label profile_continue, done; |
goetz@7424 | 1846 | |
goetz@7424 | 1847 | test_method_data_pointer(profile_continue); |
goetz@7424 | 1848 | |
goetz@7424 | 1849 | // Load the offset of the area within the MDO used for |
goetz@7424 | 1850 | // parameters. If it's negative we're not profiling any parameters. |
goetz@7424 | 1851 | lwz(tmp1, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()), R28_mdx); |
goetz@7424 | 1852 | cmpwi(CCR0, tmp1, 0); |
goetz@7424 | 1853 | blt(CCR0, profile_continue); |
goetz@7424 | 1854 | |
goetz@7424 | 1855 | // Compute a pointer to the area for parameters from the offset |
goetz@7424 | 1856 | // and move the pointer to the slot for the last |
goetz@7424 | 1857 | // parameters. Collect profiling from last parameter down. |
goetz@7424 | 1858 | // mdo start + parameters offset + array length - 1 |
goetz@7424 | 1859 | |
goetz@7424 | 1860 | // Pointer to the parameter area in the MDO. |
goetz@7424 | 1861 | const Register mdp = tmp1; |
goetz@7424 | 1862 | add(mdp, tmp1, R28_mdx); |
goetz@7424 | 1863 | |
goetz@7424 | 1864 | // Pffset of the current profile entry to update. |
goetz@7424 | 1865 | const Register entry_offset = tmp2; |
goetz@7424 | 1866 | // entry_offset = array len in number of cells |
goetz@7424 | 1867 | ld(entry_offset, in_bytes(ArrayData::array_len_offset()), mdp); |
goetz@7424 | 1868 | |
goetz@7424 | 1869 | int off_base = in_bytes(ParametersTypeData::stack_slot_offset(0)); |
goetz@7424 | 1870 | assert(off_base % DataLayout::cell_size == 0, "should be a number of cells"); |
goetz@7424 | 1871 | |
goetz@7424 | 1872 | // entry_offset (number of cells) = array len - size of 1 entry + offset of the stack slot field |
goetz@7424 | 1873 | addi(entry_offset, entry_offset, -TypeStackSlotEntries::per_arg_count() + (off_base / DataLayout::cell_size)); |
goetz@7424 | 1874 | // entry_offset in bytes |
goetz@7424 | 1875 | sldi(entry_offset, entry_offset, exact_log2(DataLayout::cell_size)); |
goetz@7424 | 1876 | |
goetz@7424 | 1877 | Label loop; |
goetz@7424 | 1878 | align(32, 12); |
goetz@7424 | 1879 | bind(loop); |
goetz@7424 | 1880 | |
goetz@7424 | 1881 | // Load offset on the stack from the slot for this parameter. |
goetz@7424 | 1882 | ld(tmp3, entry_offset, mdp); |
goetz@7424 | 1883 | sldi(tmp3, tmp3, Interpreter::logStackElementSize); |
goetz@7424 | 1884 | neg(tmp3, tmp3); |
goetz@7424 | 1885 | // Read the parameter from the local area. |
goetz@7424 | 1886 | ldx(tmp3, tmp3, R18_locals); |
goetz@7424 | 1887 | |
goetz@7424 | 1888 | // Make entry_offset now point to the type field for this parameter. |
goetz@7424 | 1889 | int type_base = in_bytes(ParametersTypeData::type_offset(0)); |
goetz@7424 | 1890 | assert(type_base > off_base, "unexpected"); |
goetz@7424 | 1891 | addi(entry_offset, entry_offset, type_base - off_base); |
goetz@7424 | 1892 | |
goetz@7424 | 1893 | // Profile the parameter. |
goetz@7424 | 1894 | profile_obj_type(tmp3, mdp, entry_offset, tmp4, tmp3); |
goetz@7424 | 1895 | |
goetz@7424 | 1896 | // Go to next parameter. |
goetz@7424 | 1897 | int delta = TypeStackSlotEntries::per_arg_count() * DataLayout::cell_size + (type_base - off_base); |
goetz@7424 | 1898 | cmpdi(CCR0, entry_offset, off_base + delta); |
goetz@7424 | 1899 | addi(entry_offset, entry_offset, -delta); |
goetz@7424 | 1900 | bge(CCR0, loop); |
goetz@7424 | 1901 | |
goetz@7424 | 1902 | align(32, 12); |
goetz@7424 | 1903 | bind(profile_continue); |
goetz@7424 | 1904 | } |
goetz@7424 | 1905 | } |
goetz@7424 | 1906 | |
aoqi@0 | 1907 | // Add a InterpMonitorElem to stack (see frame_sparc.hpp). |
aoqi@0 | 1908 | void InterpreterMacroAssembler::add_monitor_to_stack(bool stack_is_empty, Register Rtemp1, Register Rtemp2) { |
aoqi@0 | 1909 | |
aoqi@0 | 1910 | // Very-local scratch registers. |
aoqi@0 | 1911 | const Register esp = Rtemp1; |
aoqi@0 | 1912 | const Register slot = Rtemp2; |
aoqi@0 | 1913 | |
aoqi@0 | 1914 | // Extracted monitor_size. |
aoqi@0 | 1915 | int monitor_size = frame::interpreter_frame_monitor_size_in_bytes(); |
aoqi@0 | 1916 | assert(Assembler::is_aligned((unsigned int)monitor_size, |
aoqi@0 | 1917 | (unsigned int)frame::alignment_in_bytes), |
aoqi@0 | 1918 | "size of a monitor must respect alignment of SP"); |
aoqi@0 | 1919 | |
aoqi@0 | 1920 | resize_frame(-monitor_size, /*temp*/esp); // Allocate space for new monitor |
aoqi@0 | 1921 | std(R1_SP, _ijava_state_neg(top_frame_sp), esp); // esp contains fp |
aoqi@0 | 1922 | |
aoqi@0 | 1923 | // Shuffle expression stack down. Recall that stack_base points |
aoqi@0 | 1924 | // just above the new expression stack bottom. Old_tos and new_tos |
aoqi@0 | 1925 | // are used to scan thru the old and new expression stacks. |
aoqi@0 | 1926 | if (!stack_is_empty) { |
aoqi@0 | 1927 | Label copy_slot, copy_slot_finished; |
aoqi@0 | 1928 | const Register n_slots = slot; |
aoqi@0 | 1929 | |
aoqi@0 | 1930 | addi(esp, R15_esp, Interpreter::stackElementSize); // Point to first element (pre-pushed stack). |
aoqi@0 | 1931 | subf(n_slots, esp, R26_monitor); |
aoqi@0 | 1932 | srdi_(n_slots, n_slots, LogBytesPerWord); // Compute number of slots to copy. |
aoqi@0 | 1933 | assert(LogBytesPerWord == 3, "conflicts assembler instructions"); |
aoqi@0 | 1934 | beq(CCR0, copy_slot_finished); // Nothing to copy. |
aoqi@0 | 1935 | |
aoqi@0 | 1936 | mtctr(n_slots); |
aoqi@0 | 1937 | |
aoqi@0 | 1938 | // loop |
aoqi@0 | 1939 | bind(copy_slot); |
aoqi@0 | 1940 | ld(slot, 0, esp); // Move expression stack down. |
aoqi@0 | 1941 | std(slot, -monitor_size, esp); // distance = monitor_size |
aoqi@0 | 1942 | addi(esp, esp, BytesPerWord); |
aoqi@0 | 1943 | bdnz(copy_slot); |
aoqi@0 | 1944 | |
aoqi@0 | 1945 | bind(copy_slot_finished); |
aoqi@0 | 1946 | } |
aoqi@0 | 1947 | |
aoqi@0 | 1948 | addi(R15_esp, R15_esp, -monitor_size); |
aoqi@0 | 1949 | addi(R26_monitor, R26_monitor, -monitor_size); |
aoqi@0 | 1950 | |
aoqi@0 | 1951 | // Restart interpreter |
aoqi@0 | 1952 | } |
aoqi@0 | 1953 | |
aoqi@0 | 1954 | // ============================================================================ |
aoqi@0 | 1955 | // Java locals access |
aoqi@0 | 1956 | |
aoqi@0 | 1957 | // Load a local variable at index in Rindex into register Rdst_value. |
aoqi@0 | 1958 | // Also puts address of local into Rdst_address as a service. |
aoqi@0 | 1959 | // Kills: |
aoqi@0 | 1960 | // - Rdst_value |
aoqi@0 | 1961 | // - Rdst_address |
aoqi@0 | 1962 | void InterpreterMacroAssembler::load_local_int(Register Rdst_value, Register Rdst_address, Register Rindex) { |
aoqi@0 | 1963 | sldi(Rdst_address, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 1964 | subf(Rdst_address, Rdst_address, R18_locals); |
aoqi@0 | 1965 | lwz(Rdst_value, 0, Rdst_address); |
aoqi@0 | 1966 | } |
aoqi@0 | 1967 | |
aoqi@0 | 1968 | // Load a local variable at index in Rindex into register Rdst_value. |
aoqi@0 | 1969 | // Also puts address of local into Rdst_address as a service. |
aoqi@0 | 1970 | // Kills: |
aoqi@0 | 1971 | // - Rdst_value |
aoqi@0 | 1972 | // - Rdst_address |
aoqi@0 | 1973 | void InterpreterMacroAssembler::load_local_long(Register Rdst_value, Register Rdst_address, Register Rindex) { |
aoqi@0 | 1974 | sldi(Rdst_address, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 1975 | subf(Rdst_address, Rdst_address, R18_locals); |
aoqi@0 | 1976 | ld(Rdst_value, -8, Rdst_address); |
aoqi@0 | 1977 | } |
aoqi@0 | 1978 | |
aoqi@0 | 1979 | // Load a local variable at index in Rindex into register Rdst_value. |
aoqi@0 | 1980 | // Also puts address of local into Rdst_address as a service. |
aoqi@0 | 1981 | // Input: |
aoqi@0 | 1982 | // - Rindex: slot nr of local variable |
aoqi@0 | 1983 | // Kills: |
aoqi@0 | 1984 | // - Rdst_value |
aoqi@0 | 1985 | // - Rdst_address |
aoqi@0 | 1986 | void InterpreterMacroAssembler::load_local_ptr(Register Rdst_value, Register Rdst_address, Register Rindex) { |
aoqi@0 | 1987 | sldi(Rdst_address, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 1988 | subf(Rdst_address, Rdst_address, R18_locals); |
aoqi@0 | 1989 | ld(Rdst_value, 0, Rdst_address); |
aoqi@0 | 1990 | } |
aoqi@0 | 1991 | |
aoqi@0 | 1992 | // Load a local variable at index in Rindex into register Rdst_value. |
aoqi@0 | 1993 | // Also puts address of local into Rdst_address as a service. |
aoqi@0 | 1994 | // Kills: |
aoqi@0 | 1995 | // - Rdst_value |
aoqi@0 | 1996 | // - Rdst_address |
aoqi@0 | 1997 | void InterpreterMacroAssembler::load_local_float(FloatRegister Rdst_value, Register Rdst_address, Register Rindex) { |
aoqi@0 | 1998 | sldi(Rdst_address, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 1999 | subf(Rdst_address, Rdst_address, R18_locals); |
aoqi@0 | 2000 | lfs(Rdst_value, 0, Rdst_address); |
aoqi@0 | 2001 | } |
aoqi@0 | 2002 | |
aoqi@0 | 2003 | // Load a local variable at index in Rindex into register Rdst_value. |
aoqi@0 | 2004 | // Also puts address of local into Rdst_address as a service. |
aoqi@0 | 2005 | // Kills: |
aoqi@0 | 2006 | // - Rdst_value |
aoqi@0 | 2007 | // - Rdst_address |
aoqi@0 | 2008 | void InterpreterMacroAssembler::load_local_double(FloatRegister Rdst_value, Register Rdst_address, Register Rindex) { |
aoqi@0 | 2009 | sldi(Rdst_address, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 2010 | subf(Rdst_address, Rdst_address, R18_locals); |
aoqi@0 | 2011 | lfd(Rdst_value, -8, Rdst_address); |
aoqi@0 | 2012 | } |
aoqi@0 | 2013 | |
aoqi@0 | 2014 | // Store an int value at local variable slot Rindex. |
aoqi@0 | 2015 | // Kills: |
aoqi@0 | 2016 | // - Rindex |
aoqi@0 | 2017 | void InterpreterMacroAssembler::store_local_int(Register Rvalue, Register Rindex) { |
aoqi@0 | 2018 | sldi(Rindex, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 2019 | subf(Rindex, Rindex, R18_locals); |
aoqi@0 | 2020 | stw(Rvalue, 0, Rindex); |
aoqi@0 | 2021 | } |
aoqi@0 | 2022 | |
aoqi@0 | 2023 | // Store a long value at local variable slot Rindex. |
aoqi@0 | 2024 | // Kills: |
aoqi@0 | 2025 | // - Rindex |
aoqi@0 | 2026 | void InterpreterMacroAssembler::store_local_long(Register Rvalue, Register Rindex) { |
aoqi@0 | 2027 | sldi(Rindex, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 2028 | subf(Rindex, Rindex, R18_locals); |
aoqi@0 | 2029 | std(Rvalue, -8, Rindex); |
aoqi@0 | 2030 | } |
aoqi@0 | 2031 | |
aoqi@0 | 2032 | // Store an oop value at local variable slot Rindex. |
aoqi@0 | 2033 | // Kills: |
aoqi@0 | 2034 | // - Rindex |
aoqi@0 | 2035 | void InterpreterMacroAssembler::store_local_ptr(Register Rvalue, Register Rindex) { |
aoqi@0 | 2036 | sldi(Rindex, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 2037 | subf(Rindex, Rindex, R18_locals); |
aoqi@0 | 2038 | std(Rvalue, 0, Rindex); |
aoqi@0 | 2039 | } |
aoqi@0 | 2040 | |
aoqi@0 | 2041 | // Store an int value at local variable slot Rindex. |
aoqi@0 | 2042 | // Kills: |
aoqi@0 | 2043 | // - Rindex |
aoqi@0 | 2044 | void InterpreterMacroAssembler::store_local_float(FloatRegister Rvalue, Register Rindex) { |
aoqi@0 | 2045 | sldi(Rindex, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 2046 | subf(Rindex, Rindex, R18_locals); |
aoqi@0 | 2047 | stfs(Rvalue, 0, Rindex); |
aoqi@0 | 2048 | } |
aoqi@0 | 2049 | |
aoqi@0 | 2050 | // Store an int value at local variable slot Rindex. |
aoqi@0 | 2051 | // Kills: |
aoqi@0 | 2052 | // - Rindex |
aoqi@0 | 2053 | void InterpreterMacroAssembler::store_local_double(FloatRegister Rvalue, Register Rindex) { |
aoqi@0 | 2054 | sldi(Rindex, Rindex, Interpreter::logStackElementSize); |
aoqi@0 | 2055 | subf(Rindex, Rindex, R18_locals); |
aoqi@0 | 2056 | stfd(Rvalue, -8, Rindex); |
aoqi@0 | 2057 | } |
aoqi@0 | 2058 | |
aoqi@0 | 2059 | // Read pending exception from thread and jump to interpreter. |
aoqi@0 | 2060 | // Throw exception entry if one if pending. Fall through otherwise. |
aoqi@0 | 2061 | void InterpreterMacroAssembler::check_and_forward_exception(Register Rscratch1, Register Rscratch2) { |
aoqi@0 | 2062 | assert_different_registers(Rscratch1, Rscratch2, R3); |
aoqi@0 | 2063 | Register Rexception = Rscratch1; |
aoqi@0 | 2064 | Register Rtmp = Rscratch2; |
aoqi@0 | 2065 | Label Ldone; |
aoqi@0 | 2066 | // Get pending exception oop. |
aoqi@0 | 2067 | ld(Rexception, thread_(pending_exception)); |
aoqi@0 | 2068 | cmpdi(CCR0, Rexception, 0); |
aoqi@0 | 2069 | beq(CCR0, Ldone); |
aoqi@0 | 2070 | li(Rtmp, 0); |
aoqi@0 | 2071 | mr_if_needed(R3, Rexception); |
aoqi@0 | 2072 | std(Rtmp, thread_(pending_exception)); // Clear exception in thread |
aoqi@0 | 2073 | if (Interpreter::rethrow_exception_entry() != NULL) { |
aoqi@0 | 2074 | // Already got entry address. |
aoqi@0 | 2075 | load_dispatch_table(Rtmp, (address*)Interpreter::rethrow_exception_entry()); |
aoqi@0 | 2076 | } else { |
aoqi@0 | 2077 | // Dynamically load entry address. |
aoqi@0 | 2078 | int simm16_rest = load_const_optimized(Rtmp, &Interpreter::_rethrow_exception_entry, R0, true); |
aoqi@0 | 2079 | ld(Rtmp, simm16_rest, Rtmp); |
aoqi@0 | 2080 | } |
aoqi@0 | 2081 | mtctr(Rtmp); |
aoqi@0 | 2082 | save_interpreter_state(Rtmp); |
aoqi@0 | 2083 | bctr(); |
aoqi@0 | 2084 | |
aoqi@0 | 2085 | align(32, 12); |
aoqi@0 | 2086 | bind(Ldone); |
aoqi@0 | 2087 | } |
aoqi@0 | 2088 | |
aoqi@0 | 2089 | void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point, bool check_exceptions) { |
aoqi@0 | 2090 | save_interpreter_state(R11_scratch1); |
aoqi@0 | 2091 | |
aoqi@0 | 2092 | MacroAssembler::call_VM(oop_result, entry_point, false); |
aoqi@0 | 2093 | |
aoqi@0 | 2094 | restore_interpreter_state(R11_scratch1, /*bcp_and_mdx_only*/ true); |
aoqi@0 | 2095 | |
aoqi@0 | 2096 | check_and_handle_popframe(R11_scratch1); |
aoqi@0 | 2097 | check_and_handle_earlyret(R11_scratch1); |
aoqi@0 | 2098 | // Now check exceptions manually. |
aoqi@0 | 2099 | if (check_exceptions) { |
aoqi@0 | 2100 | check_and_forward_exception(R11_scratch1, R12_scratch2); |
aoqi@0 | 2101 | } |
aoqi@0 | 2102 | } |
aoqi@0 | 2103 | |
aoqi@0 | 2104 | void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions) { |
aoqi@0 | 2105 | // ARG1 is reserved for the thread. |
aoqi@0 | 2106 | mr_if_needed(R4_ARG2, arg_1); |
aoqi@0 | 2107 | call_VM(oop_result, entry_point, check_exceptions); |
aoqi@0 | 2108 | } |
aoqi@0 | 2109 | |
aoqi@0 | 2110 | void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { |
aoqi@0 | 2111 | // ARG1 is reserved for the thread. |
aoqi@0 | 2112 | mr_if_needed(R4_ARG2, arg_1); |
aoqi@0 | 2113 | assert(arg_2 != R4_ARG2, "smashed argument"); |
aoqi@0 | 2114 | mr_if_needed(R5_ARG3, arg_2); |
aoqi@0 | 2115 | call_VM(oop_result, entry_point, check_exceptions); |
aoqi@0 | 2116 | } |
aoqi@0 | 2117 | |
aoqi@0 | 2118 | void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { |
aoqi@0 | 2119 | // ARG1 is reserved for the thread. |
aoqi@0 | 2120 | mr_if_needed(R4_ARG2, arg_1); |
aoqi@0 | 2121 | assert(arg_2 != R4_ARG2, "smashed argument"); |
aoqi@0 | 2122 | mr_if_needed(R5_ARG3, arg_2); |
aoqi@0 | 2123 | assert(arg_3 != R4_ARG2 && arg_3 != R5_ARG3, "smashed argument"); |
aoqi@0 | 2124 | mr_if_needed(R6_ARG4, arg_3); |
aoqi@0 | 2125 | call_VM(oop_result, entry_point, check_exceptions); |
aoqi@0 | 2126 | } |
aoqi@0 | 2127 | |
aoqi@0 | 2128 | void InterpreterMacroAssembler::save_interpreter_state(Register scratch) { |
aoqi@0 | 2129 | ld(scratch, 0, R1_SP); |
aoqi@0 | 2130 | std(R15_esp, _ijava_state_neg(esp), scratch); |
aoqi@0 | 2131 | std(R14_bcp, _ijava_state_neg(bcp), scratch); |
aoqi@0 | 2132 | std(R26_monitor, _ijava_state_neg(monitors), scratch); |
aoqi@0 | 2133 | if (ProfileInterpreter) { std(R28_mdx, _ijava_state_neg(mdx), scratch); } |
aoqi@0 | 2134 | // Other entries should be unchanged. |
aoqi@0 | 2135 | } |
aoqi@0 | 2136 | |
aoqi@0 | 2137 | void InterpreterMacroAssembler::restore_interpreter_state(Register scratch, bool bcp_and_mdx_only) { |
aoqi@0 | 2138 | ld(scratch, 0, R1_SP); |
aoqi@0 | 2139 | ld(R14_bcp, _ijava_state_neg(bcp), scratch); // Changed by VM code (exception). |
aoqi@0 | 2140 | if (ProfileInterpreter) { ld(R28_mdx, _ijava_state_neg(mdx), scratch); } // Changed by VM code. |
aoqi@0 | 2141 | if (!bcp_and_mdx_only) { |
aoqi@0 | 2142 | // Following ones are Metadata. |
aoqi@0 | 2143 | ld(R19_method, _ijava_state_neg(method), scratch); |
aoqi@0 | 2144 | ld(R27_constPoolCache, _ijava_state_neg(cpoolCache), scratch); |
aoqi@0 | 2145 | // Following ones are stack addresses and don't require reload. |
aoqi@0 | 2146 | ld(R15_esp, _ijava_state_neg(esp), scratch); |
aoqi@0 | 2147 | ld(R18_locals, _ijava_state_neg(locals), scratch); |
aoqi@0 | 2148 | ld(R26_monitor, _ijava_state_neg(monitors), scratch); |
aoqi@0 | 2149 | } |
aoqi@0 | 2150 | #ifdef ASSERT |
aoqi@0 | 2151 | { |
aoqi@0 | 2152 | Label Lok; |
aoqi@0 | 2153 | subf(R0, R1_SP, scratch); |
aoqi@0 | 2154 | cmpdi(CCR0, R0, frame::abi_reg_args_size + frame::ijava_state_size); |
aoqi@0 | 2155 | bge(CCR0, Lok); |
aoqi@0 | 2156 | stop("frame too small (restore istate)", 0x5432); |
aoqi@0 | 2157 | bind(Lok); |
aoqi@0 | 2158 | } |
aoqi@0 | 2159 | { |
aoqi@0 | 2160 | Label Lok; |
aoqi@0 | 2161 | ld(R0, _ijava_state_neg(ijava_reserved), scratch); |
aoqi@0 | 2162 | cmpdi(CCR0, R0, 0x5afe); |
aoqi@0 | 2163 | beq(CCR0, Lok); |
aoqi@0 | 2164 | stop("frame corrupted (restore istate)", 0x5afe); |
aoqi@0 | 2165 | bind(Lok); |
aoqi@0 | 2166 | } |
aoqi@0 | 2167 | #endif |
aoqi@0 | 2168 | } |
aoqi@0 | 2169 | |
aoqi@0 | 2170 | #endif // !CC_INTERP |
aoqi@0 | 2171 | |
aoqi@0 | 2172 | void InterpreterMacroAssembler::get_method_counters(Register method, |
aoqi@0 | 2173 | Register Rcounters, |
aoqi@0 | 2174 | Label& skip) { |
aoqi@0 | 2175 | BLOCK_COMMENT("Load and ev. allocate counter object {"); |
aoqi@0 | 2176 | Label has_counters; |
aoqi@0 | 2177 | ld(Rcounters, in_bytes(Method::method_counters_offset()), method); |
aoqi@0 | 2178 | cmpdi(CCR0, Rcounters, 0); |
aoqi@0 | 2179 | bne(CCR0, has_counters); |
aoqi@0 | 2180 | call_VM(noreg, CAST_FROM_FN_PTR(address, |
aoqi@0 | 2181 | InterpreterRuntime::build_method_counters), method, false); |
aoqi@0 | 2182 | ld(Rcounters, in_bytes(Method::method_counters_offset()), method); |
aoqi@0 | 2183 | cmpdi(CCR0, Rcounters, 0); |
aoqi@0 | 2184 | beq(CCR0, skip); // No MethodCounters, OutOfMemory. |
aoqi@0 | 2185 | BLOCK_COMMENT("} Load and ev. allocate counter object"); |
aoqi@0 | 2186 | |
aoqi@0 | 2187 | bind(has_counters); |
aoqi@0 | 2188 | } |
aoqi@0 | 2189 | |
aoqi@0 | 2190 | void InterpreterMacroAssembler::increment_invocation_counter(Register Rcounters, Register iv_be_count, Register Rtmp_r0) { |
aoqi@0 | 2191 | assert(UseCompiler, "incrementing must be useful"); |
aoqi@0 | 2192 | Register invocation_count = iv_be_count; |
aoqi@0 | 2193 | Register backedge_count = Rtmp_r0; |
aoqi@0 | 2194 | int delta = InvocationCounter::count_increment; |
aoqi@0 | 2195 | |
aoqi@0 | 2196 | // Load each counter in a register. |
aoqi@0 | 2197 | // ld(inv_counter, Rtmp); |
aoqi@0 | 2198 | // ld(be_counter, Rtmp2); |
aoqi@0 | 2199 | int inv_counter_offset = in_bytes(MethodCounters::invocation_counter_offset() + |
aoqi@0 | 2200 | InvocationCounter::counter_offset()); |
aoqi@0 | 2201 | int be_counter_offset = in_bytes(MethodCounters::backedge_counter_offset() + |
aoqi@0 | 2202 | InvocationCounter::counter_offset()); |
aoqi@0 | 2203 | |
aoqi@0 | 2204 | BLOCK_COMMENT("Increment profiling counters {"); |
aoqi@0 | 2205 | |
aoqi@0 | 2206 | // Load the backedge counter. |
aoqi@0 | 2207 | lwz(backedge_count, be_counter_offset, Rcounters); // is unsigned int |
aoqi@0 | 2208 | // Mask the backedge counter. |
aoqi@0 | 2209 | Register tmp = invocation_count; |
aoqi@0 | 2210 | li(tmp, InvocationCounter::count_mask_value); |
aoqi@0 | 2211 | andr(backedge_count, tmp, backedge_count); // Cannot use andi, need sign extension of count_mask_value. |
aoqi@0 | 2212 | |
aoqi@0 | 2213 | // Load the invocation counter. |
aoqi@0 | 2214 | lwz(invocation_count, inv_counter_offset, Rcounters); // is unsigned int |
aoqi@0 | 2215 | // Add the delta to the invocation counter and store the result. |
aoqi@0 | 2216 | addi(invocation_count, invocation_count, delta); |
aoqi@0 | 2217 | // Store value. |
aoqi@0 | 2218 | stw(invocation_count, inv_counter_offset, Rcounters); |
aoqi@0 | 2219 | |
aoqi@0 | 2220 | // Add invocation counter + backedge counter. |
aoqi@0 | 2221 | add(iv_be_count, backedge_count, invocation_count); |
aoqi@0 | 2222 | |
aoqi@0 | 2223 | // Note that this macro must leave the backedge_count + invocation_count in |
aoqi@0 | 2224 | // register iv_be_count! |
aoqi@0 | 2225 | BLOCK_COMMENT("} Increment profiling counters"); |
aoqi@0 | 2226 | } |
aoqi@0 | 2227 | |
aoqi@0 | 2228 | void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { |
aoqi@0 | 2229 | if (state == atos) { MacroAssembler::verify_oop(reg); } |
aoqi@0 | 2230 | } |
aoqi@0 | 2231 | |
aoqi@0 | 2232 | #ifndef CC_INTERP |
aoqi@0 | 2233 | // Local helper function for the verify_oop_or_return_address macro. |
aoqi@0 | 2234 | static bool verify_return_address(Method* m, int bci) { |
aoqi@0 | 2235 | #ifndef PRODUCT |
aoqi@0 | 2236 | address pc = (address)(m->constMethod()) + in_bytes(ConstMethod::codes_offset()) + bci; |
aoqi@0 | 2237 | // Assume it is a valid return address if it is inside m and is preceded by a jsr. |
aoqi@0 | 2238 | if (!m->contains(pc)) return false; |
aoqi@0 | 2239 | address jsr_pc; |
aoqi@0 | 2240 | jsr_pc = pc - Bytecodes::length_for(Bytecodes::_jsr); |
aoqi@0 | 2241 | if (*jsr_pc == Bytecodes::_jsr && jsr_pc >= m->code_base()) return true; |
aoqi@0 | 2242 | jsr_pc = pc - Bytecodes::length_for(Bytecodes::_jsr_w); |
aoqi@0 | 2243 | if (*jsr_pc == Bytecodes::_jsr_w && jsr_pc >= m->code_base()) return true; |
aoqi@0 | 2244 | #endif // PRODUCT |
aoqi@0 | 2245 | return false; |
aoqi@0 | 2246 | } |
aoqi@0 | 2247 | |
aoqi@0 | 2248 | void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { |
aoqi@0 | 2249 | if (VerifyFPU) { |
aoqi@0 | 2250 | unimplemented("verfiyFPU"); |
aoqi@0 | 2251 | } |
aoqi@0 | 2252 | } |
aoqi@0 | 2253 | |
aoqi@0 | 2254 | void InterpreterMacroAssembler::verify_oop_or_return_address(Register reg, Register Rtmp) { |
aoqi@0 | 2255 | if (!VerifyOops) return; |
aoqi@0 | 2256 | |
aoqi@0 | 2257 | // The VM documentation for the astore[_wide] bytecode allows |
aoqi@0 | 2258 | // the TOS to be not only an oop but also a return address. |
aoqi@0 | 2259 | Label test; |
aoqi@0 | 2260 | Label skip; |
aoqi@0 | 2261 | // See if it is an address (in the current method): |
aoqi@0 | 2262 | |
aoqi@0 | 2263 | const int log2_bytecode_size_limit = 16; |
aoqi@0 | 2264 | srdi_(Rtmp, reg, log2_bytecode_size_limit); |
aoqi@0 | 2265 | bne(CCR0, test); |
aoqi@0 | 2266 | |
aoqi@0 | 2267 | address fd = CAST_FROM_FN_PTR(address, verify_return_address); |
goetz@7424 | 2268 | const int nbytes_save = 11*8; // volatile gprs except R0 |
goetz@7424 | 2269 | save_volatile_gprs(R1_SP, -nbytes_save); // except R0 |
goetz@7424 | 2270 | save_LR_CR(Rtmp); // Save in old frame. |
aoqi@0 | 2271 | push_frame_reg_args(nbytes_save, Rtmp); |
aoqi@0 | 2272 | |
aoqi@0 | 2273 | load_const_optimized(Rtmp, fd, R0); |
aoqi@0 | 2274 | mr_if_needed(R4_ARG2, reg); |
aoqi@0 | 2275 | mr(R3_ARG1, R19_method); |
aoqi@0 | 2276 | call_c(Rtmp); // call C |
aoqi@0 | 2277 | |
aoqi@0 | 2278 | pop_frame(); |
aoqi@0 | 2279 | restore_LR_CR(Rtmp); |
goetz@7424 | 2280 | restore_volatile_gprs(R1_SP, -nbytes_save); // except R0 |
aoqi@0 | 2281 | b(skip); |
aoqi@0 | 2282 | |
aoqi@0 | 2283 | // Perform a more elaborate out-of-line call. |
aoqi@0 | 2284 | // Not an address; verify it: |
aoqi@0 | 2285 | bind(test); |
aoqi@0 | 2286 | verify_oop(reg); |
aoqi@0 | 2287 | bind(skip); |
aoqi@0 | 2288 | } |
aoqi@0 | 2289 | #endif // !CC_INTERP |
aoqi@0 | 2290 | |
aoqi@0 | 2291 | // Inline assembly for: |
aoqi@0 | 2292 | // |
aoqi@0 | 2293 | // if (thread is in interp_only_mode) { |
aoqi@0 | 2294 | // InterpreterRuntime::post_method_entry(); |
aoqi@0 | 2295 | // } |
aoqi@0 | 2296 | // if (*jvmpi::event_flags_array_at_addr(JVMPI_EVENT_METHOD_ENTRY ) || |
aoqi@0 | 2297 | // *jvmpi::event_flags_array_at_addr(JVMPI_EVENT_METHOD_ENTRY2) ) { |
aoqi@0 | 2298 | // SharedRuntime::jvmpi_method_entry(method, receiver); |
aoqi@0 | 2299 | // } |
aoqi@0 | 2300 | void InterpreterMacroAssembler::notify_method_entry() { |
aoqi@0 | 2301 | // JVMTI |
aoqi@0 | 2302 | // Whenever JVMTI puts a thread in interp_only_mode, method |
aoqi@0 | 2303 | // entry/exit events are sent for that thread to track stack |
aoqi@0 | 2304 | // depth. If it is possible to enter interp_only_mode we add |
aoqi@0 | 2305 | // the code to check if the event should be sent. |
aoqi@0 | 2306 | if (JvmtiExport::can_post_interpreter_events()) { |
aoqi@0 | 2307 | Label jvmti_post_done; |
aoqi@0 | 2308 | |
aoqi@0 | 2309 | lwz(R0, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread); |
aoqi@0 | 2310 | cmpwi(CCR0, R0, 0); |
aoqi@0 | 2311 | beq(CCR0, jvmti_post_done); |
aoqi@0 | 2312 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_entry), |
aoqi@0 | 2313 | /*check_exceptions=*/true CC_INTERP_ONLY(&& false)); |
aoqi@0 | 2314 | |
aoqi@0 | 2315 | bind(jvmti_post_done); |
aoqi@0 | 2316 | } |
aoqi@0 | 2317 | } |
aoqi@0 | 2318 | |
aoqi@0 | 2319 | // Inline assembly for: |
aoqi@0 | 2320 | // |
aoqi@0 | 2321 | // if (thread is in interp_only_mode) { |
aoqi@0 | 2322 | // // save result |
aoqi@0 | 2323 | // InterpreterRuntime::post_method_exit(); |
aoqi@0 | 2324 | // // restore result |
aoqi@0 | 2325 | // } |
aoqi@0 | 2326 | // if (*jvmpi::event_flags_array_at_addr(JVMPI_EVENT_METHOD_EXIT)) { |
aoqi@0 | 2327 | // // save result |
aoqi@0 | 2328 | // SharedRuntime::jvmpi_method_exit(); |
aoqi@0 | 2329 | // // restore result |
aoqi@0 | 2330 | // } |
aoqi@0 | 2331 | // |
aoqi@0 | 2332 | // Native methods have their result stored in d_tmp and l_tmp. |
aoqi@0 | 2333 | // Java methods have their result stored in the expression stack. |
aoqi@0 | 2334 | void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, TosState state, |
aoqi@0 | 2335 | NotifyMethodExitMode mode, bool check_exceptions) { |
aoqi@0 | 2336 | // JVMTI |
aoqi@0 | 2337 | // Whenever JVMTI puts a thread in interp_only_mode, method |
aoqi@0 | 2338 | // entry/exit events are sent for that thread to track stack |
aoqi@0 | 2339 | // depth. If it is possible to enter interp_only_mode we add |
aoqi@0 | 2340 | // the code to check if the event should be sent. |
aoqi@0 | 2341 | if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { |
aoqi@0 | 2342 | Label jvmti_post_done; |
aoqi@0 | 2343 | |
aoqi@0 | 2344 | lwz(R0, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread); |
aoqi@0 | 2345 | cmpwi(CCR0, R0, 0); |
aoqi@0 | 2346 | beq(CCR0, jvmti_post_done); |
aoqi@0 | 2347 | CC_INTERP_ONLY(assert(is_native_method && !check_exceptions, "must not push state")); |
aoqi@0 | 2348 | if (!is_native_method) push(state); // Expose tos to GC. |
aoqi@0 | 2349 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit), |
aoqi@0 | 2350 | /*check_exceptions=*/check_exceptions); |
aoqi@0 | 2351 | if (!is_native_method) pop(state); |
aoqi@0 | 2352 | |
aoqi@0 | 2353 | align(32, 12); |
aoqi@0 | 2354 | bind(jvmti_post_done); |
aoqi@0 | 2355 | } |
aoqi@0 | 2356 | |
aoqi@0 | 2357 | // Dtrace support not implemented. |
aoqi@0 | 2358 | } |
aoqi@0 | 2359 | |
aoqi@0 | 2360 | #ifdef CC_INTERP |
aoqi@0 | 2361 | // Convert the current TOP_IJAVA_FRAME into a PARENT_IJAVA_FRAME |
aoqi@0 | 2362 | // (using parent_frame_resize) and push a new interpreter |
aoqi@0 | 2363 | // TOP_IJAVA_FRAME (using frame_size). |
aoqi@0 | 2364 | void InterpreterMacroAssembler::push_interpreter_frame(Register top_frame_size, Register parent_frame_resize, |
aoqi@0 | 2365 | Register tmp1, Register tmp2, Register tmp3, |
aoqi@0 | 2366 | Register tmp4, Register pc) { |
aoqi@0 | 2367 | assert_different_registers(top_frame_size, parent_frame_resize, tmp1, tmp2, tmp3, tmp4); |
aoqi@0 | 2368 | ld(tmp1, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
aoqi@0 | 2369 | mr(tmp2/*top_frame_sp*/, R1_SP); |
aoqi@0 | 2370 | // Move initial_caller_sp. |
aoqi@0 | 2371 | ld(tmp4, _top_ijava_frame_abi(initial_caller_sp), R1_SP); |
aoqi@0 | 2372 | neg(parent_frame_resize, parent_frame_resize); |
aoqi@0 | 2373 | resize_frame(parent_frame_resize/*-parent_frame_resize*/, tmp3); |
aoqi@0 | 2374 | |
aoqi@0 | 2375 | // Set LR in new parent frame. |
aoqi@0 | 2376 | std(tmp1, _abi(lr), R1_SP); |
aoqi@0 | 2377 | // Set top_frame_sp info for new parent frame. |
aoqi@0 | 2378 | std(tmp2, _parent_ijava_frame_abi(top_frame_sp), R1_SP); |
aoqi@0 | 2379 | std(tmp4, _parent_ijava_frame_abi(initial_caller_sp), R1_SP); |
aoqi@0 | 2380 | |
aoqi@0 | 2381 | // Push new TOP_IJAVA_FRAME. |
aoqi@0 | 2382 | push_frame(top_frame_size, tmp2); |
aoqi@0 | 2383 | |
aoqi@0 | 2384 | get_PC_trash_LR(tmp3); |
aoqi@0 | 2385 | std(tmp3, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
aoqi@0 | 2386 | // Used for non-initial callers by unextended_sp(). |
aoqi@0 | 2387 | std(R1_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); |
aoqi@0 | 2388 | } |
aoqi@0 | 2389 | |
aoqi@0 | 2390 | // Pop the topmost TOP_IJAVA_FRAME and convert the previous |
aoqi@0 | 2391 | // PARENT_IJAVA_FRAME back into a TOP_IJAVA_FRAME. |
aoqi@0 | 2392 | void InterpreterMacroAssembler::pop_interpreter_frame(Register tmp1, Register tmp2, Register tmp3, Register tmp4) { |
aoqi@0 | 2393 | assert_different_registers(tmp1, tmp2, tmp3, tmp4); |
aoqi@0 | 2394 | |
aoqi@0 | 2395 | ld(tmp1/*caller's sp*/, _abi(callers_sp), R1_SP); |
aoqi@0 | 2396 | ld(tmp3, _abi(lr), tmp1); |
aoqi@0 | 2397 | |
aoqi@0 | 2398 | ld(tmp4, _parent_ijava_frame_abi(initial_caller_sp), tmp1); |
aoqi@0 | 2399 | |
aoqi@0 | 2400 | ld(tmp2/*caller's caller's sp*/, _abi(callers_sp), tmp1); |
aoqi@0 | 2401 | // Merge top frame. |
aoqi@0 | 2402 | std(tmp2, _abi(callers_sp), R1_SP); |
aoqi@0 | 2403 | |
aoqi@0 | 2404 | ld(tmp2, _parent_ijava_frame_abi(top_frame_sp), tmp1); |
aoqi@0 | 2405 | |
aoqi@0 | 2406 | // Update C stack pointer to caller's top_abi. |
aoqi@0 | 2407 | resize_frame_absolute(tmp2/*addr*/, tmp1/*tmp*/, tmp2/*tmp*/); |
aoqi@0 | 2408 | |
aoqi@0 | 2409 | // Update LR in top_frame. |
aoqi@0 | 2410 | std(tmp3, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
aoqi@0 | 2411 | |
aoqi@0 | 2412 | std(tmp4, _top_ijava_frame_abi(initial_caller_sp), R1_SP); |
aoqi@0 | 2413 | |
aoqi@0 | 2414 | // Store the top-frame stack-pointer for c2i adapters. |
aoqi@0 | 2415 | std(R1_SP, _top_ijava_frame_abi(top_frame_sp), R1_SP); |
aoqi@0 | 2416 | } |
aoqi@0 | 2417 | |
aoqi@0 | 2418 | // Turn state's interpreter frame into the current TOP_IJAVA_FRAME. |
aoqi@0 | 2419 | void InterpreterMacroAssembler::pop_interpreter_frame_to_state(Register state, Register tmp1, Register tmp2, Register tmp3) { |
aoqi@0 | 2420 | assert_different_registers(R14_state, R15_prev_state, tmp1, tmp2, tmp3); |
aoqi@0 | 2421 | |
aoqi@0 | 2422 | if (state == R14_state) { |
aoqi@0 | 2423 | ld(tmp1/*state's fp*/, state_(_last_Java_fp)); |
aoqi@0 | 2424 | ld(tmp2/*state's sp*/, state_(_last_Java_sp)); |
aoqi@0 | 2425 | } else if (state == R15_prev_state) { |
aoqi@0 | 2426 | ld(tmp1/*state's fp*/, prev_state_(_last_Java_fp)); |
aoqi@0 | 2427 | ld(tmp2/*state's sp*/, prev_state_(_last_Java_sp)); |
aoqi@0 | 2428 | } else { |
aoqi@0 | 2429 | ShouldNotReachHere(); |
aoqi@0 | 2430 | } |
aoqi@0 | 2431 | |
aoqi@0 | 2432 | // Merge top frames. |
aoqi@0 | 2433 | std(tmp1, _abi(callers_sp), R1_SP); |
aoqi@0 | 2434 | |
aoqi@0 | 2435 | // Tmp2 is new SP. |
aoqi@0 | 2436 | // Tmp1 is parent's SP. |
aoqi@0 | 2437 | resize_frame_absolute(tmp2/*addr*/, tmp1/*tmp*/, tmp2/*tmp*/); |
aoqi@0 | 2438 | |
aoqi@0 | 2439 | // Update LR in top_frame. |
aoqi@0 | 2440 | // Must be interpreter frame. |
aoqi@0 | 2441 | get_PC_trash_LR(tmp3); |
aoqi@0 | 2442 | std(tmp3, _top_ijava_frame_abi(frame_manager_lr), R1_SP); |
aoqi@0 | 2443 | // Used for non-initial callers by unextended_sp(). |
aoqi@0 | 2444 | std(R1_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); |
aoqi@0 | 2445 | } |
aoqi@0 | 2446 | |
aoqi@0 | 2447 | // Set SP to initial caller's sp, but before fix the back chain. |
aoqi@0 | 2448 | void InterpreterMacroAssembler::resize_frame_to_initial_caller(Register tmp1, Register tmp2) { |
aoqi@0 | 2449 | ld(tmp1, _parent_ijava_frame_abi(initial_caller_sp), R1_SP); |
aoqi@0 | 2450 | ld(tmp2, _parent_ijava_frame_abi(callers_sp), R1_SP); |
aoqi@0 | 2451 | std(tmp2, _parent_ijava_frame_abi(callers_sp), tmp1); // Fix back chain ... |
aoqi@0 | 2452 | mr(R1_SP, tmp1); // ... and resize to initial caller. |
aoqi@0 | 2453 | } |
aoqi@0 | 2454 | |
aoqi@0 | 2455 | // Pop the current interpreter state (without popping the correspoding |
aoqi@0 | 2456 | // frame) and restore R14_state and R15_prev_state accordingly. |
aoqi@0 | 2457 | // Use prev_state_may_be_0 to indicate whether prev_state may be 0 |
aoqi@0 | 2458 | // in order to generate an extra check before retrieving prev_state_(_prev_link). |
aoqi@0 | 2459 | void InterpreterMacroAssembler::pop_interpreter_state(bool prev_state_may_be_0) |
aoqi@0 | 2460 | { |
aoqi@0 | 2461 | // Move prev_state to state and restore prev_state from state_(_prev_link). |
aoqi@0 | 2462 | Label prev_state_is_0; |
aoqi@0 | 2463 | mr(R14_state, R15_prev_state); |
aoqi@0 | 2464 | |
aoqi@0 | 2465 | // Don't retrieve /*state==*/prev_state_(_prev_link) |
aoqi@0 | 2466 | // if /*state==*/prev_state is 0. |
aoqi@0 | 2467 | if (prev_state_may_be_0) { |
aoqi@0 | 2468 | cmpdi(CCR0, R15_prev_state, 0); |
aoqi@0 | 2469 | beq(CCR0, prev_state_is_0); |
aoqi@0 | 2470 | } |
aoqi@0 | 2471 | |
aoqi@0 | 2472 | ld(R15_prev_state, /*state==*/prev_state_(_prev_link)); |
aoqi@0 | 2473 | bind(prev_state_is_0); |
aoqi@0 | 2474 | } |
aoqi@0 | 2475 | |
aoqi@0 | 2476 | void InterpreterMacroAssembler::restore_prev_state() { |
aoqi@0 | 2477 | // _prev_link is private, but cInterpreter is a friend. |
aoqi@0 | 2478 | ld(R15_prev_state, state_(_prev_link)); |
aoqi@0 | 2479 | } |
aoqi@0 | 2480 | #endif // CC_INTERP |