diff -r b57e01e9f81e -r 1510f9dcc0fa src/cpu/mips/vm/macroAssembler_mips.cpp --- a/src/cpu/mips/vm/macroAssembler_mips.cpp Fri Nov 03 15:51:07 2017 +0800 +++ b/src/cpu/mips/vm/macroAssembler_mips.cpp Mon Oct 23 17:07:19 2017 +0800 @@ -1474,28 +1474,274 @@ sd(last_java_sp, Address(thread, JavaThread::last_Java_sp_offset())); } + ////////////////////////////////////////////////////////////////////////////////// #if INCLUDE_ALL_GCS void MacroAssembler::g1_write_barrier_pre(Register obj, -#ifndef _LP64 + Register pre_val, Register thread, -#endif Register tmp, - Register tmp2, - bool tosca_live) { - Unimplemented(); + bool tosca_live, + bool expand_call) { + + // If expand_call is true then we expand the call_VM_leaf macro + // directly to skip generating the check by + // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. + +#ifdef _LP64 + assert(thread == TREG, "must be"); +#endif // _LP64 + + Label done; + Label runtime; + + assert(pre_val != noreg, "check this code"); + + if (obj != noreg) { + assert_different_registers(obj, pre_val, tmp); + assert(pre_val != V0, "check this code"); + } + + Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_active())); + Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_index())); + Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_buf())); + + + // Is marking active? + if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { + //cmpl(in_progress, 0); + lw(AT, in_progress); + } else { + assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); + //cmpb(in_progress, 0); + lb(AT, in_progress); + } + //jcc(Assembler::equal, done); + beq(AT, R0, done); + nop(); + + // Do we need to load the previous value? + if (obj != noreg) { + load_heap_oop(pre_val, Address(obj, 0)); + } + + // Is the previous value null? + //cmpptr(pre_val, (int32_t) NULL_WORD); + //jcc(Assembler::equal, done); + beq(pre_val, R0, done); + nop(); + + // Can we store original value in the thread's buffer? + // Is index == 0? + // (The index field is typed as size_t.) + + //movptr(tmp, index); // tmp := *index_adr + ld(tmp, index); + //cmpptr(tmp, 0); // tmp == 0? + //jcc(Assembler::equal, runtime); // If yes, goto runtime + beq(tmp, R0, runtime); + nop(); + + //subptr(tmp, wordSize); // tmp := tmp - wordSize + //movptr(index, tmp); // *index_adr := tmp + //addptr(tmp, buffer); // tmp := tmp + *buffer_adr + daddiu(tmp, tmp, -1 * wordSize); + sd(tmp, index); + ld(AT, buffer); + daddu(tmp, tmp, AT); + + // Record the previous value + //movptr(Address(tmp, 0), pre_val); + //jmp(done); + sd(pre_val, tmp, 0); + beq(R0, R0, done); + nop(); + + bind(runtime); + // save the live input values + //if(tosca_live) push(rax); + if(tosca_live) push(V0); + + //if (obj != noreg && obj != rax) + if (obj != noreg && obj != V0) + push(obj); + + //if (pre_val != rax) + if (pre_val != V0) + push(pre_val); + + // Calling the runtime using the regular call_VM_leaf mechanism generates + // code (generated by InterpreterMacroAssember::call_VM_leaf_base) + // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL. + // + // If we care generating the pre-barrier without a frame (e.g. in the + // intrinsified Reference.get() routine) then ebp might be pointing to + // the caller frame and so this check will most likely fail at runtime. + // + // Expanding the call directly bypasses the generation of the check. + // So when we do not have have a full interpreter frame on the stack + // expand_call should be passed true. + + NOT_LP64( push(thread); ) + + if (expand_call) { + //LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) + LP64_ONLY( assert(pre_val != A1, "smashed arg"); ) + //pass_arg1(this, thread); + if (thread != A1) move(A1, thread); + //pass_arg0(this, pre_val); + if (pre_val != A0) move(A0, pre_val); + MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2); + } else { + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread); + } + + NOT_LP64( pop(thread); ) + + // save the live input values + //if (pre_val != rax) + if (pre_val != V0) + pop(pre_val); + + //if (obj != noreg && obj != rax) + if (obj != noreg && obj != V0) + pop(obj); + + //if(tosca_live) pop(rax); + if(tosca_live) pop(V0); + + bind(done); } void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val, -#ifndef _LP64 Register thread, -#endif Register tmp, Register tmp2) { - - Unimplemented(); + assert(tmp == AT, "must be"); + assert(tmp2 == AT, "must be"); +#ifdef _LP64 + assert(thread == TREG, "must be"); +#endif // _LP64 + + Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() + + PtrQueue::byte_offset_of_index())); + Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() + + PtrQueue::byte_offset_of_buf())); + + BarrierSet* bs = Universe::heap()->barrier_set(); + CardTableModRefBS* ct = (CardTableModRefBS*)bs; + assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); + + Label done; + Label runtime; + + // Does store cross heap regions? + + //movptr(tmp, store_addr); + //xorptr(tmp, new_val); + //shrptr(tmp, HeapRegion::LogOfHRGrainBytes); + //jcc(Assembler::equal, done); + xorr(AT, store_addr, new_val); + dsrl(AT, AT, HeapRegion::LogOfHRGrainBytes); + beq(AT, R0, done); + nop(); + + + // crosses regions, storing NULL? + + //cmpptr(new_val, (int32_t) NULL_WORD); + //jcc(Assembler::equal, done); + beq(new_val, R0, done); + nop(); + + // storing region crossing non-NULL, is card already dirty? + + const Register card_addr = tmp; + const Register cardtable = tmp2; + + //movptr(card_addr, store_addr); + //shrptr(card_addr, CardTableModRefBS::card_shift); + move(card_addr, store_addr); + dsrl(card_addr, card_addr, CardTableModRefBS::card_shift); + // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT + // a valid address and therefore is not properly handled by the relocation code. + //movptr(cardtable, (intptr_t)ct->byte_map_base); + //addptr(card_addr, cardtable); + set64(cardtable, (intptr_t)ct->byte_map_base); + daddu(card_addr, card_addr, cardtable); + + //cmpb(Address(card_addr, 0), (int)G1SATBCardTableModRefBS::g1_young_card_val()); + //jcc(Assembler::equal, done); + lb(AT, card_addr, 0); + daddiu(AT, AT, -1 * (int)G1SATBCardTableModRefBS::g1_young_card_val()); + beq(AT, R0, done); + nop(); + + //membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); + //cmpb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val()); + //jcc(Assembler::equal, done); + sync(); + lb(AT, card_addr, 0); + daddiu(AT, AT, -1 * (int)(int)CardTableModRefBS::dirty_card_val()); + beq(AT, R0, done); + nop(); + + + // storing a region crossing, non-NULL oop, card is clean. + // dirty card and log. + + //movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val()); + move(AT, (int)CardTableModRefBS::dirty_card_val()); + sb(AT, card_addr, 0); + + //cmpl(queue_index, 0); + //jcc(Assembler::equal, runtime); + //subl(queue_index, wordSize); + //movptr(tmp2, buffer); + lw(AT, queue_index); + beq(AT, R0, runtime); + nop(); + daddiu(AT, AT, -1 * wordSize); + sw(AT, queue_index); + ld(tmp2, buffer); +#ifdef _LP64 + //movslq(rscratch1, queue_index); + //addq(tmp2, rscratch1); + //movq(Address(tmp2, 0), card_addr); + ld(AT, queue_index); + daddu(tmp2, tmp2, AT); + sd(card_addr, tmp2, 0); +#else + //addl(tmp2, queue_index); + //movl(Address(tmp2, 0), card_addr); + lw(AT, queue_index); + addu32(tmp2, tmp2, AT); + sw(card_addr, tmp2, 0); +#endif + //jmp(done); + beq(R0, R0, done); + nop(); + + bind(runtime); + // save the live input values + push(store_addr); + push(new_val); +#ifdef _LP64 + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, TREG); +#else + push(thread); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); + pop(thread); +#endif + pop(new_val); + pop(store_addr); + + bind(done); } #endif // INCLUDE_ALL_GCS