< prev index next >
src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
Print this page
rev 12152 : [mq]: verification.patch
@@ -413,10 +413,12 @@
assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout");
Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes());
Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes());
Address saved_mark_addr(lock_reg, 0);
+ shenandoah_store_addr_check(obj_reg);
+
// Biased locking
// See whether the lock is currently biased toward our thread and
// whether the epoch is still valid
// Note that the runtime guarantees sufficient alignment of JavaThread
// pointers to allow age to be placed into low bits
@@ -563,10 +565,11 @@
// Note: we do not have to check the thread ID for two reasons.
// First, the interpreter checks for IllegalMonitorStateException at
// a higher level. Second, if the bias was revoked while we held the
// lock, the object could not be rebiased toward another thread, so
// the bias bit would be clear.
+ shenandoah_store_addr_check(obj_reg); // Access mark word
ldr(temp_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
andr(temp_reg, temp_reg, markOopDesc::biased_lock_mask_in_place);
cmp(temp_reg, markOopDesc::biased_lock_pattern);
br(Assembler::EQ, done);
}
@@ -1973,11 +1976,11 @@
#endif
void MacroAssembler::stop(const char* msg, Label *l) {
address ip = pc();
pusha();
- mov(c_rarg0, (address)msg);
+ lea(c_rarg0, ExternalAddress((address) msg));
if (! l) {
adr(c_rarg1, (address)ip);
} else {
adr(c_rarg1, *l);
}
@@ -3615,11 +3618,10 @@
ldr(dst, src);
}
}
void MacroAssembler::store_heap_oop(Address dst, Register src) {
- shenandoah_store_check(src, dst);
if (UseCompressedOops) {
assert(!dst.uses(src), "not enough registers");
encode_heap_oop(src);
strw(src, dst);
} else
@@ -5195,129 +5197,156 @@
// Shenandoah requires that all objects are evacuated before being
// written to, and that fromspace pointers are not written into
// objects during concurrent marking. These methods check for that.
-const bool ShenandoahStoreCheck = false;
-
-void MacroAssembler::in_heap_check(Register r, Label &nope) {
+void MacroAssembler::in_heap_check(Register r, Register tmp, Label &nope) {
ShenandoahHeap *h = (ShenandoahHeap *)Universe::heap();
HeapWord* first_region_bottom = h->first_region_bottom();
HeapWord* last_region_end = first_region_bottom + (ShenandoahHeapRegion::RegionSizeBytes / HeapWordSize) * h->max_regions();
- mov(rscratch1, (uintptr_t)first_region_bottom);
- cmp(r, rscratch1);
+ mov(tmp, (uintptr_t)first_region_bottom);
+ cmp(r, tmp);
br(Assembler::LO, nope);
- mov(rscratch1, (uintptr_t)last_region_end);
- cmp(r, rscratch1);
+ mov(tmp, (uintptr_t)last_region_end);
+ cmp(r, tmp);
br(Assembler::HS, nope);
}
-void MacroAssembler::shenandoah_store_check(Register r, Address dest) {
- if (! ShenandoahStoreCheck)
- return;
-
- assert_different_registers(rscratch1, rscratch2, r);
- assert(! dest.uses(rscratch1), "invalid register");
- assert(! dest.uses(rscratch2), "invalid register");
-
- assert(! InlineObjectCopy, "ShenandoahStoreCheck is incompatible with InlineObjectCopy");
-
- Label done;
- cbz(r, done);
-
- mov(rscratch2, ShenandoahHeap::concurrent_mark_in_progress_addr());
- Assembler::ldrw(rscratch2, Address(rscratch2));
- cbzw(rscratch2, done);
-
- in_heap_check(r, done);
-
- // Check for object in collection set.
- lsr(rscratch1, r, ShenandoahHeapRegion::RegionSizeShift);
- mov(rscratch2, ShenandoahHeap::in_cset_fast_test_addr());
- ldrb(rscratch2, Address(rscratch2, rscratch1));
- tbz(rscratch2, 0, done);
+void MacroAssembler::shenandoah_cset_check(Register obj, Register tmp1, Register tmp2, Label& done) {
- // Check for dest in heap
- lea(rscratch2, dest);
- in_heap_check(rscratch2, done);
+ // Test that oop is not in to-space.
+ lsr(tmp1, obj, ShenandoahHeapRegion::RegionSizeShift);
+ assert(ShenandoahHeap::in_cset_fast_test_addr() != 0, "sanity");
+ mov(tmp2, ShenandoahHeap::in_cset_fast_test_addr());
+ ldrb(tmp2, Address(tmp2, tmp1));
+ tbz(tmp2, 0, done);
- lsr(rscratch1, rscratch2, ShenandoahHeapRegion::RegionSizeShift);
- mov(rscratch2, ShenandoahHeap::in_cset_fast_test_addr());
- ldrb(rscratch2, Address(rscratch2, rscratch1));
- tbz(rscratch2, 0, done);
+ // Check for cancelled GC.
+ assert(ShenandoahHeap::cancelled_concgc_addr() != 0, "sanity");
+ mov(tmp2, ShenandoahHeap::cancelled_concgc_addr());
+ ldrb(tmp2, Address(tmp2));
+ cbnz(tmp2, done);
+}
- ldr(rscratch2, Address(r, BrooksPointer::byte_offset()));
+void MacroAssembler::_shenandoah_store_check(Address addr, Register value, const char* msg, const char* file, int line) {
+ _shenandoah_store_check(addr.base(), value, msg, file, line);
+}
- stop("Shenandoah: store of oop in collection set during marking!", &done);
- should_not_reach_here();
+void MacroAssembler::_shenandoah_store_check(Register addr, Register value, const char* msg, const char* file, int line) {
- bind(done);
-}
+ if (! UseShenandoahGC || ! ShenandoahStoreCheck) return;
+ if (addr == r31_sp || addr == sp) return; // Stack-based target
-void MacroAssembler::shenandoah_store_check(Address dest) {
- if (! ShenandoahStoreCheck)
- return;
+ Register raddr = r8;
+ Register rval = r9;
+ Register tmp1 = r10;
+ Register tmp2 = r11;
- assert(! dest.uses(rscratch1), "invalid register");
- assert(! dest.uses(rscratch2), "invalid register");
+ RegSet to_save = RegSet::of(raddr, rval, tmp1, tmp2);
- Label done, yes;
+ // Push tmp regs and flags.
+ push(to_save, sp);
+ get_nzcv(tmp1);
+ push(RegSet::of(tmp1), sp);
- ldr(rscratch2, Address(rthread, in_bytes(JavaThread::evacuation_in_progress_offset())));
- cbnzw(rscratch2, yes);
+ mov(rval, value);
+ mov(raddr, addr);
- mov(rscratch2, ShenandoahHeap::concurrent_mark_in_progress_addr());
- Assembler::ldrw(rscratch2, Address(rscratch2));
- cbzw(rscratch2, done);
+ Label done;
- bind(yes);
+ // If not in-heap target, skip check.
+ in_heap_check(raddr, tmp1, done);
- // Check for dest in heap
- lea(rscratch2, dest);
- cbz(rscratch2, done);
- in_heap_check(rscratch2, done);
+ // Test that target oop is not in to-space.
+ shenandoah_cset_check(raddr, tmp1, tmp2, done);
- lsr(rscratch1, rscratch2, ShenandoahHeapRegion::RegionSizeShift);
- mov(rscratch2, ShenandoahHeap::in_cset_fast_test_addr());
- ldrb(rscratch2, Address(rscratch2, rscratch1));
- tbz(rscratch2, 0, done);
+ // Do value-check only when concurrent mark is in progress.
+ mov(tmp1, ShenandoahHeap::concurrent_mark_in_progress_addr());
+ ldrw(tmp1, Address(tmp1));
+ cbzw(tmp1, done);
+
+ // Null-check value.
+ cbz(rval, done);
+
+ // Test that value oop is not in to-space.
+ shenandoah_cset_check(rval, tmp1, tmp2, done);
+
+ // Failure.
+ // Pop tmp regs and flags.
+ pop(RegSet::of(tmp1), sp);
+ set_nzcv(tmp1);
+ pop(to_save, sp);
+ const char* b = NULL;
+ {
+ ResourceMark rm;
+ stringStream ss;
+ ss.print("shenandoah_store_check: %s in file: %s line: %i", msg, file, line);
+ b = code_string(ss.as_string());
+ }
+ // hlt(0);
- stop("Shenandoah: store in collection set during marking/evacuation!", &done);
- should_not_reach_here();
+ stop(b);
bind(done);
+ // Pop tmp regs and flags.
+ pop(RegSet::of(tmp1), sp);
+ set_nzcv(tmp1);
+ pop(to_save, sp);
}
-void MacroAssembler::shenandoah_store_check(Register dest) {
- if (! ShenandoahStoreCheck)
- return;
+void MacroAssembler::_shenandoah_store_addr_check(Address addr, const char* msg, const char* file, int line) {
+ _shenandoah_store_addr_check(addr.base(), msg, file, line);
+}
- assert_different_registers(rscratch1, rscratch2, dest);
+void MacroAssembler::_shenandoah_store_addr_check(Register dst, const char* msg, const char* file, int line) {
- Label done, yes;
+ if (! UseShenandoahGC || ! ShenandoahStoreCheck) return;
+ if (dst == r31_sp || dst == sp) return; // Stack-based target
- ldr(rscratch2, Address(rthread, in_bytes(JavaThread::evacuation_in_progress_offset())));
- cbnzw(rscratch2, yes);
+ Register addr = r8;
+ Register tmp1 = r9;
+ Register tmp2 = r10;
- mov(rscratch2, ShenandoahHeap::concurrent_mark_in_progress_addr());
- Assembler::ldrw(rscratch2, Address(rscratch2));
- cbzw(rscratch2, done);
+ Label done;
+ RegSet to_save = RegSet::of(addr, tmp1, tmp2);
- bind(yes);
+ // Push tmp regs and flags.
+ push(to_save, sp);
+ get_nzcv(tmp1);
+ push(RegSet::of(tmp1), sp);
- // Check for dest in heap
- cbz(dest, done);
- in_heap_check(dest, done);
+ orr(addr, zr, dst);
+ // mov(addr, dst);
- lsr(rscratch1, dest, ShenandoahHeapRegion::RegionSizeShift);
- mov(rscratch2, ShenandoahHeap::in_cset_fast_test_addr());
- ldrb(rscratch2, Address(rscratch2, rscratch1));
- tbz(rscratch2, 0, done);
+ // Check null.
+ cbz(addr, done);
- stop("Shenandoah: store in collection set during marking/evacuation!", &done);
- should_not_reach_here();
+ in_heap_check(addr, tmp1, done);
+
+ shenandoah_cset_check(addr, tmp1, tmp2, done);
+
+ // Fail.
+ // Pop tmp regs and flags.
+ pop(RegSet::of(tmp1), sp);
+ set_nzcv(tmp1);
+ pop(to_save, sp);
+ const char* b = NULL;
+ {
+ ResourceMark rm;
+ stringStream ss;
+ ss.print("shenandoah_store_check: %s in file: %s line: %i", msg, file, line);
+ b = code_string(ss.as_string());
+ }
+ // hlt(0);
+ stop(b);
+ // should_not_reach_here();
bind(done);
+ // Pop tmp regs and flags.
+ pop(RegSet::of(tmp1), sp);
+ set_nzcv(tmp1);
+ pop(to_save, sp);
+
}
< prev index next >