Mercurial > hg > truffle
comparison src/cpu/sparc/vm/assembler_sparc.cpp @ 3888:4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
Summary: Remove the macro assembler routine br_on_reg_cond() and replace the remaining calls to that routine with an equivalent.
Reviewed-by: kvn, iveresov
author | johnc |
---|---|
date | Wed, 31 Aug 2011 10:16:02 -0700 |
parents | 3d42f82cd811 |
children | d968f546734e |
comparison
equal
deleted
inserted
replaced
3887:9447b2fb6fcf | 3888:4fe626cbf0bf |
---|---|
2157 bpr( rc_nz, a, p, s1, L ); | 2157 bpr( rc_nz, a, p, s1, L ); |
2158 #else | 2158 #else |
2159 tst(s1); | 2159 tst(s1); |
2160 br ( notZero, a, p, L ); | 2160 br ( notZero, a, p, L ); |
2161 #endif | 2161 #endif |
2162 } | |
2163 | |
2164 void MacroAssembler::br_on_reg_cond( RCondition rc, bool a, Predict p, | |
2165 Register s1, address d, | |
2166 relocInfo::relocType rt ) { | |
2167 assert_not_delayed(); | |
2168 if (VM_Version::v9_instructions_work()) { | |
2169 bpr(rc, a, p, s1, d, rt); | |
2170 } else { | |
2171 tst(s1); | |
2172 br(reg_cond_to_cc_cond(rc), a, p, d, rt); | |
2173 } | |
2174 } | |
2175 | |
2176 void MacroAssembler::br_on_reg_cond( RCondition rc, bool a, Predict p, | |
2177 Register s1, Label& L ) { | |
2178 assert_not_delayed(); | |
2179 if (VM_Version::v9_instructions_work()) { | |
2180 bpr(rc, a, p, s1, L); | |
2181 } else { | |
2182 tst(s1); | |
2183 br(reg_cond_to_cc_cond(rc), a, p, L); | |
2184 } | |
2185 } | 2162 } |
2186 | 2163 |
2187 // Compare registers and branch with nop in delay slot or cbcond without delay slot. | 2164 // Compare registers and branch with nop in delay slot or cbcond without delay slot. |
2188 | 2165 |
2189 // Compare integer (32 bit) values (icc only). | 2166 // Compare integer (32 bit) values (icc only). |
4338 __ save_frame(0); | 4315 __ save_frame(0); |
4339 pre_val = I0; // Was O0 before the save. | 4316 pre_val = I0; // Was O0 before the save. |
4340 } else { | 4317 } else { |
4341 pre_val = O0; | 4318 pre_val = O0; |
4342 } | 4319 } |
4320 | |
4343 int satb_q_index_byte_offset = | 4321 int satb_q_index_byte_offset = |
4344 in_bytes(JavaThread::satb_mark_queue_offset() + | 4322 in_bytes(JavaThread::satb_mark_queue_offset() + |
4345 PtrQueue::byte_offset_of_index()); | 4323 PtrQueue::byte_offset_of_index()); |
4324 | |
4346 int satb_q_buf_byte_offset = | 4325 int satb_q_buf_byte_offset = |
4347 in_bytes(JavaThread::satb_mark_queue_offset() + | 4326 in_bytes(JavaThread::satb_mark_queue_offset() + |
4348 PtrQueue::byte_offset_of_buf()); | 4327 PtrQueue::byte_offset_of_buf()); |
4328 | |
4349 assert(in_bytes(PtrQueue::byte_width_of_index()) == sizeof(intptr_t) && | 4329 assert(in_bytes(PtrQueue::byte_width_of_index()) == sizeof(intptr_t) && |
4350 in_bytes(PtrQueue::byte_width_of_buf()) == sizeof(intptr_t), | 4330 in_bytes(PtrQueue::byte_width_of_buf()) == sizeof(intptr_t), |
4351 "check sizes in assembly below"); | 4331 "check sizes in assembly below"); |
4352 | 4332 |
4353 __ bind(restart); | 4333 __ bind(restart); |
4334 | |
4335 // Load the index into the SATB buffer. PtrQueue::_index is a size_t | |
4336 // so ld_ptr is appropriate. | |
4354 __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); | 4337 __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); |
4355 | 4338 |
4356 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, L0, refill); | 4339 // index == 0? |
4357 // If the branch is taken, no harm in executing this in the delay slot. | 4340 __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); |
4358 __ delayed()->ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); | 4341 |
4342 __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); | |
4359 __ sub(L0, oopSize, L0); | 4343 __ sub(L0, oopSize, L0); |
4360 | 4344 |
4361 __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 | 4345 __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 |
4362 if (!with_frame) { | 4346 if (!with_frame) { |
4363 // Use return-from-leaf | 4347 // Use return-from-leaf |
4464 in_bytes(JavaThread::satb_mark_queue_offset() + | 4448 in_bytes(JavaThread::satb_mark_queue_offset() + |
4465 PtrQueue::byte_offset_of_active()), | 4449 PtrQueue::byte_offset_of_active()), |
4466 tmp); | 4450 tmp); |
4467 } | 4451 } |
4468 | 4452 |
4469 // Check on whether to annul. | 4453 // Is marking active? |
4470 br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered); | 4454 cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); |
4471 delayed()->nop(); | |
4472 | 4455 |
4473 // Do we need to load the previous value? | 4456 // Do we need to load the previous value? |
4474 if (obj != noreg) { | 4457 if (obj != noreg) { |
4475 // Load the previous value... | 4458 // Load the previous value... |
4476 if (index == noreg) { | 4459 if (index == noreg) { |
4488 } | 4471 } |
4489 | 4472 |
4490 assert(pre_val != noreg, "must have a real register"); | 4473 assert(pre_val != noreg, "must have a real register"); |
4491 | 4474 |
4492 // Is the previous value null? | 4475 // Is the previous value null? |
4493 // Check on whether to annul. | 4476 cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); |
4494 br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, pre_val, filtered); | |
4495 delayed()->nop(); | |
4496 | 4477 |
4497 // OK, it's not filtered, so we'll need to call enqueue. In the normal | 4478 // OK, it's not filtered, so we'll need to call enqueue. In the normal |
4498 // case, pre_val will be a scratch G-reg, but there are some cases in | 4479 // case, pre_val will be a scratch G-reg, but there are some cases in |
4499 // which it's an O-reg. In the first case, do a normal call. In the | 4480 // which it's an O-reg. In the first case, do a normal call. In the |
4500 // latter, do a save here and call the frameless version. | 4481 // latter, do a save here and call the frameless version. |
4515 delayed()->mov(pre_val->after_save(), O0); | 4496 delayed()->mov(pre_val->after_save(), O0); |
4516 restore(); | 4497 restore(); |
4517 } | 4498 } |
4518 | 4499 |
4519 bind(filtered); | 4500 bind(filtered); |
4520 } | |
4521 | |
4522 static jint num_ct_writes = 0; | |
4523 static jint num_ct_writes_filtered_in_hr = 0; | |
4524 static jint num_ct_writes_filtered_null = 0; | |
4525 static G1CollectedHeap* g1 = NULL; | |
4526 | |
4527 static Thread* count_ct_writes(void* filter_val, void* new_val) { | |
4528 Atomic::inc(&num_ct_writes); | |
4529 if (filter_val == NULL) { | |
4530 Atomic::inc(&num_ct_writes_filtered_in_hr); | |
4531 } else if (new_val == NULL) { | |
4532 Atomic::inc(&num_ct_writes_filtered_null); | |
4533 } else { | |
4534 if (g1 == NULL) { | |
4535 g1 = G1CollectedHeap::heap(); | |
4536 } | |
4537 } | |
4538 if ((num_ct_writes % 1000000) == 0) { | |
4539 jint num_ct_writes_filtered = | |
4540 num_ct_writes_filtered_in_hr + | |
4541 num_ct_writes_filtered_null; | |
4542 | |
4543 tty->print_cr("%d potential CT writes: %5.2f%% filtered\n" | |
4544 " (%5.2f%% intra-HR, %5.2f%% null).", | |
4545 num_ct_writes, | |
4546 100.0*(float)num_ct_writes_filtered/(float)num_ct_writes, | |
4547 100.0*(float)num_ct_writes_filtered_in_hr/ | |
4548 (float)num_ct_writes, | |
4549 100.0*(float)num_ct_writes_filtered_null/ | |
4550 (float)num_ct_writes); | |
4551 } | |
4552 return Thread::current(); | |
4553 } | 4501 } |
4554 | 4502 |
4555 static address dirty_card_log_enqueue = 0; | 4503 static address dirty_card_log_enqueue = 0; |
4556 static u_char* dirty_card_log_enqueue_end = 0; | 4504 static u_char* dirty_card_log_enqueue_end = 0; |
4557 | 4505 |
4572 #endif | 4520 #endif |
4573 AddressLiteral addrlit(byte_map_base); | 4521 AddressLiteral addrlit(byte_map_base); |
4574 __ set(addrlit, O1); // O1 := <card table base> | 4522 __ set(addrlit, O1); // O1 := <card table base> |
4575 __ ldub(O0, O1, O2); // O2 := [O0 + O1] | 4523 __ ldub(O0, O1, O2); // O2 := [O0 + O1] |
4576 | 4524 |
4577 __ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt, | 4525 assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); |
4578 O2, not_already_dirty); | 4526 __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); |
4579 // Get O1 + O2 into a reg by itself -- useful in the take-the-branch | |
4580 // case, harmless if not. | |
4581 __ delayed()->add(O0, O1, O3); | |
4582 | 4527 |
4583 // We didn't take the branch, so we're already dirty: return. | 4528 // We didn't take the branch, so we're already dirty: return. |
4584 // Use return-from-leaf | 4529 // Use return-from-leaf |
4585 __ retl(); | 4530 __ retl(); |
4586 __ delayed()->nop(); | 4531 __ delayed()->nop(); |
4587 | 4532 |
4588 // Not dirty. | 4533 // Not dirty. |
4589 __ bind(not_already_dirty); | 4534 __ bind(not_already_dirty); |
4535 | |
4536 // Get O0 + O1 into a reg by itself | |
4537 __ add(O0, O1, O3); | |
4538 | |
4590 // First, dirty it. | 4539 // First, dirty it. |
4591 __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). | 4540 __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). |
4541 | |
4592 int dirty_card_q_index_byte_offset = | 4542 int dirty_card_q_index_byte_offset = |
4593 in_bytes(JavaThread::dirty_card_queue_offset() + | 4543 in_bytes(JavaThread::dirty_card_queue_offset() + |
4594 PtrQueue::byte_offset_of_index()); | 4544 PtrQueue::byte_offset_of_index()); |
4595 int dirty_card_q_buf_byte_offset = | 4545 int dirty_card_q_buf_byte_offset = |
4596 in_bytes(JavaThread::dirty_card_queue_offset() + | 4546 in_bytes(JavaThread::dirty_card_queue_offset() + |
4597 PtrQueue::byte_offset_of_buf()); | 4547 PtrQueue::byte_offset_of_buf()); |
4598 __ bind(restart); | 4548 __ bind(restart); |
4549 | |
4550 // Load the index into the update buffer. PtrQueue::_index is | |
4551 // a size_t so ld_ptr is appropriate here. | |
4599 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); | 4552 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); |
4600 | 4553 |
4601 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, | 4554 // index == 0? |
4602 L0, refill); | 4555 __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); |
4603 // If the branch is taken, no harm in executing this in the delay slot. | 4556 |
4604 __ delayed()->ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); | 4557 __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); |
4605 __ sub(L0, oopSize, L0); | 4558 __ sub(L0, oopSize, L0); |
4606 | 4559 |
4607 __ st_ptr(O3, L1, L0); // [_buf + index] := I0 | 4560 __ st_ptr(O3, L1, L0); // [_buf + index] := I0 |
4608 // Use return-from-leaf | 4561 // Use return-from-leaf |
4609 __ retl(); | 4562 __ retl(); |
4662 if (new_val == G0) return; | 4615 if (new_val == G0) return; |
4663 | 4616 |
4664 G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); | 4617 G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); |
4665 assert(bs->kind() == BarrierSet::G1SATBCT || | 4618 assert(bs->kind() == BarrierSet::G1SATBCT || |
4666 bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); | 4619 bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); |
4620 | |
4667 if (G1RSBarrierRegionFilter) { | 4621 if (G1RSBarrierRegionFilter) { |
4668 xor3(store_addr, new_val, tmp); | 4622 xor3(store_addr, new_val, tmp); |
4669 #ifdef _LP64 | 4623 #ifdef _LP64 |
4670 srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); | 4624 srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); |
4671 #else | 4625 #else |
4672 srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); | 4626 srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); |
4673 #endif | 4627 #endif |
4674 | 4628 |
4675 if (G1PrintCTFilterStats) { | 4629 // XXX Should I predict this taken or not? Does it matter? |
4676 guarantee(tmp->is_global(), "Or stats won't work..."); | 4630 cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); |
4677 // This is a sleazy hack: I'm temporarily hijacking G2, which I | |
4678 // promise to restore. | |
4679 mov(new_val, G2); | |
4680 save_frame(0); | |
4681 mov(tmp, O0); | |
4682 mov(G2, O1); | |
4683 // Save G-regs that target may use. | |
4684 mov(G1, L1); | |
4685 mov(G2, L2); | |
4686 mov(G3, L3); | |
4687 mov(G4, L4); | |
4688 mov(G5, L5); | |
4689 call(CAST_FROM_FN_PTR(address, &count_ct_writes)); | |
4690 delayed()->nop(); | |
4691 mov(O0, G2); | |
4692 // Restore G-regs that target may have used. | |
4693 mov(L1, G1); | |
4694 mov(L3, G3); | |
4695 mov(L4, G4); | |
4696 mov(L5, G5); | |
4697 restore(G0, G0, G0); | |
4698 } | |
4699 // XXX Should I predict this taken or not? Does it mattern? | |
4700 br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered); | |
4701 delayed()->nop(); | |
4702 } | 4631 } |
4703 | 4632 |
4704 // If the "store_addr" register is an "in" or "local" register, move it to | 4633 // If the "store_addr" register is an "in" or "local" register, move it to |
4705 // a scratch reg so we can pass it as an argument. | 4634 // a scratch reg so we can pass it as an argument. |
4706 bool use_scr = !(store_addr->is_global() || store_addr->is_out()); | 4635 bool use_scr = !(store_addr->is_global() || store_addr->is_out()); |
4721 delayed()->mov(store_addr->after_save(), O0); | 4650 delayed()->mov(store_addr->after_save(), O0); |
4722 } | 4651 } |
4723 restore(); | 4652 restore(); |
4724 | 4653 |
4725 bind(filtered); | 4654 bind(filtered); |
4726 | |
4727 } | 4655 } |
4728 | 4656 |
4729 #endif // SERIALGC | 4657 #endif // SERIALGC |
4730 /////////////////////////////////////////////////////////////////////////////////// | 4658 /////////////////////////////////////////////////////////////////////////////////// |
4731 | 4659 |