< prev index next >

src/cpu/sparc/vm/macroAssembler_sparc.cpp

Print this page
rev 12906 : [mq]: gc_interface

*** 25,34 **** --- 25,36 ---- #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/cardTableModRefBS.hpp" #include "gc/shared/collectedHeap.inline.hpp" + #include "gc/shared/barrierSet.hpp" + #include "gc/shared/barrierSetCodeGen.hpp" #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp"
*** 37,51 **** #include "runtime/objectMonitor.hpp" #include "runtime/os.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/macros.hpp" - #if INCLUDE_ALL_GCS - #include "gc/g1/g1CollectedHeap.inline.hpp" - #include "gc/g1/g1SATBCardTableModRefBS.hpp" - #include "gc/g1/heapRegion.hpp" - #endif // INCLUDE_ALL_GCS #ifdef COMPILER2 #include "opto/intrinsicnode.hpp" #endif #ifdef PRODUCT --- 39,48 ----
*** 165,174 **** --- 162,191 ---- } } return r; } + void MacroAssembler::resolve_jobject(Register value, + Register tmp) { + BarrierSetCodeGen* code_gen = Universe::heap()->barrier_set()->code_gen(); + Label done, not_weak; + br_null(value, true, Assembler::pn, done); // Use NULL as-is. + delayed()->andcc(value, JNIHandles::weak_tag_mask, G0); // Test for jweak + br(Assembler::zero, false, Assembler::pt, not_weak); + delayed()->nop(); + code_gen->load_at(this, ACCESS_ON_ROOT | GC_ACCESS_ON_PHANTOM, T_OBJECT, + value, noreg, 0, value, tmp); + verify_oop(value); + br(Assembler::always, false, Assembler::pt, done); + delayed()->nop(); + bind(not_weak); + code_gen->load_at(this, ACCESS_ON_ROOT | GC_ACCESS_ON_STRONG, T_OBJECT, + value, noreg, -JNIHandles::weak_tag_value, value, tmp); + verify_oop(value); + bind(done); + } + void MacroAssembler::null_check(Register reg, int offset) { if (needs_explicit_null_check((intptr_t)offset)) { // provoke OS NULL exception if reg = NULL by // accessing M[reg] w/o changing any registers ld_ptr(reg, 0, G0);
*** 636,654 **** if (emit_delay) { delayed()->nop(); } } - void MacroAssembler::card_table_write(jbyte* byte_map_base, - Register tmp, Register obj) { - srlx(obj, CardTableModRefBS::card_shift, obj); - assert(tmp != obj, "need separate temp reg"); - set((address) byte_map_base, tmp); - stb(G0, tmp, obj); - } - - void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { address save_pc; int shiftcnt; # ifdef CHECK_DELAY assert_not_delayed((char*) "cannot put two instructions in delay slot"); --- 653,662 ----
*** 3454,3820 **** should_not_reach_here(); bind(no_reserved_zone_enabling); } - /////////////////////////////////////////////////////////////////////////////////// - #if INCLUDE_ALL_GCS - - static address satb_log_enqueue_with_frame = NULL; - static u_char* satb_log_enqueue_with_frame_end = NULL; - - static address satb_log_enqueue_frameless = NULL; - static u_char* satb_log_enqueue_frameless_end = NULL; - - static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions? - - static void generate_satb_log_enqueue(bool with_frame) { - BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize); - CodeBuffer buf(bb); - MacroAssembler masm(&buf); - - #define __ masm. - - address start = __ pc(); - Register pre_val; - - Label refill, restart; - if (with_frame) { - __ save_frame(0); - pre_val = I0; // Was O0 before the save. - } else { - pre_val = O0; - } - - int satb_q_index_byte_offset = - in_bytes(JavaThread::satb_mark_queue_offset() + - SATBMarkQueue::byte_offset_of_index()); - - int satb_q_buf_byte_offset = - in_bytes(JavaThread::satb_mark_queue_offset() + - SATBMarkQueue::byte_offset_of_buf()); - - assert(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t) && - in_bytes(SATBMarkQueue::byte_width_of_buf()) == sizeof(intptr_t), - "check sizes in assembly below"); - - __ bind(restart); - - // Load the index into the SATB buffer. SATBMarkQueue::_index is a size_t - // so ld_ptr is appropriate. - __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); - - // index == 0? - __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); - - __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); - __ sub(L0, oopSize, L0); - - __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 - if (!with_frame) { - // Use return-from-leaf - __ retl(); - __ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset); - } else { - // Not delayed. - __ st_ptr(L0, G2_thread, satb_q_index_byte_offset); - } - if (with_frame) { - __ ret(); - __ delayed()->restore(); - } - __ bind(refill); - - address handle_zero = - CAST_FROM_FN_PTR(address, - &SATBMarkQueueSet::handle_zero_index_for_thread); - // This should be rare enough that we can afford to save all the - // scratch registers that the calling context might be using. - __ mov(G1_scratch, L0); - __ mov(G3_scratch, L1); - __ mov(G4, L2); - // We need the value of O0 above (for the write into the buffer), so we - // save and restore it. - __ mov(O0, L3); - // Since the call will overwrite O7, we save and restore that, as well. - __ mov(O7, L4); - __ call_VM_leaf(L5, handle_zero, G2_thread); - __ mov(L0, G1_scratch); - __ mov(L1, G3_scratch); - __ mov(L2, G4); - __ mov(L3, O0); - __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); - __ delayed()->mov(L4, O7); - - if (with_frame) { - satb_log_enqueue_with_frame = start; - satb_log_enqueue_with_frame_end = __ pc(); - } else { - satb_log_enqueue_frameless = start; - satb_log_enqueue_frameless_end = __ pc(); - } - - #undef __ - } - - static inline void generate_satb_log_enqueue_if_necessary(bool with_frame) { - if (with_frame) { - if (satb_log_enqueue_with_frame == 0) { - generate_satb_log_enqueue(with_frame); - assert(satb_log_enqueue_with_frame != 0, "postcondition."); - } - } else { - if (satb_log_enqueue_frameless == 0) { - generate_satb_log_enqueue(with_frame); - assert(satb_log_enqueue_frameless != 0, "postcondition."); - } - } - } - - void MacroAssembler::g1_write_barrier_pre(Register obj, - Register index, - int offset, - Register pre_val, - Register tmp, - bool preserve_o_regs) { - Label filtered; - - if (obj == noreg) { - // We are not loading the previous value so make - // sure that we don't trash the value in pre_val - // with the code below. - assert_different_registers(pre_val, tmp); - } else { - // We will be loading the previous value - // in this code so... - assert(offset == 0 || index == noreg, "choose one"); - assert(pre_val == noreg, "check this code"); - } - - // Is marking active? - if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { - ld(G2, - in_bytes(JavaThread::satb_mark_queue_offset() + - SATBMarkQueue::byte_offset_of_active()), - tmp); - } else { - guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, - "Assumption"); - ldsb(G2, - in_bytes(JavaThread::satb_mark_queue_offset() + - SATBMarkQueue::byte_offset_of_active()), - tmp); - } - - // Is marking active? - cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); - - // Do we need to load the previous value? - if (obj != noreg) { - // Load the previous value... - if (index == noreg) { - if (Assembler::is_simm13(offset)) { - load_heap_oop(obj, offset, tmp); - } else { - set(offset, tmp); - load_heap_oop(obj, tmp, tmp); - } - } else { - load_heap_oop(obj, index, tmp); - } - // Previous value has been loaded into tmp - pre_val = tmp; - } - - assert(pre_val != noreg, "must have a real register"); - - // Is the previous value null? - cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); - - // OK, it's not filtered, so we'll need to call enqueue. In the normal - // case, pre_val will be a scratch G-reg, but there are some cases in - // which it's an O-reg. In the first case, do a normal call. In the - // latter, do a save here and call the frameless version. - - guarantee(pre_val->is_global() || pre_val->is_out(), - "Or we need to think harder."); - - if (pre_val->is_global() && !preserve_o_regs) { - generate_satb_log_enqueue_if_necessary(true); // with frame - - call(satb_log_enqueue_with_frame); - delayed()->mov(pre_val, O0); - } else { - generate_satb_log_enqueue_if_necessary(false); // frameless - - save_frame(0); - call(satb_log_enqueue_frameless); - delayed()->mov(pre_val->after_save(), O0); - restore(); - } - - bind(filtered); - } - - static address dirty_card_log_enqueue = 0; - static u_char* dirty_card_log_enqueue_end = 0; - - // This gets to assume that o0 contains the object address. - static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { - BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2); - CodeBuffer buf(bb); - MacroAssembler masm(&buf); - #define __ masm. - address start = __ pc(); - - Label not_already_dirty, restart, refill, young_card; - - __ srlx(O0, CardTableModRefBS::card_shift, O0); - AddressLiteral addrlit(byte_map_base); - __ set(addrlit, O1); // O1 := <card table base> - __ ldub(O0, O1, O2); // O2 := [O0 + O1] - - __ cmp_and_br_short(O2, G1SATBCardTableModRefBS::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card); - - __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); - __ ldub(O0, O1, O2); // O2 := [O0 + O1] - - assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); - __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); - - __ bind(young_card); - // We didn't take the branch, so we're already dirty: return. - // Use return-from-leaf - __ retl(); - __ delayed()->nop(); - - // Not dirty. - __ bind(not_already_dirty); - - // Get O0 + O1 into a reg by itself - __ add(O0, O1, O3); - - // First, dirty it. - __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). - - int dirty_card_q_index_byte_offset = - in_bytes(JavaThread::dirty_card_queue_offset() + - DirtyCardQueue::byte_offset_of_index()); - int dirty_card_q_buf_byte_offset = - in_bytes(JavaThread::dirty_card_queue_offset() + - DirtyCardQueue::byte_offset_of_buf()); - __ bind(restart); - - // Load the index into the update buffer. DirtyCardQueue::_index is - // a size_t so ld_ptr is appropriate here. - __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); - - // index == 0? - __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); - - __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); - __ sub(L0, oopSize, L0); - - __ st_ptr(O3, L1, L0); // [_buf + index] := I0 - // Use return-from-leaf - __ retl(); - __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset); - - __ bind(refill); - address handle_zero = - CAST_FROM_FN_PTR(address, - &DirtyCardQueueSet::handle_zero_index_for_thread); - // This should be rare enough that we can afford to save all the - // scratch registers that the calling context might be using. - __ mov(G1_scratch, L3); - __ mov(G3_scratch, L5); - // We need the value of O3 above (for the write into the buffer), so we - // save and restore it. - __ mov(O3, L6); - // Since the call will overwrite O7, we save and restore that, as well. - __ mov(O7, L4); - - __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread); - __ mov(L3, G1_scratch); - __ mov(L5, G3_scratch); - __ mov(L6, O3); - __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); - __ delayed()->mov(L4, O7); - - dirty_card_log_enqueue = start; - dirty_card_log_enqueue_end = __ pc(); - // XXX Should have a guarantee here about not going off the end! - // Does it already do so? Do an experiment... - - #undef __ - - } - - static inline void - generate_dirty_card_log_enqueue_if_necessary(jbyte* byte_map_base) { - if (dirty_card_log_enqueue == 0) { - generate_dirty_card_log_enqueue(byte_map_base); - assert(dirty_card_log_enqueue != 0, "postcondition."); - } - } - - - void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val, Register tmp) { - - Label filtered; - MacroAssembler* post_filter_masm = this; - - if (new_val == G0) return; - - G1SATBCardTableLoggingModRefBS* bs = - barrier_set_cast<G1SATBCardTableLoggingModRefBS>(Universe::heap()->barrier_set()); - - if (G1RSBarrierRegionFilter) { - xor3(store_addr, new_val, tmp); - srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); - - // XXX Should I predict this taken or not? Does it matter? - cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); - } - - // If the "store_addr" register is an "in" or "local" register, move it to - // a scratch reg so we can pass it as an argument. - bool use_scr = !(store_addr->is_global() || store_addr->is_out()); - // Pick a scratch register different from "tmp". - Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch); - // Make sure we use up the delay slot! - if (use_scr) { - post_filter_masm->mov(store_addr, scr); - } else { - post_filter_masm->nop(); - } - generate_dirty_card_log_enqueue_if_necessary(bs->byte_map_base); - save_frame(0); - call(dirty_card_log_enqueue); - if (use_scr) { - delayed()->mov(scr, O0); - } else { - delayed()->mov(store_addr->after_save(), O0); - } - restore(); - - bind(filtered); - } - - #endif // INCLUDE_ALL_GCS - /////////////////////////////////////////////////////////////////////////////////// - - void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) { - // If we're writing constant NULL, we can skip the write barrier. - if (new_val == G0) return; - CardTableModRefBS* bs = - barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set()); - assert(bs->kind() == BarrierSet::CardTableForRS || - bs->kind() == BarrierSet::CardTableExtension, "wrong barrier"); - card_table_write(bs->byte_map_base, tmp, store_addr); - } - void MacroAssembler::load_mirror(Register mirror, Register method) { const int mirror_offset = in_bytes(Klass::java_mirror_offset()); ld_ptr(method, in_bytes(Method::const_offset()), mirror); ld_ptr(mirror, in_bytes(ConstMethod::constants_offset()), mirror); ld_ptr(mirror, ConstantPool::pool_holder_offset_in_bytes(), mirror); --- 3462,3471 ----
< prev index next >