< 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 >