Mercurial > hg > graal-compiler
comparison src/cpu/x86/vm/interp_masm_x86_32.cpp @ 304:dc7f315e41f7
5108146: Merge i486 and amd64 cpu directories
6459804: Want client (c1) compiler for x86_64 (amd64) for faster start-up
Reviewed-by: kvn
author | never |
---|---|
date | Wed, 27 Aug 2008 00:21:55 -0700 |
parents | a61af66fc99e |
children | 9ee9cf798b59 |
comparison
equal
deleted
inserted
replaced
303:fa4d1d240383 | 304:dc7f315e41f7 |
---|---|
27 | 27 |
28 | 28 |
29 // Implementation of InterpreterMacroAssembler | 29 // Implementation of InterpreterMacroAssembler |
30 #ifdef CC_INTERP | 30 #ifdef CC_INTERP |
31 void InterpreterMacroAssembler::get_method(Register reg) { | 31 void InterpreterMacroAssembler::get_method(Register reg) { |
32 movl(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); | 32 movptr(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); |
33 movl(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); | 33 movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); |
34 } | 34 } |
35 #endif // CC_INTERP | 35 #endif // CC_INTERP |
36 | 36 |
37 | 37 |
38 #ifndef CC_INTERP | 38 #ifndef CC_INTERP |
51 // saved! There used to be a save_bcp() that only happened in | 51 // saved! There used to be a save_bcp() that only happened in |
52 // the ASSERT path (no restore_bcp). Which caused bizarre failures | 52 // the ASSERT path (no restore_bcp). Which caused bizarre failures |
53 // when jvm built with ASSERTs. | 53 // when jvm built with ASSERTs. |
54 #ifdef ASSERT | 54 #ifdef ASSERT |
55 { Label L; | 55 { Label L; |
56 cmpl(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); | 56 cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); |
57 jcc(Assembler::equal, L); | 57 jcc(Assembler::equal, L); |
58 stop("InterpreterMacroAssembler::call_VM_leaf_base: last_sp != NULL"); | 58 stop("InterpreterMacroAssembler::call_VM_leaf_base: last_sp != NULL"); |
59 bind(L); | 59 bind(L); |
60 } | 60 } |
61 #endif | 61 #endif |
77 int number_of_arguments, | 77 int number_of_arguments, |
78 bool check_exceptions | 78 bool check_exceptions |
79 ) { | 79 ) { |
80 #ifdef ASSERT | 80 #ifdef ASSERT |
81 { Label L; | 81 { Label L; |
82 cmpl(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); | 82 cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); |
83 jcc(Assembler::equal, L); | 83 jcc(Assembler::equal, L); |
84 stop("InterpreterMacroAssembler::call_VM_base: last_sp != NULL"); | 84 stop("InterpreterMacroAssembler::call_VM_base: last_sp != NULL"); |
85 bind(L); | 85 bind(L); |
86 } | 86 } |
87 #endif /* ASSERT */ | 87 #endif /* ASSERT */ |
130 const Address oop_addr (rcx, JvmtiThreadState::earlyret_oop_offset()); | 130 const Address oop_addr (rcx, JvmtiThreadState::earlyret_oop_offset()); |
131 const Address val_addr (rcx, JvmtiThreadState::earlyret_value_offset()); | 131 const Address val_addr (rcx, JvmtiThreadState::earlyret_value_offset()); |
132 const Address val_addr1(rcx, JvmtiThreadState::earlyret_value_offset() | 132 const Address val_addr1(rcx, JvmtiThreadState::earlyret_value_offset() |
133 + in_ByteSize(wordSize)); | 133 + in_ByteSize(wordSize)); |
134 switch (state) { | 134 switch (state) { |
135 case atos: movl(rax, oop_addr); | 135 case atos: movptr(rax, oop_addr); |
136 movl(oop_addr, NULL_WORD); | 136 movptr(oop_addr, (int32_t)NULL_WORD); |
137 verify_oop(rax, state); break; | 137 verify_oop(rax, state); break; |
138 case ltos: movl(rdx, val_addr1); // fall through | 138 case ltos: |
139 movl(rdx, val_addr1); // fall through | |
139 case btos: // fall through | 140 case btos: // fall through |
140 case ctos: // fall through | 141 case ctos: // fall through |
141 case stos: // fall through | 142 case stos: // fall through |
142 case itos: movl(rax, val_addr); break; | 143 case itos: movl(rax, val_addr); break; |
143 case ftos: fld_s(val_addr); break; | 144 case ftos: fld_s(val_addr); break; |
144 case dtos: fld_d(val_addr); break; | 145 case dtos: fld_d(val_addr); break; |
145 case vtos: /* nothing to do */ break; | 146 case vtos: /* nothing to do */ break; |
146 default : ShouldNotReachHere(); | 147 default : ShouldNotReachHere(); |
147 } | 148 } |
148 // Clean up tos value in the thread object | 149 // Clean up tos value in the thread object |
149 movl(tos_addr, (int) ilgl); | 150 movl(tos_addr, (int32_t) ilgl); |
150 movl(val_addr, NULL_WORD); | 151 movptr(val_addr, (int32_t)NULL_WORD); |
151 movl(val_addr1, NULL_WORD); | 152 NOT_LP64(movl(val_addr1, (int32_t)NULL_WORD)); |
152 } | 153 } |
153 | 154 |
154 | 155 |
155 void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { | 156 void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { |
156 if (JvmtiExport::can_force_early_return()) { | 157 if (JvmtiExport::can_force_early_return()) { |
157 Label L; | 158 Label L; |
158 Register tmp = java_thread; | 159 Register tmp = java_thread; |
159 movl(tmp, Address(tmp, JavaThread::jvmti_thread_state_offset())); | 160 movptr(tmp, Address(tmp, JavaThread::jvmti_thread_state_offset())); |
160 testl(tmp, tmp); | 161 testptr(tmp, tmp); |
161 jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == NULL) exit; | 162 jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == NULL) exit; |
162 | 163 |
163 // Initiate earlyret handling only if it is not already being processed. | 164 // Initiate earlyret handling only if it is not already being processed. |
164 // If the flag has the earlyret_processing bit set, it means that this code | 165 // If the flag has the earlyret_processing bit set, it means that this code |
165 // is called *during* earlyret handling - we don't want to reenter. | 166 // is called *during* earlyret handling - we don't want to reenter. |
168 jcc(Assembler::notEqual, L); | 169 jcc(Assembler::notEqual, L); |
169 | 170 |
170 // Call Interpreter::remove_activation_early_entry() to get the address of the | 171 // Call Interpreter::remove_activation_early_entry() to get the address of the |
171 // same-named entrypoint in the generated interpreter code. | 172 // same-named entrypoint in the generated interpreter code. |
172 get_thread(java_thread); | 173 get_thread(java_thread); |
173 movl(tmp, Address(java_thread, JavaThread::jvmti_thread_state_offset())); | 174 movptr(tmp, Address(java_thread, JavaThread::jvmti_thread_state_offset())); |
174 pushl(Address(tmp, JvmtiThreadState::earlyret_tos_offset())); | 175 pushl(Address(tmp, JvmtiThreadState::earlyret_tos_offset())); |
175 call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), 1); | 176 call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), 1); |
176 jmp(rax); | 177 jmp(rax); |
177 bind(L); | 178 bind(L); |
178 get_thread(java_thread); | 179 get_thread(java_thread); |
181 | 182 |
182 | 183 |
183 void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset) { | 184 void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset) { |
184 assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); | 185 assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); |
185 movl(reg, Address(rsi, bcp_offset)); | 186 movl(reg, Address(rsi, bcp_offset)); |
186 bswap(reg); | 187 bswapl(reg); |
187 shrl(reg, 16); | 188 shrl(reg, 16); |
188 } | 189 } |
189 | 190 |
190 | 191 |
191 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) { | 192 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) { |
192 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); | 193 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); |
193 assert(cache != index, "must use different registers"); | 194 assert(cache != index, "must use different registers"); |
194 load_unsigned_word(index, Address(rsi, bcp_offset)); | 195 load_unsigned_word(index, Address(rsi, bcp_offset)); |
195 movl(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); | 196 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); |
196 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); | 197 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); |
197 shll(index, 2); // convert from field index to ConstantPoolCacheEntry index | 198 shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index |
198 } | 199 } |
199 | 200 |
200 | 201 |
201 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) { | 202 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) { |
202 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); | 203 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); |
204 load_unsigned_word(tmp, Address(rsi, bcp_offset)); | 205 load_unsigned_word(tmp, Address(rsi, bcp_offset)); |
205 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); | 206 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); |
206 // convert from field index to ConstantPoolCacheEntry index | 207 // convert from field index to ConstantPoolCacheEntry index |
207 // and from word offset to byte offset | 208 // and from word offset to byte offset |
208 shll(tmp, 2 + LogBytesPerWord); | 209 shll(tmp, 2 + LogBytesPerWord); |
209 movl(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); | 210 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); |
210 // skip past the header | 211 // skip past the header |
211 addl(cache, in_bytes(constantPoolCacheOopDesc::base_offset())); | 212 addptr(cache, in_bytes(constantPoolCacheOopDesc::base_offset())); |
212 addl(cache, tmp); // construct pointer to cache entry | 213 addptr(cache, tmp); // construct pointer to cache entry |
213 } | 214 } |
214 | 215 |
215 | 216 |
216 // Generate a subtype check: branch to ok_is_subtype if sub_klass is | 217 // Generate a subtype check: branch to ok_is_subtype if sub_klass is |
217 // a subtype of super_klass. EAX holds the super_klass. Blows ECX. | 218 // a subtype of super_klass. EAX holds the super_klass. Blows ECX. |
230 // Load from the sub-klass's super-class display list, or a 1-word cache of | 231 // Load from the sub-klass's super-class display list, or a 1-word cache of |
231 // the secondary superclass list, or a failing value with a sentinel offset | 232 // the secondary superclass list, or a failing value with a sentinel offset |
232 // if the super-klass is an interface or exceptionally deep in the Java | 233 // if the super-klass is an interface or exceptionally deep in the Java |
233 // hierarchy and we have to scan the secondary superclass list the hard way. | 234 // hierarchy and we have to scan the secondary superclass list the hard way. |
234 // See if we get an immediate positive hit | 235 // See if we get an immediate positive hit |
235 cmpl( rax, Address(Rsub_klass,rcx,Address::times_1) ); | 236 cmpptr( rax, Address(Rsub_klass,rcx,Address::times_1) ); |
236 jcc( Assembler::equal,ok_is_subtype ); | 237 jcc( Assembler::equal,ok_is_subtype ); |
237 | 238 |
238 // Check for immediate negative hit | 239 // Check for immediate negative hit |
239 cmpl( rcx, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); | 240 cmpl( rcx, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); |
240 jcc( Assembler::notEqual, not_subtype ); | 241 jcc( Assembler::notEqual, not_subtype ); |
241 // Check for self | 242 // Check for self |
242 cmpl( Rsub_klass, rax ); | 243 cmpptr( Rsub_klass, rax ); |
243 jcc( Assembler::equal, ok_is_subtype ); | 244 jcc( Assembler::equal, ok_is_subtype ); |
244 | 245 |
245 // Now do a linear scan of the secondary super-klass chain. | 246 // Now do a linear scan of the secondary super-klass chain. |
246 movl( rdi, Address(Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes()) ); | 247 movptr( rdi, Address(Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes()) ); |
247 // EDI holds the objArrayOop of secondary supers. | 248 // EDI holds the objArrayOop of secondary supers. |
248 movl( rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));// Load the array length | 249 movl( rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));// Load the array length |
249 // Skip to start of data; also clear Z flag incase ECX is zero | 250 // Skip to start of data; also clear Z flag incase ECX is zero |
250 addl( rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT) ); | 251 addptr( rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT) ); |
251 // Scan ECX words at [EDI] for occurance of EAX | 252 // Scan ECX words at [EDI] for occurance of EAX |
252 // Set NZ/Z based on last compare | 253 // Set NZ/Z based on last compare |
253 repne_scan(); | 254 repne_scan(); |
254 restore_locals(); // Restore EDI; Must not blow flags | 255 restore_locals(); // Restore EDI; Must not blow flags |
255 // Not equal? | 256 // Not equal? |
256 jcc( Assembler::notEqual, not_subtype ); | 257 jcc( Assembler::notEqual, not_subtype ); |
257 // Must be equal but missed in cache. Update cache. | 258 // Must be equal but missed in cache. Update cache. |
258 movl( Address(Rsub_klass, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()), rax ); | 259 movptr( Address(Rsub_klass, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()), rax ); |
259 jmp( ok_is_subtype ); | 260 jmp( ok_is_subtype ); |
260 | 261 |
261 bind(not_subtype); | 262 bind(not_subtype); |
262 profile_typecheck_failed(rcx); // blows rcx | 263 profile_typecheck_failed(rcx); // blows rcx |
263 } | 264 } |
274 if (IEEEPrecision) { | 275 if (IEEEPrecision) { |
275 fstp_d(Address(rsp, 0)); | 276 fstp_d(Address(rsp, 0)); |
276 fld_d(Address(rsp, 0)); | 277 fld_d(Address(rsp, 0)); |
277 } | 278 } |
278 } | 279 } |
279 #endif // CC_INTERP | |
280 | 280 |
281 // Java Expression Stack | 281 // Java Expression Stack |
282 | 282 |
283 #ifdef ASSERT | 283 #ifdef ASSERT |
284 void InterpreterMacroAssembler::verify_stack_tag(frame::Tag t) { | 284 void InterpreterMacroAssembler::verify_stack_tag(frame::Tag t) { |
285 if (TaggedStackInterpreter) { | 285 if (TaggedStackInterpreter) { |
286 Label okay; | 286 Label okay; |
287 cmpl(Address(rsp, wordSize), (int)t); | 287 cmpptr(Address(rsp, wordSize), (int32_t)t); |
288 jcc(Assembler::equal, okay); | 288 jcc(Assembler::equal, okay); |
289 // Also compare if the stack value is zero, then the tag might | 289 // Also compare if the stack value is zero, then the tag might |
290 // not have been set coming from deopt. | 290 // not have been set coming from deopt. |
291 cmpl(Address(rsp, 0), 0); | 291 cmpptr(Address(rsp, 0), 0); |
292 jcc(Assembler::equal, okay); | 292 jcc(Assembler::equal, okay); |
293 stop("Java Expression stack tag value is bad"); | 293 stop("Java Expression stack tag value is bad"); |
294 bind(okay); | 294 bind(okay); |
295 } | 295 } |
296 } | 296 } |
297 #endif // ASSERT | 297 #endif // ASSERT |
298 | 298 |
299 void InterpreterMacroAssembler::pop_ptr(Register r) { | 299 void InterpreterMacroAssembler::pop_ptr(Register r) { |
300 debug_only(verify_stack_tag(frame::TagReference)); | 300 debug_only(verify_stack_tag(frame::TagReference)); |
301 popl(r); | 301 pop(r); |
302 if (TaggedStackInterpreter) addl(rsp, 1 * wordSize); | 302 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); |
303 } | 303 } |
304 | 304 |
305 void InterpreterMacroAssembler::pop_ptr(Register r, Register tag) { | 305 void InterpreterMacroAssembler::pop_ptr(Register r, Register tag) { |
306 popl(r); | 306 pop(r); |
307 // Tag may not be reference for jsr, can be returnAddress | 307 // Tag may not be reference for jsr, can be returnAddress |
308 if (TaggedStackInterpreter) popl(tag); | 308 if (TaggedStackInterpreter) pop(tag); |
309 } | 309 } |
310 | 310 |
311 void InterpreterMacroAssembler::pop_i(Register r) { | 311 void InterpreterMacroAssembler::pop_i(Register r) { |
312 debug_only(verify_stack_tag(frame::TagValue)); | 312 debug_only(verify_stack_tag(frame::TagValue)); |
313 popl(r); | 313 pop(r); |
314 if (TaggedStackInterpreter) addl(rsp, 1 * wordSize); | 314 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); |
315 } | 315 } |
316 | 316 |
317 void InterpreterMacroAssembler::pop_l(Register lo, Register hi) { | 317 void InterpreterMacroAssembler::pop_l(Register lo, Register hi) { |
318 debug_only(verify_stack_tag(frame::TagValue)); | 318 debug_only(verify_stack_tag(frame::TagValue)); |
319 popl(lo); | 319 pop(lo); |
320 if (TaggedStackInterpreter) addl(rsp, 1 * wordSize); | 320 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); |
321 debug_only(verify_stack_tag(frame::TagValue)); | 321 debug_only(verify_stack_tag(frame::TagValue)); |
322 popl(hi); | 322 pop(hi); |
323 if (TaggedStackInterpreter) addl(rsp, 1 * wordSize); | 323 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); |
324 } | 324 } |
325 | 325 |
326 void InterpreterMacroAssembler::pop_f() { | 326 void InterpreterMacroAssembler::pop_f() { |
327 debug_only(verify_stack_tag(frame::TagValue)); | 327 debug_only(verify_stack_tag(frame::TagValue)); |
328 fld_s(Address(rsp, 0)); | 328 fld_s(Address(rsp, 0)); |
329 addl(rsp, 1 * wordSize); | 329 addptr(rsp, 1 * wordSize); |
330 if (TaggedStackInterpreter) addl(rsp, 1 * wordSize); | 330 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); |
331 } | 331 } |
332 | 332 |
333 void InterpreterMacroAssembler::pop_d() { | 333 void InterpreterMacroAssembler::pop_d() { |
334 // Write double to stack contiguously and load into ST0 | 334 // Write double to stack contiguously and load into ST0 |
335 pop_dtos_to_rsp(); | 335 pop_dtos_to_rsp(); |
336 fld_d(Address(rsp, 0)); | 336 fld_d(Address(rsp, 0)); |
337 addl(rsp, 2 * wordSize); | 337 addptr(rsp, 2 * wordSize); |
338 } | 338 } |
339 | 339 |
340 | 340 |
341 // Pop the top of the java expression stack to execution stack (which | 341 // Pop the top of the java expression stack to execution stack (which |
342 // happens to be the same place). | 342 // happens to be the same place). |
343 void InterpreterMacroAssembler::pop_dtos_to_rsp() { | 343 void InterpreterMacroAssembler::pop_dtos_to_rsp() { |
344 if (TaggedStackInterpreter) { | 344 if (TaggedStackInterpreter) { |
345 // Pop double value into scratch registers | 345 // Pop double value into scratch registers |
346 debug_only(verify_stack_tag(frame::TagValue)); | 346 debug_only(verify_stack_tag(frame::TagValue)); |
347 popl(rax); | 347 pop(rax); |
348 addl(rsp, 1* wordSize); | 348 addptr(rsp, 1* wordSize); |
349 debug_only(verify_stack_tag(frame::TagValue)); | 349 debug_only(verify_stack_tag(frame::TagValue)); |
350 popl(rdx); | 350 pop(rdx); |
351 addl(rsp, 1* wordSize); | 351 addptr(rsp, 1* wordSize); |
352 pushl(rdx); | 352 push(rdx); |
353 pushl(rax); | 353 push(rax); |
354 } | 354 } |
355 } | 355 } |
356 | 356 |
357 void InterpreterMacroAssembler::pop_ftos_to_rsp() { | 357 void InterpreterMacroAssembler::pop_ftos_to_rsp() { |
358 if (TaggedStackInterpreter) { | 358 if (TaggedStackInterpreter) { |
359 debug_only(verify_stack_tag(frame::TagValue)); | 359 debug_only(verify_stack_tag(frame::TagValue)); |
360 popl(rax); | 360 pop(rax); |
361 addl(rsp, 1 * wordSize); | 361 addptr(rsp, 1 * wordSize); |
362 pushl(rax); // ftos is at rsp | 362 push(rax); // ftos is at rsp |
363 } | 363 } |
364 } | 364 } |
365 | 365 |
366 void InterpreterMacroAssembler::pop(TosState state) { | 366 void InterpreterMacroAssembler::pop(TosState state) { |
367 switch (state) { | 367 switch (state) { |
378 } | 378 } |
379 verify_oop(rax, state); | 379 verify_oop(rax, state); |
380 } | 380 } |
381 | 381 |
382 void InterpreterMacroAssembler::push_ptr(Register r) { | 382 void InterpreterMacroAssembler::push_ptr(Register r) { |
383 if (TaggedStackInterpreter) pushl(frame::TagReference); | 383 if (TaggedStackInterpreter) push(frame::TagReference); |
384 pushl(r); | 384 push(r); |
385 } | 385 } |
386 | 386 |
387 void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { | 387 void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { |
388 if (TaggedStackInterpreter) pushl(tag); // tag first | 388 if (TaggedStackInterpreter) push(tag); // tag first |
389 pushl(r); | 389 push(r); |
390 } | 390 } |
391 | 391 |
392 void InterpreterMacroAssembler::push_i(Register r) { | 392 void InterpreterMacroAssembler::push_i(Register r) { |
393 if (TaggedStackInterpreter) pushl(frame::TagValue); | 393 if (TaggedStackInterpreter) push(frame::TagValue); |
394 pushl(r); | 394 push(r); |
395 } | 395 } |
396 | 396 |
397 void InterpreterMacroAssembler::push_l(Register lo, Register hi) { | 397 void InterpreterMacroAssembler::push_l(Register lo, Register hi) { |
398 if (TaggedStackInterpreter) pushl(frame::TagValue); | 398 if (TaggedStackInterpreter) push(frame::TagValue); |
399 pushl(hi); | 399 push(hi); |
400 if (TaggedStackInterpreter) pushl(frame::TagValue); | 400 if (TaggedStackInterpreter) push(frame::TagValue); |
401 pushl(lo); | 401 push(lo); |
402 } | 402 } |
403 | 403 |
404 void InterpreterMacroAssembler::push_f() { | 404 void InterpreterMacroAssembler::push_f() { |
405 if (TaggedStackInterpreter) pushl(frame::TagValue); | 405 if (TaggedStackInterpreter) push(frame::TagValue); |
406 // Do not schedule for no AGI! Never write beyond rsp! | 406 // Do not schedule for no AGI! Never write beyond rsp! |
407 subl(rsp, 1 * wordSize); | 407 subptr(rsp, 1 * wordSize); |
408 fstp_s(Address(rsp, 0)); | 408 fstp_s(Address(rsp, 0)); |
409 } | 409 } |
410 | 410 |
411 void InterpreterMacroAssembler::push_d(Register r) { | 411 void InterpreterMacroAssembler::push_d(Register r) { |
412 if (TaggedStackInterpreter) { | 412 if (TaggedStackInterpreter) { |
413 // Double values are stored as: | 413 // Double values are stored as: |
414 // tag | 414 // tag |
415 // high | 415 // high |
416 // tag | 416 // tag |
417 // low | 417 // low |
418 pushl(frame::TagValue); | 418 push(frame::TagValue); |
419 subl(rsp, 3 * wordSize); | 419 subptr(rsp, 3 * wordSize); |
420 fstp_d(Address(rsp, 0)); | 420 fstp_d(Address(rsp, 0)); |
421 // move high word up to slot n-1 | 421 // move high word up to slot n-1 |
422 movl(r, Address(rsp, 1*wordSize)); | 422 movl(r, Address(rsp, 1*wordSize)); |
423 movl(Address(rsp, 2*wordSize), r); | 423 movl(Address(rsp, 2*wordSize), r); |
424 // move tag | 424 // move tag |
425 movl(Address(rsp, 1*wordSize), frame::TagValue); | 425 movl(Address(rsp, 1*wordSize), frame::TagValue); |
426 } else { | 426 } else { |
427 // Do not schedule for no AGI! Never write beyond rsp! | 427 // Do not schedule for no AGI! Never write beyond rsp! |
428 subl(rsp, 2 * wordSize); | 428 subptr(rsp, 2 * wordSize); |
429 fstp_d(Address(rsp, 0)); | 429 fstp_d(Address(rsp, 0)); |
430 } | 430 } |
431 } | 431 } |
432 | 432 |
433 | 433 |
445 case vtos: /* nothing to do */ break; | 445 case vtos: /* nothing to do */ break; |
446 default : ShouldNotReachHere(); | 446 default : ShouldNotReachHere(); |
447 } | 447 } |
448 } | 448 } |
449 | 449 |
450 #ifndef CC_INTERP | |
451 | 450 |
452 // Tagged stack helpers for swap and dup | 451 // Tagged stack helpers for swap and dup |
453 void InterpreterMacroAssembler::load_ptr_and_tag(int n, Register val, | 452 void InterpreterMacroAssembler::load_ptr_and_tag(int n, Register val, |
454 Register tag) { | 453 Register tag) { |
455 movl(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); | 454 movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); |
456 if (TaggedStackInterpreter) { | 455 if (TaggedStackInterpreter) { |
457 movl(tag, Address(rsp, Interpreter::expr_tag_offset_in_bytes(n))); | 456 movptr(tag, Address(rsp, Interpreter::expr_tag_offset_in_bytes(n))); |
458 } | 457 } |
459 } | 458 } |
460 | 459 |
461 void InterpreterMacroAssembler::store_ptr_and_tag(int n, Register val, | 460 void InterpreterMacroAssembler::store_ptr_and_tag(int n, Register val, |
462 Register tag) { | 461 Register tag) { |
463 movl(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); | 462 movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); |
464 if (TaggedStackInterpreter) { | 463 if (TaggedStackInterpreter) { |
465 movl(Address(rsp, Interpreter::expr_tag_offset_in_bytes(n)), tag); | 464 movptr(Address(rsp, Interpreter::expr_tag_offset_in_bytes(n)), tag); |
466 } | 465 } |
467 } | 466 } |
468 | 467 |
469 | 468 |
470 // Tagged local support | 469 // Tagged local support |
471 void InterpreterMacroAssembler::tag_local(frame::Tag tag, int n) { | 470 void InterpreterMacroAssembler::tag_local(frame::Tag tag, int n) { |
472 if (TaggedStackInterpreter) { | 471 if (TaggedStackInterpreter) { |
473 if (tag == frame::TagCategory2) { | 472 if (tag == frame::TagCategory2) { |
474 movl(Address(rdi, Interpreter::local_tag_offset_in_bytes(n+1)), (int)frame::TagValue); | 473 movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n+1)), (int32_t)frame::TagValue); |
475 movl(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int)frame::TagValue); | 474 movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)frame::TagValue); |
476 } else { | 475 } else { |
477 movl(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int)tag); | 476 movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)tag); |
478 } | 477 } |
479 } | 478 } |
480 } | 479 } |
481 | 480 |
482 void InterpreterMacroAssembler::tag_local(frame::Tag tag, Register idx) { | 481 void InterpreterMacroAssembler::tag_local(frame::Tag tag, Register idx) { |
483 if (TaggedStackInterpreter) { | 482 if (TaggedStackInterpreter) { |
484 if (tag == frame::TagCategory2) { | 483 if (tag == frame::TagCategory2) { |
485 movl(Address(rdi, idx, Interpreter::stackElementScale(), | 484 movptr(Address(rdi, idx, Interpreter::stackElementScale(), |
486 Interpreter::local_tag_offset_in_bytes(1)), (int)frame::TagValue); | 485 Interpreter::local_tag_offset_in_bytes(1)), (int32_t)frame::TagValue); |
487 movl(Address(rdi, idx, Interpreter::stackElementScale(), | 486 movptr(Address(rdi, idx, Interpreter::stackElementScale(), |
488 Interpreter::local_tag_offset_in_bytes(0)), (int)frame::TagValue); | 487 Interpreter::local_tag_offset_in_bytes(0)), (int32_t)frame::TagValue); |
489 } else { | 488 } else { |
490 movl(Address(rdi, idx, Interpreter::stackElementScale(), | 489 movptr(Address(rdi, idx, Interpreter::stackElementScale(), |
491 Interpreter::local_tag_offset_in_bytes(0)), (int)tag); | 490 Interpreter::local_tag_offset_in_bytes(0)), (int32_t)tag); |
492 } | 491 } |
493 } | 492 } |
494 } | 493 } |
495 | 494 |
496 void InterpreterMacroAssembler::tag_local(Register tag, Register idx) { | 495 void InterpreterMacroAssembler::tag_local(Register tag, Register idx) { |
497 if (TaggedStackInterpreter) { | 496 if (TaggedStackInterpreter) { |
498 // can only be TagValue or TagReference | 497 // can only be TagValue or TagReference |
499 movl(Address(rdi, idx, Interpreter::stackElementScale(), | 498 movptr(Address(rdi, idx, Interpreter::stackElementScale(), |
500 Interpreter::local_tag_offset_in_bytes(0)), tag); | 499 Interpreter::local_tag_offset_in_bytes(0)), tag); |
501 } | 500 } |
502 } | 501 } |
503 | 502 |
504 | 503 |
505 void InterpreterMacroAssembler::tag_local(Register tag, int n) { | 504 void InterpreterMacroAssembler::tag_local(Register tag, int n) { |
506 if (TaggedStackInterpreter) { | 505 if (TaggedStackInterpreter) { |
507 // can only be TagValue or TagReference | 506 // can only be TagValue or TagReference |
508 movl(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), tag); | 507 movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), tag); |
509 } | 508 } |
510 } | 509 } |
511 | 510 |
512 #ifdef ASSERT | 511 #ifdef ASSERT |
513 void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, int n) { | 512 void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, int n) { |
514 if (TaggedStackInterpreter) { | 513 if (TaggedStackInterpreter) { |
515 frame::Tag t = tag; | 514 frame::Tag t = tag; |
516 if (tag == frame::TagCategory2) { | 515 if (tag == frame::TagCategory2) { |
517 Label nbl; | 516 Label nbl; |
518 t = frame::TagValue; // change to what is stored in locals | 517 t = frame::TagValue; // change to what is stored in locals |
519 cmpl(Address(rdi, Interpreter::local_tag_offset_in_bytes(n+1)), (int)t); | 518 cmpptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n+1)), (int32_t)t); |
520 jcc(Assembler::equal, nbl); | 519 jcc(Assembler::equal, nbl); |
521 stop("Local tag is bad for long/double"); | 520 stop("Local tag is bad for long/double"); |
522 bind(nbl); | 521 bind(nbl); |
523 } | 522 } |
524 Label notBad; | 523 Label notBad; |
525 cmpl(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int)t); | 524 cmpptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)t); |
526 jcc(Assembler::equal, notBad); | 525 jcc(Assembler::equal, notBad); |
527 // Also compare if the local value is zero, then the tag might | 526 // Also compare if the local value is zero, then the tag might |
528 // not have been set coming from deopt. | 527 // not have been set coming from deopt. |
529 cmpl(Address(rdi, Interpreter::local_offset_in_bytes(n)), 0); | 528 cmpptr(Address(rdi, Interpreter::local_offset_in_bytes(n)), 0); |
530 jcc(Assembler::equal, notBad); | 529 jcc(Assembler::equal, notBad); |
531 stop("Local tag is bad"); | 530 stop("Local tag is bad"); |
532 bind(notBad); | 531 bind(notBad); |
533 } | 532 } |
534 } | 533 } |
537 if (TaggedStackInterpreter) { | 536 if (TaggedStackInterpreter) { |
538 frame::Tag t = tag; | 537 frame::Tag t = tag; |
539 if (tag == frame::TagCategory2) { | 538 if (tag == frame::TagCategory2) { |
540 Label nbl; | 539 Label nbl; |
541 t = frame::TagValue; // change to what is stored in locals | 540 t = frame::TagValue; // change to what is stored in locals |
542 cmpl(Address(rdi, idx, Interpreter::stackElementScale(), | 541 cmpptr(Address(rdi, idx, Interpreter::stackElementScale(), |
543 Interpreter::local_tag_offset_in_bytes(1)), (int)t); | 542 Interpreter::local_tag_offset_in_bytes(1)), (int32_t)t); |
544 jcc(Assembler::equal, nbl); | 543 jcc(Assembler::equal, nbl); |
545 stop("Local tag is bad for long/double"); | 544 stop("Local tag is bad for long/double"); |
546 bind(nbl); | 545 bind(nbl); |
547 } | 546 } |
548 Label notBad; | 547 Label notBad; |
549 cmpl(Address(rdi, idx, Interpreter::stackElementScale(), | 548 cmpl(Address(rdi, idx, Interpreter::stackElementScale(), |
550 Interpreter::local_tag_offset_in_bytes(0)), (int)t); | 549 Interpreter::local_tag_offset_in_bytes(0)), (int32_t)t); |
551 jcc(Assembler::equal, notBad); | 550 jcc(Assembler::equal, notBad); |
552 // Also compare if the local value is zero, then the tag might | 551 // Also compare if the local value is zero, then the tag might |
553 // not have been set coming from deopt. | 552 // not have been set coming from deopt. |
554 cmpl(Address(rdi, idx, Interpreter::stackElementScale(), | 553 cmpptr(Address(rdi, idx, Interpreter::stackElementScale(), |
555 Interpreter::local_offset_in_bytes(0)), 0); | 554 Interpreter::local_offset_in_bytes(0)), 0); |
556 jcc(Assembler::equal, notBad); | 555 jcc(Assembler::equal, notBad); |
557 stop("Local tag is bad"); | 556 stop("Local tag is bad"); |
558 bind(notBad); | 557 bind(notBad); |
559 | 558 |
565 MacroAssembler::call_VM_leaf_base(entry_point, 0); | 564 MacroAssembler::call_VM_leaf_base(entry_point, 0); |
566 } | 565 } |
567 | 566 |
568 | 567 |
569 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1) { | 568 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1) { |
570 pushl(arg_1); | 569 push(arg_1); |
571 MacroAssembler::call_VM_leaf_base(entry_point, 1); | 570 MacroAssembler::call_VM_leaf_base(entry_point, 1); |
572 } | 571 } |
573 | 572 |
574 | 573 |
575 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2) { | 574 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2) { |
576 pushl(arg_2); | 575 push(arg_2); |
577 pushl(arg_1); | 576 push(arg_1); |
578 MacroAssembler::call_VM_leaf_base(entry_point, 2); | 577 MacroAssembler::call_VM_leaf_base(entry_point, 2); |
579 } | 578 } |
580 | 579 |
581 | 580 |
582 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3) { | 581 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3) { |
583 pushl(arg_3); | 582 push(arg_3); |
584 pushl(arg_2); | 583 push(arg_2); |
585 pushl(arg_1); | 584 push(arg_1); |
586 MacroAssembler::call_VM_leaf_base(entry_point, 3); | 585 MacroAssembler::call_VM_leaf_base(entry_point, 3); |
587 } | 586 } |
588 | 587 |
589 | 588 |
590 // Jump to from_interpreted entry of a call unless single stepping is possible | 589 // Jump to from_interpreted entry of a call unless single stepping is possible |
591 // in this thread in which case we must call the i2i entry | 590 // in this thread in which case we must call the i2i entry |
592 void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { | 591 void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { |
593 // set sender sp | 592 // set sender sp |
594 leal(rsi, Address(rsp, wordSize)); | 593 lea(rsi, Address(rsp, wordSize)); |
595 // record last_sp | 594 // record last_sp |
596 movl(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi); | 595 movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi); |
597 | 596 |
598 if (JvmtiExport::can_post_interpreter_events()) { | 597 if (JvmtiExport::can_post_interpreter_events()) { |
599 Label run_compiled_code; | 598 Label run_compiled_code; |
600 // JVMTI events, such as single-stepping, are implemented partly by avoiding running | 599 // JVMTI events, such as single-stepping, are implemented partly by avoiding running |
601 // compiled code in threads for which the event is enabled. Check here for | 600 // compiled code in threads for which the event is enabled. Check here for |
627 void InterpreterMacroAssembler::dispatch_base(TosState state, address* table, | 626 void InterpreterMacroAssembler::dispatch_base(TosState state, address* table, |
628 bool verifyoop) { | 627 bool verifyoop) { |
629 verify_FPU(1, state); | 628 verify_FPU(1, state); |
630 if (VerifyActivationFrameSize) { | 629 if (VerifyActivationFrameSize) { |
631 Label L; | 630 Label L; |
632 movl(rcx, rbp); | 631 mov(rcx, rbp); |
633 subl(rcx, rsp); | 632 subptr(rcx, rsp); |
634 int min_frame_size = (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * wordSize; | 633 int min_frame_size = (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * wordSize; |
635 cmpl(rcx, min_frame_size); | 634 cmpptr(rcx, min_frame_size); |
636 jcc(Assembler::greaterEqual, L); | 635 jcc(Assembler::greaterEqual, L); |
637 stop("broken stack frame"); | 636 stop("broken stack frame"); |
638 bind(L); | 637 bind(L); |
639 } | 638 } |
640 if (verifyoop) verify_oop(rax, state); | 639 if (verifyoop) verify_oop(rax, state); |
641 Address index(noreg, rbx, Address::times_4); | 640 Address index(noreg, rbx, Address::times_ptr); |
642 ExternalAddress tbl((address)table); | 641 ExternalAddress tbl((address)table); |
643 ArrayAddress dispatch(tbl, index); | 642 ArrayAddress dispatch(tbl, index); |
644 jump(dispatch); | 643 jump(dispatch); |
645 } | 644 } |
646 | 645 |
698 get_thread(rcx); | 697 get_thread(rcx); |
699 const Address do_not_unlock_if_synchronized(rcx, | 698 const Address do_not_unlock_if_synchronized(rcx, |
700 in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); | 699 in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); |
701 | 700 |
702 movbool(rbx, do_not_unlock_if_synchronized); | 701 movbool(rbx, do_not_unlock_if_synchronized); |
703 movl(rdi,rbx); | 702 mov(rdi,rbx); |
704 movbool(do_not_unlock_if_synchronized, false); // reset the flag | 703 movbool(do_not_unlock_if_synchronized, false); // reset the flag |
705 | 704 |
706 movl(rbx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); // get method access flags | 705 movptr(rbx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); // get method access flags |
707 movl(rcx, Address(rbx, methodOopDesc::access_flags_offset())); | 706 movl(rcx, Address(rbx, methodOopDesc::access_flags_offset())); |
708 | 707 |
709 testl(rcx, JVM_ACC_SYNCHRONIZED); | 708 testl(rcx, JVM_ACC_SYNCHRONIZED); |
710 jcc(Assembler::zero, unlocked); | 709 jcc(Assembler::zero, unlocked); |
711 | 710 |
712 // Don't unlock anything if the _do_not_unlock_if_synchronized flag | 711 // Don't unlock anything if the _do_not_unlock_if_synchronized flag |
713 // is set. | 712 // is set. |
714 movl(rcx,rdi); | 713 mov(rcx,rdi); |
715 testbool(rcx); | 714 testbool(rcx); |
716 jcc(Assembler::notZero, no_unlock); | 715 jcc(Assembler::notZero, no_unlock); |
717 | 716 |
718 // unlock monitor | 717 // unlock monitor |
719 push(state); // save result | 718 push(state); // save result |
720 | 719 |
721 // BasicObjectLock will be first in list, since this is a synchronized method. However, need | 720 // BasicObjectLock will be first in list, since this is a synchronized method. However, need |
722 // to check that the object has not been unlocked by an explicit monitorexit bytecode. | 721 // to check that the object has not been unlocked by an explicit monitorexit bytecode. |
723 const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); | 722 const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); |
724 leal (rdx, monitor); // address of first monitor | 723 lea (rdx, monitor); // address of first monitor |
725 | 724 |
726 movl (rax, Address(rdx, BasicObjectLock::obj_offset_in_bytes())); | 725 movptr (rax, Address(rdx, BasicObjectLock::obj_offset_in_bytes())); |
727 testl (rax, rax); | 726 testptr(rax, rax); |
728 jcc (Assembler::notZero, unlock); | 727 jcc (Assembler::notZero, unlock); |
729 | 728 |
730 pop(state); | 729 pop(state); |
731 if (throw_monitor_exception) { | 730 if (throw_monitor_exception) { |
732 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow | 731 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow |
733 | 732 |
760 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; | 759 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; |
761 const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); | 760 const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); |
762 const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset * wordSize); | 761 const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset * wordSize); |
763 | 762 |
764 bind(restart); | 763 bind(restart); |
765 movl(rcx, monitor_block_top); // points to current entry, starting with top-most entry | 764 movptr(rcx, monitor_block_top); // points to current entry, starting with top-most entry |
766 leal(rbx, monitor_block_bot); // points to word before bottom of monitor block | 765 lea(rbx, monitor_block_bot); // points to word before bottom of monitor block |
767 jmp(entry); | 766 jmp(entry); |
768 | 767 |
769 // Entry already locked, need to throw exception | 768 // Entry already locked, need to throw exception |
770 bind(exception); | 769 bind(exception); |
771 | 770 |
778 } else { | 777 } else { |
779 // Stack unrolling. Unlock object and install illegal_monitor_exception | 778 // Stack unrolling. Unlock object and install illegal_monitor_exception |
780 // Unlock does not block, so don't have to worry about the frame | 779 // Unlock does not block, so don't have to worry about the frame |
781 | 780 |
782 push(state); | 781 push(state); |
783 movl(rdx, rcx); | 782 mov(rdx, rcx); |
784 unlock_object(rdx); | 783 unlock_object(rdx); |
785 pop(state); | 784 pop(state); |
786 | 785 |
787 if (install_monitor_exception) { | 786 if (install_monitor_exception) { |
788 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow | 787 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow |
791 | 790 |
792 jmp(restart); | 791 jmp(restart); |
793 } | 792 } |
794 | 793 |
795 bind(loop); | 794 bind(loop); |
796 cmpl(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), NULL_WORD); // check if current entry is used | 795 cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used |
797 jcc(Assembler::notEqual, exception); | 796 jcc(Assembler::notEqual, exception); |
798 | 797 |
799 addl(rcx, entry_size); // otherwise advance to next entry | 798 addptr(rcx, entry_size); // otherwise advance to next entry |
800 bind(entry); | 799 bind(entry); |
801 cmpl(rcx, rbx); // check if bottom reached | 800 cmpptr(rcx, rbx); // check if bottom reached |
802 jcc(Assembler::notEqual, loop); // if not at bottom then check this entry | 801 jcc(Assembler::notEqual, loop); // if not at bottom then check this entry |
803 } | 802 } |
804 | 803 |
805 bind(no_unlock); | 804 bind(no_unlock); |
806 | 805 |
810 } else { | 809 } else { |
811 notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA | 810 notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA |
812 } | 811 } |
813 | 812 |
814 // remove activation | 813 // remove activation |
815 movl(rbx, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp | 814 movptr(rbx, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp |
816 leave(); // remove frame anchor | 815 leave(); // remove frame anchor |
817 popl(ret_addr); // get return address | 816 pop(ret_addr); // get return address |
818 movl(rsp, rbx); // set sp to sender sp | 817 mov(rsp, rbx); // set sp to sender sp |
819 if (UseSSE) { | 818 if (UseSSE) { |
820 // float and double are returned in xmm register in SSE-mode | 819 // float and double are returned in xmm register in SSE-mode |
821 if (state == ftos && UseSSE >= 1) { | 820 if (state == ftos && UseSSE >= 1) { |
822 subl(rsp, wordSize); | 821 subptr(rsp, wordSize); |
823 fstp_s(Address(rsp, 0)); | 822 fstp_s(Address(rsp, 0)); |
824 movflt(xmm0, Address(rsp, 0)); | 823 movflt(xmm0, Address(rsp, 0)); |
825 addl(rsp, wordSize); | 824 addptr(rsp, wordSize); |
826 } else if (state == dtos && UseSSE >= 2) { | 825 } else if (state == dtos && UseSSE >= 2) { |
827 subl(rsp, 2*wordSize); | 826 subptr(rsp, 2*wordSize); |
828 fstp_d(Address(rsp, 0)); | 827 fstp_d(Address(rsp, 0)); |
829 movdbl(xmm0, Address(rsp, 0)); | 828 movdbl(xmm0, Address(rsp, 0)); |
830 addl(rsp, 2*wordSize); | 829 addptr(rsp, 2*wordSize); |
831 } | 830 } |
832 } | 831 } |
833 } | 832 } |
834 | 833 |
835 #endif /* !CC_INTERP */ | 834 #endif /* !CC_INTERP */ |
856 const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes(); | 855 const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes(); |
857 | 856 |
858 Label slow_case; | 857 Label slow_case; |
859 | 858 |
860 // Load object pointer into obj_reg %rcx | 859 // Load object pointer into obj_reg %rcx |
861 movl(obj_reg, Address(lock_reg, obj_offset)); | 860 movptr(obj_reg, Address(lock_reg, obj_offset)); |
862 | 861 |
863 if (UseBiasedLocking) { | 862 if (UseBiasedLocking) { |
864 // Note: we use noreg for the temporary register since it's hard | 863 // Note: we use noreg for the temporary register since it's hard |
865 // to come up with a free register on all incoming code paths | 864 // to come up with a free register on all incoming code paths |
866 biased_locking_enter(lock_reg, obj_reg, swap_reg, noreg, false, done, &slow_case); | 865 biased_locking_enter(lock_reg, obj_reg, swap_reg, noreg, false, done, &slow_case); |
867 } | 866 } |
868 | 867 |
869 // Load immediate 1 into swap_reg %rax, | 868 // Load immediate 1 into swap_reg %rax, |
870 movl(swap_reg, 1); | 869 movptr(swap_reg, (int32_t)1); |
871 | 870 |
872 // Load (object->mark() | 1) into swap_reg %rax, | 871 // Load (object->mark() | 1) into swap_reg %rax, |
873 orl(swap_reg, Address(obj_reg, 0)); | 872 orptr(swap_reg, Address(obj_reg, 0)); |
874 | 873 |
875 // Save (object->mark() | 1) into BasicLock's displaced header | 874 // Save (object->mark() | 1) into BasicLock's displaced header |
876 movl(Address(lock_reg, mark_offset), swap_reg); | 875 movptr(Address(lock_reg, mark_offset), swap_reg); |
877 | 876 |
878 assert(lock_offset == 0, "displached header must be first word in BasicObjectLock"); | 877 assert(lock_offset == 0, "displached header must be first word in BasicObjectLock"); |
879 if (os::is_MP()) { | 878 if (os::is_MP()) { |
880 lock(); | 879 lock(); |
881 } | 880 } |
882 cmpxchg(lock_reg, Address(obj_reg, 0)); | 881 cmpxchgptr(lock_reg, Address(obj_reg, 0)); |
883 if (PrintBiasedLockingStatistics) { | 882 if (PrintBiasedLockingStatistics) { |
884 cond_inc32(Assembler::zero, | 883 cond_inc32(Assembler::zero, |
885 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); | 884 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); |
886 } | 885 } |
887 jcc(Assembler::zero, done); | 886 jcc(Assembler::zero, done); |
893 // These 3 tests can be done by evaluating the following | 892 // These 3 tests can be done by evaluating the following |
894 // expression: ((mark - rsp) & (3 - os::vm_page_size())), | 893 // expression: ((mark - rsp) & (3 - os::vm_page_size())), |
895 // assuming both stack pointer and pagesize have their | 894 // assuming both stack pointer and pagesize have their |
896 // least significant 2 bits clear. | 895 // least significant 2 bits clear. |
897 // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg | 896 // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg |
898 subl(swap_reg, rsp); | 897 subptr(swap_reg, rsp); |
899 andl(swap_reg, 3 - os::vm_page_size()); | 898 andptr(swap_reg, 3 - os::vm_page_size()); |
900 | 899 |
901 // Save the test result, for recursive case, the result is zero | 900 // Save the test result, for recursive case, the result is zero |
902 movl(Address(lock_reg, mark_offset), swap_reg); | 901 movptr(Address(lock_reg, mark_offset), swap_reg); |
903 | 902 |
904 if (PrintBiasedLockingStatistics) { | 903 if (PrintBiasedLockingStatistics) { |
905 cond_inc32(Assembler::zero, | 904 cond_inc32(Assembler::zero, |
906 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); | 905 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); |
907 } | 906 } |
937 | 936 |
938 save_bcp(); // Save in case of exception | 937 save_bcp(); // Save in case of exception |
939 | 938 |
940 // Convert from BasicObjectLock structure to object and BasicLock structure | 939 // Convert from BasicObjectLock structure to object and BasicLock structure |
941 // Store the BasicLock address into %rax, | 940 // Store the BasicLock address into %rax, |
942 leal(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); | 941 lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); |
943 | 942 |
944 // Load oop into obj_reg(%rcx) | 943 // Load oop into obj_reg(%rcx) |
945 movl(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes ())); | 944 movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes ())); |
946 | 945 |
947 // Free entry | 946 // Free entry |
948 movl(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), NULL_WORD); | 947 movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); |
949 | 948 |
950 if (UseBiasedLocking) { | 949 if (UseBiasedLocking) { |
951 biased_locking_exit(obj_reg, header_reg, done); | 950 biased_locking_exit(obj_reg, header_reg, done); |
952 } | 951 } |
953 | 952 |
954 // Load the old header from BasicLock structure | 953 // Load the old header from BasicLock structure |
955 movl(header_reg, Address(swap_reg, BasicLock::displaced_header_offset_in_bytes())); | 954 movptr(header_reg, Address(swap_reg, BasicLock::displaced_header_offset_in_bytes())); |
956 | 955 |
957 // Test for recursion | 956 // Test for recursion |
958 testl(header_reg, header_reg); | 957 testptr(header_reg, header_reg); |
959 | 958 |
960 // zero for recursive case | 959 // zero for recursive case |
961 jcc(Assembler::zero, done); | 960 jcc(Assembler::zero, done); |
962 | 961 |
963 // Atomic swap back the old header | 962 // Atomic swap back the old header |
964 if (os::is_MP()) lock(); | 963 if (os::is_MP()) lock(); |
965 cmpxchg(header_reg, Address(obj_reg, 0)); | 964 cmpxchgptr(header_reg, Address(obj_reg, 0)); |
966 | 965 |
967 // zero for recursive case | 966 // zero for recursive case |
968 jcc(Assembler::zero, done); | 967 jcc(Assembler::zero, done); |
969 | 968 |
970 // Call the runtime routine for slow case. | 969 // Call the runtime routine for slow case. |
971 movl(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), obj_reg); // restore obj | 970 movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), obj_reg); // restore obj |
972 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); | 971 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); |
973 | 972 |
974 bind(done); | 973 bind(done); |
975 | 974 |
976 restore_bcp(); | 975 restore_bcp(); |
981 #ifndef CC_INTERP | 980 #ifndef CC_INTERP |
982 | 981 |
983 // Test ImethodDataPtr. If it is null, continue at the specified label | 982 // Test ImethodDataPtr. If it is null, continue at the specified label |
984 void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, Label& zero_continue) { | 983 void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, Label& zero_continue) { |
985 assert(ProfileInterpreter, "must be profiling interpreter"); | 984 assert(ProfileInterpreter, "must be profiling interpreter"); |
986 movl(mdp, Address(rbp, frame::interpreter_frame_mdx_offset * wordSize)); | 985 movptr(mdp, Address(rbp, frame::interpreter_frame_mdx_offset * wordSize)); |
987 testl(mdp, mdp); | 986 testptr(mdp, mdp); |
988 jcc(Assembler::zero, zero_continue); | 987 jcc(Assembler::zero, zero_continue); |
989 } | 988 } |
990 | 989 |
991 | 990 |
992 // Set the method data pointer for the current bcp. | 991 // Set the method data pointer for the current bcp. |
993 void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { | 992 void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { |
994 assert(ProfileInterpreter, "must be profiling interpreter"); | 993 assert(ProfileInterpreter, "must be profiling interpreter"); |
995 Label zero_continue; | 994 Label zero_continue; |
996 pushl(rax); | 995 push(rax); |
997 pushl(rbx); | 996 push(rbx); |
998 | 997 |
999 get_method(rbx); | 998 get_method(rbx); |
1000 // Test MDO to avoid the call if it is NULL. | 999 // Test MDO to avoid the call if it is NULL. |
1001 movl(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); | 1000 movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
1002 testl(rax, rax); | 1001 testptr(rax, rax); |
1003 jcc(Assembler::zero, zero_continue); | 1002 jcc(Assembler::zero, zero_continue); |
1004 | 1003 |
1005 // rbx,: method | 1004 // rbx,: method |
1006 // rsi: bcp | 1005 // rsi: bcp |
1007 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi); | 1006 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi); |
1008 // rax,: mdi | 1007 // rax,: mdi |
1009 | 1008 |
1010 movl(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); | 1009 movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
1011 testl(rbx, rbx); | 1010 testptr(rbx, rbx); |
1012 jcc(Assembler::zero, zero_continue); | 1011 jcc(Assembler::zero, zero_continue); |
1013 addl(rbx, in_bytes(methodDataOopDesc::data_offset())); | 1012 addptr(rbx, in_bytes(methodDataOopDesc::data_offset())); |
1014 addl(rbx, rax); | 1013 addptr(rbx, rax); |
1015 movl(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx); | 1014 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx); |
1016 | 1015 |
1017 bind(zero_continue); | 1016 bind(zero_continue); |
1018 popl(rbx); | 1017 pop(rbx); |
1019 popl(rax); | 1018 pop(rax); |
1020 } | 1019 } |
1021 | 1020 |
1022 void InterpreterMacroAssembler::verify_method_data_pointer() { | 1021 void InterpreterMacroAssembler::verify_method_data_pointer() { |
1023 assert(ProfileInterpreter, "must be profiling interpreter"); | 1022 assert(ProfileInterpreter, "must be profiling interpreter"); |
1024 #ifdef ASSERT | 1023 #ifdef ASSERT |
1025 Label verify_continue; | 1024 Label verify_continue; |
1026 pushl(rax); | 1025 push(rax); |
1027 pushl(rbx); | 1026 push(rbx); |
1028 pushl(rcx); | 1027 push(rcx); |
1029 pushl(rdx); | 1028 push(rdx); |
1030 test_method_data_pointer(rcx, verify_continue); // If mdp is zero, continue | 1029 test_method_data_pointer(rcx, verify_continue); // If mdp is zero, continue |
1031 get_method(rbx); | 1030 get_method(rbx); |
1032 | 1031 |
1033 // If the mdp is valid, it will point to a DataLayout header which is | 1032 // If the mdp is valid, it will point to a DataLayout header which is |
1034 // consistent with the bcp. The converse is highly probable also. | 1033 // consistent with the bcp. The converse is highly probable also. |
1035 load_unsigned_word(rdx, Address(rcx, in_bytes(DataLayout::bci_offset()))); | 1034 load_unsigned_word(rdx, Address(rcx, in_bytes(DataLayout::bci_offset()))); |
1036 addl(rdx, Address(rbx, methodOopDesc::const_offset())); | 1035 addptr(rdx, Address(rbx, methodOopDesc::const_offset())); |
1037 leal(rdx, Address(rdx, constMethodOopDesc::codes_offset())); | 1036 lea(rdx, Address(rdx, constMethodOopDesc::codes_offset())); |
1038 cmpl(rdx, rsi); | 1037 cmpptr(rdx, rsi); |
1039 jcc(Assembler::equal, verify_continue); | 1038 jcc(Assembler::equal, verify_continue); |
1040 // rbx,: method | 1039 // rbx,: method |
1041 // rsi: bcp | 1040 // rsi: bcp |
1042 // rcx: mdp | 1041 // rcx: mdp |
1043 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), rbx, rsi, rcx); | 1042 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), rbx, rsi, rcx); |
1044 bind(verify_continue); | 1043 bind(verify_continue); |
1045 popl(rdx); | 1044 pop(rdx); |
1046 popl(rcx); | 1045 pop(rcx); |
1047 popl(rbx); | 1046 pop(rbx); |
1048 popl(rax); | 1047 pop(rax); |
1049 #endif // ASSERT | 1048 #endif // ASSERT |
1050 } | 1049 } |
1051 | 1050 |
1052 | 1051 |
1053 void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, int constant, Register value) { | 1052 void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, int constant, Register value) { |
1053 // %%% this seems to be used to store counter data which is surely 32bits | |
1054 // however 64bit side stores 64 bits which seems wrong | |
1054 assert(ProfileInterpreter, "must be profiling interpreter"); | 1055 assert(ProfileInterpreter, "must be profiling interpreter"); |
1055 Address data(mdp_in, constant); | 1056 Address data(mdp_in, constant); |
1056 movl(data, value); | 1057 movptr(data, value); |
1057 } | 1058 } |
1058 | 1059 |
1059 | 1060 |
1060 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, | 1061 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, |
1061 int constant, | 1062 int constant, |
1071 bool decrement) { | 1072 bool decrement) { |
1072 | 1073 |
1073 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); | 1074 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); |
1074 assert(ProfileInterpreter, "must be profiling interpreter"); | 1075 assert(ProfileInterpreter, "must be profiling interpreter"); |
1075 | 1076 |
1077 // %%% 64bit treats this as 64 bit which seems unlikely | |
1076 if (decrement) { | 1078 if (decrement) { |
1077 // Decrement the register. Set condition codes. | 1079 // Decrement the register. Set condition codes. |
1078 addl(data, -DataLayout::counter_increment); | 1080 addl(data, -DataLayout::counter_increment); |
1079 // If the decrement causes the counter to overflow, stay negative | 1081 // If the decrement causes the counter to overflow, stay negative |
1080 Label L; | 1082 Label L; |
1117 Register value, | 1119 Register value, |
1118 Register test_value_out, | 1120 Register test_value_out, |
1119 Label& not_equal_continue) { | 1121 Label& not_equal_continue) { |
1120 assert(ProfileInterpreter, "must be profiling interpreter"); | 1122 assert(ProfileInterpreter, "must be profiling interpreter"); |
1121 if (test_value_out == noreg) { | 1123 if (test_value_out == noreg) { |
1122 cmpl(value, Address(mdp_in, offset)); | 1124 cmpptr(value, Address(mdp_in, offset)); |
1123 } else { | 1125 } else { |
1124 // Put the test value into a register, so caller can use it: | 1126 // Put the test value into a register, so caller can use it: |
1125 movl(test_value_out, Address(mdp_in, offset)); | 1127 movptr(test_value_out, Address(mdp_in, offset)); |
1126 cmpl(test_value_out, value); | 1128 cmpptr(test_value_out, value); |
1127 } | 1129 } |
1128 jcc(Assembler::notEqual, not_equal_continue); | 1130 jcc(Assembler::notEqual, not_equal_continue); |
1129 } | 1131 } |
1130 | 1132 |
1131 | 1133 |
1132 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, int offset_of_disp) { | 1134 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, int offset_of_disp) { |
1133 assert(ProfileInterpreter, "must be profiling interpreter"); | 1135 assert(ProfileInterpreter, "must be profiling interpreter"); |
1134 Address disp_address(mdp_in, offset_of_disp); | 1136 Address disp_address(mdp_in, offset_of_disp); |
1135 addl(mdp_in,disp_address); | 1137 addptr(mdp_in,disp_address); |
1136 movl(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | 1138 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); |
1137 } | 1139 } |
1138 | 1140 |
1139 | 1141 |
1140 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp) { | 1142 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp) { |
1141 assert(ProfileInterpreter, "must be profiling interpreter"); | 1143 assert(ProfileInterpreter, "must be profiling interpreter"); |
1142 Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); | 1144 Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); |
1143 addl(mdp_in, disp_address); | 1145 addptr(mdp_in, disp_address); |
1144 movl(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | 1146 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); |
1145 } | 1147 } |
1146 | 1148 |
1147 | 1149 |
1148 void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, int constant) { | 1150 void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, int constant) { |
1149 assert(ProfileInterpreter, "must be profiling interpreter"); | 1151 assert(ProfileInterpreter, "must be profiling interpreter"); |
1150 addl(mdp_in, constant); | 1152 addptr(mdp_in, constant); |
1151 movl(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | 1153 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); |
1152 } | 1154 } |
1153 | 1155 |
1154 | 1156 |
1155 void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { | 1157 void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { |
1156 assert(ProfileInterpreter, "must be profiling interpreter"); | 1158 assert(ProfileInterpreter, "must be profiling interpreter"); |
1157 pushl(return_bci); // save/restore across call_VM | 1159 push(return_bci); // save/restore across call_VM |
1158 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); | 1160 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); |
1159 popl(return_bci); | 1161 pop(return_bci); |
1160 } | 1162 } |
1161 | 1163 |
1162 | 1164 |
1163 void InterpreterMacroAssembler::profile_taken_branch(Register mdp, Register bumped_count) { | 1165 void InterpreterMacroAssembler::profile_taken_branch(Register mdp, Register bumped_count) { |
1164 if (ProfileInterpreter) { | 1166 if (ProfileInterpreter) { |
1170 | 1172 |
1171 // We are taking a branch. Increment the taken count. | 1173 // We are taking a branch. Increment the taken count. |
1172 // We inline increment_mdp_data_at to return bumped_count in a register | 1174 // We inline increment_mdp_data_at to return bumped_count in a register |
1173 //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); | 1175 //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); |
1174 Address data(mdp, in_bytes(JumpData::taken_offset())); | 1176 Address data(mdp, in_bytes(JumpData::taken_offset())); |
1177 | |
1178 // %%% 64bit treats these cells as 64 bit but they seem to be 32 bit | |
1175 movl(bumped_count,data); | 1179 movl(bumped_count,data); |
1176 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); | 1180 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); |
1177 addl(bumped_count, DataLayout::counter_increment); | 1181 addl(bumped_count, DataLayout::counter_increment); |
1178 sbbl(bumped_count, 0); | 1182 sbbl(bumped_count, 0); |
1179 movl(data,bumped_count); // Store back out | 1183 movl(data,bumped_count); // Store back out |
1287 jmp(done); | 1291 jmp(done); |
1288 bind(next_test); | 1292 bind(next_test); |
1289 | 1293 |
1290 if (row == start_row) { | 1294 if (row == start_row) { |
1291 // Failed the equality check on receiver[n]... Test for null. | 1295 // Failed the equality check on receiver[n]... Test for null. |
1292 testl(reg2, reg2); | 1296 testptr(reg2, reg2); |
1293 if (start_row == last_row) { | 1297 if (start_row == last_row) { |
1294 // The only thing left to do is handle the null case. | 1298 // The only thing left to do is handle the null case. |
1295 jcc(Assembler::notZero, done); | 1299 jcc(Assembler::notZero, done); |
1296 break; | 1300 break; |
1297 } | 1301 } |
1313 | 1317 |
1314 // Fill in the receiver field and increment the count. | 1318 // Fill in the receiver field and increment the count. |
1315 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); | 1319 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); |
1316 set_mdp_data_at(mdp, recvr_offset, receiver); | 1320 set_mdp_data_at(mdp, recvr_offset, receiver); |
1317 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); | 1321 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); |
1318 movl(reg2, DataLayout::counter_increment); | 1322 movptr(reg2, (int32_t)DataLayout::counter_increment); |
1319 set_mdp_data_at(mdp, count_offset, reg2); | 1323 set_mdp_data_at(mdp, count_offset, reg2); |
1320 jmp(done); | 1324 jmp(done); |
1321 } | 1325 } |
1322 | 1326 |
1323 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, | 1327 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, |
1452 | 1456 |
1453 // If no method data exists, go to profile_continue. | 1457 // If no method data exists, go to profile_continue. |
1454 test_method_data_pointer(mdp, profile_continue); | 1458 test_method_data_pointer(mdp, profile_continue); |
1455 | 1459 |
1456 // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() | 1460 // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() |
1457 movl(reg2, in_bytes(MultiBranchData::per_case_size())); | 1461 movptr(reg2, (int32_t)in_bytes(MultiBranchData::per_case_size())); |
1458 imull(index, reg2); | 1462 // index is positive and so should have correct value if this code were |
1459 addl(index, in_bytes(MultiBranchData::case_array_offset())); | 1463 // used on 64bits |
1464 imulptr(index, reg2); | |
1465 addptr(index, in_bytes(MultiBranchData::case_array_offset())); | |
1460 | 1466 |
1461 // Update the case count | 1467 // Update the case count |
1462 increment_mdp_data_at(mdp, index, in_bytes(MultiBranchData::relative_count_offset())); | 1468 increment_mdp_data_at(mdp, index, in_bytes(MultiBranchData::relative_count_offset())); |
1463 | 1469 |
1464 // The method data pointer needs to be updated. | 1470 // The method data pointer needs to be updated. |
1533 NOT_CC_INTERP(pop(state);) | 1539 NOT_CC_INTERP(pop(state);) |
1534 } | 1540 } |
1535 | 1541 |
1536 { | 1542 { |
1537 SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); | 1543 SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); |
1538 push(state); | 1544 NOT_CC_INTERP(push(state)); |
1539 get_thread(rbx); | 1545 get_thread(rbx); |
1540 get_method(rcx); | 1546 get_method(rcx); |
1541 call_VM_leaf( | 1547 call_VM_leaf( |
1542 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), | 1548 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), |
1543 rbx, rcx); | 1549 rbx, rcx); |
1544 pop(state); | 1550 NOT_CC_INTERP(pop(state)); |
1545 } | 1551 } |
1546 } | 1552 } |