< prev index next >

src/cpu/x86/vm/templateTable_x86.cpp

Print this page
rev 12163 : Replace read-barrier in monitor-search-loop with store checks.


4258 // Note: monitorenter & exit are symmetric routines; which is reflected
4259 //       in the assembly code structure as well
4260 //
4261 // Stack layout:
4262 //
4263 // [expressions  ] <--- rsp               = expression stack top
4264 // ..
4265 // [expressions  ]
4266 // [monitor entry] <--- monitor block top = expression stack bot
4267 // ..
4268 // [monitor entry]
4269 // [frame data   ] <--- monitor block bot
4270 // ...
4271 // [saved rbp    ] <--- rbp
4272 void TemplateTable::monitorenter() {
4273   transition(atos, vtos);
4274 
4275   // check for NULL object
4276   __ null_check(rax);
4277 
4278   // We need to preemptively evacuate the object, because we later compare
4279   // it to objects in the BasicObjectLock list, and we might get false negatives
4280   // if another thread evacuates the object in the meantime. See acmp.
4281   oopDesc::bs()->interpreter_write_barrier(_masm, rax);
4282 
4283   const Address monitor_block_top(
4284         rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
4285   const Address monitor_block_bot(
4286         rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
4287   const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
4288 
4289   Label allocated;
4290 
4291   Register rtop = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
4292   Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx);
4293   Register rmon = LP64_ONLY(c_rarg1) NOT_LP64(rdx);
4294 
4295   // initialize entry pointer
4296   __ xorl(rmon, rmon); // points to free slot or NULL
4297 
4298   // find a free slot in the monitor block (result in rmon)
4299   {
4300     Label entry, loop, exit;
4301     __ movptr(rtop, monitor_block_top); // points to current entry,
4302                                         // starting with top-most entry
4303     __ lea(rbot, monitor_block_bot);    // points to word before bottom
4304                                         // of monitor block
4305     __ jmpb_if_possible(entry);
4306 
4307     __ bind(loop);
4308     // check if current entry is used
4309     __ cmpptr(Address(rtop, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD);
4310     // if not used then remember entry in rmon
4311     __ cmovptr(Assembler::equal, rmon, rtop);   // cmov => cmovptr
4312     // check if current entry is for same object
4313     __ movptr(rscratch1, Address(rtop, BasicObjectLock::obj_offset_in_bytes()));
4314     __ shenandoah_store_addr_check(rscratch1); // Invariant
4315     oopDesc::bs()->interpreter_read_barrier(_masm, rscratch1);
4316     __ cmpptr(rax, rscratch1);
4317     // if same object then stop searching
4318     __ jccb(Assembler::equal, exit);
4319     // otherwise advance to next entry
4320     __ addptr(rtop, entry_size);
4321     __ bind(entry);
4322     // check if bottom reached
4323     __ cmpptr(rtop, rbot);
4324     // if not at bottom then check this entry
4325     __ jcc(Assembler::notEqual, loop);
4326     __ bind(exit);
4327   }
4328 
4329   __ testptr(rmon, rmon); // check if a slot has been found
4330   __ jcc(Assembler::notZero, allocated); // if found, continue with that one
4331 
4332   // allocate one if there's no free slot
4333   {
4334     Label entry, loop;
4335     // 1. compute new pointers          // rsp: old expression stack top
4336     __ movptr(rmon, monitor_block_bot); // rmon: old expression stack bottom


4364   // store object
4365   __ shenandoah_store_addr_check(rax); // Invariant
4366   __ movptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), rax);
4367   __ lock_object(rmon);
4368 
4369   // check to make sure this monitor doesn't cause stack overflow after locking
4370   __ save_bcp();  // in case of exception
4371   __ generate_stack_overflow_check(0);
4372 
4373   // The bcp has already been incremented. Just need to dispatch to
4374   // next instruction.
4375   __ dispatch_next(vtos);
4376 }
4377 
4378 void TemplateTable::monitorexit() {
4379   transition(atos, vtos);
4380 
4381   // check for NULL object
4382   __ null_check(rax);
4383 
4384   // We need to preemptively evacuate the object, because we later compare
4385   // it to objects in the BasicObjectLock list, and we might get false negatives
4386   // if another thread evacuates the object in the meantime. See acmp.
4387   oopDesc::bs()->interpreter_write_barrier(_masm, rax);
4388 
4389   const Address monitor_block_top(
4390         rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
4391   const Address monitor_block_bot(
4392         rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
4393   const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
4394 
4395   Register rtop = LP64_ONLY(c_rarg1) NOT_LP64(rdx);
4396   Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx);
4397 
4398   Label found;
4399 
4400   // find matching slot
4401   {
4402     Label entry, loop;
4403     __ movptr(rtop, monitor_block_top); // points to current entry,
4404                                         // starting with top-most entry
4405     __ lea(rbot, monitor_block_bot);    // points to word before bottom
4406                                         // of monitor block
4407     __ jmpb_if_possible(entry);
4408 
4409     __ bind(loop);
4410     // check if current entry is for same object
4411     __ movptr(rscratch1, Address(rtop, BasicObjectLock::obj_offset_in_bytes()));
4412     __ shenandoah_store_addr_check(rscratch1); // Invariant
4413     oopDesc::bs()->interpreter_read_barrier(_masm, rscratch1);
4414     __ cmpptr(rax, rscratch1);
4415     // if same object then stop searching
4416     __ jcc(Assembler::equal, found);
4417     // otherwise advance to next entry
4418     __ addptr(rtop, entry_size);
4419     __ bind(entry);
4420     // check if bottom reached
4421     __ cmpptr(rtop, rbot);
4422     // if not at bottom then check this entry
4423     __ jcc(Assembler::notEqual, loop);
4424   }
4425 
4426   // error handling. Unlocking was not block-structured
4427   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
4428                    InterpreterRuntime::throw_illegal_monitor_state_exception));
4429   __ should_not_reach_here();
4430 
4431   // call run-time routine
4432   __ bind(found);
4433   __ push_ptr(rax); // make sure object is on stack (contract with oopMaps)
4434   __ unlock_object(rtop);




4258 // Note: monitorenter & exit are symmetric routines; which is reflected
4259 //       in the assembly code structure as well
4260 //
4261 // Stack layout:
4262 //
4263 // [expressions  ] <--- rsp               = expression stack top
4264 // ..
4265 // [expressions  ]
4266 // [monitor entry] <--- monitor block top = expression stack bot
4267 // ..
4268 // [monitor entry]
4269 // [frame data   ] <--- monitor block bot
4270 // ...
4271 // [saved rbp    ] <--- rbp
4272 void TemplateTable::monitorenter() {
4273   transition(atos, vtos);
4274 
4275   // check for NULL object
4276   __ null_check(rax);
4277 



4278   oopDesc::bs()->interpreter_write_barrier(_masm, rax);
4279 
4280   const Address monitor_block_top(
4281         rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
4282   const Address monitor_block_bot(
4283         rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
4284   const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
4285 
4286   Label allocated;
4287 
4288   Register rtop = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
4289   Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx);
4290   Register rmon = LP64_ONLY(c_rarg1) NOT_LP64(rdx);
4291 
4292   // initialize entry pointer
4293   __ xorl(rmon, rmon); // points to free slot or NULL
4294 
4295   // find a free slot in the monitor block (result in rmon)
4296   {
4297     Label entry, loop, exit;
4298     __ movptr(rtop, monitor_block_top); // points to current entry,
4299                                         // starting with top-most entry
4300     __ lea(rbot, monitor_block_bot);    // points to word before bottom
4301                                         // of monitor block
4302     __ jmpb_if_possible(entry);
4303 
4304     __ bind(loop);
4305     // check if current entry is used
4306     __ cmpptr(Address(rtop, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD);
4307     // if not used then remember entry in rmon
4308     __ cmovptr(Assembler::equal, rmon, rtop);   // cmov => cmovptr
4309     // check if current entry is for same object
4310     __ shenandoah_lock_check(rtop); // Invariant
4311     __ cmpptr(rax, Address(rtop, BasicObjectLock::obj_offset_in_bytes()));


4312     // if same object then stop searching
4313     __ jccb(Assembler::equal, exit);
4314     // otherwise advance to next entry
4315     __ addptr(rtop, entry_size);
4316     __ bind(entry);
4317     // check if bottom reached
4318     __ cmpptr(rtop, rbot);
4319     // if not at bottom then check this entry
4320     __ jcc(Assembler::notEqual, loop);
4321     __ bind(exit);
4322   }
4323 
4324   __ testptr(rmon, rmon); // check if a slot has been found
4325   __ jcc(Assembler::notZero, allocated); // if found, continue with that one
4326 
4327   // allocate one if there's no free slot
4328   {
4329     Label entry, loop;
4330     // 1. compute new pointers          // rsp: old expression stack top
4331     __ movptr(rmon, monitor_block_bot); // rmon: old expression stack bottom


4359   // store object
4360   __ shenandoah_store_addr_check(rax); // Invariant
4361   __ movptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), rax);
4362   __ lock_object(rmon);
4363 
4364   // check to make sure this monitor doesn't cause stack overflow after locking
4365   __ save_bcp();  // in case of exception
4366   __ generate_stack_overflow_check(0);
4367 
4368   // The bcp has already been incremented. Just need to dispatch to
4369   // next instruction.
4370   __ dispatch_next(vtos);
4371 }
4372 
4373 void TemplateTable::monitorexit() {
4374   transition(atos, vtos);
4375 
4376   // check for NULL object
4377   __ null_check(rax);
4378 



4379   oopDesc::bs()->interpreter_write_barrier(_masm, rax);
4380 
4381   const Address monitor_block_top(
4382         rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
4383   const Address monitor_block_bot(
4384         rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
4385   const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
4386 
4387   Register rtop = LP64_ONLY(c_rarg1) NOT_LP64(rdx);
4388   Register rbot = LP64_ONLY(c_rarg2) NOT_LP64(rbx);
4389 
4390   Label found;
4391 
4392   // find matching slot
4393   {
4394     Label entry, loop;
4395     __ movptr(rtop, monitor_block_top); // points to current entry,
4396                                         // starting with top-most entry
4397     __ lea(rbot, monitor_block_bot);    // points to word before bottom
4398                                         // of monitor block
4399     __ jmpb_if_possible(entry);
4400 
4401     __ bind(loop);
4402     // check if current entry is for same object
4403     __ shenandoah_lock_check(rtop); // Invariant
4404     __ cmpptr(rax, Address(rtop, BasicObjectLock::obj_offset_in_bytes()));


4405     // if same object then stop searching
4406     __ jcc(Assembler::equal, found);
4407     // otherwise advance to next entry
4408     __ addptr(rtop, entry_size);
4409     __ bind(entry);
4410     // check if bottom reached
4411     __ cmpptr(rtop, rbot);
4412     // if not at bottom then check this entry
4413     __ jcc(Assembler::notEqual, loop);
4414   }
4415 
4416   // error handling. Unlocking was not block-structured
4417   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
4418                    InterpreterRuntime::throw_illegal_monitor_state_exception));
4419   __ should_not_reach_here();
4420 
4421   // call run-time routine
4422   __ bind(found);
4423   __ push_ptr(rax); // make sure object is on stack (contract with oopMaps)
4424   __ unlock_object(rtop);


< prev index next >