Fri, 27 Feb 2009 13:27:09 -0800
6810672: Comment typos
Summary: I have collected some typos I have found while looking at the code.
Reviewed-by: kvn, 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 ) { |
duke@435 | 869 | Label not_subtype, loop; |
duke@435 | 870 | |
duke@435 | 871 | // Profile the not-null value's klass. |
duke@435 | 872 | profile_typecheck(Rsub_klass, Rtmp1); |
duke@435 | 873 | |
duke@435 | 874 | // Load the super-klass's check offset into Rtmp1 |
duke@435 | 875 | ld( Rsuper_klass, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), Rtmp1 ); |
duke@435 | 876 | // Load from the sub-klass's super-class display list, or a 1-word cache of |
duke@435 | 877 | // the secondary superclass list, or a failing value with a sentinel offset |
duke@435 | 878 | // if the super-klass is an interface or exceptionally deep in the Java |
duke@435 | 879 | // hierarchy and we have to scan the secondary superclass list the hard way. |
duke@435 | 880 | ld_ptr( Rsub_klass, Rtmp1, Rtmp2 ); |
duke@435 | 881 | // See if we get an immediate positive hit |
duke@435 | 882 | cmp( Rtmp2, Rsuper_klass ); |
duke@435 | 883 | brx( Assembler::equal, false, Assembler::pt, ok_is_subtype ); |
duke@435 | 884 | // In the delay slot, check for immediate negative hit |
duke@435 | 885 | delayed()->cmp( Rtmp1, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); |
duke@435 | 886 | br( Assembler::notEqual, false, Assembler::pt, not_subtype ); |
duke@435 | 887 | // In the delay slot, check for self |
duke@435 | 888 | delayed()->cmp( Rsub_klass, Rsuper_klass ); |
duke@435 | 889 | brx( Assembler::equal, false, Assembler::pt, ok_is_subtype ); |
duke@435 | 890 | |
duke@435 | 891 | // Now do a linear scan of the secondary super-klass chain. |
duke@435 | 892 | delayed()->ld_ptr( Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), Rtmp2 ); |
duke@435 | 893 | |
coleenp@548 | 894 | // compress superclass |
coleenp@548 | 895 | if (UseCompressedOops) encode_heap_oop(Rsuper_klass); |
coleenp@548 | 896 | |
duke@435 | 897 | // Rtmp2 holds the objArrayOop of secondary supers. |
duke@435 | 898 | ld( Rtmp2, arrayOopDesc::length_offset_in_bytes(), Rtmp1 );// Load the array length |
duke@435 | 899 | // Check for empty secondary super list |
duke@435 | 900 | tst(Rtmp1); |
duke@435 | 901 | |
duke@435 | 902 | // Top of search loop |
duke@435 | 903 | bind( loop ); |
duke@435 | 904 | br( Assembler::equal, false, Assembler::pn, not_subtype ); |
duke@435 | 905 | delayed()->nop(); |
coleenp@548 | 906 | |
duke@435 | 907 | // load next super to check |
coleenp@548 | 908 | if (UseCompressedOops) { |
coleenp@857 | 909 | lduw( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); |
coleenp@548 | 910 | // Bump array pointer forward one oop |
coleenp@548 | 911 | add( Rtmp2, 4, Rtmp2 ); |
coleenp@548 | 912 | } else { |
coleenp@548 | 913 | ld_ptr( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); |
coleenp@548 | 914 | // Bump array pointer forward one oop |
coleenp@548 | 915 | add( Rtmp2, wordSize, Rtmp2); |
coleenp@548 | 916 | } |
duke@435 | 917 | // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list |
duke@435 | 918 | cmp( Rtmp3, Rsuper_klass ); |
duke@435 | 919 | // A miss means we are NOT a subtype and need to keep looping |
duke@435 | 920 | brx( Assembler::notEqual, false, Assembler::pt, loop ); |
duke@435 | 921 | delayed()->deccc( Rtmp1 ); // dec trip counter in delay slot |
duke@435 | 922 | // Falling out the bottom means we found a hit; we ARE a subtype |
coleenp@548 | 923 | if (UseCompressedOops) decode_heap_oop(Rsuper_klass); |
duke@435 | 924 | br( Assembler::always, false, Assembler::pt, ok_is_subtype ); |
duke@435 | 925 | // Update the cache |
coleenp@548 | 926 | delayed()->st_ptr( Rsuper_klass, Rsub_klass, |
coleenp@548 | 927 | sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); |
duke@435 | 928 | |
duke@435 | 929 | bind(not_subtype); |
duke@435 | 930 | profile_typecheck_failed(Rtmp1); |
duke@435 | 931 | } |
duke@435 | 932 | |
duke@435 | 933 | // Separate these two to allow for delay slot in middle |
duke@435 | 934 | // These are used to do a test and full jump to exception-throwing code. |
duke@435 | 935 | |
duke@435 | 936 | // %%%%% Could possibly reoptimize this by testing to see if could use |
duke@435 | 937 | // a single conditional branch (i.e. if span is small enough. |
duke@435 | 938 | // If you go that route, than get rid of the split and give up |
duke@435 | 939 | // on the delay-slot hack. |
duke@435 | 940 | |
duke@435 | 941 | void InterpreterMacroAssembler::throw_if_not_1_icc( Condition ok_condition, |
duke@435 | 942 | Label& ok ) { |
duke@435 | 943 | assert_not_delayed(); |
duke@435 | 944 | br(ok_condition, true, pt, ok); |
duke@435 | 945 | // DELAY SLOT |
duke@435 | 946 | } |
duke@435 | 947 | |
duke@435 | 948 | void InterpreterMacroAssembler::throw_if_not_1_xcc( Condition ok_condition, |
duke@435 | 949 | Label& ok ) { |
duke@435 | 950 | assert_not_delayed(); |
duke@435 | 951 | bp( ok_condition, true, Assembler::xcc, pt, ok); |
duke@435 | 952 | // DELAY SLOT |
duke@435 | 953 | } |
duke@435 | 954 | |
duke@435 | 955 | void InterpreterMacroAssembler::throw_if_not_1_x( Condition ok_condition, |
duke@435 | 956 | Label& ok ) { |
duke@435 | 957 | assert_not_delayed(); |
duke@435 | 958 | brx(ok_condition, true, pt, ok); |
duke@435 | 959 | // DELAY SLOT |
duke@435 | 960 | } |
duke@435 | 961 | |
duke@435 | 962 | void InterpreterMacroAssembler::throw_if_not_2( address throw_entry_point, |
duke@435 | 963 | Register Rscratch, |
duke@435 | 964 | Label& ok ) { |
duke@435 | 965 | assert(throw_entry_point != NULL, "entry point must be generated by now"); |
duke@435 | 966 | Address dest(Rscratch, throw_entry_point); |
duke@435 | 967 | jump_to(dest); |
duke@435 | 968 | delayed()->nop(); |
duke@435 | 969 | bind(ok); |
duke@435 | 970 | } |
duke@435 | 971 | |
duke@435 | 972 | |
duke@435 | 973 | // And if you cannot use the delay slot, here is a shorthand: |
duke@435 | 974 | |
duke@435 | 975 | void InterpreterMacroAssembler::throw_if_not_icc( Condition ok_condition, |
duke@435 | 976 | address throw_entry_point, |
duke@435 | 977 | Register Rscratch ) { |
duke@435 | 978 | Label ok; |
duke@435 | 979 | if (ok_condition != never) { |
duke@435 | 980 | throw_if_not_1_icc( ok_condition, ok); |
duke@435 | 981 | delayed()->nop(); |
duke@435 | 982 | } |
duke@435 | 983 | throw_if_not_2( throw_entry_point, Rscratch, ok); |
duke@435 | 984 | } |
duke@435 | 985 | void InterpreterMacroAssembler::throw_if_not_xcc( Condition ok_condition, |
duke@435 | 986 | address throw_entry_point, |
duke@435 | 987 | Register Rscratch ) { |
duke@435 | 988 | Label ok; |
duke@435 | 989 | if (ok_condition != never) { |
duke@435 | 990 | throw_if_not_1_xcc( ok_condition, ok); |
duke@435 | 991 | delayed()->nop(); |
duke@435 | 992 | } |
duke@435 | 993 | throw_if_not_2( throw_entry_point, Rscratch, ok); |
duke@435 | 994 | } |
duke@435 | 995 | void InterpreterMacroAssembler::throw_if_not_x( Condition ok_condition, |
duke@435 | 996 | address throw_entry_point, |
duke@435 | 997 | Register Rscratch ) { |
duke@435 | 998 | Label ok; |
duke@435 | 999 | if (ok_condition != never) { |
duke@435 | 1000 | throw_if_not_1_x( ok_condition, ok); |
duke@435 | 1001 | delayed()->nop(); |
duke@435 | 1002 | } |
duke@435 | 1003 | throw_if_not_2( throw_entry_point, Rscratch, ok); |
duke@435 | 1004 | } |
duke@435 | 1005 | |
duke@435 | 1006 | // Check that index is in range for array, then shift index by index_shift, and put arrayOop + shifted_index into res |
duke@435 | 1007 | // Note: res is still shy of address by array offset into object. |
duke@435 | 1008 | |
duke@435 | 1009 | void InterpreterMacroAssembler::index_check_without_pop(Register array, Register index, int index_shift, Register tmp, Register res) { |
duke@435 | 1010 | assert_not_delayed(); |
duke@435 | 1011 | |
duke@435 | 1012 | verify_oop(array); |
duke@435 | 1013 | #ifdef _LP64 |
duke@435 | 1014 | // sign extend since tos (index) can be a 32bit value |
duke@435 | 1015 | sra(index, G0, index); |
duke@435 | 1016 | #endif // _LP64 |
duke@435 | 1017 | |
duke@435 | 1018 | // check array |
duke@435 | 1019 | Label ptr_ok; |
duke@435 | 1020 | tst(array); |
duke@435 | 1021 | throw_if_not_1_x( notZero, ptr_ok ); |
duke@435 | 1022 | delayed()->ld( array, arrayOopDesc::length_offset_in_bytes(), tmp ); // check index |
duke@435 | 1023 | throw_if_not_2( Interpreter::_throw_NullPointerException_entry, G3_scratch, ptr_ok); |
duke@435 | 1024 | |
duke@435 | 1025 | Label index_ok; |
duke@435 | 1026 | cmp(index, tmp); |
duke@435 | 1027 | throw_if_not_1_icc( lessUnsigned, index_ok ); |
duke@435 | 1028 | if (index_shift > 0) delayed()->sll(index, index_shift, index); |
duke@435 | 1029 | else delayed()->add(array, index, res); // addr - const offset in index |
duke@435 | 1030 | // convention: move aberrant index into G3_scratch for exception message |
duke@435 | 1031 | mov(index, G3_scratch); |
duke@435 | 1032 | throw_if_not_2( Interpreter::_throw_ArrayIndexOutOfBoundsException_entry, G4_scratch, index_ok); |
duke@435 | 1033 | |
duke@435 | 1034 | // add offset if didn't do it in delay slot |
duke@435 | 1035 | if (index_shift > 0) add(array, index, res); // addr - const offset in index |
duke@435 | 1036 | } |
duke@435 | 1037 | |
duke@435 | 1038 | |
duke@435 | 1039 | void InterpreterMacroAssembler::index_check(Register array, Register index, int index_shift, Register tmp, Register res) { |
duke@435 | 1040 | assert_not_delayed(); |
duke@435 | 1041 | |
duke@435 | 1042 | // pop array |
duke@435 | 1043 | pop_ptr(array); |
duke@435 | 1044 | |
duke@435 | 1045 | // check array |
duke@435 | 1046 | index_check_without_pop(array, index, index_shift, tmp, res); |
duke@435 | 1047 | } |
duke@435 | 1048 | |
duke@435 | 1049 | |
duke@435 | 1050 | void InterpreterMacroAssembler::get_constant_pool(Register Rdst) { |
duke@435 | 1051 | ld_ptr(Lmethod, in_bytes(methodOopDesc::constants_offset()), Rdst); |
duke@435 | 1052 | } |
duke@435 | 1053 | |
duke@435 | 1054 | |
duke@435 | 1055 | void InterpreterMacroAssembler::get_constant_pool_cache(Register Rdst) { |
duke@435 | 1056 | get_constant_pool(Rdst); |
duke@435 | 1057 | ld_ptr(Rdst, constantPoolOopDesc::cache_offset_in_bytes(), Rdst); |
duke@435 | 1058 | } |
duke@435 | 1059 | |
duke@435 | 1060 | |
duke@435 | 1061 | void InterpreterMacroAssembler::get_cpool_and_tags(Register Rcpool, Register Rtags) { |
duke@435 | 1062 | get_constant_pool(Rcpool); |
duke@435 | 1063 | ld_ptr(Rcpool, constantPoolOopDesc::tags_offset_in_bytes(), Rtags); |
duke@435 | 1064 | } |
duke@435 | 1065 | |
duke@435 | 1066 | |
duke@435 | 1067 | // unlock if synchronized method |
duke@435 | 1068 | // |
duke@435 | 1069 | // Unlock the receiver if this is a synchronized method. |
duke@435 | 1070 | // Unlock any Java monitors from syncronized blocks. |
duke@435 | 1071 | // |
duke@435 | 1072 | // If there are locked Java monitors |
duke@435 | 1073 | // If throw_monitor_exception |
duke@435 | 1074 | // throws IllegalMonitorStateException |
duke@435 | 1075 | // Else if install_monitor_exception |
duke@435 | 1076 | // installs IllegalMonitorStateException |
duke@435 | 1077 | // Else |
duke@435 | 1078 | // no error processing |
duke@435 | 1079 | void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, |
duke@435 | 1080 | bool throw_monitor_exception, |
duke@435 | 1081 | bool install_monitor_exception) { |
duke@435 | 1082 | Label unlocked, unlock, no_unlock; |
duke@435 | 1083 | |
duke@435 | 1084 | // get the value of _do_not_unlock_if_synchronized into G1_scratch |
duke@435 | 1085 | const Address do_not_unlock_if_synchronized(G2_thread, 0, |
duke@435 | 1086 | in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); |
duke@435 | 1087 | ldbool(do_not_unlock_if_synchronized, G1_scratch); |
duke@435 | 1088 | stbool(G0, do_not_unlock_if_synchronized); // reset the flag |
duke@435 | 1089 | |
duke@435 | 1090 | // check if synchronized method |
duke@435 | 1091 | const Address access_flags(Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset())); |
duke@435 | 1092 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 1093 | push(state); // save tos |
duke@435 | 1094 | ld(access_flags, G3_scratch); |
duke@435 | 1095 | btst(JVM_ACC_SYNCHRONIZED, G3_scratch); |
duke@435 | 1096 | br( zero, false, pt, unlocked); |
duke@435 | 1097 | delayed()->nop(); |
duke@435 | 1098 | |
duke@435 | 1099 | // Don't unlock anything if the _do_not_unlock_if_synchronized flag |
duke@435 | 1100 | // is set. |
duke@435 | 1101 | tstbool(G1_scratch); |
duke@435 | 1102 | br(Assembler::notZero, false, pn, no_unlock); |
duke@435 | 1103 | delayed()->nop(); |
duke@435 | 1104 | |
duke@435 | 1105 | // BasicObjectLock will be first in list, since this is a synchronized method. However, need |
duke@435 | 1106 | // to check that the object has not been unlocked by an explicit monitorexit bytecode. |
duke@435 | 1107 | |
duke@435 | 1108 | //Intel: if (throw_monitor_exception) ... else ... |
duke@435 | 1109 | // Entry already unlocked, need to throw exception |
duke@435 | 1110 | //... |
duke@435 | 1111 | |
duke@435 | 1112 | // pass top-most monitor elem |
duke@435 | 1113 | add( top_most_monitor(), O1 ); |
duke@435 | 1114 | |
duke@435 | 1115 | ld_ptr(O1, BasicObjectLock::obj_offset_in_bytes(), G3_scratch); |
duke@435 | 1116 | br_notnull(G3_scratch, false, pt, unlock); |
duke@435 | 1117 | delayed()->nop(); |
duke@435 | 1118 | |
duke@435 | 1119 | if (throw_monitor_exception) { |
duke@435 | 1120 | // Entry already unlocked need to throw an exception |
duke@435 | 1121 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); |
duke@435 | 1122 | should_not_reach_here(); |
duke@435 | 1123 | } else { |
duke@435 | 1124 | // Monitor already unlocked during a stack unroll. |
duke@435 | 1125 | // If requested, install an illegal_monitor_state_exception. |
duke@435 | 1126 | // Continue with stack unrolling. |
duke@435 | 1127 | if (install_monitor_exception) { |
duke@435 | 1128 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); |
duke@435 | 1129 | } |
duke@435 | 1130 | ba(false, unlocked); |
duke@435 | 1131 | delayed()->nop(); |
duke@435 | 1132 | } |
duke@435 | 1133 | |
duke@435 | 1134 | bind(unlock); |
duke@435 | 1135 | |
duke@435 | 1136 | unlock_object(O1); |
duke@435 | 1137 | |
duke@435 | 1138 | bind(unlocked); |
duke@435 | 1139 | |
duke@435 | 1140 | // I0, I1: Might contain return value |
duke@435 | 1141 | |
duke@435 | 1142 | // Check that all monitors are unlocked |
duke@435 | 1143 | { Label loop, exception, entry, restart; |
duke@435 | 1144 | |
duke@435 | 1145 | Register Rmptr = O0; |
duke@435 | 1146 | Register Rtemp = O1; |
duke@435 | 1147 | Register Rlimit = Lmonitors; |
duke@435 | 1148 | const jint delta = frame::interpreter_frame_monitor_size() * wordSize; |
duke@435 | 1149 | assert( (delta & LongAlignmentMask) == 0, |
duke@435 | 1150 | "sizeof BasicObjectLock must be even number of doublewords"); |
duke@435 | 1151 | |
duke@435 | 1152 | #ifdef ASSERT |
duke@435 | 1153 | add(top_most_monitor(), Rmptr, delta); |
duke@435 | 1154 | { Label L; |
duke@435 | 1155 | // ensure that Rmptr starts out above (or at) Rlimit |
duke@435 | 1156 | cmp(Rmptr, Rlimit); |
duke@435 | 1157 | brx(Assembler::greaterEqualUnsigned, false, pn, L); |
duke@435 | 1158 | delayed()->nop(); |
duke@435 | 1159 | stop("monitor stack has negative size"); |
duke@435 | 1160 | bind(L); |
duke@435 | 1161 | } |
duke@435 | 1162 | #endif |
duke@435 | 1163 | bind(restart); |
duke@435 | 1164 | ba(false, entry); |
duke@435 | 1165 | delayed()-> |
duke@435 | 1166 | add(top_most_monitor(), Rmptr, delta); // points to current entry, starting with bottom-most entry |
duke@435 | 1167 | |
duke@435 | 1168 | // Entry is still locked, need to throw exception |
duke@435 | 1169 | bind(exception); |
duke@435 | 1170 | if (throw_monitor_exception) { |
duke@435 | 1171 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); |
duke@435 | 1172 | should_not_reach_here(); |
duke@435 | 1173 | } else { |
duke@435 | 1174 | // Stack unrolling. Unlock object and if requested, install illegal_monitor_exception. |
duke@435 | 1175 | // Unlock does not block, so don't have to worry about the frame |
duke@435 | 1176 | unlock_object(Rmptr); |
duke@435 | 1177 | if (install_monitor_exception) { |
duke@435 | 1178 | MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); |
duke@435 | 1179 | } |
duke@435 | 1180 | ba(false, restart); |
duke@435 | 1181 | delayed()->nop(); |
duke@435 | 1182 | } |
duke@435 | 1183 | |
duke@435 | 1184 | bind(loop); |
duke@435 | 1185 | cmp(Rtemp, G0); // check if current entry is used |
duke@435 | 1186 | brx(Assembler::notEqual, false, pn, exception); |
duke@435 | 1187 | delayed()-> |
duke@435 | 1188 | dec(Rmptr, delta); // otherwise advance to next entry |
duke@435 | 1189 | #ifdef ASSERT |
duke@435 | 1190 | { Label L; |
duke@435 | 1191 | // ensure that Rmptr has not somehow stepped below Rlimit |
duke@435 | 1192 | cmp(Rmptr, Rlimit); |
duke@435 | 1193 | brx(Assembler::greaterEqualUnsigned, false, pn, L); |
duke@435 | 1194 | delayed()->nop(); |
duke@435 | 1195 | stop("ran off the end of the monitor stack"); |
duke@435 | 1196 | bind(L); |
duke@435 | 1197 | } |
duke@435 | 1198 | #endif |
duke@435 | 1199 | bind(entry); |
duke@435 | 1200 | cmp(Rmptr, Rlimit); // check if bottom reached |
duke@435 | 1201 | brx(Assembler::notEqual, true, pn, loop); // if not at bottom then check this entry |
duke@435 | 1202 | delayed()-> |
duke@435 | 1203 | ld_ptr(Rmptr, BasicObjectLock::obj_offset_in_bytes() - delta, Rtemp); |
duke@435 | 1204 | } |
duke@435 | 1205 | |
duke@435 | 1206 | bind(no_unlock); |
duke@435 | 1207 | pop(state); |
duke@435 | 1208 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 1209 | } |
duke@435 | 1210 | |
duke@435 | 1211 | |
duke@435 | 1212 | // remove activation |
duke@435 | 1213 | // |
duke@435 | 1214 | // Unlock the receiver if this is a synchronized method. |
duke@435 | 1215 | // Unlock any Java monitors from syncronized blocks. |
duke@435 | 1216 | // Remove the activation from the stack. |
duke@435 | 1217 | // |
duke@435 | 1218 | // If there are locked Java monitors |
duke@435 | 1219 | // If throw_monitor_exception |
duke@435 | 1220 | // throws IllegalMonitorStateException |
duke@435 | 1221 | // Else if install_monitor_exception |
duke@435 | 1222 | // installs IllegalMonitorStateException |
duke@435 | 1223 | // Else |
duke@435 | 1224 | // no error processing |
duke@435 | 1225 | void InterpreterMacroAssembler::remove_activation(TosState state, |
duke@435 | 1226 | bool throw_monitor_exception, |
duke@435 | 1227 | bool install_monitor_exception) { |
duke@435 | 1228 | |
duke@435 | 1229 | unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception); |
duke@435 | 1230 | |
duke@435 | 1231 | // save result (push state before jvmti call and pop it afterwards) and notify jvmti |
duke@435 | 1232 | notify_method_exit(false, state, NotifyJVMTI); |
duke@435 | 1233 | |
duke@435 | 1234 | interp_verify_oop(Otos_i, state, __FILE__, __LINE__); |
duke@435 | 1235 | verify_oop(Lmethod); |
duke@435 | 1236 | verify_thread(); |
duke@435 | 1237 | |
duke@435 | 1238 | // return tos |
duke@435 | 1239 | assert(Otos_l1 == Otos_i, "adjust code below"); |
duke@435 | 1240 | switch (state) { |
duke@435 | 1241 | #ifdef _LP64 |
duke@435 | 1242 | case ltos: mov(Otos_l, Otos_l->after_save()); break; // O0 -> I0 |
duke@435 | 1243 | #else |
duke@435 | 1244 | case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 |
duke@435 | 1245 | #endif |
duke@435 | 1246 | case btos: // fall through |
duke@435 | 1247 | case ctos: |
duke@435 | 1248 | case stos: // fall through |
duke@435 | 1249 | case atos: // fall through |
duke@435 | 1250 | case itos: mov(Otos_l1, Otos_l1->after_save()); break; // O0 -> I0 |
duke@435 | 1251 | case ftos: // fall through |
duke@435 | 1252 | case dtos: // fall through |
duke@435 | 1253 | case vtos: /* nothing to do */ break; |
duke@435 | 1254 | default : ShouldNotReachHere(); |
duke@435 | 1255 | } |
duke@435 | 1256 | |
duke@435 | 1257 | #if defined(COMPILER2) && !defined(_LP64) |
duke@435 | 1258 | if (state == ltos) { |
duke@435 | 1259 | // C2 expects long results in G1 we can't tell if we're returning to interpreted |
duke@435 | 1260 | // or compiled so just be safe use G1 and O0/O1 |
duke@435 | 1261 | |
duke@435 | 1262 | // Shift bits into high (msb) of G1 |
duke@435 | 1263 | sllx(Otos_l1->after_save(), 32, G1); |
duke@435 | 1264 | // Zero extend low bits |
duke@435 | 1265 | srl (Otos_l2->after_save(), 0, Otos_l2->after_save()); |
duke@435 | 1266 | or3 (Otos_l2->after_save(), G1, G1); |
duke@435 | 1267 | } |
duke@435 | 1268 | #endif /* COMPILER2 */ |
duke@435 | 1269 | |
duke@435 | 1270 | } |
duke@435 | 1271 | #endif /* CC_INTERP */ |
duke@435 | 1272 | |
duke@435 | 1273 | |
duke@435 | 1274 | // Lock object |
duke@435 | 1275 | // |
duke@435 | 1276 | // Argument - lock_reg points to the BasicObjectLock to be used for locking, |
duke@435 | 1277 | // it must be initialized with the object to lock |
duke@435 | 1278 | void InterpreterMacroAssembler::lock_object(Register lock_reg, Register Object) { |
duke@435 | 1279 | if (UseHeavyMonitors) { |
duke@435 | 1280 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); |
duke@435 | 1281 | } |
duke@435 | 1282 | else { |
duke@435 | 1283 | Register obj_reg = Object; |
duke@435 | 1284 | Register mark_reg = G4_scratch; |
duke@435 | 1285 | Register temp_reg = G1_scratch; |
duke@435 | 1286 | Address lock_addr = Address(lock_reg, 0, BasicObjectLock::lock_offset_in_bytes()); |
duke@435 | 1287 | Address mark_addr = Address(obj_reg, 0, oopDesc::mark_offset_in_bytes()); |
duke@435 | 1288 | Label done; |
duke@435 | 1289 | |
duke@435 | 1290 | Label slow_case; |
duke@435 | 1291 | |
duke@435 | 1292 | assert_different_registers(lock_reg, obj_reg, mark_reg, temp_reg); |
duke@435 | 1293 | |
duke@435 | 1294 | // load markOop from object into mark_reg |
duke@435 | 1295 | ld_ptr(mark_addr, mark_reg); |
duke@435 | 1296 | |
duke@435 | 1297 | if (UseBiasedLocking) { |
duke@435 | 1298 | biased_locking_enter(obj_reg, mark_reg, temp_reg, done, &slow_case); |
duke@435 | 1299 | } |
duke@435 | 1300 | |
duke@435 | 1301 | // get the address of basicLock on stack that will be stored in the object |
duke@435 | 1302 | // we need a temporary register here as we do not want to clobber lock_reg |
duke@435 | 1303 | // (cas clobbers the destination register) |
duke@435 | 1304 | mov(lock_reg, temp_reg); |
duke@435 | 1305 | // set mark reg to be (markOop of object | UNLOCK_VALUE) |
duke@435 | 1306 | or3(mark_reg, markOopDesc::unlocked_value, mark_reg); |
duke@435 | 1307 | // initialize the box (Must happen before we update the object mark!) |
duke@435 | 1308 | st_ptr(mark_reg, lock_addr, BasicLock::displaced_header_offset_in_bytes()); |
duke@435 | 1309 | // compare and exchange object_addr, markOop | 1, stack address of basicLock |
duke@435 | 1310 | assert(mark_addr.disp() == 0, "cas must take a zero displacement"); |
duke@435 | 1311 | casx_under_lock(mark_addr.base(), mark_reg, temp_reg, |
duke@435 | 1312 | (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); |
duke@435 | 1313 | |
duke@435 | 1314 | // if the compare and exchange succeeded we are done (we saw an unlocked object) |
duke@435 | 1315 | cmp(mark_reg, temp_reg); |
duke@435 | 1316 | brx(Assembler::equal, true, Assembler::pt, done); |
duke@435 | 1317 | delayed()->nop(); |
duke@435 | 1318 | |
duke@435 | 1319 | // We did not see an unlocked object so try the fast recursive case |
duke@435 | 1320 | |
duke@435 | 1321 | // Check if owner is self by comparing the value in the markOop of object |
duke@435 | 1322 | // with the stack pointer |
duke@435 | 1323 | sub(temp_reg, SP, temp_reg); |
duke@435 | 1324 | #ifdef _LP64 |
duke@435 | 1325 | sub(temp_reg, STACK_BIAS, temp_reg); |
duke@435 | 1326 | #endif |
duke@435 | 1327 | assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); |
duke@435 | 1328 | |
duke@435 | 1329 | // Composite "andcc" test: |
duke@435 | 1330 | // (a) %sp -vs- markword proximity check, and, |
duke@435 | 1331 | // (b) verify mark word LSBs == 0 (Stack-locked). |
duke@435 | 1332 | // |
duke@435 | 1333 | // FFFFF003/FFFFFFFFFFFF003 is (markOopDesc::lock_mask_in_place | -os::vm_page_size()) |
duke@435 | 1334 | // Note that the page size used for %sp proximity testing is arbitrary and is |
duke@435 | 1335 | // unrelated to the actual MMU page size. We use a 'logical' page size of |
duke@435 | 1336 | // 4096 bytes. F..FFF003 is designed to fit conveniently in the SIMM13 immediate |
duke@435 | 1337 | // field of the andcc instruction. |
duke@435 | 1338 | andcc (temp_reg, 0xFFFFF003, G0) ; |
duke@435 | 1339 | |
duke@435 | 1340 | // if condition is true we are done and hence we can store 0 in the displaced |
duke@435 | 1341 | // header indicating it is a recursive lock and be done |
duke@435 | 1342 | brx(Assembler::zero, true, Assembler::pt, done); |
duke@435 | 1343 | delayed()->st_ptr(G0, lock_addr, BasicLock::displaced_header_offset_in_bytes()); |
duke@435 | 1344 | |
duke@435 | 1345 | // none of the above fast optimizations worked so we have to get into the |
duke@435 | 1346 | // slow case of monitor enter |
duke@435 | 1347 | bind(slow_case); |
duke@435 | 1348 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); |
duke@435 | 1349 | |
duke@435 | 1350 | bind(done); |
duke@435 | 1351 | } |
duke@435 | 1352 | } |
duke@435 | 1353 | |
duke@435 | 1354 | // Unlocks an object. Used in monitorexit bytecode and remove_activation. |
duke@435 | 1355 | // |
duke@435 | 1356 | // Argument - lock_reg points to the BasicObjectLock for lock |
duke@435 | 1357 | // Throw IllegalMonitorException if object is not locked by current thread |
duke@435 | 1358 | void InterpreterMacroAssembler::unlock_object(Register lock_reg) { |
duke@435 | 1359 | if (UseHeavyMonitors) { |
duke@435 | 1360 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); |
duke@435 | 1361 | } else { |
duke@435 | 1362 | Register obj_reg = G3_scratch; |
duke@435 | 1363 | Register mark_reg = G4_scratch; |
duke@435 | 1364 | Register displaced_header_reg = G1_scratch; |
duke@435 | 1365 | Address lock_addr = Address(lock_reg, 0, BasicObjectLock::lock_offset_in_bytes()); |
duke@435 | 1366 | Address lockobj_addr = Address(lock_reg, 0, BasicObjectLock::obj_offset_in_bytes()); |
duke@435 | 1367 | Address mark_addr = Address(obj_reg, 0, oopDesc::mark_offset_in_bytes()); |
duke@435 | 1368 | Label done; |
duke@435 | 1369 | |
duke@435 | 1370 | if (UseBiasedLocking) { |
duke@435 | 1371 | // load the object out of the BasicObjectLock |
duke@435 | 1372 | ld_ptr(lockobj_addr, obj_reg); |
duke@435 | 1373 | biased_locking_exit(mark_addr, mark_reg, done, true); |
duke@435 | 1374 | st_ptr(G0, lockobj_addr); // free entry |
duke@435 | 1375 | } |
duke@435 | 1376 | |
duke@435 | 1377 | // Test first if we are in the fast recursive case |
duke@435 | 1378 | ld_ptr(lock_addr, displaced_header_reg, BasicLock::displaced_header_offset_in_bytes()); |
duke@435 | 1379 | br_null(displaced_header_reg, true, Assembler::pn, done); |
duke@435 | 1380 | delayed()->st_ptr(G0, lockobj_addr); // free entry |
duke@435 | 1381 | |
duke@435 | 1382 | // See if it is still a light weight lock, if so we just unlock |
duke@435 | 1383 | // the object and we are done |
duke@435 | 1384 | |
duke@435 | 1385 | if (!UseBiasedLocking) { |
duke@435 | 1386 | // load the object out of the BasicObjectLock |
duke@435 | 1387 | ld_ptr(lockobj_addr, obj_reg); |
duke@435 | 1388 | } |
duke@435 | 1389 | |
duke@435 | 1390 | // we have the displaced header in displaced_header_reg |
duke@435 | 1391 | // we expect to see the stack address of the basicLock in case the |
duke@435 | 1392 | // lock is still a light weight lock (lock_reg) |
duke@435 | 1393 | assert(mark_addr.disp() == 0, "cas must take a zero displacement"); |
duke@435 | 1394 | casx_under_lock(mark_addr.base(), lock_reg, displaced_header_reg, |
duke@435 | 1395 | (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); |
duke@435 | 1396 | cmp(lock_reg, displaced_header_reg); |
duke@435 | 1397 | brx(Assembler::equal, true, Assembler::pn, done); |
duke@435 | 1398 | delayed()->st_ptr(G0, lockobj_addr); // free entry |
duke@435 | 1399 | |
duke@435 | 1400 | // The lock has been converted into a heavy lock and hence |
duke@435 | 1401 | // we need to get into the slow case |
duke@435 | 1402 | |
duke@435 | 1403 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); |
duke@435 | 1404 | |
duke@435 | 1405 | bind(done); |
duke@435 | 1406 | } |
duke@435 | 1407 | } |
duke@435 | 1408 | |
duke@435 | 1409 | #ifndef CC_INTERP |
duke@435 | 1410 | |
duke@435 | 1411 | // Get the method data pointer from the methodOop and set the |
duke@435 | 1412 | // specified register to its value. |
duke@435 | 1413 | |
duke@435 | 1414 | void InterpreterMacroAssembler::set_method_data_pointer_offset(Register Roff) { |
duke@435 | 1415 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1416 | Label get_continue; |
duke@435 | 1417 | |
duke@435 | 1418 | ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr); |
duke@435 | 1419 | test_method_data_pointer(get_continue); |
duke@435 | 1420 | add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr); |
duke@435 | 1421 | if (Roff != noreg) |
duke@435 | 1422 | // Roff contains a method data index ("mdi"). It defaults to zero. |
duke@435 | 1423 | add(ImethodDataPtr, Roff, ImethodDataPtr); |
duke@435 | 1424 | bind(get_continue); |
duke@435 | 1425 | } |
duke@435 | 1426 | |
duke@435 | 1427 | // Set the method data pointer for the current bcp. |
duke@435 | 1428 | |
duke@435 | 1429 | void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { |
duke@435 | 1430 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1431 | Label zero_continue; |
duke@435 | 1432 | |
duke@435 | 1433 | // Test MDO to avoid the call if it is NULL. |
duke@435 | 1434 | ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr); |
duke@435 | 1435 | test_method_data_pointer(zero_continue); |
duke@435 | 1436 | call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), Lmethod, Lbcp); |
duke@435 | 1437 | set_method_data_pointer_offset(O0); |
duke@435 | 1438 | bind(zero_continue); |
duke@435 | 1439 | } |
duke@435 | 1440 | |
duke@435 | 1441 | // Test ImethodDataPtr. If it is null, continue at the specified label |
duke@435 | 1442 | |
duke@435 | 1443 | void InterpreterMacroAssembler::test_method_data_pointer(Label& zero_continue) { |
duke@435 | 1444 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1445 | #ifdef _LP64 |
duke@435 | 1446 | bpr(Assembler::rc_z, false, Assembler::pn, ImethodDataPtr, zero_continue); |
duke@435 | 1447 | #else |
duke@435 | 1448 | tst(ImethodDataPtr); |
duke@435 | 1449 | br(Assembler::zero, false, Assembler::pn, zero_continue); |
duke@435 | 1450 | #endif |
duke@435 | 1451 | delayed()->nop(); |
duke@435 | 1452 | } |
duke@435 | 1453 | |
duke@435 | 1454 | void InterpreterMacroAssembler::verify_method_data_pointer() { |
duke@435 | 1455 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1456 | #ifdef ASSERT |
duke@435 | 1457 | Label verify_continue; |
duke@435 | 1458 | test_method_data_pointer(verify_continue); |
duke@435 | 1459 | |
duke@435 | 1460 | // If the mdp is valid, it will point to a DataLayout header which is |
duke@435 | 1461 | // consistent with the bcp. The converse is highly probable also. |
duke@435 | 1462 | lduh(ImethodDataPtr, in_bytes(DataLayout::bci_offset()), G3_scratch); |
duke@435 | 1463 | ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::const_offset())), O5); |
duke@435 | 1464 | add(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()), G3_scratch); |
duke@435 | 1465 | add(G3_scratch, O5, G3_scratch); |
duke@435 | 1466 | cmp(Lbcp, G3_scratch); |
duke@435 | 1467 | brx(Assembler::equal, false, Assembler::pt, verify_continue); |
duke@435 | 1468 | |
duke@435 | 1469 | Register temp_reg = O5; |
duke@435 | 1470 | delayed()->mov(ImethodDataPtr, temp_reg); |
duke@435 | 1471 | // %%% should use call_VM_leaf here? |
duke@435 | 1472 | //call_VM_leaf(noreg, ..., Lmethod, Lbcp, ImethodDataPtr); |
duke@435 | 1473 | save_frame_and_mov(sizeof(jdouble) / wordSize, Lmethod, O0, Lbcp, O1); |
duke@435 | 1474 | Address d_save(FP, 0, -sizeof(jdouble) + STACK_BIAS); |
duke@435 | 1475 | stf(FloatRegisterImpl::D, Ftos_d, d_save); |
duke@435 | 1476 | mov(temp_reg->after_save(), O2); |
duke@435 | 1477 | save_thread(L7_thread_cache); |
duke@435 | 1478 | call(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), relocInfo::none); |
duke@435 | 1479 | delayed()->nop(); |
duke@435 | 1480 | restore_thread(L7_thread_cache); |
duke@435 | 1481 | ldf(FloatRegisterImpl::D, d_save, Ftos_d); |
duke@435 | 1482 | restore(); |
duke@435 | 1483 | bind(verify_continue); |
duke@435 | 1484 | #endif // ASSERT |
duke@435 | 1485 | } |
duke@435 | 1486 | |
duke@435 | 1487 | void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count, |
duke@435 | 1488 | Register cur_bcp, |
duke@435 | 1489 | Register Rtmp, |
duke@435 | 1490 | Label &profile_continue) { |
duke@435 | 1491 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1492 | // Control will flow to "profile_continue" if the counter is less than the |
duke@435 | 1493 | // limit or if we call profile_method() |
duke@435 | 1494 | |
duke@435 | 1495 | Label done; |
duke@435 | 1496 | |
duke@435 | 1497 | // if no method data exists, and the counter is high enough, make one |
duke@435 | 1498 | #ifdef _LP64 |
duke@435 | 1499 | bpr(Assembler::rc_nz, false, Assembler::pn, ImethodDataPtr, done); |
duke@435 | 1500 | #else |
duke@435 | 1501 | tst(ImethodDataPtr); |
duke@435 | 1502 | br(Assembler::notZero, false, Assembler::pn, done); |
duke@435 | 1503 | #endif |
duke@435 | 1504 | |
duke@435 | 1505 | // Test to see if we should create a method data oop |
duke@435 | 1506 | Address profile_limit(Rtmp, (address)&InvocationCounter::InterpreterProfileLimit); |
duke@435 | 1507 | #ifdef _LP64 |
duke@435 | 1508 | delayed()->nop(); |
duke@435 | 1509 | sethi(profile_limit); |
duke@435 | 1510 | #else |
duke@435 | 1511 | delayed()->sethi(profile_limit); |
duke@435 | 1512 | #endif |
duke@435 | 1513 | ld(profile_limit, Rtmp); |
duke@435 | 1514 | cmp(invocation_count, Rtmp); |
duke@435 | 1515 | br(Assembler::lessUnsigned, false, Assembler::pn, profile_continue); |
duke@435 | 1516 | delayed()->nop(); |
duke@435 | 1517 | |
duke@435 | 1518 | // Build it now. |
duke@435 | 1519 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), cur_bcp); |
duke@435 | 1520 | set_method_data_pointer_offset(O0); |
duke@435 | 1521 | ba(false, profile_continue); |
duke@435 | 1522 | delayed()->nop(); |
duke@435 | 1523 | bind(done); |
duke@435 | 1524 | } |
duke@435 | 1525 | |
duke@435 | 1526 | // Store a value at some constant offset from the method data pointer. |
duke@435 | 1527 | |
duke@435 | 1528 | void InterpreterMacroAssembler::set_mdp_data_at(int constant, Register value) { |
duke@435 | 1529 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1530 | st_ptr(value, ImethodDataPtr, constant); |
duke@435 | 1531 | } |
duke@435 | 1532 | |
duke@435 | 1533 | void InterpreterMacroAssembler::increment_mdp_data_at(Address counter, |
duke@435 | 1534 | Register bumped_count, |
duke@435 | 1535 | bool decrement) { |
duke@435 | 1536 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1537 | |
duke@435 | 1538 | // Load the counter. |
duke@435 | 1539 | ld_ptr(counter, bumped_count); |
duke@435 | 1540 | |
duke@435 | 1541 | if (decrement) { |
duke@435 | 1542 | // Decrement the register. Set condition codes. |
duke@435 | 1543 | subcc(bumped_count, DataLayout::counter_increment, bumped_count); |
duke@435 | 1544 | |
duke@435 | 1545 | // If the decrement causes the counter to overflow, stay negative |
duke@435 | 1546 | Label L; |
duke@435 | 1547 | brx(Assembler::negative, true, Assembler::pn, L); |
duke@435 | 1548 | |
duke@435 | 1549 | // Store the decremented counter, if it is still negative. |
duke@435 | 1550 | delayed()->st_ptr(bumped_count, counter); |
duke@435 | 1551 | bind(L); |
duke@435 | 1552 | } else { |
duke@435 | 1553 | // Increment the register. Set carry flag. |
duke@435 | 1554 | addcc(bumped_count, DataLayout::counter_increment, bumped_count); |
duke@435 | 1555 | |
duke@435 | 1556 | // If the increment causes the counter to overflow, pull back by 1. |
duke@435 | 1557 | assert(DataLayout::counter_increment == 1, "subc works"); |
duke@435 | 1558 | subc(bumped_count, G0, bumped_count); |
duke@435 | 1559 | |
duke@435 | 1560 | // Store the incremented counter. |
duke@435 | 1561 | st_ptr(bumped_count, counter); |
duke@435 | 1562 | } |
duke@435 | 1563 | } |
duke@435 | 1564 | |
duke@435 | 1565 | // Increment the value at some constant offset from the method data pointer. |
duke@435 | 1566 | |
duke@435 | 1567 | void InterpreterMacroAssembler::increment_mdp_data_at(int constant, |
duke@435 | 1568 | Register bumped_count, |
duke@435 | 1569 | bool decrement) { |
duke@435 | 1570 | // Locate the counter at a fixed offset from the mdp: |
duke@435 | 1571 | Address counter(ImethodDataPtr, 0, constant); |
duke@435 | 1572 | increment_mdp_data_at(counter, bumped_count, decrement); |
duke@435 | 1573 | } |
duke@435 | 1574 | |
duke@435 | 1575 | // Increment the value at some non-fixed (reg + constant) offset from |
duke@435 | 1576 | // the method data pointer. |
duke@435 | 1577 | |
duke@435 | 1578 | void InterpreterMacroAssembler::increment_mdp_data_at(Register reg, |
duke@435 | 1579 | int constant, |
duke@435 | 1580 | Register bumped_count, |
duke@435 | 1581 | Register scratch2, |
duke@435 | 1582 | bool decrement) { |
duke@435 | 1583 | // Add the constant to reg to get the offset. |
duke@435 | 1584 | add(ImethodDataPtr, reg, scratch2); |
duke@435 | 1585 | Address counter(scratch2, 0, constant); |
duke@435 | 1586 | increment_mdp_data_at(counter, bumped_count, decrement); |
duke@435 | 1587 | } |
duke@435 | 1588 | |
duke@435 | 1589 | // Set a flag value at the current method data pointer position. |
duke@435 | 1590 | // Updates a single byte of the header, to avoid races with other header bits. |
duke@435 | 1591 | |
duke@435 | 1592 | void InterpreterMacroAssembler::set_mdp_flag_at(int flag_constant, |
duke@435 | 1593 | Register scratch) { |
duke@435 | 1594 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1595 | // Load the data header |
duke@435 | 1596 | ldub(ImethodDataPtr, in_bytes(DataLayout::flags_offset()), scratch); |
duke@435 | 1597 | |
duke@435 | 1598 | // Set the flag |
duke@435 | 1599 | or3(scratch, flag_constant, scratch); |
duke@435 | 1600 | |
duke@435 | 1601 | // Store the modified header. |
duke@435 | 1602 | stb(scratch, ImethodDataPtr, in_bytes(DataLayout::flags_offset())); |
duke@435 | 1603 | } |
duke@435 | 1604 | |
duke@435 | 1605 | // Test the location at some offset from the method data pointer. |
duke@435 | 1606 | // If it is not equal to value, branch to the not_equal_continue Label. |
duke@435 | 1607 | // Set condition codes to match the nullness of the loaded value. |
duke@435 | 1608 | |
duke@435 | 1609 | void InterpreterMacroAssembler::test_mdp_data_at(int offset, |
duke@435 | 1610 | Register value, |
duke@435 | 1611 | Label& not_equal_continue, |
duke@435 | 1612 | Register scratch) { |
duke@435 | 1613 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1614 | ld_ptr(ImethodDataPtr, offset, scratch); |
duke@435 | 1615 | cmp(value, scratch); |
duke@435 | 1616 | brx(Assembler::notEqual, false, Assembler::pn, not_equal_continue); |
duke@435 | 1617 | delayed()->tst(scratch); |
duke@435 | 1618 | } |
duke@435 | 1619 | |
duke@435 | 1620 | // Update the method data pointer by the displacement located at some fixed |
duke@435 | 1621 | // offset from the method data pointer. |
duke@435 | 1622 | |
duke@435 | 1623 | void InterpreterMacroAssembler::update_mdp_by_offset(int offset_of_disp, |
duke@435 | 1624 | Register scratch) { |
duke@435 | 1625 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1626 | ld_ptr(ImethodDataPtr, offset_of_disp, scratch); |
duke@435 | 1627 | add(ImethodDataPtr, scratch, ImethodDataPtr); |
duke@435 | 1628 | } |
duke@435 | 1629 | |
duke@435 | 1630 | // Update the method data pointer by the displacement located at the |
duke@435 | 1631 | // offset (reg + offset_of_disp). |
duke@435 | 1632 | |
duke@435 | 1633 | void InterpreterMacroAssembler::update_mdp_by_offset(Register reg, |
duke@435 | 1634 | int offset_of_disp, |
duke@435 | 1635 | Register scratch) { |
duke@435 | 1636 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1637 | add(reg, offset_of_disp, scratch); |
duke@435 | 1638 | ld_ptr(ImethodDataPtr, scratch, scratch); |
duke@435 | 1639 | add(ImethodDataPtr, scratch, ImethodDataPtr); |
duke@435 | 1640 | } |
duke@435 | 1641 | |
duke@435 | 1642 | // Update the method data pointer by a simple constant displacement. |
duke@435 | 1643 | |
duke@435 | 1644 | void InterpreterMacroAssembler::update_mdp_by_constant(int constant) { |
duke@435 | 1645 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1646 | add(ImethodDataPtr, constant, ImethodDataPtr); |
duke@435 | 1647 | } |
duke@435 | 1648 | |
duke@435 | 1649 | // Update the method data pointer for a _ret bytecode whose target |
duke@435 | 1650 | // was not among our cached targets. |
duke@435 | 1651 | |
duke@435 | 1652 | void InterpreterMacroAssembler::update_mdp_for_ret(TosState state, |
duke@435 | 1653 | Register return_bci) { |
duke@435 | 1654 | assert(ProfileInterpreter, "must be profiling interpreter"); |
duke@435 | 1655 | push(state); |
duke@435 | 1656 | st_ptr(return_bci, l_tmp); // protect return_bci, in case it is volatile |
duke@435 | 1657 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); |
duke@435 | 1658 | ld_ptr(l_tmp, return_bci); |
duke@435 | 1659 | pop(state); |
duke@435 | 1660 | } |
duke@435 | 1661 | |
duke@435 | 1662 | // Count a taken branch in the bytecodes. |
duke@435 | 1663 | |
duke@435 | 1664 | void InterpreterMacroAssembler::profile_taken_branch(Register scratch, Register bumped_count) { |
duke@435 | 1665 | if (ProfileInterpreter) { |
duke@435 | 1666 | Label profile_continue; |
duke@435 | 1667 | |
duke@435 | 1668 | // If no method data exists, go to profile_continue. |
duke@435 | 1669 | test_method_data_pointer(profile_continue); |
duke@435 | 1670 | |
duke@435 | 1671 | // We are taking a branch. Increment the taken count. |
duke@435 | 1672 | increment_mdp_data_at(in_bytes(JumpData::taken_offset()), bumped_count); |
duke@435 | 1673 | |
duke@435 | 1674 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1675 | update_mdp_by_offset(in_bytes(JumpData::displacement_offset()), scratch); |
duke@435 | 1676 | bind (profile_continue); |
duke@435 | 1677 | } |
duke@435 | 1678 | } |
duke@435 | 1679 | |
duke@435 | 1680 | |
duke@435 | 1681 | // Count a not-taken branch in the bytecodes. |
duke@435 | 1682 | |
duke@435 | 1683 | void InterpreterMacroAssembler::profile_not_taken_branch(Register scratch) { |
duke@435 | 1684 | if (ProfileInterpreter) { |
duke@435 | 1685 | Label profile_continue; |
duke@435 | 1686 | |
duke@435 | 1687 | // If no method data exists, go to profile_continue. |
duke@435 | 1688 | test_method_data_pointer(profile_continue); |
duke@435 | 1689 | |
duke@435 | 1690 | // We are taking a branch. Increment the not taken count. |
duke@435 | 1691 | increment_mdp_data_at(in_bytes(BranchData::not_taken_offset()), scratch); |
duke@435 | 1692 | |
duke@435 | 1693 | // The method data pointer needs to be updated to correspond to the |
duke@435 | 1694 | // next bytecode. |
duke@435 | 1695 | update_mdp_by_constant(in_bytes(BranchData::branch_data_size())); |
duke@435 | 1696 | bind (profile_continue); |
duke@435 | 1697 | } |
duke@435 | 1698 | } |
duke@435 | 1699 | |
duke@435 | 1700 | |
duke@435 | 1701 | // Count a non-virtual call in the bytecodes. |
duke@435 | 1702 | |
duke@435 | 1703 | void InterpreterMacroAssembler::profile_call(Register scratch) { |
duke@435 | 1704 | if (ProfileInterpreter) { |
duke@435 | 1705 | Label profile_continue; |
duke@435 | 1706 | |
duke@435 | 1707 | // If no method data exists, go to profile_continue. |
duke@435 | 1708 | test_method_data_pointer(profile_continue); |
duke@435 | 1709 | |
duke@435 | 1710 | // We are making a call. Increment the count. |
duke@435 | 1711 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1712 | |
duke@435 | 1713 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1714 | update_mdp_by_constant(in_bytes(CounterData::counter_data_size())); |
duke@435 | 1715 | bind (profile_continue); |
duke@435 | 1716 | } |
duke@435 | 1717 | } |
duke@435 | 1718 | |
duke@435 | 1719 | |
duke@435 | 1720 | // Count a final call in the bytecodes. |
duke@435 | 1721 | |
duke@435 | 1722 | void InterpreterMacroAssembler::profile_final_call(Register scratch) { |
duke@435 | 1723 | if (ProfileInterpreter) { |
duke@435 | 1724 | Label profile_continue; |
duke@435 | 1725 | |
duke@435 | 1726 | // If no method data exists, go to profile_continue. |
duke@435 | 1727 | test_method_data_pointer(profile_continue); |
duke@435 | 1728 | |
duke@435 | 1729 | // We are making a call. Increment the count. |
duke@435 | 1730 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1731 | |
duke@435 | 1732 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1733 | update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); |
duke@435 | 1734 | bind (profile_continue); |
duke@435 | 1735 | } |
duke@435 | 1736 | } |
duke@435 | 1737 | |
duke@435 | 1738 | |
duke@435 | 1739 | // Count a virtual call in the bytecodes. |
duke@435 | 1740 | |
duke@435 | 1741 | void InterpreterMacroAssembler::profile_virtual_call(Register receiver, |
duke@435 | 1742 | Register scratch) { |
duke@435 | 1743 | if (ProfileInterpreter) { |
duke@435 | 1744 | Label profile_continue; |
duke@435 | 1745 | |
duke@435 | 1746 | // If no method data exists, go to profile_continue. |
duke@435 | 1747 | test_method_data_pointer(profile_continue); |
duke@435 | 1748 | |
duke@435 | 1749 | // We are making a call. Increment the count. |
duke@435 | 1750 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1751 | |
duke@435 | 1752 | // Record the receiver type. |
duke@435 | 1753 | record_klass_in_profile(receiver, scratch); |
duke@435 | 1754 | |
duke@435 | 1755 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1756 | update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); |
duke@435 | 1757 | bind (profile_continue); |
duke@435 | 1758 | } |
duke@435 | 1759 | } |
duke@435 | 1760 | |
duke@435 | 1761 | void InterpreterMacroAssembler::record_klass_in_profile_helper( |
duke@435 | 1762 | Register receiver, Register scratch, |
duke@435 | 1763 | int start_row, Label& done) { |
duke@435 | 1764 | int last_row = VirtualCallData::row_limit() - 1; |
duke@435 | 1765 | assert(start_row <= last_row, "must be work left to do"); |
duke@435 | 1766 | // Test this row for both the receiver and for null. |
duke@435 | 1767 | // Take any of three different outcomes: |
duke@435 | 1768 | // 1. found receiver => increment count and goto done |
duke@435 | 1769 | // 2. found null => keep looking for case 1, maybe allocate this cell |
duke@435 | 1770 | // 3. found something else => keep looking for cases 1 and 2 |
duke@435 | 1771 | // Case 3 is handled by a recursive call. |
duke@435 | 1772 | for (int row = start_row; row <= last_row; row++) { |
duke@435 | 1773 | Label next_test; |
duke@435 | 1774 | bool test_for_null_also = (row == start_row); |
duke@435 | 1775 | |
duke@435 | 1776 | // See if the receiver is receiver[n]. |
duke@435 | 1777 | int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); |
duke@435 | 1778 | test_mdp_data_at(recvr_offset, receiver, next_test, scratch); |
duke@435 | 1779 | |
duke@435 | 1780 | // The receiver is receiver[n]. Increment count[n]. |
duke@435 | 1781 | int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); |
duke@435 | 1782 | increment_mdp_data_at(count_offset, scratch); |
duke@435 | 1783 | ba(false, done); |
duke@435 | 1784 | delayed()->nop(); |
duke@435 | 1785 | bind(next_test); |
duke@435 | 1786 | |
duke@435 | 1787 | if (test_for_null_also) { |
duke@435 | 1788 | // Failed the equality check on receiver[n]... Test for null. |
duke@435 | 1789 | if (start_row == last_row) { |
duke@435 | 1790 | // The only thing left to do is handle the null case. |
duke@435 | 1791 | brx(Assembler::notZero, false, Assembler::pt, done); |
duke@435 | 1792 | delayed()->nop(); |
duke@435 | 1793 | break; |
duke@435 | 1794 | } |
duke@435 | 1795 | // Since null is rare, make it be the branch-taken case. |
duke@435 | 1796 | Label found_null; |
duke@435 | 1797 | brx(Assembler::zero, false, Assembler::pn, found_null); |
duke@435 | 1798 | delayed()->nop(); |
duke@435 | 1799 | |
duke@435 | 1800 | // Put all the "Case 3" tests here. |
duke@435 | 1801 | record_klass_in_profile_helper(receiver, scratch, start_row + 1, done); |
duke@435 | 1802 | |
duke@435 | 1803 | // Found a null. Keep searching for a matching receiver, |
duke@435 | 1804 | // but remember that this is an empty (unused) slot. |
duke@435 | 1805 | bind(found_null); |
duke@435 | 1806 | } |
duke@435 | 1807 | } |
duke@435 | 1808 | |
duke@435 | 1809 | // In the fall-through case, we found no matching receiver, but we |
duke@435 | 1810 | // observed the receiver[start_row] is NULL. |
duke@435 | 1811 | |
duke@435 | 1812 | // Fill in the receiver field and increment the count. |
duke@435 | 1813 | int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); |
duke@435 | 1814 | set_mdp_data_at(recvr_offset, receiver); |
duke@435 | 1815 | int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); |
duke@435 | 1816 | mov(DataLayout::counter_increment, scratch); |
duke@435 | 1817 | set_mdp_data_at(count_offset, scratch); |
duke@435 | 1818 | ba(false, done); |
duke@435 | 1819 | delayed()->nop(); |
duke@435 | 1820 | } |
duke@435 | 1821 | |
duke@435 | 1822 | void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, |
duke@435 | 1823 | Register scratch) { |
duke@435 | 1824 | assert(ProfileInterpreter, "must be profiling"); |
duke@435 | 1825 | Label done; |
duke@435 | 1826 | |
duke@435 | 1827 | record_klass_in_profile_helper(receiver, scratch, 0, done); |
duke@435 | 1828 | |
duke@435 | 1829 | bind (done); |
duke@435 | 1830 | } |
duke@435 | 1831 | |
duke@435 | 1832 | |
duke@435 | 1833 | // Count a ret in the bytecodes. |
duke@435 | 1834 | |
duke@435 | 1835 | void InterpreterMacroAssembler::profile_ret(TosState state, |
duke@435 | 1836 | Register return_bci, |
duke@435 | 1837 | Register scratch) { |
duke@435 | 1838 | if (ProfileInterpreter) { |
duke@435 | 1839 | Label profile_continue; |
duke@435 | 1840 | uint row; |
duke@435 | 1841 | |
duke@435 | 1842 | // If no method data exists, go to profile_continue. |
duke@435 | 1843 | test_method_data_pointer(profile_continue); |
duke@435 | 1844 | |
duke@435 | 1845 | // Update the total ret count. |
duke@435 | 1846 | increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); |
duke@435 | 1847 | |
duke@435 | 1848 | for (row = 0; row < RetData::row_limit(); row++) { |
duke@435 | 1849 | Label next_test; |
duke@435 | 1850 | |
duke@435 | 1851 | // See if return_bci is equal to bci[n]: |
duke@435 | 1852 | test_mdp_data_at(in_bytes(RetData::bci_offset(row)), |
duke@435 | 1853 | return_bci, next_test, scratch); |
duke@435 | 1854 | |
duke@435 | 1855 | // return_bci is equal to bci[n]. Increment the count. |
duke@435 | 1856 | increment_mdp_data_at(in_bytes(RetData::bci_count_offset(row)), scratch); |
duke@435 | 1857 | |
duke@435 | 1858 | // The method data pointer needs to be updated to reflect the new target. |
duke@435 | 1859 | update_mdp_by_offset(in_bytes(RetData::bci_displacement_offset(row)), scratch); |
duke@435 | 1860 | ba(false, profile_continue); |
duke@435 | 1861 | delayed()->nop(); |
duke@435 | 1862 | bind(next_test); |
duke@435 | 1863 | } |
duke@435 | 1864 | |
duke@435 | 1865 | update_mdp_for_ret(state, return_bci); |
duke@435 | 1866 | |
duke@435 | 1867 | bind (profile_continue); |
duke@435 | 1868 | } |
duke@435 | 1869 | } |
duke@435 | 1870 | |
duke@435 | 1871 | // Profile an unexpected null in the bytecodes. |
duke@435 | 1872 | void InterpreterMacroAssembler::profile_null_seen(Register scratch) { |
duke@435 | 1873 | if (ProfileInterpreter) { |
duke@435 | 1874 | Label profile_continue; |
duke@435 | 1875 | |
duke@435 | 1876 | // If no method data exists, go to profile_continue. |
duke@435 | 1877 | test_method_data_pointer(profile_continue); |
duke@435 | 1878 | |
duke@435 | 1879 | set_mdp_flag_at(BitData::null_seen_byte_constant(), scratch); |
duke@435 | 1880 | |
duke@435 | 1881 | // The method data pointer needs to be updated. |
duke@435 | 1882 | int mdp_delta = in_bytes(BitData::bit_data_size()); |
duke@435 | 1883 | if (TypeProfileCasts) { |
duke@435 | 1884 | mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); |
duke@435 | 1885 | } |
duke@435 | 1886 | update_mdp_by_constant(mdp_delta); |
duke@435 | 1887 | |
duke@435 | 1888 | bind (profile_continue); |
duke@435 | 1889 | } |
duke@435 | 1890 | } |
duke@435 | 1891 | |
duke@435 | 1892 | void InterpreterMacroAssembler::profile_typecheck(Register klass, |
duke@435 | 1893 | Register scratch) { |
duke@435 | 1894 | if (ProfileInterpreter) { |
duke@435 | 1895 | Label profile_continue; |
duke@435 | 1896 | |
duke@435 | 1897 | // If no method data exists, go to profile_continue. |
duke@435 | 1898 | test_method_data_pointer(profile_continue); |
duke@435 | 1899 | |
duke@435 | 1900 | int mdp_delta = in_bytes(BitData::bit_data_size()); |
duke@435 | 1901 | if (TypeProfileCasts) { |
duke@435 | 1902 | mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); |
duke@435 | 1903 | |
duke@435 | 1904 | // Record the object type. |
duke@435 | 1905 | record_klass_in_profile(klass, scratch); |
duke@435 | 1906 | } |
duke@435 | 1907 | |
duke@435 | 1908 | // The method data pointer needs to be updated. |
duke@435 | 1909 | update_mdp_by_constant(mdp_delta); |
duke@435 | 1910 | |
duke@435 | 1911 | bind (profile_continue); |
duke@435 | 1912 | } |
duke@435 | 1913 | } |
duke@435 | 1914 | |
duke@435 | 1915 | void InterpreterMacroAssembler::profile_typecheck_failed(Register scratch) { |
duke@435 | 1916 | if (ProfileInterpreter && TypeProfileCasts) { |
duke@435 | 1917 | Label profile_continue; |
duke@435 | 1918 | |
duke@435 | 1919 | // If no method data exists, go to profile_continue. |
duke@435 | 1920 | test_method_data_pointer(profile_continue); |
duke@435 | 1921 | |
duke@435 | 1922 | int count_offset = in_bytes(CounterData::count_offset()); |
duke@435 | 1923 | // Back up the address, since we have already bumped the mdp. |
duke@435 | 1924 | count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); |
duke@435 | 1925 | |
duke@435 | 1926 | // *Decrement* the counter. We expect to see zero or small negatives. |
duke@435 | 1927 | increment_mdp_data_at(count_offset, scratch, true); |
duke@435 | 1928 | |
duke@435 | 1929 | bind (profile_continue); |
duke@435 | 1930 | } |
duke@435 | 1931 | } |
duke@435 | 1932 | |
duke@435 | 1933 | // Count the default case of a switch construct. |
duke@435 | 1934 | |
duke@435 | 1935 | void InterpreterMacroAssembler::profile_switch_default(Register scratch) { |
duke@435 | 1936 | if (ProfileInterpreter) { |
duke@435 | 1937 | Label profile_continue; |
duke@435 | 1938 | |
duke@435 | 1939 | // If no method data exists, go to profile_continue. |
duke@435 | 1940 | test_method_data_pointer(profile_continue); |
duke@435 | 1941 | |
duke@435 | 1942 | // Update the default case count |
duke@435 | 1943 | increment_mdp_data_at(in_bytes(MultiBranchData::default_count_offset()), |
duke@435 | 1944 | scratch); |
duke@435 | 1945 | |
duke@435 | 1946 | // The method data pointer needs to be updated. |
duke@435 | 1947 | update_mdp_by_offset( |
duke@435 | 1948 | in_bytes(MultiBranchData::default_displacement_offset()), |
duke@435 | 1949 | scratch); |
duke@435 | 1950 | |
duke@435 | 1951 | bind (profile_continue); |
duke@435 | 1952 | } |
duke@435 | 1953 | } |
duke@435 | 1954 | |
duke@435 | 1955 | // Count the index'th case of a switch construct. |
duke@435 | 1956 | |
duke@435 | 1957 | void InterpreterMacroAssembler::profile_switch_case(Register index, |
duke@435 | 1958 | Register scratch, |
duke@435 | 1959 | Register scratch2, |
duke@435 | 1960 | Register scratch3) { |
duke@435 | 1961 | if (ProfileInterpreter) { |
duke@435 | 1962 | Label profile_continue; |
duke@435 | 1963 | |
duke@435 | 1964 | // If no method data exists, go to profile_continue. |
duke@435 | 1965 | test_method_data_pointer(profile_continue); |
duke@435 | 1966 | |
duke@435 | 1967 | // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() |
duke@435 | 1968 | set(in_bytes(MultiBranchData::per_case_size()), scratch); |
duke@435 | 1969 | smul(index, scratch, scratch); |
duke@435 | 1970 | add(scratch, in_bytes(MultiBranchData::case_array_offset()), scratch); |
duke@435 | 1971 | |
duke@435 | 1972 | // Update the case count |
duke@435 | 1973 | increment_mdp_data_at(scratch, |
duke@435 | 1974 | in_bytes(MultiBranchData::relative_count_offset()), |
duke@435 | 1975 | scratch2, |
duke@435 | 1976 | scratch3); |
duke@435 | 1977 | |
duke@435 | 1978 | // The method data pointer needs to be updated. |
duke@435 | 1979 | update_mdp_by_offset(scratch, |
duke@435 | 1980 | in_bytes(MultiBranchData::relative_displacement_offset()), |
duke@435 | 1981 | scratch2); |
duke@435 | 1982 | |
duke@435 | 1983 | bind (profile_continue); |
duke@435 | 1984 | } |
duke@435 | 1985 | } |
duke@435 | 1986 | |
duke@435 | 1987 | // add a InterpMonitorElem to stack (see frame_sparc.hpp) |
duke@435 | 1988 | |
duke@435 | 1989 | void InterpreterMacroAssembler::add_monitor_to_stack( bool stack_is_empty, |
duke@435 | 1990 | Register Rtemp, |
duke@435 | 1991 | Register Rtemp2 ) { |
duke@435 | 1992 | |
duke@435 | 1993 | Register Rlimit = Lmonitors; |
duke@435 | 1994 | const jint delta = frame::interpreter_frame_monitor_size() * wordSize; |
duke@435 | 1995 | assert( (delta & LongAlignmentMask) == 0, |
duke@435 | 1996 | "sizeof BasicObjectLock must be even number of doublewords"); |
duke@435 | 1997 | |
duke@435 | 1998 | sub( SP, delta, SP); |
duke@435 | 1999 | sub( Lesp, delta, Lesp); |
duke@435 | 2000 | sub( Lmonitors, delta, Lmonitors); |
duke@435 | 2001 | |
duke@435 | 2002 | if (!stack_is_empty) { |
duke@435 | 2003 | |
duke@435 | 2004 | // must copy stack contents down |
duke@435 | 2005 | |
duke@435 | 2006 | Label start_copying, next; |
duke@435 | 2007 | |
duke@435 | 2008 | // untested("monitor stack expansion"); |
duke@435 | 2009 | compute_stack_base(Rtemp); |
duke@435 | 2010 | ba( false, start_copying ); |
duke@435 | 2011 | delayed()->cmp( Rtemp, Rlimit); // done? duplicated below |
duke@435 | 2012 | |
duke@435 | 2013 | // note: must copy from low memory upwards |
duke@435 | 2014 | // On entry to loop, |
duke@435 | 2015 | // Rtemp points to new base of stack, Lesp points to new end of stack (1 past TOS) |
duke@435 | 2016 | // Loop mutates Rtemp |
duke@435 | 2017 | |
duke@435 | 2018 | bind( next); |
duke@435 | 2019 | |
duke@435 | 2020 | st_ptr(Rtemp2, Rtemp, 0); |
duke@435 | 2021 | inc(Rtemp, wordSize); |
duke@435 | 2022 | cmp(Rtemp, Rlimit); // are we done? (duplicated above) |
duke@435 | 2023 | |
duke@435 | 2024 | bind( start_copying ); |
duke@435 | 2025 | |
duke@435 | 2026 | brx( notEqual, true, pn, next ); |
duke@435 | 2027 | delayed()->ld_ptr( Rtemp, delta, Rtemp2 ); |
duke@435 | 2028 | |
duke@435 | 2029 | // done copying stack |
duke@435 | 2030 | } |
duke@435 | 2031 | } |
duke@435 | 2032 | |
duke@435 | 2033 | // Locals |
duke@435 | 2034 | #ifdef ASSERT |
duke@435 | 2035 | void InterpreterMacroAssembler::verify_local_tag(frame::Tag t, |
duke@435 | 2036 | Register base, |
duke@435 | 2037 | Register scratch, |
duke@435 | 2038 | int n) { |
duke@435 | 2039 | if (TaggedStackInterpreter) { |
duke@435 | 2040 | Label ok, long_ok; |
duke@435 | 2041 | // Use dst for scratch |
duke@435 | 2042 | assert_different_registers(base, scratch); |
duke@435 | 2043 | ld_ptr(base, Interpreter::local_tag_offset_in_bytes(n), scratch); |
duke@435 | 2044 | if (t == frame::TagCategory2) { |
duke@435 | 2045 | cmp(scratch, G0); |
duke@435 | 2046 | brx(Assembler::equal, false, Assembler::pt, long_ok); |
duke@435 | 2047 | delayed()->ld_ptr(base, Interpreter::local_tag_offset_in_bytes(n+1), scratch); |
duke@435 | 2048 | stop("local long/double tag value bad"); |
duke@435 | 2049 | bind(long_ok); |
duke@435 | 2050 | // compare second half tag |
duke@435 | 2051 | cmp(scratch, G0); |
duke@435 | 2052 | } else if (t == frame::TagValue) { |
duke@435 | 2053 | cmp(scratch, G0); |
duke@435 | 2054 | } else { |
duke@435 | 2055 | assert_different_registers(O3, base, scratch); |
duke@435 | 2056 | mov(t, O3); |
duke@435 | 2057 | cmp(scratch, O3); |
duke@435 | 2058 | } |
duke@435 | 2059 | brx(Assembler::equal, false, Assembler::pt, ok); |
duke@435 | 2060 | delayed()->nop(); |
duke@435 | 2061 | // Also compare if the local value is zero, then the tag might |
duke@435 | 2062 | // not have been set coming from deopt. |
duke@435 | 2063 | ld_ptr(base, Interpreter::local_offset_in_bytes(n), scratch); |
duke@435 | 2064 | cmp(scratch, G0); |
duke@435 | 2065 | brx(Assembler::equal, false, Assembler::pt, ok); |
duke@435 | 2066 | delayed()->nop(); |
duke@435 | 2067 | stop("Local tag value is bad"); |
duke@435 | 2068 | bind(ok); |
duke@435 | 2069 | } |
duke@435 | 2070 | } |
duke@435 | 2071 | #endif // ASSERT |
duke@435 | 2072 | |
duke@435 | 2073 | void InterpreterMacroAssembler::access_local_ptr( Register index, Register dst ) { |
duke@435 | 2074 | assert_not_delayed(); |
duke@435 | 2075 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2076 | sub(Llocals, index, index); |
duke@435 | 2077 | debug_only(verify_local_tag(frame::TagReference, index, dst)); |
duke@435 | 2078 | ld_ptr(index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2079 | // Note: index must hold the effective address--the iinc template uses it |
duke@435 | 2080 | } |
duke@435 | 2081 | |
duke@435 | 2082 | // Just like access_local_ptr but the tag is a returnAddress |
duke@435 | 2083 | void InterpreterMacroAssembler::access_local_returnAddress(Register index, |
duke@435 | 2084 | Register dst ) { |
duke@435 | 2085 | assert_not_delayed(); |
duke@435 | 2086 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2087 | sub(Llocals, index, index); |
duke@435 | 2088 | debug_only(verify_local_tag(frame::TagValue, index, dst)); |
duke@435 | 2089 | ld_ptr(index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2090 | } |
duke@435 | 2091 | |
duke@435 | 2092 | void InterpreterMacroAssembler::access_local_int( Register index, Register dst ) { |
duke@435 | 2093 | assert_not_delayed(); |
duke@435 | 2094 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2095 | sub(Llocals, index, index); |
duke@435 | 2096 | debug_only(verify_local_tag(frame::TagValue, index, dst)); |
duke@435 | 2097 | ld(index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2098 | // Note: index must hold the effective address--the iinc template uses it |
duke@435 | 2099 | } |
duke@435 | 2100 | |
duke@435 | 2101 | |
duke@435 | 2102 | void InterpreterMacroAssembler::access_local_long( Register index, Register dst ) { |
duke@435 | 2103 | assert_not_delayed(); |
duke@435 | 2104 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2105 | sub(Llocals, index, index); |
duke@435 | 2106 | debug_only(verify_local_tag(frame::TagCategory2, index, dst)); |
duke@435 | 2107 | // First half stored at index n+1 (which grows down from Llocals[n]) |
duke@435 | 2108 | load_unaligned_long(index, Interpreter::local_offset_in_bytes(1), dst); |
duke@435 | 2109 | } |
duke@435 | 2110 | |
duke@435 | 2111 | |
duke@435 | 2112 | void InterpreterMacroAssembler::access_local_float( Register index, FloatRegister dst ) { |
duke@435 | 2113 | assert_not_delayed(); |
duke@435 | 2114 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2115 | sub(Llocals, index, index); |
duke@435 | 2116 | debug_only(verify_local_tag(frame::TagValue, index, G1_scratch)); |
duke@435 | 2117 | ldf(FloatRegisterImpl::S, index, Interpreter::value_offset_in_bytes(), dst); |
duke@435 | 2118 | } |
duke@435 | 2119 | |
duke@435 | 2120 | |
duke@435 | 2121 | void InterpreterMacroAssembler::access_local_double( Register index, FloatRegister dst ) { |
duke@435 | 2122 | assert_not_delayed(); |
duke@435 | 2123 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2124 | sub(Llocals, index, index); |
duke@435 | 2125 | debug_only(verify_local_tag(frame::TagCategory2, index, G1_scratch)); |
duke@435 | 2126 | load_unaligned_double(index, Interpreter::local_offset_in_bytes(1), dst); |
duke@435 | 2127 | } |
duke@435 | 2128 | |
duke@435 | 2129 | |
duke@435 | 2130 | #ifdef ASSERT |
duke@435 | 2131 | void InterpreterMacroAssembler::check_for_regarea_stomp(Register Rindex, int offset, Register Rlimit, Register Rscratch, Register Rscratch1) { |
duke@435 | 2132 | Label L; |
duke@435 | 2133 | |
duke@435 | 2134 | assert(Rindex != Rscratch, "Registers cannot be same"); |
duke@435 | 2135 | assert(Rindex != Rscratch1, "Registers cannot be same"); |
duke@435 | 2136 | assert(Rlimit != Rscratch, "Registers cannot be same"); |
duke@435 | 2137 | assert(Rlimit != Rscratch1, "Registers cannot be same"); |
duke@435 | 2138 | assert(Rscratch1 != Rscratch, "Registers cannot be same"); |
duke@435 | 2139 | |
duke@435 | 2140 | // untested("reg area corruption"); |
duke@435 | 2141 | add(Rindex, offset, Rscratch); |
duke@435 | 2142 | add(Rlimit, 64 + STACK_BIAS, Rscratch1); |
duke@435 | 2143 | cmp(Rscratch, Rscratch1); |
duke@435 | 2144 | brx(Assembler::greaterEqualUnsigned, false, pn, L); |
duke@435 | 2145 | delayed()->nop(); |
duke@435 | 2146 | stop("regsave area is being clobbered"); |
duke@435 | 2147 | bind(L); |
duke@435 | 2148 | } |
duke@435 | 2149 | #endif // ASSERT |
duke@435 | 2150 | |
duke@435 | 2151 | void InterpreterMacroAssembler::tag_local(frame::Tag t, |
duke@435 | 2152 | Register base, |
duke@435 | 2153 | Register src, |
duke@435 | 2154 | int n) { |
duke@435 | 2155 | if (TaggedStackInterpreter) { |
duke@435 | 2156 | // have to store zero because local slots can be reused (rats!) |
duke@435 | 2157 | if (t == frame::TagValue) { |
duke@435 | 2158 | st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2159 | } else if (t == frame::TagCategory2) { |
duke@435 | 2160 | st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2161 | st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n+1)); |
duke@435 | 2162 | } else { |
duke@435 | 2163 | // assert that we don't stomp the value in 'src' |
duke@435 | 2164 | // O3 is arbitrary because it's not used. |
duke@435 | 2165 | assert_different_registers(src, base, O3); |
duke@435 | 2166 | mov( t, O3); |
duke@435 | 2167 | st_ptr(O3, base, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2168 | } |
duke@435 | 2169 | } |
duke@435 | 2170 | } |
duke@435 | 2171 | |
duke@435 | 2172 | |
duke@435 | 2173 | void InterpreterMacroAssembler::store_local_int( Register index, Register src ) { |
duke@435 | 2174 | assert_not_delayed(); |
duke@435 | 2175 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2176 | sub(Llocals, index, index); |
duke@435 | 2177 | debug_only(check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch);) |
duke@435 | 2178 | tag_local(frame::TagValue, index, src); |
duke@435 | 2179 | st(src, index, Interpreter::value_offset_in_bytes()); |
duke@435 | 2180 | } |
duke@435 | 2181 | |
duke@435 | 2182 | void InterpreterMacroAssembler::store_local_ptr( Register index, Register src, |
duke@435 | 2183 | Register tag ) { |
duke@435 | 2184 | assert_not_delayed(); |
duke@435 | 2185 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2186 | sub(Llocals, index, index); |
duke@435 | 2187 | #ifdef ASSERT |
duke@435 | 2188 | check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch); |
duke@435 | 2189 | #endif |
duke@435 | 2190 | st_ptr(src, index, Interpreter::value_offset_in_bytes()); |
duke@435 | 2191 | // Store tag register directly |
duke@435 | 2192 | if (TaggedStackInterpreter) { |
duke@435 | 2193 | st_ptr(tag, index, Interpreter::tag_offset_in_bytes()); |
duke@435 | 2194 | } |
duke@435 | 2195 | } |
duke@435 | 2196 | |
duke@435 | 2197 | |
duke@435 | 2198 | |
duke@435 | 2199 | void InterpreterMacroAssembler::store_local_ptr( int n, Register src, |
duke@435 | 2200 | Register tag ) { |
duke@435 | 2201 | st_ptr(src, Llocals, Interpreter::local_offset_in_bytes(n)); |
duke@435 | 2202 | if (TaggedStackInterpreter) { |
duke@435 | 2203 | st_ptr(tag, Llocals, Interpreter::local_tag_offset_in_bytes(n)); |
duke@435 | 2204 | } |
duke@435 | 2205 | } |
duke@435 | 2206 | |
duke@435 | 2207 | void InterpreterMacroAssembler::store_local_long( Register index, Register src ) { |
duke@435 | 2208 | assert_not_delayed(); |
duke@435 | 2209 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2210 | sub(Llocals, index, index); |
duke@435 | 2211 | #ifdef ASSERT |
duke@435 | 2212 | check_for_regarea_stomp(index, Interpreter::local_offset_in_bytes(1), FP, G1_scratch, G4_scratch); |
duke@435 | 2213 | #endif |
duke@435 | 2214 | tag_local(frame::TagCategory2, index, src); |
duke@435 | 2215 | store_unaligned_long(src, index, Interpreter::local_offset_in_bytes(1)); // which is n+1 |
duke@435 | 2216 | } |
duke@435 | 2217 | |
duke@435 | 2218 | |
duke@435 | 2219 | void InterpreterMacroAssembler::store_local_float( Register index, FloatRegister src ) { |
duke@435 | 2220 | assert_not_delayed(); |
duke@435 | 2221 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2222 | sub(Llocals, index, index); |
duke@435 | 2223 | #ifdef ASSERT |
duke@435 | 2224 | check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch); |
duke@435 | 2225 | #endif |
duke@435 | 2226 | tag_local(frame::TagValue, index, G1_scratch); |
duke@435 | 2227 | stf(FloatRegisterImpl::S, src, index, Interpreter::value_offset_in_bytes()); |
duke@435 | 2228 | } |
duke@435 | 2229 | |
duke@435 | 2230 | |
duke@435 | 2231 | void InterpreterMacroAssembler::store_local_double( Register index, FloatRegister src ) { |
duke@435 | 2232 | assert_not_delayed(); |
duke@435 | 2233 | sll(index, Interpreter::logStackElementSize(), index); |
duke@435 | 2234 | sub(Llocals, index, index); |
duke@435 | 2235 | #ifdef ASSERT |
duke@435 | 2236 | check_for_regarea_stomp(index, Interpreter::local_offset_in_bytes(1), FP, G1_scratch, G4_scratch); |
duke@435 | 2237 | #endif |
duke@435 | 2238 | tag_local(frame::TagCategory2, index, G1_scratch); |
duke@435 | 2239 | store_unaligned_double(src, index, Interpreter::local_offset_in_bytes(1)); |
duke@435 | 2240 | } |
duke@435 | 2241 | |
duke@435 | 2242 | |
duke@435 | 2243 | int InterpreterMacroAssembler::top_most_monitor_byte_offset() { |
duke@435 | 2244 | const jint delta = frame::interpreter_frame_monitor_size() * wordSize; |
duke@435 | 2245 | int rounded_vm_local_words = ::round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); |
duke@435 | 2246 | return ((-rounded_vm_local_words * wordSize) - delta ) + STACK_BIAS; |
duke@435 | 2247 | } |
duke@435 | 2248 | |
duke@435 | 2249 | |
duke@435 | 2250 | Address InterpreterMacroAssembler::top_most_monitor() { |
duke@435 | 2251 | return Address(FP, 0, top_most_monitor_byte_offset()); |
duke@435 | 2252 | } |
duke@435 | 2253 | |
duke@435 | 2254 | |
duke@435 | 2255 | void InterpreterMacroAssembler::compute_stack_base( Register Rdest ) { |
duke@435 | 2256 | add( Lesp, wordSize, Rdest ); |
duke@435 | 2257 | } |
duke@435 | 2258 | |
duke@435 | 2259 | #endif /* CC_INTERP */ |
duke@435 | 2260 | |
duke@435 | 2261 | void InterpreterMacroAssembler::increment_invocation_counter( Register Rtmp, Register Rtmp2 ) { |
duke@435 | 2262 | assert(UseCompiler, "incrementing must be useful"); |
duke@435 | 2263 | #ifdef CC_INTERP |
duke@435 | 2264 | Address inv_counter(G5_method, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2265 | + InvocationCounter::counter_offset())); |
duke@435 | 2266 | Address be_counter(G5_method, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2267 | + InvocationCounter::counter_offset())); |
duke@435 | 2268 | #else |
duke@435 | 2269 | Address inv_counter(Lmethod, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2270 | + InvocationCounter::counter_offset())); |
duke@435 | 2271 | Address be_counter(Lmethod, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2272 | + InvocationCounter::counter_offset())); |
duke@435 | 2273 | #endif /* CC_INTERP */ |
duke@435 | 2274 | int delta = InvocationCounter::count_increment; |
duke@435 | 2275 | |
duke@435 | 2276 | // Load each counter in a register |
duke@435 | 2277 | ld( inv_counter, Rtmp ); |
duke@435 | 2278 | ld( be_counter, Rtmp2 ); |
duke@435 | 2279 | |
duke@435 | 2280 | assert( is_simm13( delta ), " delta too large."); |
duke@435 | 2281 | |
duke@435 | 2282 | // Add the delta to the invocation counter and store the result |
duke@435 | 2283 | add( Rtmp, delta, Rtmp ); |
duke@435 | 2284 | |
duke@435 | 2285 | // Mask the backedge counter |
duke@435 | 2286 | and3( Rtmp2, InvocationCounter::count_mask_value, Rtmp2 ); |
duke@435 | 2287 | |
duke@435 | 2288 | // Store value |
duke@435 | 2289 | st( Rtmp, inv_counter); |
duke@435 | 2290 | |
duke@435 | 2291 | // Add invocation counter + backedge counter |
duke@435 | 2292 | add( Rtmp, Rtmp2, Rtmp); |
duke@435 | 2293 | |
duke@435 | 2294 | // Note that this macro must leave the backedge_count + invocation_count in Rtmp! |
duke@435 | 2295 | } |
duke@435 | 2296 | |
duke@435 | 2297 | void InterpreterMacroAssembler::increment_backedge_counter( Register Rtmp, Register Rtmp2 ) { |
duke@435 | 2298 | assert(UseCompiler, "incrementing must be useful"); |
duke@435 | 2299 | #ifdef CC_INTERP |
duke@435 | 2300 | Address be_counter(G5_method, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2301 | + InvocationCounter::counter_offset())); |
duke@435 | 2302 | Address inv_counter(G5_method, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2303 | + InvocationCounter::counter_offset())); |
duke@435 | 2304 | #else |
duke@435 | 2305 | Address be_counter(Lmethod, 0, in_bytes(methodOopDesc::backedge_counter_offset() |
duke@435 | 2306 | + InvocationCounter::counter_offset())); |
duke@435 | 2307 | Address inv_counter(Lmethod, 0, in_bytes(methodOopDesc::invocation_counter_offset() |
duke@435 | 2308 | + InvocationCounter::counter_offset())); |
duke@435 | 2309 | #endif /* CC_INTERP */ |
duke@435 | 2310 | int delta = InvocationCounter::count_increment; |
duke@435 | 2311 | // Load each counter in a register |
duke@435 | 2312 | ld( be_counter, Rtmp ); |
duke@435 | 2313 | ld( inv_counter, Rtmp2 ); |
duke@435 | 2314 | |
duke@435 | 2315 | // Add the delta to the backedge counter |
duke@435 | 2316 | add( Rtmp, delta, Rtmp ); |
duke@435 | 2317 | |
duke@435 | 2318 | // Mask the invocation counter, add to backedge counter |
duke@435 | 2319 | and3( Rtmp2, InvocationCounter::count_mask_value, Rtmp2 ); |
duke@435 | 2320 | |
duke@435 | 2321 | // and store the result to memory |
duke@435 | 2322 | st( Rtmp, be_counter ); |
duke@435 | 2323 | |
duke@435 | 2324 | // Add backedge + invocation counter |
duke@435 | 2325 | add( Rtmp, Rtmp2, Rtmp ); |
duke@435 | 2326 | |
duke@435 | 2327 | // Note that this macro must leave backedge_count + invocation_count in Rtmp! |
duke@435 | 2328 | } |
duke@435 | 2329 | |
duke@435 | 2330 | #ifndef CC_INTERP |
duke@435 | 2331 | void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count, |
duke@435 | 2332 | Register branch_bcp, |
duke@435 | 2333 | Register Rtmp ) { |
duke@435 | 2334 | Label did_not_overflow; |
duke@435 | 2335 | Label overflow_with_error; |
duke@435 | 2336 | assert_different_registers(backedge_count, Rtmp, branch_bcp); |
duke@435 | 2337 | assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr"); |
duke@435 | 2338 | |
duke@435 | 2339 | Address limit(Rtmp, address(&InvocationCounter::InterpreterBackwardBranchLimit)); |
duke@435 | 2340 | load_contents(limit, Rtmp); |
duke@435 | 2341 | cmp(backedge_count, Rtmp); |
duke@435 | 2342 | br(Assembler::lessUnsigned, false, Assembler::pt, did_not_overflow); |
duke@435 | 2343 | delayed()->nop(); |
duke@435 | 2344 | |
duke@435 | 2345 | // When ProfileInterpreter is on, the backedge_count comes from the |
duke@435 | 2346 | // methodDataOop, which value does not get reset on the call to |
duke@435 | 2347 | // frequency_counter_overflow(). To avoid excessive calls to the overflow |
duke@435 | 2348 | // routine while the method is being compiled, add a second test to make sure |
duke@435 | 2349 | // the overflow function is called only once every overflow_frequency. |
duke@435 | 2350 | if (ProfileInterpreter) { |
duke@435 | 2351 | const int overflow_frequency = 1024; |
duke@435 | 2352 | andcc(backedge_count, overflow_frequency-1, Rtmp); |
duke@435 | 2353 | brx(Assembler::notZero, false, Assembler::pt, did_not_overflow); |
duke@435 | 2354 | delayed()->nop(); |
duke@435 | 2355 | } |
duke@435 | 2356 | |
duke@435 | 2357 | // overflow in loop, pass branch bytecode |
duke@435 | 2358 | set(6,Rtmp); |
duke@435 | 2359 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), branch_bcp, Rtmp); |
duke@435 | 2360 | |
duke@435 | 2361 | // Was an OSR adapter generated? |
duke@435 | 2362 | // O0 = osr nmethod |
duke@435 | 2363 | tst(O0); |
duke@435 | 2364 | brx(Assembler::zero, false, Assembler::pn, overflow_with_error); |
duke@435 | 2365 | delayed()->nop(); |
duke@435 | 2366 | |
duke@435 | 2367 | // Has the nmethod been invalidated already? |
duke@435 | 2368 | ld(O0, nmethod::entry_bci_offset(), O2); |
duke@435 | 2369 | cmp(O2, InvalidOSREntryBci); |
duke@435 | 2370 | br(Assembler::equal, false, Assembler::pn, overflow_with_error); |
duke@435 | 2371 | delayed()->nop(); |
duke@435 | 2372 | |
duke@435 | 2373 | // migrate the interpreter frame off of the stack |
duke@435 | 2374 | |
duke@435 | 2375 | mov(G2_thread, L7); |
duke@435 | 2376 | // save nmethod |
duke@435 | 2377 | mov(O0, L6); |
duke@435 | 2378 | set_last_Java_frame(SP, noreg); |
duke@435 | 2379 | call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin), L7); |
duke@435 | 2380 | reset_last_Java_frame(); |
duke@435 | 2381 | mov(L7, G2_thread); |
duke@435 | 2382 | |
duke@435 | 2383 | // move OSR nmethod to I1 |
duke@435 | 2384 | mov(L6, I1); |
duke@435 | 2385 | |
duke@435 | 2386 | // OSR buffer to I0 |
duke@435 | 2387 | mov(O0, I0); |
duke@435 | 2388 | |
duke@435 | 2389 | // remove the interpreter frame |
duke@435 | 2390 | restore(I5_savedSP, 0, SP); |
duke@435 | 2391 | |
duke@435 | 2392 | // Jump to the osr code. |
duke@435 | 2393 | ld_ptr(O1, nmethod::osr_entry_point_offset(), O2); |
duke@435 | 2394 | jmp(O2, G0); |
duke@435 | 2395 | delayed()->nop(); |
duke@435 | 2396 | |
duke@435 | 2397 | bind(overflow_with_error); |
duke@435 | 2398 | |
duke@435 | 2399 | bind(did_not_overflow); |
duke@435 | 2400 | } |
duke@435 | 2401 | |
duke@435 | 2402 | |
duke@435 | 2403 | |
duke@435 | 2404 | void InterpreterMacroAssembler::interp_verify_oop(Register reg, TosState state, const char * file, int line) { |
duke@435 | 2405 | if (state == atos) { MacroAssembler::_verify_oop(reg, "broken oop ", file, line); } |
duke@435 | 2406 | } |
duke@435 | 2407 | |
duke@435 | 2408 | |
duke@435 | 2409 | // local helper function for the verify_oop_or_return_address macro |
duke@435 | 2410 | static bool verify_return_address(methodOopDesc* m, int bci) { |
duke@435 | 2411 | #ifndef PRODUCT |
duke@435 | 2412 | address pc = (address)(m->constMethod()) |
duke@435 | 2413 | + in_bytes(constMethodOopDesc::codes_offset()) + bci; |
duke@435 | 2414 | // assume it is a valid return address if it is inside m and is preceded by a jsr |
duke@435 | 2415 | if (!m->contains(pc)) return false; |
duke@435 | 2416 | address jsr_pc; |
duke@435 | 2417 | jsr_pc = pc - Bytecodes::length_for(Bytecodes::_jsr); |
duke@435 | 2418 | if (*jsr_pc == Bytecodes::_jsr && jsr_pc >= m->code_base()) return true; |
duke@435 | 2419 | jsr_pc = pc - Bytecodes::length_for(Bytecodes::_jsr_w); |
duke@435 | 2420 | if (*jsr_pc == Bytecodes::_jsr_w && jsr_pc >= m->code_base()) return true; |
duke@435 | 2421 | #endif // PRODUCT |
duke@435 | 2422 | return false; |
duke@435 | 2423 | } |
duke@435 | 2424 | |
duke@435 | 2425 | |
duke@435 | 2426 | void InterpreterMacroAssembler::verify_oop_or_return_address(Register reg, Register Rtmp) { |
duke@435 | 2427 | if (!VerifyOops) return; |
duke@435 | 2428 | // the VM documentation for the astore[_wide] bytecode allows |
duke@435 | 2429 | // the TOS to be not only an oop but also a return address |
duke@435 | 2430 | Label test; |
duke@435 | 2431 | Label skip; |
duke@435 | 2432 | // See if it is an address (in the current method): |
duke@435 | 2433 | |
duke@435 | 2434 | mov(reg, Rtmp); |
duke@435 | 2435 | const int log2_bytecode_size_limit = 16; |
duke@435 | 2436 | srl(Rtmp, log2_bytecode_size_limit, Rtmp); |
duke@435 | 2437 | br_notnull( Rtmp, false, pt, test ); |
duke@435 | 2438 | delayed()->nop(); |
duke@435 | 2439 | |
duke@435 | 2440 | // %%% should use call_VM_leaf here? |
duke@435 | 2441 | save_frame_and_mov(0, Lmethod, O0, reg, O1); |
duke@435 | 2442 | save_thread(L7_thread_cache); |
duke@435 | 2443 | call(CAST_FROM_FN_PTR(address,verify_return_address), relocInfo::none); |
duke@435 | 2444 | delayed()->nop(); |
duke@435 | 2445 | restore_thread(L7_thread_cache); |
duke@435 | 2446 | br_notnull( O0, false, pt, skip ); |
duke@435 | 2447 | delayed()->restore(); |
duke@435 | 2448 | |
duke@435 | 2449 | // Perform a more elaborate out-of-line call |
duke@435 | 2450 | // Not an address; verify it: |
duke@435 | 2451 | bind(test); |
duke@435 | 2452 | verify_oop(reg); |
duke@435 | 2453 | bind(skip); |
duke@435 | 2454 | } |
duke@435 | 2455 | |
duke@435 | 2456 | |
duke@435 | 2457 | void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { |
duke@435 | 2458 | if (state == ftos || state == dtos) MacroAssembler::verify_FPU(stack_depth); |
duke@435 | 2459 | } |
duke@435 | 2460 | #endif /* CC_INTERP */ |
duke@435 | 2461 | |
duke@435 | 2462 | // Inline assembly for: |
duke@435 | 2463 | // |
duke@435 | 2464 | // if (thread is in interp_only_mode) { |
duke@435 | 2465 | // InterpreterRuntime::post_method_entry(); |
duke@435 | 2466 | // } |
duke@435 | 2467 | // if (DTraceMethodProbes) { |
twisti@1040 | 2468 | // SharedRuntime::dtrace_method_entry(method, receiver); |
duke@435 | 2469 | // } |
duke@435 | 2470 | |
duke@435 | 2471 | void InterpreterMacroAssembler::notify_method_entry() { |
duke@435 | 2472 | |
duke@435 | 2473 | // C++ interpreter only uses this for native methods. |
duke@435 | 2474 | |
duke@435 | 2475 | // Whenever JVMTI puts a thread in interp_only_mode, method |
duke@435 | 2476 | // entry/exit events are sent for that thread to track stack |
duke@435 | 2477 | // depth. If it is possible to enter interp_only_mode we add |
duke@435 | 2478 | // the code to check if the event should be sent. |
duke@435 | 2479 | if (JvmtiExport::can_post_interpreter_events()) { |
duke@435 | 2480 | Label L; |
duke@435 | 2481 | Register temp_reg = O5; |
duke@435 | 2482 | |
duke@435 | 2483 | const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset())); |
duke@435 | 2484 | |
duke@435 | 2485 | ld(interp_only, temp_reg); |
duke@435 | 2486 | tst(temp_reg); |
duke@435 | 2487 | br(zero, false, pt, L); |
duke@435 | 2488 | delayed()->nop(); |
duke@435 | 2489 | call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_entry)); |
duke@435 | 2490 | bind(L); |
duke@435 | 2491 | } |
duke@435 | 2492 | |
duke@435 | 2493 | { |
duke@435 | 2494 | Register temp_reg = O5; |
duke@435 | 2495 | SkipIfEqual skip_if(this, temp_reg, &DTraceMethodProbes, zero); |
duke@435 | 2496 | call_VM_leaf(noreg, |
duke@435 | 2497 | CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), |
duke@435 | 2498 | G2_thread, Lmethod); |
duke@435 | 2499 | } |
duke@435 | 2500 | } |
duke@435 | 2501 | |
duke@435 | 2502 | |
duke@435 | 2503 | // Inline assembly for: |
duke@435 | 2504 | // |
duke@435 | 2505 | // if (thread is in interp_only_mode) { |
duke@435 | 2506 | // // save result |
duke@435 | 2507 | // InterpreterRuntime::post_method_exit(); |
duke@435 | 2508 | // // restore result |
duke@435 | 2509 | // } |
duke@435 | 2510 | // if (DTraceMethodProbes) { |
duke@435 | 2511 | // SharedRuntime::dtrace_method_exit(thread, method); |
duke@435 | 2512 | // } |
duke@435 | 2513 | // |
duke@435 | 2514 | // Native methods have their result stored in d_tmp and l_tmp |
duke@435 | 2515 | // Java methods have their result stored in the expression stack |
duke@435 | 2516 | |
duke@435 | 2517 | void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, |
duke@435 | 2518 | TosState state, |
duke@435 | 2519 | NotifyMethodExitMode mode) { |
duke@435 | 2520 | // C++ interpreter only uses this for native methods. |
duke@435 | 2521 | |
duke@435 | 2522 | // Whenever JVMTI puts a thread in interp_only_mode, method |
duke@435 | 2523 | // entry/exit events are sent for that thread to track stack |
duke@435 | 2524 | // depth. If it is possible to enter interp_only_mode we add |
duke@435 | 2525 | // the code to check if the event should be sent. |
duke@435 | 2526 | if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { |
duke@435 | 2527 | Label L; |
duke@435 | 2528 | Register temp_reg = O5; |
duke@435 | 2529 | |
duke@435 | 2530 | const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset())); |
duke@435 | 2531 | |
duke@435 | 2532 | ld(interp_only, temp_reg); |
duke@435 | 2533 | tst(temp_reg); |
duke@435 | 2534 | br(zero, false, pt, L); |
duke@435 | 2535 | delayed()->nop(); |
duke@435 | 2536 | |
duke@435 | 2537 | // Note: frame::interpreter_frame_result has a dependency on how the |
duke@435 | 2538 | // method result is saved across the call to post_method_exit. For |
duke@435 | 2539 | // native methods it assumes the result registers are saved to |
duke@435 | 2540 | // l_scratch and d_scratch. If this changes then the interpreter_frame_result |
duke@435 | 2541 | // implementation will need to be updated too. |
duke@435 | 2542 | |
duke@435 | 2543 | save_return_value(state, is_native_method); |
duke@435 | 2544 | call_VM(noreg, |
duke@435 | 2545 | CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); |
duke@435 | 2546 | restore_return_value(state, is_native_method); |
duke@435 | 2547 | bind(L); |
duke@435 | 2548 | } |
duke@435 | 2549 | |
duke@435 | 2550 | { |
duke@435 | 2551 | Register temp_reg = O5; |
duke@435 | 2552 | // Dtrace notification |
duke@435 | 2553 | SkipIfEqual skip_if(this, temp_reg, &DTraceMethodProbes, zero); |
duke@435 | 2554 | save_return_value(state, is_native_method); |
duke@435 | 2555 | call_VM_leaf( |
duke@435 | 2556 | noreg, |
duke@435 | 2557 | CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), |
duke@435 | 2558 | G2_thread, Lmethod); |
duke@435 | 2559 | restore_return_value(state, is_native_method); |
duke@435 | 2560 | } |
duke@435 | 2561 | } |
duke@435 | 2562 | |
duke@435 | 2563 | void InterpreterMacroAssembler::save_return_value(TosState state, bool is_native_call) { |
duke@435 | 2564 | #ifdef CC_INTERP |
duke@435 | 2565 | // result potentially in O0/O1: save it across calls |
duke@435 | 2566 | stf(FloatRegisterImpl::D, F0, STATE(_native_fresult)); |
duke@435 | 2567 | #ifdef _LP64 |
duke@435 | 2568 | stx(O0, STATE(_native_lresult)); |
duke@435 | 2569 | #else |
duke@435 | 2570 | std(O0, STATE(_native_lresult)); |
duke@435 | 2571 | #endif |
duke@435 | 2572 | #else // CC_INTERP |
duke@435 | 2573 | if (is_native_call) { |
duke@435 | 2574 | stf(FloatRegisterImpl::D, F0, d_tmp); |
duke@435 | 2575 | #ifdef _LP64 |
duke@435 | 2576 | stx(O0, l_tmp); |
duke@435 | 2577 | #else |
duke@435 | 2578 | std(O0, l_tmp); |
duke@435 | 2579 | #endif |
duke@435 | 2580 | } else { |
duke@435 | 2581 | push(state); |
duke@435 | 2582 | } |
duke@435 | 2583 | #endif // CC_INTERP |
duke@435 | 2584 | } |
duke@435 | 2585 | |
duke@435 | 2586 | void InterpreterMacroAssembler::restore_return_value( TosState state, bool is_native_call) { |
duke@435 | 2587 | #ifdef CC_INTERP |
duke@435 | 2588 | ldf(FloatRegisterImpl::D, STATE(_native_fresult), F0); |
duke@435 | 2589 | #ifdef _LP64 |
duke@435 | 2590 | ldx(STATE(_native_lresult), O0); |
duke@435 | 2591 | #else |
duke@435 | 2592 | ldd(STATE(_native_lresult), O0); |
duke@435 | 2593 | #endif |
duke@435 | 2594 | #else // CC_INTERP |
duke@435 | 2595 | if (is_native_call) { |
duke@435 | 2596 | ldf(FloatRegisterImpl::D, d_tmp, F0); |
duke@435 | 2597 | #ifdef _LP64 |
duke@435 | 2598 | ldx(l_tmp, O0); |
duke@435 | 2599 | #else |
duke@435 | 2600 | ldd(l_tmp, O0); |
duke@435 | 2601 | #endif |
duke@435 | 2602 | } else { |
duke@435 | 2603 | pop(state); |
duke@435 | 2604 | } |
duke@435 | 2605 | #endif // CC_INTERP |
duke@435 | 2606 | } |