Wed, 08 Apr 2009 10:56:49 -0700
6655638: dynamic languages need method handles
Summary: initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.)
Reviewed-by: kvn, twisti, never
duke@435 | 1 | /* |
xdono@631 | 2 | * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | #include "incls/_precompiled.incl" |
duke@435 | 26 | #include "incls/_interp_masm_sparc.cpp.incl" |
duke@435 | 27 | |
duke@435 | 28 | #ifndef CC_INTERP |
duke@435 | 29 | #ifndef FAST_DISPATCH |
duke@435 | 30 | #define FAST_DISPATCH 1 |
duke@435 | 31 | #endif |
duke@435 | 32 | #undef FAST_DISPATCH |
duke@435 | 33 | |
duke@435 | 34 | // Implementation of InterpreterMacroAssembler |
duke@435 | 35 | |
duke@435 | 36 | // This file specializes the assember with interpreter-specific macros |
duke@435 | 37 | |
duke@435 | 38 | const Address InterpreterMacroAssembler::l_tmp( FP, 0, (frame::interpreter_frame_l_scratch_fp_offset * wordSize ) + STACK_BIAS); |
duke@435 | 39 | const Address InterpreterMacroAssembler::d_tmp( FP, 0, (frame::interpreter_frame_d_scratch_fp_offset * wordSize) + STACK_BIAS); |
duke@435 | 40 | |
duke@435 | 41 | #else // CC_INTERP |
duke@435 | 42 | #ifndef STATE |
duke@435 | 43 | #define STATE(field_name) Lstate, in_bytes(byte_offset_of(BytecodeInterpreter, field_name)) |
duke@435 | 44 | #endif // STATE |
duke@435 | 45 | |
duke@435 | 46 | #endif // CC_INTERP |
duke@435 | 47 | |
duke@435 | 48 | void InterpreterMacroAssembler::compute_extra_locals_size_in_bytes(Register args_size, Register locals_size, Register delta) { |
duke@435 | 49 | // Note: this algorithm is also used by C1's OSR entry sequence. |
duke@435 | 50 | // Any changes should also be applied to CodeEmitter::emit_osr_entry(). |
duke@435 | 51 | assert_different_registers(args_size, locals_size); |
duke@435 | 52 | // max_locals*2 for TAGS. Assumes that args_size has already been adjusted. |
duke@435 | 53 | if (TaggedStackInterpreter) sll(locals_size, 1, locals_size); |
duke@435 | 54 | subcc(locals_size, args_size, delta);// extra space for non-arguments locals in words |
duke@435 | 55 | // Use br/mov combination because it works on both V8 and V9 and is |
duke@435 | 56 | // faster. |
duke@435 | 57 | Label skip_move; |
duke@435 | 58 | br(Assembler::negative, true, Assembler::pt, skip_move); |
duke@435 | 59 | delayed()->mov(G0, delta); |
duke@435 | 60 | bind(skip_move); |
duke@435 | 61 | round_to(delta, WordsPerLong); // make multiple of 2 (SP must be 2-word aligned) |
duke@435 | 62 | sll(delta, LogBytesPerWord, delta); // extra space for locals in bytes |
duke@435 | 63 | } |
duke@435 | 64 | |
duke@435 | 65 | #ifndef CC_INTERP |
duke@435 | 66 | |
duke@435 | 67 | // Dispatch code executed in the prolog of a bytecode which does not do it's |
duke@435 | 68 | // own dispatch. The dispatch address is computed and placed in IdispatchAddress |
duke@435 | 69 | void InterpreterMacroAssembler::dispatch_prolog(TosState state, int bcp_incr) { |
duke@435 | 70 | assert_not_delayed(); |
duke@435 | 71 | #ifdef FAST_DISPATCH |
duke@435 | 72 | // FAST_DISPATCH and ProfileInterpreter are mutually exclusive since |
duke@435 | 73 | // they both use I2. |
duke@435 | 74 | assert(!ProfileInterpreter, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive"); |
duke@435 | 75 | ldub(Lbcp, bcp_incr, Lbyte_code); // load next bytecode |
duke@435 | 76 | add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); |
duke@435 | 77 | // add offset to correct dispatch table |
duke@435 | 78 | sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize |
duke@435 | 79 | ld_ptr(IdispatchTables, Lbyte_code, IdispatchAddress);// get entry addr |
duke@435 | 80 | #else |
duke@435 | 81 | ldub( Lbcp, bcp_incr, Lbyte_code); // load next bytecode |
duke@435 | 82 | // dispatch table to use |
duke@435 | 83 | Address tbl(G3_scratch, (address)Interpreter::dispatch_table(state)); |
duke@435 | 84 | |
duke@435 | 85 | sethi(tbl); |
duke@435 | 86 | sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize |
duke@435 | 87 | add(tbl, tbl.base(), 0); |
duke@435 | 88 | ld_ptr( G3_scratch, Lbyte_code, IdispatchAddress); // get entry addr |
duke@435 | 89 | #endif |
duke@435 | 90 | } |
duke@435 | 91 | |
duke@435 | 92 | |
duke@435 | 93 | // Dispatch code executed in the epilog of a bytecode which does not do it's |
duke@435 | 94 | // own dispatch. The dispatch address in IdispatchAddress is used for the |
duke@435 | 95 | // dispatch. |
duke@435 | 96 | void InterpreterMacroAssembler::dispatch_epilog(TosState state, int bcp_incr) { |
duke@435 | 97 | assert_not_delayed(); |
duke@435 | 98 | verify_FPU(1, state); |
duke@435 | 99 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 100 | jmp( IdispatchAddress, 0 ); |
duke@435 | 101 | if (bcp_incr != 0) delayed()->inc(Lbcp, bcp_incr); |
duke@435 | 102 | else delayed()->nop(); |
duke@435 | 103 | } |
duke@435 | 104 | |
duke@435 | 105 | |
duke@435 | 106 | void InterpreterMacroAssembler::dispatch_next(TosState state, int bcp_incr) { |
duke@435 | 107 | // %%%% consider branching to a single shared dispatch stub (for each bcp_incr) |
duke@435 | 108 | assert_not_delayed(); |
duke@435 | 109 | ldub( Lbcp, bcp_incr, Lbyte_code); // load next bytecode |
duke@435 | 110 | dispatch_Lbyte_code(state, Interpreter::dispatch_table(state), bcp_incr); |
duke@435 | 111 | } |
duke@435 | 112 | |
duke@435 | 113 | |
duke@435 | 114 | void InterpreterMacroAssembler::dispatch_next_noverify_oop(TosState state, int bcp_incr) { |
duke@435 | 115 | // %%%% consider branching to a single shared dispatch stub (for each bcp_incr) |
duke@435 | 116 | assert_not_delayed(); |
duke@435 | 117 | ldub( Lbcp, bcp_incr, Lbyte_code); // load next bytecode |
duke@435 | 118 | dispatch_Lbyte_code(state, Interpreter::dispatch_table(state), bcp_incr, false); |
duke@435 | 119 | } |
duke@435 | 120 | |
duke@435 | 121 | |
duke@435 | 122 | void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { |
duke@435 | 123 | // load current bytecode |
duke@435 | 124 | assert_not_delayed(); |
duke@435 | 125 | ldub( Lbcp, 0, Lbyte_code); // load next bytecode |
duke@435 | 126 | dispatch_base(state, table); |
duke@435 | 127 | } |
duke@435 | 128 | |
duke@435 | 129 | |
duke@435 | 130 | void InterpreterMacroAssembler::call_VM_leaf_base( |
duke@435 | 131 | Register java_thread, |
duke@435 | 132 | address entry_point, |
duke@435 | 133 | int number_of_arguments |
duke@435 | 134 | ) { |
duke@435 | 135 | if (!java_thread->is_valid()) |
duke@435 | 136 | java_thread = L7_thread_cache; |
duke@435 | 137 | // super call |
duke@435 | 138 | MacroAssembler::call_VM_leaf_base(java_thread, entry_point, number_of_arguments); |
duke@435 | 139 | } |
duke@435 | 140 | |
duke@435 | 141 | |
duke@435 | 142 | void InterpreterMacroAssembler::call_VM_base( |
duke@435 | 143 | Register oop_result, |
duke@435 | 144 | Register java_thread, |
duke@435 | 145 | Register last_java_sp, |
duke@435 | 146 | address entry_point, |
duke@435 | 147 | int number_of_arguments, |
duke@435 | 148 | bool check_exception |
duke@435 | 149 | ) { |
duke@435 | 150 | if (!java_thread->is_valid()) |
duke@435 | 151 | java_thread = L7_thread_cache; |
duke@435 | 152 | // See class ThreadInVMfromInterpreter, which assumes that the interpreter |
duke@435 | 153 | // takes responsibility for setting its own thread-state on call-out. |
duke@435 | 154 | // However, ThreadInVMfromInterpreter resets the state to "in_Java". |
duke@435 | 155 | |
duke@435 | 156 | //save_bcp(); // save bcp |
duke@435 | 157 | MacroAssembler::call_VM_base(oop_result, java_thread, last_java_sp, entry_point, number_of_arguments, check_exception); |
duke@435 | 158 | //restore_bcp(); // restore bcp |
duke@435 | 159 | //restore_locals(); // restore locals pointer |
duke@435 | 160 | } |
duke@435 | 161 | |
duke@435 | 162 | |
duke@435 | 163 | void InterpreterMacroAssembler::check_and_handle_popframe(Register scratch_reg) { |
duke@435 | 164 | if (JvmtiExport::can_pop_frame()) { |
duke@435 | 165 | Label L; |
duke@435 | 166 | |
duke@435 | 167 | // Check the "pending popframe condition" flag in the current thread |
duke@435 | 168 | Address popframe_condition_addr(G2_thread, 0, in_bytes(JavaThread::popframe_condition_offset())); |
duke@435 | 169 | ld(popframe_condition_addr, scratch_reg); |
duke@435 | 170 | |
duke@435 | 171 | // Initiate popframe handling only if it is not already being processed. If the flag |
duke@435 | 172 | // has the popframe_processing bit set, it means that this code is called *during* popframe |
duke@435 | 173 | // handling - we don't want to reenter. |
duke@435 | 174 | btst(JavaThread::popframe_pending_bit, scratch_reg); |
duke@435 | 175 | br(zero, false, pt, L); |
duke@435 | 176 | delayed()->nop(); |
duke@435 | 177 | btst(JavaThread::popframe_processing_bit, scratch_reg); |
duke@435 | 178 | br(notZero, false, pt, L); |
duke@435 | 179 | delayed()->nop(); |
duke@435 | 180 | |
duke@435 | 181 | // Call Interpreter::remove_activation_preserving_args_entry() to get the |
duke@435 | 182 | // address of the same-named entrypoint in the generated interpreter code. |
duke@435 | 183 | call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); |
duke@435 | 184 | |
duke@435 | 185 | // Jump to Interpreter::_remove_activation_preserving_args_entry |
duke@435 | 186 | jmpl(O0, G0, G0); |
duke@435 | 187 | delayed()->nop(); |
duke@435 | 188 | bind(L); |
duke@435 | 189 | } |
duke@435 | 190 | } |
duke@435 | 191 | |
duke@435 | 192 | |
duke@435 | 193 | void InterpreterMacroAssembler::load_earlyret_value(TosState state) { |
duke@435 | 194 | Register thr_state = G4_scratch; |
duke@435 | 195 | ld_ptr(Address(G2_thread, 0, in_bytes(JavaThread::jvmti_thread_state_offset())), |
duke@435 | 196 | thr_state); |
duke@435 | 197 | const Address tos_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_tos_offset())); |
duke@435 | 198 | const Address oop_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_oop_offset())); |
duke@435 | 199 | const Address val_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_value_offset())); |
duke@435 | 200 | switch (state) { |
duke@435 | 201 | case ltos: ld_long(val_addr, Otos_l); break; |
duke@435 | 202 | case atos: ld_ptr(oop_addr, Otos_l); |
duke@435 | 203 | st_ptr(G0, oop_addr); break; |
duke@435 | 204 | case btos: // fall through |
duke@435 | 205 | case ctos: // fall through |
duke@435 | 206 | case stos: // fall through |
duke@435 | 207 | case itos: ld(val_addr, Otos_l1); break; |
duke@435 | 208 | case ftos: ldf(FloatRegisterImpl::S, val_addr, Ftos_f); break; |
duke@435 | 209 | case dtos: ldf(FloatRegisterImpl::D, val_addr, Ftos_d); break; |
duke@435 | 210 | case vtos: /* nothing to do */ break; |
duke@435 | 211 | default : ShouldNotReachHere(); |
duke@435 | 212 | } |
duke@435 | 213 | // Clean up tos value in the jvmti thread state |
duke@435 | 214 | or3(G0, ilgl, G3_scratch); |
duke@435 | 215 | stw(G3_scratch, tos_addr); |
duke@435 | 216 | st_long(G0, val_addr); |
duke@435 | 217 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 218 | } |
duke@435 | 219 | |
duke@435 | 220 | |
duke@435 | 221 | void InterpreterMacroAssembler::check_and_handle_earlyret(Register scratch_reg) { |
duke@435 | 222 | if (JvmtiExport::can_force_early_return()) { |
duke@435 | 223 | Label L; |
duke@435 | 224 | Register thr_state = G3_scratch; |
duke@435 | 225 | ld_ptr(Address(G2_thread, 0, in_bytes(JavaThread::jvmti_thread_state_offset())), |
duke@435 | 226 | thr_state); |
duke@435 | 227 | tst(thr_state); |
duke@435 | 228 | br(zero, false, pt, L); // if (thread->jvmti_thread_state() == NULL) exit; |
duke@435 | 229 | delayed()->nop(); |
duke@435 | 230 | |
duke@435 | 231 | // Initiate earlyret handling only if it is not already being processed. |
duke@435 | 232 | // If the flag has the earlyret_processing bit set, it means that this code |
duke@435 | 233 | // is called *during* earlyret handling - we don't want to reenter. |
duke@435 | 234 | ld(Address(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_state_offset())), |
duke@435 | 235 | G4_scratch); |
duke@435 | 236 | cmp(G4_scratch, JvmtiThreadState::earlyret_pending); |
duke@435 | 237 | br(Assembler::notEqual, false, pt, L); |
duke@435 | 238 | delayed()->nop(); |
duke@435 | 239 | |
duke@435 | 240 | // Call Interpreter::remove_activation_early_entry() to get the address of the |
duke@435 | 241 | // same-named entrypoint in the generated interpreter code |
duke@435 | 242 | Address tos_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_tos_offset())); |
duke@435 | 243 | ld(tos_addr, Otos_l1); |
duke@435 | 244 | call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), Otos_l1); |
duke@435 | 245 | |
duke@435 | 246 | // Jump to Interpreter::_remove_activation_early_entry |
duke@435 | 247 | jmpl(O0, G0, G0); |
duke@435 | 248 | delayed()->nop(); |
duke@435 | 249 | bind(L); |
duke@435 | 250 | } |
duke@435 | 251 | } |
duke@435 | 252 | |
duke@435 | 253 | |
duke@435 | 254 | void InterpreterMacroAssembler::super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1) { |
duke@435 | 255 | mov(arg_1, O0); |
duke@435 | 256 | MacroAssembler::call_VM_leaf_base(thread_cache, entry_point, 1); |
duke@435 | 257 | } |
duke@435 | 258 | #endif /* CC_INTERP */ |
duke@435 | 259 | |
duke@435 | 260 | |
duke@435 | 261 | #ifndef CC_INTERP |
duke@435 | 262 | |
duke@435 | 263 | void InterpreterMacroAssembler::dispatch_base(TosState state, address* table) { |
duke@435 | 264 | assert_not_delayed(); |
duke@435 | 265 | dispatch_Lbyte_code(state, table); |
duke@435 | 266 | } |
duke@435 | 267 | |
duke@435 | 268 | |
duke@435 | 269 | void InterpreterMacroAssembler::dispatch_normal(TosState state) { |
duke@435 | 270 | dispatch_base(state, Interpreter::normal_table(state)); |
duke@435 | 271 | } |
duke@435 | 272 | |
duke@435 | 273 | |
duke@435 | 274 | void InterpreterMacroAssembler::dispatch_only(TosState state) { |
duke@435 | 275 | dispatch_base(state, Interpreter::dispatch_table(state)); |
duke@435 | 276 | } |
duke@435 | 277 | |
duke@435 | 278 | |
duke@435 | 279 | // common code to dispatch and dispatch_only |
duke@435 | 280 | // dispatch value in Lbyte_code and increment Lbcp |
duke@435 | 281 | |
duke@435 | 282 | void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, address* table, int bcp_incr, bool verify) { |
duke@435 | 283 | verify_FPU(1, state); |
duke@435 | 284 | // %%%%% maybe implement +VerifyActivationFrameSize here |
duke@435 | 285 | //verify_thread(); //too slow; we will just verify on method entry & exit |
duke@435 | 286 | if (verify) interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 287 | #ifdef FAST_DISPATCH |
duke@435 | 288 | if (table == Interpreter::dispatch_table(state)) { |
duke@435 | 289 | // use IdispatchTables |
duke@435 | 290 | add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); |
duke@435 | 291 | // add offset to correct dispatch table |
duke@435 | 292 | sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize |
duke@435 | 293 | ld_ptr(IdispatchTables, Lbyte_code, G3_scratch); // get entry addr |
duke@435 | 294 | } else { |
duke@435 | 295 | #endif |
duke@435 | 296 | // dispatch table to use |
duke@435 | 297 | Address tbl(G3_scratch, (address)table); |
duke@435 | 298 | |
duke@435 | 299 | sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize |
duke@435 | 300 | load_address(tbl); // compute addr of table |
duke@435 | 301 | ld_ptr(G3_scratch, Lbyte_code, G3_scratch); // get entry addr |
duke@435 | 302 | #ifdef FAST_DISPATCH |
duke@435 | 303 | } |
duke@435 | 304 | #endif |
duke@435 | 305 | jmp( G3_scratch, 0 ); |
duke@435 | 306 | if (bcp_incr != 0) delayed()->inc(Lbcp, bcp_incr); |
duke@435 | 307 | else delayed()->nop(); |
duke@435 | 308 | } |
duke@435 | 309 | |
duke@435 | 310 | |
duke@435 | 311 | // Helpers for expression stack |
duke@435 | 312 | |
duke@435 | 313 | // Longs and doubles are Category 2 computational types in the |
duke@435 | 314 | // JVM specification (section 3.11.1) and take 2 expression stack or |
duke@435 | 315 | // local slots. |
duke@435 | 316 | // Aligning them on 32 bit with tagged stacks is hard because the code generated |
duke@435 | 317 | // for the dup* bytecodes depends on what types are already on the stack. |
duke@435 | 318 | // If the types are split into the two stack/local slots, that is much easier |
duke@435 | 319 | // (and we can use 0 for non-reference tags). |
duke@435 | 320 | |
duke@435 | 321 | // Known good alignment in _LP64 but unknown otherwise |
duke@435 | 322 | void InterpreterMacroAssembler::load_unaligned_double(Register r1, int offset, FloatRegister d) { |
duke@435 | 323 | assert_not_delayed(); |
duke@435 | 324 | |
duke@435 | 325 | #ifdef _LP64 |
duke@435 | 326 | ldf(FloatRegisterImpl::D, r1, offset, d); |
duke@435 | 327 | #else |
duke@435 | 328 | ldf(FloatRegisterImpl::S, r1, offset, d); |
duke@435 | 329 | ldf(FloatRegisterImpl::S, r1, offset + Interpreter::stackElementSize(), d->successor()); |
duke@435 | 330 | #endif |
duke@435 | 331 | } |
duke@435 | 332 | |
duke@435 | 333 | // Known good alignment in _LP64 but unknown otherwise |
duke@435 | 334 | void InterpreterMacroAssembler::store_unaligned_double(FloatRegister d, Register r1, int offset) { |
duke@435 | 335 | assert_not_delayed(); |
duke@435 | 336 | |
duke@435 | 337 | #ifdef _LP64 |
duke@435 | 338 | stf(FloatRegisterImpl::D, d, r1, offset); |
duke@435 | 339 | // store something more useful here |
duke@435 | 340 | debug_only(stx(G0, r1, offset+Interpreter::stackElementSize());) |
duke@435 | 341 | #else |
duke@435 | 342 | stf(FloatRegisterImpl::S, d, r1, offset); |
duke@435 | 343 | stf(FloatRegisterImpl::S, d->successor(), r1, offset + Interpreter::stackElementSize()); |
duke@435 | 344 | #endif |
duke@435 | 345 | } |
duke@435 | 346 | |
duke@435 | 347 | |
duke@435 | 348 | // Known good alignment in _LP64 but unknown otherwise |
duke@435 | 349 | void InterpreterMacroAssembler::load_unaligned_long(Register r1, int offset, Register rd) { |
duke@435 | 350 | assert_not_delayed(); |
duke@435 | 351 | #ifdef _LP64 |
duke@435 | 352 | ldx(r1, offset, rd); |
duke@435 | 353 | #else |
duke@435 | 354 | ld(r1, offset, rd); |
duke@435 | 355 | ld(r1, offset + Interpreter::stackElementSize(), rd->successor()); |
duke@435 | 356 | #endif |
duke@435 | 357 | } |
duke@435 | 358 | |
duke@435 | 359 | // Known good alignment in _LP64 but unknown otherwise |
duke@435 | 360 | void InterpreterMacroAssembler::store_unaligned_long(Register l, Register r1, int offset) { |
duke@435 | 361 | assert_not_delayed(); |
duke@435 | 362 | |
duke@435 | 363 | #ifdef _LP64 |
duke@435 | 364 | stx(l, r1, offset); |
duke@435 | 365 | // store something more useful here |
duke@435 | 366 | debug_only(stx(G0, r1, offset+Interpreter::stackElementSize());) |
duke@435 | 367 | #else |
duke@435 | 368 | st(l, r1, offset); |
duke@435 | 369 | st(l->successor(), r1, offset + Interpreter::stackElementSize()); |
duke@435 | 370 | #endif |
duke@435 | 371 | } |
duke@435 | 372 | |
duke@435 | 373 | #ifdef ASSERT |
duke@435 | 374 | void InterpreterMacroAssembler::verify_stack_tag(frame::Tag t, |
duke@435 | 375 | Register r, |
duke@435 | 376 | Register scratch) { |
duke@435 | 377 | if (TaggedStackInterpreter) { |
duke@435 | 378 | Label ok, long_ok; |
duke@435 | 379 | ld_ptr(Lesp, Interpreter::expr_tag_offset_in_bytes(0), r); |
duke@435 | 380 | if (t == frame::TagCategory2) { |
duke@435 | 381 | cmp(r, G0); |
duke@435 | 382 | brx(Assembler::equal, false, Assembler::pt, long_ok); |
duke@435 | 383 | delayed()->ld_ptr(Lesp, Interpreter::expr_tag_offset_in_bytes(1), r); |
duke@435 | 384 | stop("stack long/double tag value bad"); |
duke@435 | 385 | bind(long_ok); |
duke@435 | 386 | cmp(r, G0); |
duke@435 | 387 | } else if (t == frame::TagValue) { |
duke@435 | 388 | cmp(r, G0); |
duke@435 | 389 | } else { |
duke@435 | 390 | assert_different_registers(r, scratch); |
duke@435 | 391 | mov(t, scratch); |
duke@435 | 392 | cmp(r, scratch); |
duke@435 | 393 | } |
duke@435 | 394 | brx(Assembler::equal, false, Assembler::pt, ok); |
duke@435 | 395 | delayed()->nop(); |
duke@435 | 396 | // Also compare if the stack value is zero, then the tag might |
duke@435 | 397 | // not have been set coming from deopt. |
duke@435 | 398 | ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), r); |
duke@435 | 399 | cmp(r, G0); |
duke@435 | 400 | brx(Assembler::equal, false, Assembler::pt, ok); |
duke@435 | 401 | delayed()->nop(); |
duke@435 | 402 | stop("Stack tag value is bad"); |
duke@435 | 403 | bind(ok); |
duke@435 | 404 | } |
duke@435 | 405 | } |
duke@435 | 406 | #endif // ASSERT |
duke@435 | 407 | |
duke@435 | 408 | void InterpreterMacroAssembler::pop_i(Register r) { |
duke@435 | 409 | assert_not_delayed(); |
duke@435 | 410 | // Uses destination register r for scratch |
duke@435 | 411 | debug_only(verify_stack_tag(frame::TagValue, r)); |
duke@435 | 412 | ld(Lesp, Interpreter::expr_offset_in_bytes(0), r); |
duke@435 | 413 | inc(Lesp, Interpreter::stackElementSize()); |
duke@435 | 414 | debug_only(verify_esp(Lesp)); |
duke@435 | 415 | } |
duke@435 | 416 | |
duke@435 | 417 | void InterpreterMacroAssembler::pop_ptr(Register r, Register scratch) { |
duke@435 | 418 | assert_not_delayed(); |
duke@435 | 419 | // Uses destination register r for scratch |
duke@435 | 420 | debug_only(verify_stack_tag(frame::TagReference, r, scratch)); |
duke@435 | 421 | ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), r); |
duke@435 | 422 | inc(Lesp, Interpreter::stackElementSize()); |
duke@435 | 423 | debug_only(verify_esp(Lesp)); |
duke@435 | 424 | } |
duke@435 | 425 | |
duke@435 | 426 | void InterpreterMacroAssembler::pop_l(Register r) { |
duke@435 | 427 | assert_not_delayed(); |
duke@435 | 428 | // Uses destination register r for scratch |
duke@435 | 429 | debug_only(verify_stack_tag(frame::TagCategory2, r)); |
duke@435 | 430 | load_unaligned_long(Lesp, Interpreter::expr_offset_in_bytes(0), r); |
duke@435 | 431 | inc(Lesp, 2*Interpreter::stackElementSize()); |
duke@435 | 432 | debug_only(verify_esp(Lesp)); |
duke@435 | 433 | } |
duke@435 | 434 | |
duke@435 | 435 | |
duke@435 | 436 | void InterpreterMacroAssembler::pop_f(FloatRegister f, Register scratch) { |
duke@435 | 437 | assert_not_delayed(); |
duke@435 | 438 | debug_only(verify_stack_tag(frame::TagValue, scratch)); |
duke@435 | 439 | ldf(FloatRegisterImpl::S, Lesp, Interpreter::expr_offset_in_bytes(0), f); |
duke@435 | 440 | inc(Lesp, Interpreter::stackElementSize()); |
duke@435 | 441 | debug_only(verify_esp(Lesp)); |
duke@435 | 442 | } |
duke@435 | 443 | |
duke@435 | 444 | |
duke@435 | 445 | void InterpreterMacroAssembler::pop_d(FloatRegister f, Register scratch) { |
duke@435 | 446 | assert_not_delayed(); |
duke@435 | 447 | debug_only(verify_stack_tag(frame::TagCategory2, scratch)); |
duke@435 | 448 | load_unaligned_double(Lesp, Interpreter::expr_offset_in_bytes(0), f); |
duke@435 | 449 | inc(Lesp, 2*Interpreter::stackElementSize()); |
duke@435 | 450 | debug_only(verify_esp(Lesp)); |
duke@435 | 451 | } |
duke@435 | 452 | |
duke@435 | 453 | |
duke@435 | 454 | // (Note use register first, then decrement so dec can be done during store stall) |
duke@435 | 455 | void InterpreterMacroAssembler::tag_stack(Register r) { |
duke@435 | 456 | if (TaggedStackInterpreter) { |
duke@435 | 457 | st_ptr(r, Lesp, Interpreter::tag_offset_in_bytes()); |
duke@435 | 458 | } |
duke@435 | 459 | } |
duke@435 | 460 | |
duke@435 | 461 | void InterpreterMacroAssembler::tag_stack(frame::Tag t, Register r) { |
duke@435 | 462 | if (TaggedStackInterpreter) { |
duke@435 | 463 | assert (frame::TagValue == 0, "TagValue must be zero"); |
duke@435 | 464 | if (t == frame::TagValue) { |
duke@435 | 465 | st_ptr(G0, Lesp, Interpreter::tag_offset_in_bytes()); |
duke@435 | 466 | } else if (t == frame::TagCategory2) { |
duke@435 | 467 | st_ptr(G0, Lesp, Interpreter::tag_offset_in_bytes()); |
duke@435 | 468 | // Tag next slot down too |
duke@435 | 469 | st_ptr(G0, Lesp, -Interpreter::stackElementSize() + Interpreter::tag_offset_in_bytes()); |
duke@435 | 470 | } else { |
duke@435 | 471 | assert_different_registers(r, O3); |
duke@435 | 472 | mov(t, O3); |
duke@435 | 473 | st_ptr(O3, Lesp, Interpreter::tag_offset_in_bytes()); |
duke@435 | 474 | } |
duke@435 | 475 | } |
duke@435 | 476 | } |
duke@435 | 477 | |
duke@435 | 478 | void InterpreterMacroAssembler::push_i(Register r) { |
duke@435 | 479 | assert_not_delayed(); |
duke@435 | 480 | debug_only(verify_esp(Lesp)); |
duke@435 | 481 | tag_stack(frame::TagValue, r); |
duke@435 | 482 | st( r, Lesp, Interpreter::value_offset_in_bytes()); |
duke@435 | 483 | dec( Lesp, Interpreter::stackElementSize()); |
duke@435 | 484 | } |
duke@435 | 485 | |
duke@435 | 486 | void InterpreterMacroAssembler::push_ptr(Register r) { |
duke@435 | 487 | assert_not_delayed(); |
duke@435 | 488 | tag_stack(frame::TagReference, r); |
duke@435 | 489 | st_ptr( r, Lesp, Interpreter::value_offset_in_bytes()); |
duke@435 | 490 | dec( Lesp, Interpreter::stackElementSize()); |
duke@435 | 491 | } |
duke@435 | 492 | |
duke@435 | 493 | void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { |
duke@435 | 494 | assert_not_delayed(); |
duke@435 | 495 | tag_stack(tag); |
duke@435 | 496 | st_ptr(r, Lesp, Interpreter::value_offset_in_bytes()); |
duke@435 | 497 | dec( Lesp, Interpreter::stackElementSize()); |
duke@435 | 498 | } |
duke@435 | 499 | |
duke@435 | 500 | // remember: our convention for longs in SPARC is: |
duke@435 | 501 | // O0 (Otos_l1) has high-order part in first word, |
duke@435 | 502 | // O1 (Otos_l2) has low-order part in second word |
duke@435 | 503 | |
duke@435 | 504 | void InterpreterMacroAssembler::push_l(Register r) { |
duke@435 | 505 | assert_not_delayed(); |
duke@435 | 506 | debug_only(verify_esp(Lesp)); |
duke@435 | 507 | tag_stack(frame::TagCategory2, r); |
duke@435 | 508 | // Longs are in stored in memory-correct order, even if unaligned. |
duke@435 | 509 | // and may be separated by stack tags. |
duke@435 | 510 | int offset = -Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); |
duke@435 | 511 | store_unaligned_long(r, Lesp, offset); |
duke@435 | 512 | dec(Lesp, 2 * Interpreter::stackElementSize()); |
duke@435 | 513 | } |
duke@435 | 514 | |
duke@435 | 515 | |
duke@435 | 516 | void InterpreterMacroAssembler::push_f(FloatRegister f) { |
duke@435 | 517 | assert_not_delayed(); |
duke@435 | 518 | debug_only(verify_esp(Lesp)); |
duke@435 | 519 | tag_stack(frame::TagValue, Otos_i); |
duke@435 | 520 | stf(FloatRegisterImpl::S, f, Lesp, Interpreter::value_offset_in_bytes()); |
duke@435 | 521 | dec(Lesp, Interpreter::stackElementSize()); |
duke@435 | 522 | } |
duke@435 | 523 | |
duke@435 | 524 | |
duke@435 | 525 | void InterpreterMacroAssembler::push_d(FloatRegister d) { |
duke@435 | 526 | assert_not_delayed(); |
duke@435 | 527 | debug_only(verify_esp(Lesp)); |
duke@435 | 528 | tag_stack(frame::TagCategory2, Otos_i); |
duke@435 | 529 | // Longs are in stored in memory-correct order, even if unaligned. |
duke@435 | 530 | // and may be separated by stack tags. |
duke@435 | 531 | int offset = -Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); |
duke@435 | 532 | store_unaligned_double(d, Lesp, offset); |
duke@435 | 533 | dec(Lesp, 2 * Interpreter::stackElementSize()); |
duke@435 | 534 | } |
duke@435 | 535 | |
duke@435 | 536 | |
duke@435 | 537 | void InterpreterMacroAssembler::push(TosState state) { |
duke@435 | 538 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 539 | switch (state) { |
duke@435 | 540 | case atos: push_ptr(); break; |
duke@435 | 541 | case btos: push_i(); break; |
duke@435 | 542 | case ctos: |
duke@435 | 543 | case stos: push_i(); break; |
duke@435 | 544 | case itos: push_i(); break; |
duke@435 | 545 | case ltos: push_l(); break; |
duke@435 | 546 | case ftos: push_f(); break; |
duke@435 | 547 | case dtos: push_d(); break; |
duke@435 | 548 | case vtos: /* nothing to do */ break; |
duke@435 | 549 | default : ShouldNotReachHere(); |
duke@435 | 550 | } |
duke@435 | 551 | } |
duke@435 | 552 | |
duke@435 | 553 | |
duke@435 | 554 | void InterpreterMacroAssembler::pop(TosState state) { |
duke@435 | 555 | switch (state) { |
duke@435 | 556 | case atos: pop_ptr(); break; |
duke@435 | 557 | case btos: pop_i(); break; |
duke@435 | 558 | case ctos: |
duke@435 | 559 | case stos: pop_i(); break; |
duke@435 | 560 | case itos: pop_i(); break; |
duke@435 | 561 | case ltos: pop_l(); break; |
duke@435 | 562 | case ftos: pop_f(); break; |
duke@435 | 563 | case dtos: pop_d(); break; |
duke@435 | 564 | case vtos: /* nothing to do */ break; |
duke@435 | 565 | default : ShouldNotReachHere(); |
duke@435 | 566 | } |
duke@435 | 567 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 568 | } |
duke@435 | 569 | |
duke@435 | 570 | |
duke@435 | 571 | // Tagged stack helpers for swap and dup |
duke@435 | 572 | void InterpreterMacroAssembler::load_ptr_and_tag(int n, Register val, |
duke@435 | 573 | Register tag) { |
duke@435 | 574 | ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(n), val); |
duke@435 | 575 | if (TaggedStackInterpreter) { |
duke@435 | 576 | ld_ptr(Lesp, Interpreter::expr_tag_offset_in_bytes(n), tag); |
duke@435 | 577 | } |
duke@435 | 578 | } |
duke@435 | 579 | void InterpreterMacroAssembler::store_ptr_and_tag(int n, Register val, |
duke@435 | 580 | Register tag) { |
duke@435 | 581 | st_ptr(val, Lesp, Interpreter::expr_offset_in_bytes(n)); |
duke@435 | 582 | if (TaggedStackInterpreter) { |
duke@435 | 583 | st_ptr(tag, Lesp, Interpreter::expr_tag_offset_in_bytes(n)); |
duke@435 | 584 | } |
duke@435 | 585 | } |
duke@435 | 586 | |
duke@435 | 587 | |
duke@435 | 588 | void InterpreterMacroAssembler::load_receiver(Register param_count, |
duke@435 | 589 | Register recv) { |
duke@435 | 590 | |
duke@435 | 591 | sll(param_count, Interpreter::logStackElementSize(), param_count); |
duke@435 | 592 | if (TaggedStackInterpreter) { |
duke@435 | 593 | add(param_count, Interpreter::value_offset_in_bytes(), param_count); // get obj address |
duke@435 | 594 | } |
duke@435 | 595 | ld_ptr(Lesp, param_count, recv); // gets receiver Oop |
duke@435 | 596 | } |
duke@435 | 597 | |
duke@435 | 598 | void InterpreterMacroAssembler::empty_expression_stack() { |
duke@435 | 599 | // Reset Lesp. |
duke@435 | 600 | sub( Lmonitors, wordSize, Lesp ); |
duke@435 | 601 | |
duke@435 | 602 | // Reset SP by subtracting more space from Lesp. |
duke@435 | 603 | Label done; |
duke@435 | 604 | |
duke@435 | 605 | const Address max_stack (Lmethod, 0, in_bytes(methodOopDesc::max_stack_offset())); |
duke@435 | 606 | const Address access_flags(Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset())); |
duke@435 | 607 | |
duke@435 | 608 | verify_oop(Lmethod); |
duke@435 | 609 | |
duke@435 | 610 | |
duke@435 | 611 | assert( G4_scratch != Gframe_size, |
duke@435 | 612 | "Only you can prevent register aliasing!"); |
duke@435 | 613 | |
duke@435 | 614 | // A native does not need to do this, since its callee does not change SP. |
duke@435 | 615 | ld(access_flags, Gframe_size); |
duke@435 | 616 | btst(JVM_ACC_NATIVE, Gframe_size); |
duke@435 | 617 | br(Assembler::notZero, false, Assembler::pt, done); |
duke@435 | 618 | delayed()->nop(); |
duke@435 | 619 | |
duke@435 | 620 | // |
duke@435 | 621 | // Compute max expression stack+register save area |
duke@435 | 622 | // |
duke@435 | 623 | lduh( max_stack, Gframe_size ); |
duke@435 | 624 | if (TaggedStackInterpreter) sll ( Gframe_size, 1, Gframe_size); // max_stack * 2 for TAGS |
duke@435 | 625 | add( Gframe_size, frame::memory_parameter_word_sp_offset, Gframe_size ); |
duke@435 | 626 | |
duke@435 | 627 | // |
duke@435 | 628 | // now set up a stack frame with the size computed above |
duke@435 | 629 | // |
duke@435 | 630 | //round_to( Gframe_size, WordsPerLong ); // -- moved down to the "and" below |
duke@435 | 631 | sll( Gframe_size, LogBytesPerWord, Gframe_size ); |
duke@435 | 632 | sub( Lesp, Gframe_size, Gframe_size ); |
duke@435 | 633 | and3( Gframe_size, -(2 * wordSize), Gframe_size ); // align SP (downwards) to an 8/16-byte boundary |
duke@435 | 634 | debug_only(verify_sp(Gframe_size, G4_scratch)); |
duke@435 | 635 | #ifdef _LP64 |
duke@435 | 636 | sub(Gframe_size, STACK_BIAS, Gframe_size ); |
duke@435 | 637 | #endif |
duke@435 | 638 | mov(Gframe_size, SP); |
duke@435 | 639 | |
duke@435 | 640 | bind(done); |
duke@435 | 641 | } |
duke@435 | 642 | |
duke@435 | 643 | |
duke@435 | 644 | #ifdef ASSERT |
duke@435 | 645 | void InterpreterMacroAssembler::verify_sp(Register Rsp, Register Rtemp) { |
duke@435 | 646 | Label Bad, OK; |
duke@435 | 647 | |
duke@435 | 648 | // Saved SP must be aligned. |
duke@435 | 649 | #ifdef _LP64 |
duke@435 | 650 | btst(2*BytesPerWord-1, Rsp); |
duke@435 | 651 | #else |
duke@435 | 652 | btst(LongAlignmentMask, Rsp); |
duke@435 | 653 | #endif |
duke@435 | 654 | br(Assembler::notZero, false, Assembler::pn, Bad); |
duke@435 | 655 | delayed()->nop(); |
duke@435 | 656 | |
duke@435 | 657 | // Saved SP, plus register window size, must not be above FP. |
duke@435 | 658 | add(Rsp, frame::register_save_words * wordSize, Rtemp); |
duke@435 | 659 | #ifdef _LP64 |
duke@435 | 660 | sub(Rtemp, STACK_BIAS, Rtemp); // Bias Rtemp before cmp to FP |
duke@435 | 661 | #endif |
duke@435 | 662 | cmp(Rtemp, FP); |
duke@435 | 663 | brx(Assembler::greaterUnsigned, false, Assembler::pn, Bad); |
duke@435 | 664 | delayed()->nop(); |
duke@435 | 665 | |
duke@435 | 666 | // Saved SP must not be ridiculously below current SP. |
duke@435 | 667 | size_t maxstack = MAX2(JavaThread::stack_size_at_create(), (size_t) 4*K*K); |
duke@435 | 668 | set(maxstack, Rtemp); |
duke@435 | 669 | sub(SP, Rtemp, Rtemp); |
duke@435 | 670 | #ifdef _LP64 |
duke@435 | 671 | add(Rtemp, STACK_BIAS, Rtemp); // Unbias Rtemp before cmp to Rsp |
duke@435 | 672 | #endif |
duke@435 | 673 | cmp(Rsp, Rtemp); |
duke@435 | 674 | brx(Assembler::lessUnsigned, false, Assembler::pn, Bad); |
duke@435 | 675 | delayed()->nop(); |
duke@435 | 676 | |
duke@435 | 677 | br(Assembler::always, false, Assembler::pn, OK); |
duke@435 | 678 | delayed()->nop(); |
duke@435 | 679 | |
duke@435 | 680 | bind(Bad); |
duke@435 | 681 | stop("on return to interpreted call, restored SP is corrupted"); |
duke@435 | 682 | |
duke@435 | 683 | bind(OK); |
duke@435 | 684 | } |
duke@435 | 685 | |
duke@435 | 686 | |
duke@435 | 687 | void InterpreterMacroAssembler::verify_esp(Register Resp) { |
duke@435 | 688 | // about to read or write Resp[0] |
duke@435 | 689 | // make sure it is not in the monitors or the register save area |
duke@435 | 690 | Label OK1, OK2; |
duke@435 | 691 | |
duke@435 | 692 | cmp(Resp, Lmonitors); |
duke@435 | 693 | brx(Assembler::lessUnsigned, true, Assembler::pt, OK1); |
duke@435 | 694 | delayed()->sub(Resp, frame::memory_parameter_word_sp_offset * wordSize, Resp); |
duke@435 | 695 | stop("too many pops: Lesp points into monitor area"); |
duke@435 | 696 | bind(OK1); |
duke@435 | 697 | #ifdef _LP64 |
duke@435 | 698 | sub(Resp, STACK_BIAS, Resp); |
duke@435 | 699 | #endif |
duke@435 | 700 | cmp(Resp, SP); |
duke@435 | 701 | brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, OK2); |
duke@435 | 702 | delayed()->add(Resp, STACK_BIAS + frame::memory_parameter_word_sp_offset * wordSize, Resp); |
duke@435 | 703 | stop("too many pushes: Lesp points into register window"); |
duke@435 | 704 | bind(OK2); |
duke@435 | 705 | } |
duke@435 | 706 | #endif // ASSERT |
duke@435 | 707 | |
duke@435 | 708 | // Load compiled (i2c) or interpreter entry when calling from interpreted and |
duke@435 | 709 | // do the call. Centralized so that all interpreter calls will do the same actions. |
duke@435 | 710 | // If jvmti single stepping is on for a thread we must not call compiled code. |
duke@435 | 711 | void InterpreterMacroAssembler::call_from_interpreter(Register target, Register scratch, Register Rret) { |
duke@435 | 712 | |
duke@435 | 713 | // Assume we want to go compiled if available |
duke@435 | 714 | |
duke@435 | 715 | ld_ptr(G5_method, in_bytes(methodOopDesc::from_interpreted_offset()), target); |
duke@435 | 716 | |
duke@435 | 717 | if (JvmtiExport::can_post_interpreter_events()) { |
duke@435 | 718 | // JVMTI events, such as single-stepping, are implemented partly by avoiding running |
duke@435 | 719 | // compiled code in threads for which the event is enabled. Check here for |
duke@435 | 720 | // interp_only_mode if these events CAN be enabled. |
duke@435 | 721 | verify_thread(); |
duke@435 | 722 | Label skip_compiled_code; |
duke@435 | 723 | |
duke@435 | 724 | const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset())); |
duke@435 | 725 | |
duke@435 | 726 | ld(interp_only, scratch); |
duke@435 | 727 | tst(scratch); |
duke@435 | 728 | br(Assembler::notZero, true, Assembler::pn, skip_compiled_code); |
duke@435 | 729 | delayed()->ld_ptr(G5_method, in_bytes(methodOopDesc::interpreter_entry_offset()), target); |
duke@435 | 730 | bind(skip_compiled_code); |
duke@435 | 731 | } |
duke@435 | 732 | |
duke@435 | 733 | // the i2c_adapters need methodOop in G5_method (right? %%%) |
duke@435 | 734 | // do the call |
duke@435 | 735 | #ifdef ASSERT |
duke@435 | 736 | { |
duke@435 | 737 | Label ok; |
duke@435 | 738 | br_notnull(target, false, Assembler::pt, ok); |
duke@435 | 739 | delayed()->nop(); |
duke@435 | 740 | stop("null entry point"); |
duke@435 | 741 | bind(ok); |
duke@435 | 742 | } |
duke@435 | 743 | #endif // ASSERT |
duke@435 | 744 | |
duke@435 | 745 | // Adjust Rret first so Llast_SP can be same as Rret |
duke@435 | 746 | add(Rret, -frame::pc_return_offset, O7); |
duke@435 | 747 | add(Lesp, BytesPerWord, Gargs); // setup parameter pointer |
duke@435 | 748 | // Record SP so we can remove any stack space allocated by adapter transition |
duke@435 | 749 | jmp(target, 0); |
duke@435 | 750 | delayed()->mov(SP, Llast_SP); |
duke@435 | 751 | } |
duke@435 | 752 | |
duke@435 | 753 | void InterpreterMacroAssembler::if_cmp(Condition cc, bool ptr_compare) { |
duke@435 | 754 | assert_not_delayed(); |
duke@435 | 755 | |
duke@435 | 756 | Label not_taken; |
duke@435 | 757 | if (ptr_compare) brx(cc, false, Assembler::pn, not_taken); |
duke@435 | 758 | else br (cc, false, Assembler::pn, not_taken); |
duke@435 | 759 | delayed()->nop(); |
duke@435 | 760 | |
duke@435 | 761 | TemplateTable::branch(false,false); |
duke@435 | 762 | |
duke@435 | 763 | bind(not_taken); |
duke@435 | 764 | |
duke@435 | 765 | profile_not_taken_branch(G3_scratch); |
duke@435 | 766 | } |
duke@435 | 767 | |
duke@435 | 768 | |
duke@435 | 769 | void InterpreterMacroAssembler::get_2_byte_integer_at_bcp( |
duke@435 | 770 | int bcp_offset, |
duke@435 | 771 | Register Rtmp, |
duke@435 | 772 | Register Rdst, |
duke@435 | 773 | signedOrNot is_signed, |
duke@435 | 774 | setCCOrNot should_set_CC ) { |
duke@435 | 775 | assert(Rtmp != Rdst, "need separate temp register"); |
duke@435 | 776 | assert_not_delayed(); |
duke@435 | 777 | switch (is_signed) { |
duke@435 | 778 | default: ShouldNotReachHere(); |
duke@435 | 779 | |
duke@435 | 780 | case Signed: ldsb( Lbcp, bcp_offset, Rdst ); break; // high byte |
duke@435 | 781 | case Unsigned: ldub( Lbcp, bcp_offset, Rdst ); break; // high byte |
duke@435 | 782 | } |
duke@435 | 783 | ldub( Lbcp, bcp_offset + 1, Rtmp ); // low byte |
duke@435 | 784 | sll( Rdst, BitsPerByte, Rdst); |
duke@435 | 785 | switch (should_set_CC ) { |
duke@435 | 786 | default: ShouldNotReachHere(); |
duke@435 | 787 | |
duke@435 | 788 | case set_CC: orcc( Rdst, Rtmp, Rdst ); break; |
duke@435 | 789 | case dont_set_CC: or3( Rdst, Rtmp, Rdst ); break; |
duke@435 | 790 | } |
duke@435 | 791 | } |
duke@435 | 792 | |
duke@435 | 793 | |
duke@435 | 794 | void InterpreterMacroAssembler::get_4_byte_integer_at_bcp( |
duke@435 | 795 | int bcp_offset, |
duke@435 | 796 | Register Rtmp, |
duke@435 | 797 | Register Rdst, |
duke@435 | 798 | setCCOrNot should_set_CC ) { |
duke@435 | 799 | assert(Rtmp != Rdst, "need separate temp register"); |
duke@435 | 800 | assert_not_delayed(); |
duke@435 | 801 | add( Lbcp, bcp_offset, Rtmp); |
duke@435 | 802 | andcc( Rtmp, 3, G0); |
duke@435 | 803 | Label aligned; |
duke@435 | 804 | switch (should_set_CC ) { |
duke@435 | 805 | default: ShouldNotReachHere(); |
duke@435 | 806 | |
duke@435 | 807 | case set_CC: break; |
duke@435 | 808 | case dont_set_CC: break; |
duke@435 | 809 | } |
duke@435 | 810 | |
duke@435 | 811 | br(Assembler::zero, true, Assembler::pn, aligned); |
duke@435 | 812 | #ifdef _LP64 |
duke@435 | 813 | delayed()->ldsw(Rtmp, 0, Rdst); |
duke@435 | 814 | #else |
duke@435 | 815 | delayed()->ld(Rtmp, 0, Rdst); |
duke@435 | 816 | #endif |
duke@435 | 817 | |
duke@435 | 818 | ldub(Lbcp, bcp_offset + 3, Rdst); |
duke@435 | 819 | ldub(Lbcp, bcp_offset + 2, Rtmp); sll(Rtmp, 8, Rtmp); or3(Rtmp, Rdst, Rdst); |
duke@435 | 820 | ldub(Lbcp, bcp_offset + 1, Rtmp); sll(Rtmp, 16, Rtmp); or3(Rtmp, Rdst, Rdst); |
duke@435 | 821 | #ifdef _LP64 |
duke@435 | 822 | ldsb(Lbcp, bcp_offset + 0, Rtmp); sll(Rtmp, 24, Rtmp); |
duke@435 | 823 | #else |
duke@435 | 824 | // Unsigned load is faster than signed on some implementations |
duke@435 | 825 | ldub(Lbcp, bcp_offset + 0, Rtmp); sll(Rtmp, 24, Rtmp); |
duke@435 | 826 | #endif |
duke@435 | 827 | or3(Rtmp, Rdst, Rdst ); |
duke@435 | 828 | |
duke@435 | 829 | bind(aligned); |
duke@435 | 830 | if (should_set_CC == set_CC) tst(Rdst); |
duke@435 | 831 | } |
duke@435 | 832 | |
duke@435 | 833 | |
duke@435 | 834 | void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset) { |
duke@435 | 835 | assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); |
duke@435 | 836 | assert_different_registers(cache, tmp); |
duke@435 | 837 | assert_not_delayed(); |
duke@435 | 838 | get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned); |
duke@435 | 839 | // convert from field index to ConstantPoolCacheEntry index |
duke@435 | 840 | // and from word index to byte offset |
duke@435 | 841 | sll(tmp, exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord), tmp); |
duke@435 | 842 | add(LcpoolCache, tmp, cache); |
duke@435 | 843 | } |
duke@435 | 844 | |
duke@435 | 845 | |
duke@435 | 846 | void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) { |
duke@435 | 847 | assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); |
duke@435 | 848 | assert_different_registers(cache, tmp); |
duke@435 | 849 | assert_not_delayed(); |
duke@435 | 850 | get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned); |
duke@435 | 851 | // convert from field index to ConstantPoolCacheEntry index |
duke@435 | 852 | // and from word index to byte offset |
duke@435 | 853 | sll(tmp, exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord), tmp); |
duke@435 | 854 | // skip past the header |
duke@435 | 855 | add(tmp, in_bytes(constantPoolCacheOopDesc::base_offset()), tmp); |
duke@435 | 856 | // construct pointer to cache entry |
duke@435 | 857 | add(LcpoolCache, tmp, cache); |
duke@435 | 858 | } |
duke@435 | 859 | |
duke@435 | 860 | |
duke@435 | 861 | // Generate a subtype check: branch to ok_is_subtype if sub_klass is |
coleenp@548 | 862 | // a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2. |
duke@435 | 863 | void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, |
duke@435 | 864 | Register Rsuper_klass, |
duke@435 | 865 | Register Rtmp1, |
duke@435 | 866 | Register Rtmp2, |
duke@435 | 867 | Register Rtmp3, |
duke@435 | 868 | Label &ok_is_subtype ) { |
jrose@1079 | 869 | Label not_subtype; |
duke@435 | 870 | |
duke@435 | 871 | // Profile the not-null value's klass. |
duke@435 | 872 | profile_typecheck(Rsub_klass, Rtmp1); |
duke@435 | 873 | |
jrose@1079 | 874 | check_klass_subtype_fast_path(Rsub_klass, Rsuper_klass, |
jrose@1079 | 875 | Rtmp1, Rtmp2, |
jrose@1079 | 876 | &ok_is_subtype, ¬_subtype, NULL); |
jrose@1079 | 877 | |
jrose@1079 | 878 | check_klass_subtype_slow_path(Rsub_klass, Rsuper_klass, |
jrose@1079 | 879 | Rtmp1, Rtmp2, Rtmp3, /*hack:*/ noreg, |
jrose@1079 | 880 | &ok_is_subtype, NULL); |
duke@435 | 881 | |
duke@435 | 882 | bind(not_subtype); |
duke@435 | 883 | profile_typecheck_failed(Rtmp1); |
duke@435 | 884 | } |
duke@435 | 885 | |
duke@435 | 886 | // Separate these two to allow for delay slot in middle |
duke@435 | 887 | // These are used to do a test and full jump to exception-throwing code. |
duke@435 | 888 | |
duke@435 | 889 | // %%%%% Could possibly reoptimize this by testing to see if could use |
duke@435 | 890 | // a single conditional branch (i.e. if span is small enough. |
duke@435 | 891 | // If you go that route, than get rid of the split and give up |
duke@435 | 892 | // on the delay-slot hack. |
duke@435 | 893 | |
duke@435 | 894 | void InterpreterMacroAssembler::throw_if_not_1_icc( Condition ok_condition, |
duke@435 | 895 | Label& ok ) { |
duke@435 | 896 | assert_not_delayed(); |
duke@435 | 897 | br(ok_condition, true, pt, ok); |
duke@435 | 898 | // DELAY SLOT |
duke@435 | 899 | } |
duke@435 | 900 | |
duke@435 | 901 | void InterpreterMacroAssembler::throw_if_not_1_xcc( Condition ok_condition, |
duke@435 | 902 | Label& ok ) { |
duke@435 | 903 | assert_not_delayed(); |
duke@435 | 904 | bp( ok_condition, true, Assembler::xcc, pt, ok); |
duke@435 | 905 | // DELAY SLOT |
duke@435 | 906 | } |
duke@435 | 907 | |
duke@435 | 908 | void InterpreterMacroAssembler::throw_if_not_1_x( Condition ok_condition, |
duke@435 | 909 | Label& ok ) { |
duke@435 | 910 | assert_not_delayed(); |
duke@435 | 911 | brx(ok_condition, true, pt, ok); |
duke@435 | 912 | // DELAY SLOT |
duke@435 | 913 | } |
duke@435 | 914 | |
duke@435 | 915 | void InterpreterMacroAssembler::throw_if_not_2( address throw_entry_point, |
duke@435 | 916 | Register Rscratch, |
duke@435 | 917 | Label& ok ) { |
duke@435 | 918 | assert(throw_entry_point != NULL, "entry point must be generated by now"); |
duke@435 | 919 | Address dest(Rscratch, throw_entry_point); |
duke@435 | 920 | jump_to(dest); |
duke@435 | 921 | delayed()->nop(); |
duke@435 | 922 | bind(ok); |
duke@435 | 923 | } |
duke@435 | 924 | |
duke@435 | 925 | |
duke@435 | 926 | // And if you cannot use the delay slot, here is a shorthand: |
duke@435 | 927 | |
duke@435 | 928 | void InterpreterMacroAssembler::throw_if_not_icc( Condition ok_condition, |
duke@435 | 929 | address throw_entry_point, |
duke@435 | 930 | Register Rscratch ) { |
duke@435 | 931 | Label ok; |
duke@435 | 932 | if (ok_condition != never) { |
duke@435 | 933 | throw_if_not_1_icc( ok_condition, ok); |
duke@435 | 934 | delayed()->nop(); |
duke@435 | 935 | } |
duke@435 | 936 | throw_if_not_2( throw_entry_point, Rscratch, ok); |
duke@435 | 937 | } |
duke@435 | 938 | void InterpreterMacroAssembler::throw_if_not_xcc( Condition ok_condition, |
duke@435 | 939 | address throw_entry_point, |
duke@435 | 940 | Register Rscratch ) { |
duke@435 | 941 | Label ok; |
duke@435 | 942 | if (ok_condition != never) { |
duke@435 | 943 | throw_if_not_1_xcc( ok_condition, ok); |
duke@435 | 944 | delayed()->nop(); |
duke@435 | 945 | } |
duke@435 | 946 | throw_if_not_2( throw_entry_point, Rscratch, ok); |
duke@435 | 947 | } |
duke@435 | 948 | void InterpreterMacroAssembler::throw_if_not_x( Condition ok_condition, |
duke@435 | 949 | address throw_entry_point, |
duke@435 | 950 | Register Rscratch ) { |
duke@435 | 951 | Label ok; |
duke@435 | 952 | if (ok_condition != never) { |
duke@435 | 953 | throw_if_not_1_x( ok_condition, ok); |
duke@435 | 954 | delayed()->nop(); |
duke@435 | 955 | } |
duke@435 | 956 | throw_if_not_2( throw_entry_point, Rscratch, ok); |
duke@435 | 957 | } |
duke@435 | 958 | |
duke@435 | 959 | // Check that index is in range for array, then shift index by index_shift, and put arrayOop + shifted_index into res |
duke@435 | 960 | // Note: res is still shy of address by array offset into object. |
duke@435 | 961 | |
duke@435 | 962 | void InterpreterMacroAssembler::index_check_without_pop(Register array, Register index, int index_shift, Register tmp, Register res) { |
duke@435 | 963 | assert_not_delayed(); |
duke@435 | 964 | |
duke@435 | 965 | verify_oop(array); |
duke@435 | 966 | #ifdef _LP64 |
duke@435 | 967 | // sign extend since tos (index) can be a 32bit value |
duke@435 | 968 | sra(index, G0, index); |
duke@435 | 969 | #endif // _LP64 |
duke@435 | 970 | |
duke@435 | 971 | // check array |
duke@435 | 972 | Label ptr_ok; |
duke@435 | 973 | tst(array); |
duke@435 | 974 | throw_if_not_1_x( notZero, ptr_ok ); |
duke@435 | 975 | delayed()->ld( array, arrayOopDesc::length_offset_in_bytes(), tmp ); // check index |
duke@435 | 976 | throw_if_not_2( Interpreter::_throw_NullPointerException_entry, G3_scratch, ptr_ok); |
duke@435 | 977 | |
duke@435 | 978 | Label index_ok; |
duke@435 | 979 | cmp(index, tmp); |
duke@435 | 980 | throw_if_not_1_icc( lessUnsigned, index_ok ); |
duke@435 | 981 | if (index_shift > 0) delayed()->sll(index, index_shift, index); |
duke@435 | 982 | else delayed()->add(array, index, res); // addr - const offset in index |
duke@435 | 983 | // convention: move aberrant index into G3_scratch for exception message |
duke@435 | 984 | mov(index, G3_scratch); |
duke@435 | 985 | throw_if_not_2( Interpreter::_throw_ArrayIndexOutOfBoundsException_entry, G4_scratch, index_ok); |
duke@435 | 986 | |
duke@435 | 987 | // add offset if didn't do it in delay slot |
duke@435 | 988 | if (index_shift > 0) add(array, index, res); // addr - const offset in index |
duke@435 | 989 | } |
duke@435 | 990 | |
duke@435 | 991 | |
duke@435 | 992 | void InterpreterMacroAssembler::index_check(Register array, Register index, int index_shift, Register tmp, Register res) { |
duke@435 | 993 | assert_not_delayed(); |
duke@435 | 994 | |
duke@435 | 995 | // pop array |
duke@435 | 996 | pop_ptr(array); |
duke@435 | 997 | |
duke@435 | 998 | // check array |
duke@435 | 999 | index_check_without_pop(array, index, index_shift, tmp, res); |
duke@435 | 1000 | } |
duke@435 | 1001 | |
duke@435 | 1002 | |
duke@435 | 1003 | void InterpreterMacroAssembler::get_constant_pool(Register Rdst) { |
duke@435 | 1004 | ld_ptr(Lmethod, in_bytes(methodOopDesc::constants_offset()), Rdst); |
duke@435 | 1005 | } |
duke@435 | 1006 | |
duke@435 | 1007 | |
duke@435 | 1008 | void InterpreterMacroAssembler::get_constant_pool_cache(Register Rdst) { |
duke@435 | 1009 | get_constant_pool(Rdst); |
duke@435 | 1010 | ld_ptr(Rdst, constantPoolOopDesc::cache_offset_in_bytes(), Rdst); |
duke@435 | 1011 | } |
duke@435 | 1012 | |
duke@435 | 1013 | |
duke@435 | 1014 | void InterpreterMacroAssembler::get_cpool_and_tags(Register Rcpool, Register Rtags) { |
duke@435 | 1015 | get_constant_pool(Rcpool); |
duke@435 | 1016 | ld_ptr(Rcpool, constantPoolOopDesc::tags_offset_in_bytes(), Rtags); |
duke@435 | 1017 | } |
duke@435 | 1018 | |
duke@435 | 1019 | |
duke@435 | 1020 | // unlock if synchronized method |
duke@435 | 1021 | // |
duke@435 | 1022 | // Unlock the receiver if this is a synchronized method. |
duke@435 | 1023 | // Unlock any Java monitors from syncronized blocks. |
duke@435 | 1024 | // |
duke@435 | 1025 | // If there are locked Java monitors |
duke@435 | 1026 | // If throw_monitor_exception |
duke@435 | 1027 | // throws IllegalMonitorStateException |
duke@435 | 1028 | // Else if install_monitor_exception |
duke@435 | 1029 | // installs IllegalMonitorStateException |
duke@435 | 1030 | // Else |
duke@435 | 1031 | // no error processing |
duke@435 | 1032 | void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, |
duke@435 | 1033 | bool throw_monitor_exception, |
duke@435 | 1034 | bool install_monitor_exception) { |
duke@435 | 1035 | Label unlocked, unlock, no_unlock; |
duke@435 | 1036 | |
duke@435 | 1037 | // get the value of _do_not_unlock_if_synchronized into G1_scratch |
duke@435 | 1038 | const Address do_not_unlock_if_synchronized(G2_thread, 0, |
duke@435 | 1039 | in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); |
duke@435 | 1040 | ldbool(do_not_unlock_if_synchronized, G1_scratch); |
duke@435 | 1041 | stbool(G0, do_not_unlock_if_synchronized); // reset the flag |
duke@435 | 1042 | |
duke@435 | 1043 | // check if synchronized method |
duke@435 | 1044 | const Address access_flags(Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset())); |
duke@435 | 1045 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 1046 | push(state); // save tos |
duke@435 | 1047 | ld(access_flags, G3_scratch); |
duke@435 | 1048 | btst(JVM_ACC_SYNCHRONIZED, G3_scratch); |
duke@435 | 1049 | br( zero, false, pt, unlocked); |
duke@435 | 1050 | delayed()->nop(); |
duke@435 | 1051 | |
duke@435 | 1052 | // Don't unlock anything if the _do_not_unlock_if_synchronized flag |
duke@435 | 1053 | // is set. |
duke@435 | 1054 | tstbool(G1_scratch); |
duke@435 | 1055 | br(Assembler::notZero, false, pn, no_unlock); |
duke@435 | 1056 | delayed()->nop(); |
duke@435 | 1057 | |
duke@435 | 1058 | // BasicObjectLock will be first in list, since this is a synchronized method. However, need |
duke@435 | 1059 | // to check that the object has not been unlocked by an explicit monitorexit bytecode. |
duke@435 | 1060 | |
duke@435 | 1061 | //Intel: if (throw_monitor_exception) ... else ... |
duke@435 | 1062 | // Entry already unlocked, need to throw exception |
duke@435 | 1063 | //... |
duke@435 | 1064 | |
duke@435 | 1065 | // pass top-most monitor elem |
duke@435 | 1066 | add( top_most_monitor(), O1 ); |
duke@435 | 1067 | |
duke@435 | 1068 | ld_ptr(O1, BasicObjectLock::obj_offset_in_bytes(), G3_scratch); |
duke@435 | 1069 | br_notnull(G3_scratch, false, pt, unlock); |
duke@435 | 1070 | delayed()->nop(); |
duke@435 | 1071 | |
duke@435 | 1072 | if (throw_monitor_exception) { |
duke@435 | 1073 | // Entry already unlocked need to throw an exception |
duke@435 | 1074 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); |
duke@435 | 1075 | should_not_reach_here(); |
duke@435 | 1076 | } else { |
duke@435 | 1077 | // Monitor already unlocked during a stack unroll. |
duke@435 | 1078 | // If requested, install an illegal_monitor_state_exception. |
duke@435 | 1079 | // Continue with stack unrolling. |
duke@435 | 1080 | if (install_monitor_exception) { |
duke@435 | 1081 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); |
duke@435 | 1082 | } |
duke@435 | 1083 | ba(false, unlocked); |
duke@435 | 1084 | delayed()->nop(); |
duke@435 | 1085 | } |
duke@435 | 1086 | |
duke@435 | 1087 | bind(unlock); |
duke@435 | 1088 | |
duke@435 | 1089 | unlock_object(O1); |
duke@435 | 1090 | |
duke@435 | 1091 | bind(unlocked); |
duke@435 | 1092 | |
duke@435 | 1093 | // I0, I1: Might contain return value |
duke@435 | 1094 | |
duke@435 | 1095 | // Check that all monitors are unlocked |
duke@435 | 1096 | { Label loop, exception, entry, restart; |
duke@435 | 1097 | |
duke@435 | 1098 | Register Rmptr = O0; |
duke@435 | 1099 | Register Rtemp = O1; |
duke@435 | 1100 | Register Rlimit = Lmonitors; |
duke@435 | 1101 | const jint delta = frame::interpreter_frame_monitor_size() * wordSize; |
duke@435 | 1102 | assert( (delta & LongAlignmentMask) == 0, |
duke@435 | 1103 | "sizeof BasicObjectLock must be even number of doublewords"); |
duke@435 | 1104 | |
duke@435 | 1105 | #ifdef ASSERT |
duke@435 | 1106 | add(top_most_monitor(), Rmptr, delta); |
duke@435 | 1107 | { Label L; |
duke@435 | 1108 | // ensure that Rmptr starts out above (or at) Rlimit |
duke@435 | 1109 | cmp(Rmptr, Rlimit); |
duke@435 | 1110 | brx(Assembler::greaterEqualUnsigned, false, pn, L); |
duke@435 | 1111 | delayed()->nop(); |
duke@435 | 1112 | stop("monitor stack has negative size"); |
duke@435 | 1113 | bind(L); |
duke@435 | 1114 | } |
duke@435 | 1115 | #endif |
duke@435 | 1116 | bind(restart); |
duke@435 | 1117 | ba(false, entry); |
duke@435 | 1118 | delayed()-> |
duke@435 | 1119 | add(top_most_monitor(), Rmptr, delta); // points to current entry, starting with bottom-most entry |
duke@435 | 1120 | |
duke@435 | 1121 | // Entry is still locked, need to throw exception |
duke@435 | 1122 | bind(exception); |
duke@435 | 1123 | if (throw_monitor_exception) { |
duke@435 | 1124 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); |
duke@435 | 1125 | should_not_reach_here(); |
duke@435 | 1126 | } else { |
duke@435 | 1127 | // Stack unrolling. Unlock object and if requested, install illegal_monitor_exception. |
duke@435 | 1128 | // Unlock does not block, so don't have to worry about the frame |
duke@435 | 1129 | unlock_object(Rmptr); |
duke@435 | 1130 | if (install_monitor_exception) { |
duke@435 | 1131 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); |
duke@435 | 1132 | } |
duke@435 | 1133 | ba(false, restart); |
duke@435 | 1134 | delayed()->nop(); |
duke@435 | 1135 | } |
duke@435 | 1136 | |
duke@435 | 1137 | bind(loop); |
duke@435 | 1138 | cmp(Rtemp, G0); // check if current entry is used |
duke@435 | 1139 | brx(Assembler::notEqual, false, pn, exception); |
duke@435 | 1140 | delayed()-> |
duke@435 | 1141 | dec(Rmptr, delta); // otherwise advance to next entry |
duke@435 | 1142 | #ifdef ASSERT |
duke@435 | 1143 | { Label L; |
duke@435 | 1144 | // ensure that Rmptr has not somehow stepped below Rlimit |
duke@435 | 1145 | cmp(Rmptr, Rlimit); |
duke@435 | 1146 | brx(Assembler::greaterEqualUnsigned, false, pn, L); |
duke@435 | 1147 | delayed()->nop(); |
duke@435 | 1148 | stop("ran off the end of the monitor stack"); |
duke@435 | 1149 | bind(L); |
duke@435 | 1150 | } |
duke@435 | 1151 | #endif |
duke@435 | 1152 | bind(entry); |
duke@435 | 1153 | cmp(Rmptr, Rlimit); // check if bottom reached |
duke@435 | 1154 | brx(Assembler::notEqual, true, pn, loop); // if not at bottom then check this entry |
duke@435 | 1155 | delayed()-> |
duke@435 | 1156 | ld_ptr(Rmptr, BasicObjectLock::obj_offset_in_bytes() - delta, Rtemp); |
duke@435 | 1157 | } |
duke@435 | 1158 | |
duke@435 | 1159 | bind(no_unlock); |
duke@435 | 1160 | pop(state); |
duke@435 | 1161 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 1162 | } |
duke@435 | 1163 | |
duke@435 | 1164 | |
duke@435 | 1165 | // remove activation |
duke@435 | 1166 | // |
duke@435 | 1167 | // Unlock the receiver if this is a synchronized method. |
duke@435 | 1168 | // Unlock any Java monitors from syncronized blocks. |
duke@435 | 1169 | // Remove the activation from the stack. |
duke@435 | 1170 | // |
duke@435 | 1171 | // If there are locked Java monitors |
duke@435 | 1172 | // If throw_monitor_exception |
duke@435 | 1173 | // throws IllegalMonitorStateException |
duke@435 | 1174 | // Else if install_monitor_exception |
duke@435 | 1175 | // installs IllegalMonitorStateException |
duke@435 | 1176 | // Else |
duke@435 | 1177 | // no error processing |
duke@435 | 1178 | void InterpreterMacroAssembler::remove_activation(TosState state, |
duke@435 | 1179 | bool throw_monitor_exception, |
duke@435 | 1180 | bool install_monitor_exception) { |
duke@435 | 1181 | |
duke@435 | 1182 | unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception); |
duke@435 | 1183 | |
duke@435 | 1184 | // save result (push state before jvmti call and pop it afterwards) and notify jvmti |
duke@435 | 1185 | notify_method_exit(false, state, NotifyJVMTI); |
duke@435 | 1186 | |
duke@435 | 1187 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 1188 | verify_oop(Lmethod); |
duke@435 | 1189 | verify_thread(); |
duke@435 | 1190 | |
duke@435 | 1191 | // return tos |
duke@435 | 1192 | assert(Otos_l1 == Otos_i, "adjust code below"); |
duke@435 | 1193 | switch (state) { |
duke@435 | 1194 | #ifdef _LP64 |
duke@435 | 1195 | case ltos: mov(Otos_l, Otos_l->after_save()); break; // O0 -> I0 |
duke@435 | 1196 | #else |
duke@435 | 1197 | case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 |
duke@435 | 1198 | #endif |
duke@435 | 1199 | case btos: // fall through |
duke@435 | 1200 | case ctos: |
duke@435 | 1201 | case stos: // fall through |
duke@435 | 1202 | case atos: // fall through |
duke@435 | 1203 | case itos: mov(Otos_l1, Otos_l1->after_save()); break; // O0 -> I0 |
duke@435 | 1204 | case ftos: // fall through |
duke@435 | 1205 | case dtos: // fall through |
duke@435 | 1206 | case vtos: /* nothing to do */ break; |
duke@435 | 1207 | default : ShouldNotReachHere(); |
duke@435 | 1208 | } |
duke@435 | 1209 | |
duke@435 | 1210 | #if defined(COMPILER2) && !defined(_LP64) |
duke@435 | 1211 | if (state == ltos) { |
duke@435 | 1212 | // C2 expects long results in G1 we can't tell if we're returning to interpreted |
duke@435 | 1213 | // or compiled so just be safe use G1 and O0/O1 |
duke@435 | 1214 | |
duke@435 | 1215 | // Shift bits into high (msb) of G1 |
duke@435 | 1216 | sllx(Otos_l1->after_save(), 32, G1); |
duke@435 | 1217 | // Zero extend low bits |
duke@435 | 1218 | srl (Otos_l2->after_save(), 0, Otos_l2->after_save()); |
duke@435 | 1219 | or3 (Otos_l2->after_save(), G1, G1); |
duke@435 | 1220 | } |
duke@435 | 1221 | #endif /* COMPILER2 */ |
duke@435 | 1222 | |
duke@435 | 1223 | } |
duke@435 | 1224 | #endif /* CC_INTERP */ |
duke@435 | 1225 | |
duke@435 | 1226 | |
duke@435 | 1227 | // Lock object |
duke@435 | 1228 | // |
duke@435 | 1229 | // Argument - lock_reg points to the BasicObjectLock to be used for locking, |
duke@435 | 1230 | // it must be initialized with the object to lock |
duke@435 | 1231 | void InterpreterMacroAssembler::lock_object(Register lock_reg, Register Object) { |
duke@435 | 1232 | if (UseHeavyMonitors) { |
duke@435 | 1233 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); |
duke@435 | 1234 | } |
duke@435 | 1235 | else { |
duke@435 | 1236 | Register obj_reg = Object; |
duke@435 | 1237 | Register mark_reg = G4_scratch; |
duke@435 | 1238 | Register temp_reg = G1_scratch; |
duke@435 | 1239 | Address lock_addr = Address(lock_reg, 0, BasicObjectLock::lock_offset_in_bytes()); |
duke@435 | 1240 | Address mark_addr = Address(obj_reg, 0, oopDesc::mark_offset_in_bytes()); |
duke@435 | 1241 | Label done; |
duke@435 | 1242 | |
duke@435 | 1243 | Label slow_case; |
duke@435 | 1244 | |
duke@435 | 1245 | assert_different_registers(lock_reg, obj_reg, mark_reg, temp_reg); |
duke@435 | 1246 | |
duke@435 | 1247 | // load markOop from object into mark_reg |
duke@435 | 1248 | ld_ptr(mark_addr, mark_reg); |
duke@435 | 1249 | |
duke@435 | 1250 | if (UseBiasedLocking) { |
duke@435 | 1251 | biased_locking_enter(obj_reg, mark_reg, temp_reg, done, &slow_case); |
duke@435 | 1252 | } |
duke@435 | 1253 | |
duke@435 | 1254 | // get the address of basicLock on stack that will be stored in the object |
duke@435 | 1255 | // we need a temporary register here as we do not want to clobber lock_reg |
duke@435 | 1256 | // (cas clobbers the destination register) |
duke@435 | 1257 | mov(lock_reg, temp_reg); |
duke@435 | 1258 | // set mark reg to be (markOop of object | UNLOCK_VALUE) |
duke@435 | 1259 | or3(mark_reg, markOopDesc::unlocked_value, mark_reg); |
duke@435 | 1260 | // initialize the box (Must happen before we update the object mark!) |
duke@435 | 1261 | st_ptr(mark_reg, lock_addr, BasicLock::displaced_header_offset_in_bytes()); |
duke@435 | 1262 | // compare and exchange object_addr, markOop | 1, stack address of basicLock |
duke@435 | 1263 | assert(mark_addr.disp() == 0, "cas must take a zero displacement"); |
duke@435 | 1264 | casx_under_lock(mark_addr.base(), mark_reg, temp_reg, |
duke@435 | 1265 | (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); |
duke@435 | 1266 | |
duke@435 | 1267 | // if the compare and exchange succeeded we are done (we saw an unlocked object) |
duke@435 | 1268 | cmp(mark_reg, temp_reg); |
duke@435 | 1269 | brx(Assembler::equal, true, Assembler::pt, done); |
duke@435 | 1270 | delayed()->nop(); |
duke@435 | 1271 | |
duke@435 | 1272 | // We did not see an unlocked object so try the fast recursive case |
duke@435 | 1273 | |
duke@435 | 1274 | // Check if owner is self by comparing the value in the markOop of object |
duke@435 | 1275 | // with the stack pointer |
duke@435 | 1276 | sub(temp_reg, SP, temp_reg); |
duke@435 | 1277 | #ifdef _LP64 |
duke@435 | 1278 | sub(temp_reg, STACK_BIAS, temp_reg); |
duke@435 | 1279 | #endif |
duke@435 | 1280 | assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); |
duke@435 | 1281 | |
duke@435 | 1282 | // Composite "andcc" test: |
duke@435 | 1283 | // (a) %sp -vs- markword proximity check, and, |
duke@435 | 1284 | // (b) verify mark word LSBs == 0 (Stack-locked). |
duke@435 | 1285 | // |
duke@435 | 1286 | // FFFFF003/FFFFFFFFFFFF003 is (markOopDesc::lock_mask_in_place | -os::vm_page_size()) |
duke@435 | 1287 | // Note that the page size used for %sp proximity testing is arbitrary and is |
duke@435 | 1288 | // unrelated to the actual MMU page size. We use a 'logical' page size of |
duke@435 | 1289 | // 4096 bytes. F..FFF003 is designed to fit conveniently in the SIMM13 immediate |
duke@435 | 1290 | // field of the andcc instruction. |
duke@435 | 1291 | andcc (temp_reg, 0xFFFFF003, G0) ; |
duke@435 | 1292 | |
duke@435 | 1293 | // if condition is true we are done and hence we can store 0 in the displaced |
duke@435 | 1294 | // header indicating it is a recursive lock and be done |
duke@435 | 1295 | brx(Assembler::zero, true, Assembler::pt, done); |
duke@435 | 1296 | delayed()->st_ptr(G0, lock_addr, BasicLock::displaced_header_offset_in_bytes()); |
duke@435 | 1297 | |
duke@435 | 1298 | // none of the above fast optimizations worked so we have to get into the |
duke@435 | 1299 | // slow case of monitor enter |
duke@435 | 1300 | bind(slow_case); |
duke@435 | 1301 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); |
duke@435 | 1302 | |
duke@435 | 1303 | bind(done); |
duke@435 | 1304 | } |
duke@435 | 1305 | } |
duke@435 | 1306 | |
duke@435 | 1307 | // Unlocks an object. Used in monitorexit bytecode and remove_activation. |
duke@435 | 1308 | // |
duke@435 | 1309 | // Argument - lock_reg points to the BasicObjectLock for lock |
duke@435 | 1310 | // Throw IllegalMonitorException if object is not locked by current thread |
duke@435 | 1311 | void InterpreterMacroAssembler::unlock_object(Register lock_reg) { |
duke@435 | 1312 | if (UseHeavyMonitors) { |
duke@435 | 1313 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); |
duke@435 | 1314 | } else { |
duke@435 | 1315 | Register obj_reg = G3_scratch; |
duke@435 | 1316 | Register mark_reg = G4_scratch; |
duke@435 | 1317 | Register displaced_header_reg = G1_scratch; |
duke@435 | 1318 | Address lock_addr = Address(lock_reg, 0, BasicObjectLock::lock_offset_in_bytes()); |
duke@435 | 1319 | Address lockobj_addr = Address(lock_reg, 0, BasicObjectLock::obj_offset_in_bytes()); |
duke@435 | 1320 | Address mark_addr = Address(obj_reg, 0, oopDesc::mark_offset_in_bytes()); |
duke@435 | 1321 | Label done; |
duke@435 | 1322 | |
duke@435 | 1323 | if (UseBiasedLocking) { |
duke@435 | 1324 | // load the object out of the BasicObjectLock |
duke@435 | 1325 | ld_ptr(lockobj_addr, obj_reg); |
duke@435 | 1326 | biased_locking_exit(mark_addr, mark_reg, done, true); |
duke@435 | 1327 | st_ptr(G0, lockobj_addr); // free entry |
duke@435 | 1328 | } |
duke@435 | 1329 | |
duke@435 | 1330 | // Test first if we are in the fast recursive case |
duke@435 | 1331 | ld_ptr(lock_addr, displaced_header_reg, BasicLock::displaced_header_offset_in_bytes()); |
duke@435 | 1332 | br_null(displaced_header_reg, true, Assembler::pn, done); |
duke@435 | 1333 | delayed()->st_ptr(G0, lockobj_addr); // free entry |
duke@435 | 1334 | |
duke@435 | 1335 | // See if it is still a light weight lock, if so we just unlock |
duke@435 | 1336 | // the object and we are done |
duke@435 | 1337 | |
duke@435 | 1338 | if (!UseBiasedLocking) { |
duke@435 | 1339 | // load the object out of the BasicObjectLock |
duke@435 | 1340 | ld_ptr(lockobj_addr, obj_reg); |
duke@435 | 1341 | } |
duke@435 | 1342 | |
duke@435 | 1343 | // we have the displaced header in displaced_header_reg |
duke@435 | 1344 | // we expect to see the stack address of the basicLock in case the |
duke@435 | 1345 | // lock is still a light weight lock (lock_reg) |
duke@435 | 1346 | assert(mark_addr.disp() == 0, "cas must take a zero displacement"); |
duke@435 | 1347 | casx_under_lock(mark_addr.base(), lock_reg, displaced_header_reg, |
duke@435 | 1348 | (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); |
duke@435 | 1349 | cmp(lock_reg, displaced_header_reg); |
duke@435 | 1350 | brx(Assembler::equal, true, Assembler::pn, done); |
duke@435 | 1351 | delayed()->st_ptr(G0, lockobj_addr); // free entry |
duke@435 | 1352 | |
duke@435 | 1353 | // The lock has been converted into a heavy lock and hence |
duke@435 | 1354 | // we need to get into the slow case |
duke@435 | 1355 | |
duke@435 | 1356 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); |
duke@435 | 1357 | |
duke@435 | 1358 | bind(done); |
duke@435 | 1359 | } |
duke@435 | 1360 | } |
duke@435 | 1361 | |
duke@435 | 1362 | #ifndef CC_INTERP |
duke@435 | 1363 | |
duke@435 | 1364 | // Get the method data pointer from the methodOop and set the |
duke@435 | 1365 | // specified register to its value. |
duke@435 | 1366 | |
duke@435 | 1367 | void InterpreterMacroAssembler::set_method_data_pointer_offset(Register Roff) { |
duke@435 | 1368 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1369 | Label get_continue; |
duke@435 | 1370 | |
duke@435 | 1371 | ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr); |
duke@435 | 1372 | test_method_data_pointer(get_continue); |
duke@435 | 1373 | add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr); |
duke@435 | 1374 | if (Roff != noreg) |
duke@435 | 1375 | // Roff contains a method data index ("mdi"). It defaults to zero. |
duke@435 | 1376 | add(ImethodDataPtr, Roff, ImethodDataPtr); |
duke@435 | 1377 | bind(get_continue); |
duke@435 | 1378 | } |
duke@435 | 1379 | |
duke@435 | 1380 | // Set the method data pointer for the current bcp. |
duke@435 | 1381 | |
duke@435 | 1382 | void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { |
duke@435 | 1383 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1384 | Label zero_continue; |
duke@435 | 1385 | |
duke@435 | 1386 | // Test MDO to avoid the call if it is NULL. |
duke@435 | 1387 | ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr); |
duke@435 | 1388 | test_method_data_pointer(zero_continue); |
duke@435 | 1389 | call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), Lmethod, Lbcp); |
duke@435 | 1390 | set_method_data_pointer_offset(O0); |
duke@435 | 1391 | bind(zero_continue); |
duke@435 | 1392 | } |
duke@435 | 1393 | |
duke@435 | 1394 | // Test ImethodDataPtr. If it is null, continue at the specified label |
duke@435 | 1395 | |
duke@435 | 1396 | void InterpreterMacroAssembler::test_method_data_pointer(Label& zero_continue) { |
duke@435 | 1397 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1398 | #ifdef _LP64 |
duke@435 | 1399 | bpr(Assembler::rc_z, false, Assembler::pn, ImethodDataPtr, zero_continue); |
duke@435 | 1400 | #else |
duke@435 | 1401 | tst(ImethodDataPtr); |
duke@435 | 1402 | br(Assembler::zero, false, Assembler::pn, zero_continue); |
duke@435 | 1403 | #endif |
duke@435 | 1404 | delayed()->nop(); |
duke@435 | 1405 | } |
duke@435 | 1406 | |
duke@435 | 1407 | void InterpreterMacroAssembler::verify_method_data_pointer() { |
duke@435 | 1408 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1409 | #ifdef ASSERT |
duke@435 | 1410 | Label verify_continue; |
duke@435 | 1411 | test_method_data_pointer(verify_continue); |
duke@435 | 1412 | |
duke@435 | 1413 | // If the mdp is valid, it will point to a DataLayout header which is |
duke@435 | 1414 | // consistent with the bcp. The converse is highly probable also. |
duke@435 | 1415 | lduh(ImethodDataPtr, in_bytes(DataLayout::bci_offset()), G3_scratch); |
duke@435 | 1416 | ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::const_offset())), O5); |
duke@435 | 1417 | add(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()), G3_scratch); |
duke@435 | 1418 | add(G3_scratch, O5, G3_scratch); |
duke@435 | 1419 | cmp(Lbcp, G3_scratch); |
duke@435 | 1420 | brx(Assembler::equal, false, Assembler::pt, verify_continue); |
duke@435 | 1421 | |
duke@435 | 1422 | Register temp_reg = O5; |
duke@435 | 1423 | delayed()->mov(ImethodDataPtr, temp_reg); |
duke@435 | 1424 | // %%% should use call_VM_leaf here? |
duke@435 | 1425 | //call_VM_leaf(noreg, ..., Lmethod, Lbcp, ImethodDataPtr); |
duke@435 | 1426 | save_frame_and_mov(sizeof(jdouble) / wordSize, Lmethod, O0, Lbcp, O1); |
duke@435 | 1427 | Address d_save(FP, 0, -sizeof(jdouble) + STACK_BIAS); |
duke@435 | 1428 | stf(FloatRegisterImpl::D, Ftos_d, d_save); |
duke@435 | 1429 | mov(temp_reg->after_save(), O2); |
duke@435 | 1430 | save_thread(L7_thread_cache); |
duke@435 | 1431 | call(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), relocInfo::none); |
duke@435 | 1432 | delayed()->nop(); |
duke@435 | 1433 | restore_thread(L7_thread_cache); |
duke@435 | 1434 | ldf(FloatRegisterImpl::D, d_save, Ftos_d); |
duke@435 | 1435 | restore(); |
duke@435 | 1436 | bind(verify_continue); |
duke@435 | 1437 | #endif // ASSERT |
duke@435 | 1438 | } |
duke@435 | 1439 | |
duke@435 | 1440 | void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count, |
duke@435 | 1441 | Register cur_bcp, |
duke@435 | 1442 | Register Rtmp, |
duke@435 | 1443 | Label &profile_continue) { |
duke@435 | 1444 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1445 | // Control will flow to "profile_continue" if the counter is less than the |
duke@435 | 1446 | // limit or if we call profile_method() |
duke@435 | 1447 | |
duke@435 | 1448 | Label done; |
duke@435 | 1449 | |
duke@435 | 1450 | // if no method data exists, and the counter is high enough, make one |
duke@435 | 1451 | #ifdef _LP64 |
duke@435 | 1452 | bpr(Assembler::rc_nz, false, Assembler::pn, ImethodDataPtr, done); |
duke@435 | 1453 | #else |
duke@435 | 1454 | tst(ImethodDataPtr); |
duke@435 | 1455 | br(Assembler::notZero, false, Assembler::pn, done); |
duke@435 | 1456 | #endif |
duke@435 | 1457 | |
duke@435 | 1458 | // Test to see if we should create a method data oop |
duke@435 | 1459 | Address profile_limit(Rtmp, (address)&InvocationCounter::InterpreterProfileLimit); |
duke@435 | 1460 | #ifdef _LP64 |
duke@435 | 1461 | delayed()->nop(); |
duke@435 | 1462 | sethi(profile_limit); |
duke@435 | 1463 | #else |
duke@435 | 1464 | delayed()->sethi(profile_limit); |
duke@435 | 1465 | #endif |
duke@435 | 1466 | ld(profile_limit, Rtmp); |
duke@435 | 1467 | cmp(invocation_count, Rtmp); |
duke@435 | 1468 | br(Assembler::lessUnsigned, false, Assembler::pn, profile_continue); |
duke@435 | 1469 | delayed()->nop(); |
duke@435 | 1470 | |
duke@435 | 1471 | // Build it now. |
duke@435 | 1472 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), cur_bcp); |
duke@435 | 1473 | set_method_data_pointer_offset(O0); |
duke@435 | 1474 | ba(false, profile_continue); |
duke@435 | 1475 | delayed()->nop(); |
duke@435 | 1476 | bind(done); |
duke@435 | 1477 | } |
duke@435 | 1478 | |
duke@435 | 1479 | // Store a value at some constant offset from the method data pointer. |
duke@435 | 1480 | |
duke@435 | 1481 | void InterpreterMacroAssembler::set_mdp_data_at(int constant, Register value) { |
duke@435 | 1482 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1483 | st_ptr(value, ImethodDataPtr, constant); |
duke@435 | 1484 | } |
duke@435 | 1485 | |
duke@435 | 1486 | void InterpreterMacroAssembler::increment_mdp_data_at(Address counter, |
duke@435 | 1487 | Register bumped_count, |
duke@435 | 1488 | bool decrement) { |
duke@435 | 1489 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1490 | |
duke@435 | 1491 | // Load the counter. |
duke@435 | 1492 | ld_ptr(counter, bumped_count); |
duke@435 | 1493 | |
duke@435 | 1494 | if (decrement) { |
duke@435 | 1495 | // Decrement the register. Set condition codes. |
duke@435 | 1496 | subcc(bumped_count, DataLayout::counter_increment, bumped_count); |
duke@435 | 1497 | |
duke@435 | 1498 | // If the decrement causes the counter to overflow, stay negative |
duke@435 | 1499 | Label L; |
duke@435 | 1500 | brx(Assembler::negative, true, Assembler::pn, L); |
duke@435 | 1501 | |
duke@435 | 1502 | // Store the decremented counter, if it is still negative. |
duke@435 | 1503 | delayed()->st_ptr(bumped_count, counter); |
duke@435 | 1504 | bind(L); |
duke@435 | 1505 | } else { |
duke@435 | 1506 | // Increment the register. Set carry flag. |
duke@435 | 1507 | addcc(bumped_count, DataLayout::counter_increment, bumped_count); |
duke@435 | 1508 | |
duke@435 | 1509 | // If the increment causes the counter to overflow, pull back by 1. |
duke@435 | 1510 | assert(DataLayout::counter_increment == 1, "subc works"); |
duke@435 | 1511 | subc(bumped_count, G0, bumped_count); |
duke@435 | 1512 | |
duke@435 | 1513 | // Store the incremented counter. |
duke@435 | 1514 | st_ptr(bumped_count, counter); |
duke@435 | 1515 | } |
duke@435 | 1516 | } |
duke@435 | 1517 | |
duke@435 | 1518 | // Increment the value at some constant offset from the method data pointer. |
duke@435 | 1519 | |
duke@435 | 1520 | void InterpreterMacroAssembler::increment_mdp_data_at(int constant, |
duke@435 | 1521 | Register bumped_count, |
duke@435 | 1522 | bool decrement) { |
duke@435 | 1523 | // Locate the counter at a fixed offset from the mdp: |
duke@435 | 1524 | Address counter(ImethodDataPtr, 0, constant); |
duke@435 | 1525 | increment_mdp_data_at(counter, bumped_count, decrement); |
duke@435 | 1526 | } |
duke@435 | 1527 | |
duke@435 | 1528 | // Increment the value at some non-fixed (reg + constant) offset from |
duke@435 | 1529 | // the method data pointer. |
duke@435 | 1530 | |
duke@435 | 1531 | void InterpreterMacroAssembler::increment_mdp_data_at(Register reg, |
duke@435 | 1532 | int constant, |
duke@435 | 1533 | Register bumped_count, |
duke@435 | 1534 | Register scratch2, |
duke@435 | 1535 | bool decrement) { |
duke@435 | 1536 | // Add the constant to reg to get the offset. |
duke@435 | 1537 | add(ImethodDataPtr, reg, scratch2); |
duke@435 | 1538 | Address counter(scratch2, 0, constant); |
duke@435 | 1539 | increment_mdp_data_at(counter, bumped_count, decrement); |
duke@435 | 1540 | } |
duke@435 | 1541 | |
duke@435 | 1542 | // Set a flag value at the current method data pointer position. |
duke@435 | 1543 | // Updates a single byte of the header, to avoid races with other header bits. |
duke@435 | 1544 | |
duke@435 | 1545 | void InterpreterMacroAssembler::set_mdp_flag_at(int flag_constant, |
duke@435 | 1546 | Register scratch) { |
duke@435 | 1547 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1548 | // Load the data header |
duke@435 | 1549 | ldub(ImethodDataPtr, in_bytes(DataLayout::flags_offset()), scratch); |
duke@435 | 1550 | |
duke@435 | 1551 | // Set the flag |
duke@435 | 1552 | or3(scratch, flag_constant, scratch); |
duke@435 | 1553 | |
duke@435 | 1554 | // Store the modified header. |
duke@435 | 1555 | stb(scratch, ImethodDataPtr, in_bytes(DataLayout::flags_offset())); |
duke@435 | 1556 | } |
duke@435 | 1557 | |
duke@435 | 1558 | // Test the location at some offset from the method data pointer. |
duke@435 | 1559 | // If it is not equal to value, branch to the not_equal_continue Label. |
duke@435 | 1560 | // Set condition codes to match the nullness of the loaded value. |
duke@435 | 1561 | |
duke@435 | 1562 | void InterpreterMacroAssembler::test_mdp_data_at(int offset, |
duke@435 | 1563 | Register value, |
duke@435 | 1564 | Label& not_equal_continue, |
duke@435 | 1565 | Register scratch) { |
duke@435 | 1566 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1567 | ld_ptr(ImethodDataPtr, offset, scratch); |
duke@435 | 1568 | cmp(value, scratch); |
duke@435 | 1569 | brx(Assembler::notEqual, false, Assembler::pn, not_equal_continue); |
duke@435 | 1570 | delayed()->tst(scratch); |
duke@435 | 1571 | } |
duke@435 | 1572 | |
duke@435 | 1573 | // Update the method data pointer by the displacement located at some fixed |
duke@435 | 1574 | // offset from the method data pointer. |
duke@435 | 1575 | |
duke@435 | 1576 | void InterpreterMacroAssembler::update_mdp_by_offset(int offset_of_disp, |
duke@435 | 1577 | Register scratch) { |
duke@435 | 1578 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1579 | ld_ptr(ImethodDataPtr, offset_of_disp, scratch); |
duke@435 | 1580 | add(ImethodDataPtr, scratch, ImethodDataPtr); |
duke@435 | 1581 | } |
duke@435 | 1582 | |
duke@435 | 1583 | // Update the method data pointer by the displacement located at the |
duke@435 | 1584 | // offset (reg + offset_of_disp). |
duke@435 | 1585 | |
duke@435 | 1586 | void InterpreterMacroAssembler::update_mdp_by_offset(Register reg, |
duke@435 | 1587 | int offset_of_disp, |
duke@435 | 1588 | Register scratch) { |
duke@435 | 1589 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1590 | add(reg, offset_of_disp, scratch); |
duke@435 | 1591 | ld_ptr(ImethodDataPtr, scratch, scratch); |
duke@435 | 1592 | add(ImethodDataPtr, scratch, ImethodDataPtr); |
duke@435 | 1593 | } |
duke@435 | 1594 | |
duke@435 | 1595 | // Update the method data pointer by a simple constant displacement. |
duke@435 | 1596 | |
duke@435 | 1597 | void InterpreterMacroAssembler::update_mdp_by_constant(int constant) { |
duke@435 | 1598 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1599 | add(ImethodDataPtr, constant, ImethodDataPtr); |
duke@435 | 1600 | } |
duke@435 | 1601 | |
duke@435 | 1602 | // Update the method data pointer for a _ret bytecode whose target |
duke@435 | 1603 | // was not among our cached targets. |
duke@435 | 1604 | |
duke@435 | 1605 | void InterpreterMacroAssembler::update_mdp_for_ret(TosState state, |
duke@435 | 1606 | Register return_bci) { |
duke@435 | 1607 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1608 | push(state); |
duke@435 | 1609 | st_ptr(return_bci, l_tmp); // protect return_bci, in case it is volatile |
duke@435 | 1610 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); |
duke@435 | 1611 | ld_ptr(l_tmp, return_bci); |
duke@435 | 1612 | pop(state); |
duke@435 | 1613 | } |
duke@435 | 1614 | |
duke@435 | 1615 | // Count a taken branch in the bytecodes. |
duke@435 | 1616 | |
duke@435 | 1617 | void InterpreterMacroAssembler::profile_taken_branch(Register scratch, Register bumped_count) { |
duke@435 | 1618 | if (ProfileInterpreter) { |
duke@435 | 1619 | Label profile_continue; |
duke@435 | 1620 | |
duke@435 | 1621 | // If no method data exists, go to profile_continue. |
duke@435 | 1622 | test_method_data_pointer(profile_continue); |
duke@435 | 1623 | |
duke@435 | 1624 | // We are taking a branch. Increment the taken count. |
duke@435 | 1625 | increment_mdp_data_at(in_bytes(JumpData::taken_offset()), bumped_count); |
duke@435 | 1626 | |
duke@435 | 1627 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1628 | update_mdp_by_offset(in_bytes(JumpData::displacement_offset()), scratch); |
duke@435 | 1629 | bind (profile_continue); |
duke@435 | 1630 | } |
duke@435 | 1631 | } |
duke@435 | 1632 | |
duke@435 | 1633 | |
duke@435 | 1634 | // Count a not-taken branch in the bytecodes. |
duke@435 | 1635 | |
duke@435 | 1636 | void InterpreterMacroAssembler::profile_not_taken_branch(Register scratch) { |
duke@435 | 1637 | if (ProfileInterpreter) { |
duke@435 | 1638 | Label profile_continue; |
duke@435 | 1639 | |
duke@435 | 1640 | // If no method data exists, go to profile_continue. |
duke@435 | 1641 | test_method_data_pointer(profile_continue); |
duke@435 | 1642 | |
duke@435 | 1643 | // We are taking a branch. Increment the not taken count. |
duke@435 | 1644 | increment_mdp_data_at(in_bytes(BranchData::not_taken_offset()), scratch); |
duke@435 | 1645 | |
duke@435 | 1646 | // The method data pointer needs to be updated to correspond to the |
duke@435 | 1647 | // next bytecode. |
duke@435 | 1648 | update_mdp_by_constant(in_bytes(BranchData::branch_data_size())); |
duke@435 | 1649 | bind (profile_continue); |
duke@435 | 1650 | } |
duke@435 | 1651 | } |
duke@435 | 1652 | |
duke@435 | 1653 | |
duke@435 | 1654 | // Count a non-virtual call in the bytecodes. |
duke@435 | 1655 | |
duke@435 | 1656 | void InterpreterMacroAssembler::profile_call(Register scratch) { |
duke@435 | 1657 | if (ProfileInterpreter) { |
duke@435 | 1658 | Label profile_continue; |
duke@435 | 1659 | |
duke@435 | 1660 | // If no method data exists, go to profile_continue. |
duke@435 | 1661 | test_method_data_pointer(profile_continue); |
duke@435 | 1662 | |
duke@435 | 1663 | // We are making a call. Increment the count. |
duke@435 | 1664 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1665 | |
duke@435 | 1666 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1667 | update_mdp_by_constant(in_bytes(CounterData::counter_data_size())); |
duke@435 | 1668 | bind (profile_continue); |
duke@435 | 1669 | } |
duke@435 | 1670 | } |
duke@435 | 1671 | |
duke@435 | 1672 | |
duke@435 | 1673 | // Count a final call in the bytecodes. |
duke@435 | 1674 | |
duke@435 | 1675 | void InterpreterMacroAssembler::profile_final_call(Register scratch) { |
duke@435 | 1676 | if (ProfileInterpreter) { |
duke@435 | 1677 | Label profile_continue; |
duke@435 | 1678 | |
duke@435 | 1679 | // If no method data exists, go to profile_continue. |
duke@435 | 1680 | test_method_data_pointer(profile_continue); |
duke@435 | 1681 | |
duke@435 | 1682 | // We are making a call. Increment the count. |
duke@435 | 1683 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1684 | |
duke@435 | 1685 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1686 | update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); |
duke@435 | 1687 | bind (profile_continue); |
duke@435 | 1688 | } |
duke@435 | 1689 | } |
duke@435 | 1690 | |
duke@435 | 1691 | |
duke@435 | 1692 | // Count a virtual call in the bytecodes. |
duke@435 | 1693 | |
duke@435 | 1694 | void InterpreterMacroAssembler::profile_virtual_call(Register receiver, |
duke@435 | 1695 | Register scratch) { |
duke@435 | 1696 | if (ProfileInterpreter) { |
duke@435 | 1697 | Label profile_continue; |
duke@435 | 1698 | |
duke@435 | 1699 | // If no method data exists, go to profile_continue. |
duke@435 | 1700 | test_method_data_pointer(profile_continue); |
duke@435 | 1701 | |
duke@435 | 1702 | // We are making a call. Increment the count. |
duke@435 | 1703 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1704 | |
duke@435 | 1705 | // Record the receiver type. |
duke@435 | 1706 | record_klass_in_profile(receiver, scratch); |
duke@435 | 1707 | |
duke@435 | 1708 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1709 | update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); |
duke@435 | 1710 | bind (profile_continue); |
duke@435 | 1711 | } |
duke@435 | 1712 | } |
duke@435 | 1713 | |
duke@435 | 1714 | void InterpreterMacroAssembler::record_klass_in_profile_helper( |
duke@435 | 1715 | Register receiver, Register scratch, |
duke@435 | 1716 | int start_row, Label& done) { |
duke@435 | 1717 | int last_row = VirtualCallData::row_limit() - 1; |
duke@435 | 1718 | assert(start_row <= last_row, "must be work left to do"); |
duke@435 | 1719 | // Test this row for both the receiver and for null. |
duke@435 | 1720 | // Take any of three different outcomes: |
duke@435 | 1721 | // 1. found receiver => increment count and goto done |
duke@435 | 1722 | // 2. found null => keep looking for case 1, maybe allocate this cell |
duke@435 | 1723 | // 3. found something else => keep looking for cases 1 and 2 |
duke@435 | 1724 | // Case 3 is handled by a recursive call. |
duke@435 | 1725 | for (int row = start_row; row <= last_row; row++) { |
duke@435 | 1726 | Label next_test; |
duke@435 | 1727 | bool test_for_null_also = (row == start_row); |
duke@435 | 1728 | |
duke@435 | 1729 | // See if the receiver is receiver[n]. |
duke@435 | 1730 | int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); |
duke@435 | 1731 | test_mdp_data_at(recvr_offset, receiver, next_test, scratch); |
duke@435 | 1732 | |
duke@435 | 1733 | // The receiver is receiver[n]. Increment count[n]. |
duke@435 | 1734 | int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); |
duke@435 | 1735 | increment_mdp_data_at(count_offset, scratch); |
duke@435 | 1736 | ba(false, done); |
duke@435 | 1737 | delayed()->nop(); |
duke@435 | 1738 | bind(next_test); |
duke@435 | 1739 | |
duke@435 | 1740 | if (test_for_null_also) { |
duke@435 | 1741 | // Failed the equality check on receiver[n]... Test for null. |
duke@435 | 1742 | if (start_row == last_row) { |
duke@435 | 1743 | // The only thing left to do is handle the null case. |
duke@435 | 1744 | brx(Assembler::notZero, false, Assembler::pt, done); |
duke@435 | 1745 | delayed()->nop(); |
duke@435 | 1746 | break; |
duke@435 | 1747 | } |
duke@435 | 1748 | // Since null is rare, make it be the branch-taken case. |
duke@435 | 1749 | Label found_null; |
duke@435 | 1750 | brx(Assembler::zero, false, Assembler::pn, found_null); |
duke@435 | 1751 | delayed()->nop(); |
duke@435 | 1752 | |
duke@435 | 1753 | // Put all the "Case 3" tests here. |
duke@435 | 1754 | record_klass_in_profile_helper(receiver, scratch, start_row + 1, done); |
duke@435 | 1755 | |
duke@435 | 1756 | // Found a null. Keep searching for a matching receiver, |
duke@435 | 1757 | // but remember that this is an empty (unused) slot. |
duke@435 | 1758 | bind(found_null); |
duke@435 | 1759 | } |
duke@435 | 1760 | } |
duke@435 | 1761 | |
duke@435 | 1762 | // In the fall-through case, we found no matching receiver, but we |
duke@435 | 1763 | // observed the receiver[start_row] is NULL. |
duke@435 | 1764 | |
duke@435 | 1765 | // Fill in the receiver field and increment the count. |
duke@435 | 1766 | int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); |
duke@435 | 1767 | set_mdp_data_at(recvr_offset, receiver); |
duke@435 | 1768 | int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); |
duke@435 | 1769 | mov(DataLayout::counter_increment, scratch); |
duke@435 | 1770 | set_mdp_data_at(count_offset, scratch); |
duke@435 | 1771 | ba(false, done); |
duke@435 | 1772 | delayed()->nop(); |
duke@435 | 1773 | } |
duke@435 | 1774 | |
duke@435 | 1775 | void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, |
duke@435 | 1776 | Register scratch) { |
duke@435 | 1777 | assert(ProfileInterpreter, "must be profiling"); |
duke@435 | 1778 | Label done; |
duke@435 | 1779 | |
duke@435 | 1780 | record_klass_in_profile_helper(receiver, scratch, 0, done); |
duke@435 | 1781 | |
duke@435 | 1782 | bind (done); |
duke@435 | 1783 | } |
duke@435 | 1784 | |
duke@435 | 1785 | |
duke@435 | 1786 | // Count a ret in the bytecodes. |
duke@435 | 1787 | |
duke@435 | 1788 | void InterpreterMacroAssembler::profile_ret(TosState state, |
duke@435 | 1789 | Register return_bci, |
duke@435 | 1790 | Register scratch) { |
duke@435 | 1791 | if (ProfileInterpreter) { |
duke@435 | 1792 | Label profile_continue; |
duke@435 | 1793 | uint row; |
duke@435 | 1794 | |
duke@435 | 1795 | // If no method data exists, go to profile_continue. |
duke@435 | 1796 | test_method_data_pointer(profile_continue); |
duke@435 | 1797 | |
duke@435 | 1798 | // Update the total ret count. |
duke@435 | 1799 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1800 | |
duke@435 | 1801 | for (row = 0; row < RetData::row_limit(); row++) { |
duke@435 | 1802 | Label next_test; |
duke@435 | 1803 | |
duke@435 | 1804 | // See if return_bci is equal to bci[n]: |
duke@435 | 1805 | test_mdp_data_at(in_bytes(RetData::bci_offset(row)), |
duke@435 | 1806 | return_bci, next_test, scratch); |
duke@435 | 1807 | |
duke@435 | 1808 | // return_bci is equal to bci[n]. Increment the count. |
duke@435 | 1809 | increment_mdp_data_at(in_bytes(RetData::bci_count_offset(row)), scratch); |
duke@435 | 1810 | |
duke@435 | 1811 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1812 | update_mdp_by_offset(in_bytes(RetData::bci_displacement_offset(row)), scratch); |
duke@435 | 1813 | ba(false, profile_continue); |
duke@435 | 1814 | delayed()->nop(); |
duke@435 | 1815 | bind(next_test); |
duke@435 | 1816 | } |
duke@435 | 1817 | |
duke@435 | 1818 | update_mdp_for_ret(state, return_bci); |
duke@435 | 1819 | |
duke@435 | 1820 | bind (profile_continue); |
duke@435 | 1821 | } |
duke@435 | 1822 | } |
duke@435 | 1823 | |
duke@435 | 1824 | // Profile an unexpected null in the bytecodes. |
duke@435 | 1825 | void InterpreterMacroAssembler::profile_null_seen(Register scratch) { |
duke@435 | 1826 | if (ProfileInterpreter) { |
duke@435 | 1827 | Label profile_continue; |
duke@435 | 1828 | |
duke@435 | 1829 | // If no method data exists, go to profile_continue. |
duke@435 | 1830 | test_method_data_pointer(profile_continue); |
duke@435 | 1831 | |
duke@435 | 1832 | set_mdp_flag_at(BitData::null_seen_byte_constant(), scratch); |
duke@435 | 1833 | |
duke@435 | 1834 | // The method data pointer needs to be updated. |
duke@435 | 1835 | int mdp_delta = in_bytes(BitData::bit_data_size()); |
duke@435 | 1836 | if (TypeProfileCasts) { |
duke@435 | 1837 | mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); |
duke@435 | 1838 | } |
duke@435 | 1839 | update_mdp_by_constant(mdp_delta); |
duke@435 | 1840 | |
duke@435 | 1841 | bind (profile_continue); |
duke@435 | 1842 | } |
duke@435 | 1843 | } |
duke@435 | 1844 | |
duke@435 | 1845 | void InterpreterMacroAssembler::profile_typecheck(Register klass, |
duke@435 | 1846 | Register scratch) { |
duke@435 | 1847 | if (ProfileInterpreter) { |
duke@435 | 1848 | Label profile_continue; |
duke@435 | 1849 | |
duke@435 | 1850 | // If no method data exists, go to profile_continue. |
duke@435 | 1851 | test_method_data_pointer(profile_continue); |
duke@435 | 1852 | |
duke@435 | 1853 | int mdp_delta = in_bytes(BitData::bit_data_size()); |
duke@435 | 1854 | if (TypeProfileCasts) { |
duke@435 | 1855 | mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); |
duke@435 | 1856 | |
duke@435 | 1857 | // Record the object type. |
duke@435 | 1858 | record_klass_in_profile(klass, scratch); |
duke@435 | 1859 | } |
duke@435 | 1860 | |
duke@435 | 1861 | // The method data pointer needs to be updated. |
duke@435 | 1862 | update_mdp_by_constant(mdp_delta); |
duke@435 | 1863 | |
duke@435 | 1864 | bind (profile_continue); |
duke@435 | 1865 | } |
duke@435 | 1866 | } |
duke@435 | 1867 | |
duke@435 | 1868 | void InterpreterMacroAssembler::profile_typecheck_failed(Register scratch) { |
duke@435 | 1869 | if (ProfileInterpreter && TypeProfileCasts) { |
duke@435 | 1870 | Label profile_continue; |
duke@435 | 1871 | |
duke@435 | 1872 | // If no method data exists, go to profile_continue. |
duke@435 | 1873 | test_method_data_pointer(profile_continue); |
duke@435 | 1874 | |
duke@435 | 1875 | int count_offset = in_bytes(CounterData::count_offset()); |
duke@435 | 1876 | // Back up the address, since we have already bumped the mdp. |
duke@435 | 1877 | count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); |
duke@435 | 1878 | |
duke@435 | 1879 | // *Decrement* the counter. We expect to see zero or small negatives. |
duke@435 | 1880 | increment_mdp_data_at(count_offset, scratch, true); |
duke@435 | 1881 | |
duke@435 | 1882 | bind (profile_continue); |
duke@435 | 1883 | } |
duke@435 | 1884 | } |
duke@435 | 1885 | |
duke@435 | 1886 | // Count the default case of a switch construct. |
duke@435 | 1887 | |
duke@435 | 1888 | void InterpreterMacroAssembler::profile_switch_default(Register scratch) { |
duke@435 | 1889 | if (ProfileInterpreter) { |
duke@435 | 1890 | Label profile_continue; |
duke@435 | 1891 | |
duke@435 | 1892 | // If no method data exists, go to profile_continue. |
duke@435 | 1893 | test_method_data_pointer(profile_continue); |
duke@435 | 1894 | |
duke@435 | 1895 | // Update the default case count |
duke@435 | 1896 | increment_mdp_data_at(in_bytes(MultiBranchData::default_count_offset()), |
duke@435 | 1897 | scratch); |
duke@435 | 1898 | |
duke@435 | 1899 | // The method data pointer needs to be updated. |
duke@435 | 1900 | update_mdp_by_offset( |
duke@435 | 1901 | in_bytes(MultiBranchData::default_displacement_offset()), |
duke@435 | 1902 | scratch); |
duke@435 | 1903 | |
duke@435 | 1904 | bind (profile_continue); |
duke@435 | 1905 | } |
duke@435 | 1906 | } |
duke@435 | 1907 | |
duke@435 | 1908 | // Count the index'th case of a switch construct. |
duke@435 | 1909 | |
duke@435 | 1910 | void InterpreterMacroAssembler::profile_switch_case(Register index, |
duke@435 | 1911 | Register scratch, |
duke@435 | 1912 | Register scratch2, |
duke@435 | 1913 | Register scratch3) { |
duke@435 | 1914 | if (ProfileInterpreter) { |
duke@435 | 1915 | Label profile_continue; |
duke@435 | 1916 | |
duke@435 | 1917 | // If no method data exists, go to profile_continue. |
duke@435 | 1918 | test_method_data_pointer(profile_continue); |
duke@435 | 1919 | |
duke@435 | 1920 | // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() |
duke@435 | 1921 | set(in_bytes(MultiBranchData::per_case_size()), scratch); |
duke@435 | 1922 | smul(index, scratch, scratch); |
duke@435 | 1923 | add(scratch, in_bytes(MultiBranchData::case_array_offset()), scratch); |
duke@435 | 1924 | |
duke@435 | 1925 | // Update the case count |
duke@435 | 1926 | increment_mdp_data_at(scratch, |
duke@435 | 1927 | in_bytes(MultiBranchData::relative_count_offset()), |
duke@435 | 1928 | scratch2, |
duke@435 | 1929 | scratch3); |
duke@435 | 1930 | |
duke@435 | 1931 | // The method data pointer needs to be updated. |
duke@435 | 1932 | update_mdp_by_offset(scratch, |
duke@435 | 1933 | in_bytes(MultiBranchData::relative_displacement_offset()), |
duke@435 | 1934 | scratch2); |
duke@435 | 1935 | |
duke@435 | 1936 | bind (profile_continue); |
duke@435 | 1937 | } |
duke@435 | 1938 | } |
duke@435 | 1939 | |
duke@435 | 1940 | // add a InterpMonitorElem to stack (see frame_sparc.hpp) |
duke@435 | 1941 | |
duke@435 | 1942 | void InterpreterMacroAssembler::add_monitor_to_stack( bool stack_is_empty, |
duke@435 | 1943 | Register Rtemp, |
duke@435 | 1944 | Register Rtemp2 ) { |
duke@435 | 1945 | |
duke@435 | 1946 | Register Rlimit = Lmonitors; |
duke@435 | 1947 | const jint delta = frame::interpreter_frame_monitor_size() * wordSize; |
duke@435 | 1948 | assert( (delta & LongAlignmentMask) == 0, |
duke@435 | 1949 | "sizeof BasicObjectLock must be even number of doublewords"); |
duke@435 | 1950 | |
duke@435 | 1951 | sub( SP, delta, SP); |
duke@435 | 1952 | sub( Lesp, delta, Lesp); |
duke@435 | 1953 | sub( Lmonitors, delta, Lmonitors); |
duke@435 | 1954 | |
duke@435 | 1955 | if (!stack_is_empty) { |
duke@435 | 1956 | |
duke@435 | 1957 | // must copy stack contents down |
duke@435 | 1958 | |
duke@435 | 1959 | Label start_copying, next; |
duke@435 | 1960 | |
duke@435 | 1961 | // untested("monitor stack expansion"); |
duke@435 | 1962 | compute_stack_base(Rtemp); |
duke@435 | 1963 | ba( false, start_copying ); |
duke@435 | 1964 | delayed()->cmp( Rtemp, Rlimit); // done? duplicated below |
duke@435 | 1965 | |
duke@435 | 1966 | // note: must copy from low memory upwards |
duke@435 | 1967 | // On entry to loop, |
duke@435 | 1968 | // Rtemp points to new base of stack, Lesp points to new end of stack (1 past TOS) |
duke@435 | 1969 | // Loop mutates Rtemp |
duke@435 | 1970 | |
duke@435 | 1971 | bind( next); |
duke@435 | 1972 | |
duke@435 | 1973 | st_ptr(Rtemp2, Rtemp, 0); |
duke@435 | 1974 | inc(Rtemp, wordSize); |
duke@435 | 1975 | cmp(Rtemp, Rlimit); // are we done? (duplicated above) |
duke@435 | 1976 | |
duke@435 | 1977 | bind( start_copying ); |
duke@435 | 1978 | |
duke@435 | 1979 | brx( notEqual, true, pn, next ); |
duke@435 | 1980 | delayed()->ld_ptr( Rtemp, delta, Rtemp2 ); |
duke@435 | 1981 | |
duke@435 | 1982 | // done copying stack |
duke@435 | 1983 | } |
duke@435 | 1984 | } |
duke@435 | 1985 | |
duke@435 | 1986 | // Locals |
duke@435 | 1987 | #ifdef ASSERT |
duke@435 | 1988 | void InterpreterMacroAssembler::verify_local_tag(frame::Tag t, |
duke@435 | 1989 | Register base, |
duke@435 | 1990 | Register scratch, |
duke@435 | 1991 | int n) { |
duke@435 | 1992 | if (TaggedStackInterpreter) { |
duke@435 | 1993 | Label ok, long_ok; |
duke@435 | 1994 | // Use dst for scratch |
duke@435 | 1995 | assert_different_registers(base, scratch); |
duke@435 | 1996 | ld_ptr(base, Interpreter::local_tag_offset_in_bytes(n), scratch); |
duke@435 | 1997 | if (t == frame::TagCategory2) { |
duke@435 | 1998 | cmp(scratch, G0); |
duke@435 | 1999 | brx(Assembler::equal, false, Assembler::pt, long_ok); |
duke@435 | 2000 | delayed()->ld_ptr(base, Interpreter::local_tag_offset_in_bytes(n+1), scratch); |
duke@435 | 2001 | stop("local long/double tag value bad"); |
duke@435 | 2002 | bind(long_ok); |
duke@435 | 2003 | // compare second half tag |
duke@435 | 2004 | cmp(scratch, G0); |
duke@435 | 2005 | } else if (t == frame::TagValue) { |
duke@435 | 2006 | cmp(scratch, G0); |
duke@435 | 2007 | } else { |
duke@435 | 2008 | assert_different_registers(O3, base, scratch); |
duke@435 | 2009 | mov(t, O3); |
duke@435 | 2010 | cmp(scratch, O3); |
duke@435 | 2011 | } |
duke@435 | 2012 | brx(Assembler::equal, false, Assembler::pt, ok); |
duke@435 | 2013 | delayed()->nop(); |
duke@435 | 2014 | // Also compare if the local value is zero, then the tag might |
duke@435 | 2015 | // not have been set coming from deopt. |
duke@435 | 2016 | ld_ptr(base, Interpreter::local_offset_in_bytes(n), scratch); |
duke@435 | 2017 | cmp(scratch, G0); |
duke@435 | 2018 | brx(Assembler::equal, false, Assembler::pt, ok); |
duke@435 | 2019 | delayed()->nop(); |
duke@435 | 2020 | stop("Local tag value is bad"); |
duke@435 | 2021 | bind(ok); |
duke@435 | 2022 | } |
duke@435 | 2023 | } |
duke@435 | 2024 | #endif // ASSERT |
duke@435 | 2025 | |
duke@435 | 2026 | void InterpreterMacroAssembler::access_local_ptr( Register index, Register dst ) { |
duke@435 | 2027 | assert_not_delayed(); |
duke@435 | 2028 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2029 | sub(Llocals, index, index); |
duke@435 | 2030 | debug_only(verify_local_tag(frame::TagReference, index, dst)); |
duke@435 | 2031 | ld_ptr(index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2032 | // Note: index must hold the effective address--the iinc template uses it |
duke@435 | 2033 | } |
duke@435 | 2034 | |
duke@435 | 2035 | // Just like access_local_ptr but the tag is a returnAddress |
duke@435 | 2036 | void InterpreterMacroAssembler::access_local_returnAddress(Register index, |
duke@435 | 2037 | Register dst ) { |
duke@435 | 2038 | assert_not_delayed(); |
duke@435 | 2039 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2040 | sub(Llocals, index, index); |
duke@435 | 2041 | debug_only(verify_local_tag(frame::TagValue, index, dst)); |
duke@435 | 2042 | ld_ptr(index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2043 | } |
duke@435 | 2044 | |
duke@435 | 2045 | void InterpreterMacroAssembler::access_local_int( Register index, Register dst ) { |
duke@435 | 2046 | assert_not_delayed(); |
duke@435 | 2047 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2048 | sub(Llocals, index, index); |
duke@435 | 2049 | debug_only(verify_local_tag(frame::TagValue, index, dst)); |
duke@435 | 2050 | ld(index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2051 | // Note: index must hold the effective address--the iinc template uses it |
duke@435 | 2052 | } |
duke@435 | 2053 | |
duke@435 | 2054 | |
duke@435 | 2055 | void InterpreterMacroAssembler::access_local_long( Register index, Register dst ) { |
duke@435 | 2056 | assert_not_delayed(); |
duke@435 | 2057 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2058 | sub(Llocals, index, index); |
duke@435 | 2059 | debug_only(verify_local_tag(frame::TagCategory2, index, dst)); |
duke@435 | 2060 | // First half stored at index n+1 (which grows down from Llocals[n]) |
duke@435 | 2061 | load_unaligned_long(index, Interpreter::local_offset_in_bytes(1), dst); |
duke@435 | 2062 | } |
duke@435 | 2063 | |
duke@435 | 2064 | |
duke@435 | 2065 | void InterpreterMacroAssembler::access_local_float( Register index, FloatRegister dst ) { |
duke@435 | 2066 | assert_not_delayed(); |
duke@435 | 2067 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2068 | sub(Llocals, index, index); |
duke@435 | 2069 | debug_only(verify_local_tag(frame::TagValue, index, G1_scratch)); |
duke@435 | 2070 | ldf(FloatRegisterImpl::S, index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2071 | } |
duke@435 | 2072 | |
duke@435 | 2073 | |
duke@435 | 2074 | void InterpreterMacroAssembler::access_local_double( Register index, FloatRegister dst ) { |
duke@435 | 2075 | assert_not_delayed(); |
duke@435 | 2076 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2077 | sub(Llocals, index, index); |
duke@435 | 2078 | debug_only(verify_local_tag(frame::TagCategory2, index, G1_scratch)); |
duke@435 | 2079 | load_unaligned_double(index, Interpreter::local_offset_in_bytes(1), dst); |
duke@435 | 2080 | } |
duke@435 | 2081 | |
duke@435 | 2082 | |
duke@435 | 2083 | #ifdef ASSERT |
duke@435 | 2084 | void InterpreterMacroAssembler::check_for_regarea_stomp(Register Rindex, int offset, Register Rlimit, Register Rscratch, Register Rscratch1) { |
duke@435 | 2085 | Label L; |
duke@435 | 2086 | |
duke@435 | 2087 | assert(Rindex != Rscratch, "Registers cannot be same"); |
duke@435 | 2088 | assert(Rindex != Rscratch1, "Registers cannot be same"); |
duke@435 | 2089 | assert(Rlimit != Rscratch, "Registers cannot be same"); |
duke@435 | 2090 | assert(Rlimit != Rscratch1, "Registers cannot be same"); |
duke@435 | 2091 | assert(Rscratch1 != Rscratch, "Registers cannot be same"); |
duke@435 | 2092 | |
duke@435 | 2093 | // untested("reg area corruption"); |
duke@435 | 2094 | add(Rindex, offset, Rscratch); |
duke@435 | 2095 | add(Rlimit, 64 + STACK_BIAS, Rscratch1); |
duke@435 | 2096 | cmp(Rscratch, Rscratch1); |
duke@435 | 2097 | brx(Assembler::greaterEqualUnsigned, false, pn, L); |
duke@435 | 2098 | delayed()->nop(); |
duke@435 | 2099 | stop("regsave area is being clobbered"); |
duke@435 | 2100 | bind(L); |
duke@435 | 2101 | } |
duke@435 | 2102 | #endif // ASSERT |
duke@435 | 2103 | |
duke@435 | 2104 | void InterpreterMacroAssembler::tag_local(frame::Tag t, |
duke@435 | 2105 | Register base, |
duke@435 | 2106 | Register src, |
duke@435 | 2107 | int n) { |
duke@435 | 2108 | if (TaggedStackInterpreter) { |
duke@435 | 2109 | // have to store zero because local slots can be reused (rats!) |
duke@435 | 2110 | if (t == frame::TagValue) { |
duke@435 | 2111 | st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2112 | } else if (t == frame::TagCategory2) { |
duke@435 | 2113 | st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2114 | st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n+1)); |
duke@435 | 2115 | } else { |
duke@435 | 2116 | // assert that we don't stomp the value in 'src' |
duke@435 | 2117 | // O3 is arbitrary because it's not used. |
duke@435 | 2118 | assert_different_registers(src, base, O3); |
duke@435 | 2119 | mov( t, O3); |
duke@435 | 2120 | st_ptr(O3, base, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2121 | } |
duke@435 | 2122 | } |
duke@435 | 2123 | } |
duke@435 | 2124 | |
duke@435 | 2125 | |
duke@435 | 2126 | void InterpreterMacroAssembler::store_local_int( Register index, Register src ) { |
duke@435 | 2127 | assert_not_delayed(); |
duke@435 | 2128 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2129 | sub(Llocals, index, index); |
duke@435 | 2130 | debug_only(check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch);) |
duke@435 | 2131 | tag_local(frame::TagValue, index, src); |
duke@435 | 2132 | st(src, index, Interpreter::value_offset_in_bytes()); |
duke@435 | 2133 | } |
duke@435 | 2134 | |
duke@435 | 2135 | void InterpreterMacroAssembler::store_local_ptr( Register index, Register src, |
duke@435 | 2136 | Register tag ) { |
duke@435 | 2137 | assert_not_delayed(); |
duke@435 | 2138 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2139 | sub(Llocals, index, index); |
duke@435 | 2140 | #ifdef ASSERT |
duke@435 | 2141 | check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch); |
duke@435 | 2142 | #endif |
duke@435 | 2143 | st_ptr(src, index, Interpreter::value_offset_in_bytes()); |
duke@435 | 2144 | // Store tag register directly |
duke@435 | 2145 | if (TaggedStackInterpreter) { |
duke@435 | 2146 | st_ptr(tag, index, Interpreter::tag_offset_in_bytes()); |
duke@435 | 2147 | } |
duke@435 | 2148 | } |
duke@435 | 2149 | |
duke@435 | 2150 | |
duke@435 | 2151 | |
duke@435 | 2152 | void InterpreterMacroAssembler::store_local_ptr( int n, Register src, |
duke@435 | 2153 | Register tag ) { |
duke@435 | 2154 | st_ptr(src, Llocals, Interpreter::local_offset_in_bytes(n)); |
duke@435 | 2155 | if (TaggedStackInterpreter) { |
duke@435 | 2156 | st_ptr(tag, Llocals, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2157 | } |
duke@435 | 2158 | } |
duke@435 | 2159 | |
duke@435 | 2160 | void InterpreterMacroAssembler::store_local_long( Register index, Register src ) { |
duke@435 | 2161 | assert_not_delayed(); |
duke@435 | 2162 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2163 | sub(Llocals, index, index); |
duke@435 | 2164 | #ifdef ASSERT |
duke@435 | 2165 | check_for_regarea_stomp(index, Interpreter::local_offset_in_bytes(1), FP, G1_scratch, G4_scratch); |
duke@435 | 2166 | #endif |
duke@435 | 2167 | tag_local(frame::TagCategory2, index, src); |
duke@435 | 2168 | store_unaligned_long(src, index, Interpreter::local_offset_in_bytes(1)); // which is n+1 |
duke@435 | 2169 | } |
duke@435 | 2170 | |
duke@435 | 2171 | |
duke@435 | 2172 | void InterpreterMacroAssembler::store_local_float( Register index, FloatRegister src ) { |
duke@435 | 2173 | assert_not_delayed(); |
duke@435 | 2174 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2175 | sub(Llocals, index, index); |
duke@435 | 2176 | #ifdef ASSERT |
duke@435 | 2177 | check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch); |
duke@435 | 2178 | #endif |
duke@435 | 2179 | tag_local(frame::TagValue, index, G1_scratch); |
duke@435 | 2180 | stf(FloatRegisterImpl::S, src, index, Interpreter::value_offset_in_bytes()); |
duke@435 | 2181 | } |
duke@435 | 2182 | |
duke@435 | 2183 | |
duke@435 | 2184 | void InterpreterMacroAssembler::store_local_double( Register index, FloatRegister src ) { |
duke@435 | 2185 | assert_not_delayed(); |
duke@435 | 2186 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2187 | sub(Llocals, index, index); |
duke@435 | 2188 | #ifdef ASSERT |
duke@435 | 2189 | check_for_regarea_stomp(index, Interpreter::local_offset_in_bytes(1), FP, G1_scratch, G4_scratch); |
duke@435 | 2190 | #endif |
duke@435 | 2191 | tag_local(frame::TagCategory2, index, G1_scratch); |
duke@435 | 2192 | store_unaligned_double(src, index, Interpreter::local_offset_in_bytes(1)); |
duke@435 | 2193 | } |
duke@435 | 2194 | |
duke@435 | 2195 | |
duke@435 | 2196 | int InterpreterMacroAssembler::top_most_monitor_byte_offset() { |
duke@435 | 2197 | const jint delta = frame::interpreter_frame_monitor_size() * wordSize; |
duke@435 | 2198 | int rounded_vm_local_words = ::round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); |
duke@435 | 2199 | return ((-rounded_vm_local_words * wordSize) - delta ) + STACK_BIAS; |
duke@435 | 2200 | } |
duke@435 | 2201 | |
duke@435 | 2202 | |
duke@435 | 2203 | Address InterpreterMacroAssembler::top_most_monitor() { |
duke@435 | 2204 | return Address(FP, 0, top_most_monitor_byte_offset()); |
duke@435 | 2205 | } |
duke@435 | 2206 | |
duke@435 | 2207 | |
duke@435 | 2208 | void InterpreterMacroAssembler::compute_stack_base( Register Rdest ) { |
duke@435 | 2209 | add( Lesp, wordSize, Rdest ); |
duke@435 | 2210 | } |
duke@435 | 2211 | |
duke@435 | 2212 | #endif /* CC_INTERP */ |
duke@435 | 2213 | |
duke@435 | 2214 | void InterpreterMacroAssembler::increment_invocation_counter( Register Rtmp, Register Rtmp2 ) { |
duke@435 | 2215 | assert(UseCompiler, "incrementing must be useful"); |
duke@435 | 2216 | #ifdef CC_INTERP |
duke@435 | 2217 | Address inv_counter(G5_method, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2218 | + InvocationCounter::counter_offset())); |
duke@435 | 2219 | Address be_counter(G5_method, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2220 | + InvocationCounter::counter_offset())); |
duke@435 | 2221 | #else |
duke@435 | 2222 | Address inv_counter(Lmethod, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2223 | + InvocationCounter::counter_offset())); |
duke@435 | 2224 | Address be_counter(Lmethod, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2225 | + InvocationCounter::counter_offset())); |
duke@435 | 2226 | #endif /* CC_INTERP */ |
duke@435 | 2227 | int delta = InvocationCounter::count_increment; |
duke@435 | 2228 | |
duke@435 | 2229 | // Load each counter in a register |
duke@435 | 2230 | ld( inv_counter, Rtmp ); |
duke@435 | 2231 | ld( be_counter, Rtmp2 ); |
duke@435 | 2232 | |
duke@435 | 2233 | assert( is_simm13( delta ), " delta too large."); |
duke@435 | 2234 | |
duke@435 | 2235 | // Add the delta to the invocation counter and store the result |
duke@435 | 2236 | add( Rtmp, delta, Rtmp ); |
duke@435 | 2237 | |
duke@435 | 2238 | // Mask the backedge counter |
duke@435 | 2239 | and3( Rtmp2, InvocationCounter::count_mask_value, Rtmp2 ); |
duke@435 | 2240 | |
duke@435 | 2241 | // Store value |
duke@435 | 2242 | st( Rtmp, inv_counter); |
duke@435 | 2243 | |
duke@435 | 2244 | // Add invocation counter + backedge counter |
duke@435 | 2245 | add( Rtmp, Rtmp2, Rtmp); |
duke@435 | 2246 | |
duke@435 | 2247 | // Note that this macro must leave the backedge_count + invocation_count in Rtmp! |
duke@435 | 2248 | } |
duke@435 | 2249 | |
duke@435 | 2250 | void InterpreterMacroAssembler::increment_backedge_counter( Register Rtmp, Register Rtmp2 ) { |
duke@435 | 2251 | assert(UseCompiler, "incrementing must be useful"); |
duke@435 | 2252 | #ifdef CC_INTERP |
duke@435 | 2253 | Address be_counter(G5_method, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2254 | + InvocationCounter::counter_offset())); |
duke@435 | 2255 | Address inv_counter(G5_method, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2256 | + InvocationCounter::counter_offset())); |
duke@435 | 2257 | #else |
duke@435 | 2258 | Address be_counter(Lmethod, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2259 | + InvocationCounter::counter_offset())); |
duke@435 | 2260 | Address inv_counter(Lmethod, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2261 | + InvocationCounter::counter_offset())); |
duke@435 | 2262 | #endif /* CC_INTERP */ |
duke@435 | 2263 | int delta = InvocationCounter::count_increment; |
duke@435 | 2264 | // Load each counter in a register |
duke@435 | 2265 | ld( be_counter, Rtmp ); |
duke@435 | 2266 | ld( inv_counter, Rtmp2 ); |
duke@435 | 2267 | |
duke@435 | 2268 | // Add the delta to the backedge counter |
duke@435 | 2269 | add( Rtmp, delta, Rtmp ); |
duke@435 | 2270 | |
duke@435 | 2271 | // Mask the invocation counter, add to backedge counter |
duke@435 | 2272 | and3( Rtmp2, InvocationCounter::count_mask_value, Rtmp2 ); |
duke@435 | 2273 | |
duke@435 | 2274 | // and store the result to memory |
duke@435 | 2275 | st( Rtmp, be_counter ); |
duke@435 | 2276 | |
duke@435 | 2277 | // Add backedge + invocation counter |
duke@435 | 2278 | add( Rtmp, Rtmp2, Rtmp ); |
duke@435 | 2279 | |
duke@435 | 2280 | // Note that this macro must leave backedge_count + invocation_count in Rtmp! |
duke@435 | 2281 | } |
duke@435 | 2282 | |
duke@435 | 2283 | #ifndef CC_INTERP |
duke@435 | 2284 | void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count, |
duke@435 | 2285 | Register branch_bcp, |
duke@435 | 2286 | Register Rtmp ) { |
duke@435 | 2287 | Label did_not_overflow; |
duke@435 | 2288 | Label overflow_with_error; |
duke@435 | 2289 | assert_different_registers(backedge_count, Rtmp, branch_bcp); |
duke@435 | 2290 | assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr"); |
duke@435 | 2291 | |
duke@435 | 2292 | Address limit(Rtmp, address(&InvocationCounter::InterpreterBackwardBranchLimit)); |
duke@435 | 2293 | load_contents(limit, Rtmp); |
duke@435 | 2294 | cmp(backedge_count, Rtmp); |
duke@435 | 2295 | br(Assembler::lessUnsigned, false, Assembler::pt, did_not_overflow); |
duke@435 | 2296 | delayed()->nop(); |
duke@435 | 2297 | |
duke@435 | 2298 | // When ProfileInterpreter is on, the backedge_count comes from the |
duke@435 | 2299 | // methodDataOop, which value does not get reset on the call to |
duke@435 | 2300 | // frequency_counter_overflow(). To avoid excessive calls to the overflow |
duke@435 | 2301 | // routine while the method is being compiled, add a second test to make sure |
duke@435 | 2302 | // the overflow function is called only once every overflow_frequency. |
duke@435 | 2303 | if (ProfileInterpreter) { |
duke@435 | 2304 | const int overflow_frequency = 1024; |
duke@435 | 2305 | andcc(backedge_count, overflow_frequency-1, Rtmp); |
duke@435 | 2306 | brx(Assembler::notZero, false, Assembler::pt, did_not_overflow); |
duke@435 | 2307 | delayed()->nop(); |
duke@435 | 2308 | } |
duke@435 | 2309 | |
duke@435 | 2310 | // overflow in loop, pass branch bytecode |
duke@435 | 2311 | set(6,Rtmp); |
duke@435 | 2312 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), branch_bcp, Rtmp); |
duke@435 | 2313 | |
duke@435 | 2314 | // Was an OSR adapter generated? |
duke@435 | 2315 | // O0 = osr nmethod |
duke@435 | 2316 | tst(O0); |
duke@435 | 2317 | brx(Assembler::zero, false, Assembler::pn, overflow_with_error); |
duke@435 | 2318 | delayed()->nop(); |
duke@435 | 2319 | |
duke@435 | 2320 | // Has the nmethod been invalidated already? |
duke@435 | 2321 | ld(O0, nmethod::entry_bci_offset(), O2); |
duke@435 | 2322 | cmp(O2, InvalidOSREntryBci); |
duke@435 | 2323 | br(Assembler::equal, false, Assembler::pn, overflow_with_error); |
duke@435 | 2324 | delayed()->nop(); |
duke@435 | 2325 | |
duke@435 | 2326 | // migrate the interpreter frame off of the stack |
duke@435 | 2327 | |
duke@435 | 2328 | mov(G2_thread, L7); |
duke@435 | 2329 | // save nmethod |
duke@435 | 2330 | mov(O0, L6); |
duke@435 | 2331 | set_last_Java_frame(SP, noreg); |
duke@435 | 2332 | call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin), L7); |
duke@435 | 2333 | reset_last_Java_frame(); |
duke@435 | 2334 | mov(L7, G2_thread); |
duke@435 | 2335 | |
duke@435 | 2336 | // move OSR nmethod to I1 |
duke@435 | 2337 | mov(L6, I1); |
duke@435 | 2338 | |
duke@435 | 2339 | // OSR buffer to I0 |
duke@435 | 2340 | mov(O0, I0); |
duke@435 | 2341 | |
duke@435 | 2342 | // remove the interpreter frame |
duke@435 | 2343 | restore(I5_savedSP, 0, SP); |
duke@435 | 2344 | |
duke@435 | 2345 | // Jump to the osr code. |
duke@435 | 2346 | ld_ptr(O1, nmethod::osr_entry_point_offset(), O2); |
duke@435 | 2347 | jmp(O2, G0); |
duke@435 | 2348 | delayed()->nop(); |
duke@435 | 2349 | |
duke@435 | 2350 | bind(overflow_with_error); |
duke@435 | 2351 | |
duke@435 | 2352 | bind(did_not_overflow); |
duke@435 | 2353 | } |
duke@435 | 2354 | |
duke@435 | 2355 | |
duke@435 | 2356 | |
duke@435 | 2357 | void InterpreterMacroAssembler::interp_verify_oop(Register reg, TosState state, const char * file, int line) { |
duke@435 | 2358 | if (state == atos) { MacroAssembler::_verify_oop(reg, "broken oop ", file, line); } |
duke@435 | 2359 | } |
duke@435 | 2360 | |
duke@435 | 2361 | |
duke@435 | 2362 | // local helper function for the verify_oop_or_return_address macro |
duke@435 | 2363 | static bool verify_return_address(methodOopDesc* m, int bci) { |
duke@435 | 2364 | #ifndef PRODUCT |
duke@435 | 2365 | address pc = (address)(m->constMethod()) |
duke@435 | 2366 | + in_bytes(constMethodOopDesc::codes_offset()) + bci; |
duke@435 | 2367 | // assume it is a valid return address if it is inside m and is preceded by a jsr |
duke@435 | 2368 | if (!m->contains(pc)) return false; |
duke@435 | 2369 | address jsr_pc; |
duke@435 | 2370 | jsr_pc = pc - Bytecodes::length_for(Bytecodes::_jsr); |
duke@435 | 2371 | if (*jsr_pc == Bytecodes::_jsr && jsr_pc >= m->code_base()) return true; |
duke@435 | 2372 | jsr_pc = pc - Bytecodes::length_for(Bytecodes::_jsr_w); |
duke@435 | 2373 | if (*jsr_pc == Bytecodes::_jsr_w && jsr_pc >= m->code_base()) return true; |
duke@435 | 2374 | #endif // PRODUCT |
duke@435 | 2375 | return false; |
duke@435 | 2376 | } |
duke@435 | 2377 | |
duke@435 | 2378 | |
duke@435 | 2379 | void InterpreterMacroAssembler::verify_oop_or_return_address(Register reg, Register Rtmp) { |
duke@435 | 2380 | if (!VerifyOops) return; |
duke@435 | 2381 | // the VM documentation for the astore[_wide] bytecode allows |
duke@435 | 2382 | // the TOS to be not only an oop but also a return address |
duke@435 | 2383 | Label test; |
duke@435 | 2384 | Label skip; |
duke@435 | 2385 | // See if it is an address (in the current method): |
duke@435 | 2386 | |
duke@435 | 2387 | mov(reg, Rtmp); |
duke@435 | 2388 | const int log2_bytecode_size_limit = 16; |
duke@435 | 2389 | srl(Rtmp, log2_bytecode_size_limit, Rtmp); |
duke@435 | 2390 | br_notnull( Rtmp, false, pt, test ); |
duke@435 | 2391 | delayed()->nop(); |
duke@435 | 2392 | |
duke@435 | 2393 | // %%% should use call_VM_leaf here? |
duke@435 | 2394 | save_frame_and_mov(0, Lmethod, O0, reg, O1); |
duke@435 | 2395 | save_thread(L7_thread_cache); |
duke@435 | 2396 | call(CAST_FROM_FN_PTR(address,verify_return_address), relocInfo::none); |
duke@435 | 2397 | delayed()->nop(); |
duke@435 | 2398 | restore_thread(L7_thread_cache); |
duke@435 | 2399 | br_notnull( O0, false, pt, skip ); |
duke@435 | 2400 | delayed()->restore(); |
duke@435 | 2401 | |
duke@435 | 2402 | // Perform a more elaborate out-of-line call |
duke@435 | 2403 | // Not an address; verify it: |
duke@435 | 2404 | bind(test); |
duke@435 | 2405 | verify_oop(reg); |
duke@435 | 2406 | bind(skip); |
duke@435 | 2407 | } |
duke@435 | 2408 | |
duke@435 | 2409 | |
duke@435 | 2410 | void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { |
duke@435 | 2411 | if (state == ftos || state == dtos) MacroAssembler::verify_FPU(stack_depth); |
duke@435 | 2412 | } |
duke@435 | 2413 | #endif /* CC_INTERP */ |
duke@435 | 2414 | |
duke@435 | 2415 | // Inline assembly for: |
duke@435 | 2416 | // |
duke@435 | 2417 | // if (thread is in interp_only_mode) { |
duke@435 | 2418 | // InterpreterRuntime::post_method_entry(); |
duke@435 | 2419 | // } |
duke@435 | 2420 | // if (DTraceMethodProbes) { |
twisti@1040 | 2421 | // SharedRuntime::dtrace_method_entry(method, receiver); |
duke@435 | 2422 | // } |
dcubed@1045 | 2423 | // if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { |
dcubed@1045 | 2424 | // SharedRuntime::rc_trace_method_entry(method, receiver); |
coleenp@857 | 2425 | // } |
duke@435 | 2426 | |
duke@435 | 2427 | void InterpreterMacroAssembler::notify_method_entry() { |
duke@435 | 2428 | |
duke@435 | 2429 | // C++ interpreter only uses this for native methods. |
duke@435 | 2430 | |
duke@435 | 2431 | // Whenever JVMTI puts a thread in interp_only_mode, method |
duke@435 | 2432 | // entry/exit events are sent for that thread to track stack |
duke@435 | 2433 | // depth. If it is possible to enter interp_only_mode we add |
duke@435 | 2434 | // the code to check if the event should be sent. |
duke@435 | 2435 | if (JvmtiExport::can_post_interpreter_events()) { |
duke@435 | 2436 | Label L; |
duke@435 | 2437 | Register temp_reg = O5; |
duke@435 | 2438 | |
duke@435 | 2439 | const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset())); |
duke@435 | 2440 | |
duke@435 | 2441 | ld(interp_only, temp_reg); |
duke@435 | 2442 | tst(temp_reg); |
duke@435 | 2443 | br(zero, false, pt, L); |
duke@435 | 2444 | delayed()->nop(); |
duke@435 | 2445 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_entry)); |
duke@435 | 2446 | bind(L); |
duke@435 | 2447 | } |
duke@435 | 2448 | |
duke@435 | 2449 | { |
duke@435 | 2450 | Register temp_reg = O5; |
duke@435 | 2451 | SkipIfEqual skip_if(this, temp_reg, &DTraceMethodProbes, zero); |
duke@435 | 2452 | call_VM_leaf(noreg, |
duke@435 | 2453 | CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), |
duke@435 | 2454 | G2_thread, Lmethod); |
duke@435 | 2455 | } |
dcubed@1045 | 2456 | |
dcubed@1045 | 2457 | // RedefineClasses() tracing support for obsolete method entry |
dcubed@1045 | 2458 | if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { |
dcubed@1045 | 2459 | call_VM_leaf(noreg, |
dcubed@1045 | 2460 | CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), |
dcubed@1045 | 2461 | G2_thread, Lmethod); |
dcubed@1045 | 2462 | } |
duke@435 | 2463 | } |
duke@435 | 2464 | |
duke@435 | 2465 | |
duke@435 | 2466 | // Inline assembly for: |
duke@435 | 2467 | // |
duke@435 | 2468 | // if (thread is in interp_only_mode) { |
duke@435 | 2469 | // // save result |
duke@435 | 2470 | // InterpreterRuntime::post_method_exit(); |
duke@435 | 2471 | // // restore result |
duke@435 | 2472 | // } |
duke@435 | 2473 | // if (DTraceMethodProbes) { |
duke@435 | 2474 | // SharedRuntime::dtrace_method_exit(thread, method); |
duke@435 | 2475 | // } |
duke@435 | 2476 | // |
duke@435 | 2477 | // Native methods have their result stored in d_tmp and l_tmp |
duke@435 | 2478 | // Java methods have their result stored in the expression stack |
duke@435 | 2479 | |
duke@435 | 2480 | void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, |
duke@435 | 2481 | TosState state, |
duke@435 | 2482 | NotifyMethodExitMode mode) { |
duke@435 | 2483 | // C++ interpreter only uses this for native methods. |
duke@435 | 2484 | |
duke@435 | 2485 | // Whenever JVMTI puts a thread in interp_only_mode, method |
duke@435 | 2486 | // entry/exit events are sent for that thread to track stack |
duke@435 | 2487 | // depth. If it is possible to enter interp_only_mode we add |
duke@435 | 2488 | // the code to check if the event should be sent. |
duke@435 | 2489 | if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { |
duke@435 | 2490 | Label L; |
duke@435 | 2491 | Register temp_reg = O5; |
duke@435 | 2492 | |
duke@435 | 2493 | const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset())); |
duke@435 | 2494 | |
duke@435 | 2495 | ld(interp_only, temp_reg); |
duke@435 | 2496 | tst(temp_reg); |
duke@435 | 2497 | br(zero, false, pt, L); |
duke@435 | 2498 | delayed()->nop(); |
duke@435 | 2499 | |
duke@435 | 2500 | // Note: frame::interpreter_frame_result has a dependency on how the |
duke@435 | 2501 | // method result is saved across the call to post_method_exit. For |
duke@435 | 2502 | // native methods it assumes the result registers are saved to |
duke@435 | 2503 | // l_scratch and d_scratch. If this changes then the interpreter_frame_result |
duke@435 | 2504 | // implementation will need to be updated too. |
duke@435 | 2505 | |
duke@435 | 2506 | save_return_value(state, is_native_method); |
duke@435 | 2507 | call_VM(noreg, |
duke@435 | 2508 | CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); |
duke@435 | 2509 | restore_return_value(state, is_native_method); |
duke@435 | 2510 | bind(L); |
duke@435 | 2511 | } |
duke@435 | 2512 | |
duke@435 | 2513 | { |
duke@435 | 2514 | Register temp_reg = O5; |
duke@435 | 2515 | // Dtrace notification |
duke@435 | 2516 | SkipIfEqual skip_if(this, temp_reg, &DTraceMethodProbes, zero); |
duke@435 | 2517 | save_return_value(state, is_native_method); |
duke@435 | 2518 | call_VM_leaf( |
duke@435 | 2519 | noreg, |
duke@435 | 2520 | CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), |
duke@435 | 2521 | G2_thread, Lmethod); |
duke@435 | 2522 | restore_return_value(state, is_native_method); |
duke@435 | 2523 | } |
duke@435 | 2524 | } |
duke@435 | 2525 | |
duke@435 | 2526 | void InterpreterMacroAssembler::save_return_value(TosState state, bool is_native_call) { |
duke@435 | 2527 | #ifdef CC_INTERP |
duke@435 | 2528 | // result potentially in O0/O1: save it across calls |
duke@435 | 2529 | stf(FloatRegisterImpl::D, F0, STATE(_native_fresult)); |
duke@435 | 2530 | #ifdef _LP64 |
duke@435 | 2531 | stx(O0, STATE(_native_lresult)); |
duke@435 | 2532 | #else |
duke@435 | 2533 | std(O0, STATE(_native_lresult)); |
duke@435 | 2534 | #endif |
duke@435 | 2535 | #else // CC_INTERP |
duke@435 | 2536 | if (is_native_call) { |
duke@435 | 2537 | stf(FloatRegisterImpl::D, F0, d_tmp); |
duke@435 | 2538 | #ifdef _LP64 |
duke@435 | 2539 | stx(O0, l_tmp); |
duke@435 | 2540 | #else |
duke@435 | 2541 | std(O0, l_tmp); |
duke@435 | 2542 | #endif |
duke@435 | 2543 | } else { |
duke@435 | 2544 | push(state); |
duke@435 | 2545 | } |
duke@435 | 2546 | #endif // CC_INTERP |
duke@435 | 2547 | } |
duke@435 | 2548 | |
duke@435 | 2549 | void InterpreterMacroAssembler::restore_return_value( TosState state, bool is_native_call) { |
duke@435 | 2550 | #ifdef CC_INTERP |
duke@435 | 2551 | ldf(FloatRegisterImpl::D, STATE(_native_fresult), F0); |
duke@435 | 2552 | #ifdef _LP64 |
duke@435 | 2553 | ldx(STATE(_native_lresult), O0); |
duke@435 | 2554 | #else |
duke@435 | 2555 | ldd(STATE(_native_lresult), O0); |
duke@435 | 2556 | #endif |
duke@435 | 2557 | #else // CC_INTERP |
duke@435 | 2558 | if (is_native_call) { |
duke@435 | 2559 | ldf(FloatRegisterImpl::D, d_tmp, F0); |
duke@435 | 2560 | #ifdef _LP64 |
duke@435 | 2561 | ldx(l_tmp, O0); |
duke@435 | 2562 | #else |
duke@435 | 2563 | ldd(l_tmp, O0); |
duke@435 | 2564 | #endif |
duke@435 | 2565 | } else { |
duke@435 | 2566 | pop(state); |
duke@435 | 2567 | } |
duke@435 | 2568 | #endif // CC_INTERP |
duke@435 | 2569 | } |