hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
changeset 35548 8d3afe96ffea
parent 35546 b75e269c0922
child 35913 928548a43408
child 36061 baa556050d22
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Mon Jan 11 14:23:35 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Tue Jan 12 09:19:09 2016 +0100
@@ -5426,7 +5426,7 @@
                                      Label& try_eden,
                                      Label& slow_case) {
   Register top = rax;
-  Register t1  = rcx;
+  Register t1  = rcx; // object size
   Register t2  = rsi;
   Register thread_reg = NOT_LP64(rdi) LP64_ONLY(r15_thread);
   assert_different_registers(top, thread_reg, t1, t2, /* preserve: */ rbx, rdx);
@@ -5522,12 +5522,76 @@
   addptr(top, t1);
   subptr(top, (int32_t)ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
   movptr(Address(thread_reg, in_bytes(JavaThread::tlab_end_offset())), top);
+
+  if (ZeroTLAB) {
+    // This is a fast TLAB refill, therefore the GC is not notified of it.
+    // So compiled code must fill the new TLAB with zeroes.
+    movptr(top, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset())));
+    zero_memory(top, t1, 0, t2);
+  }
+
   verify_tlab();
   jmp(retry);
 
   return thread_reg; // for use by caller
 }
 
+// Preserves the contents of address, destroys the contents length_in_bytes and temp.
+void MacroAssembler::zero_memory(Register address, Register length_in_bytes, int offset_in_bytes, Register temp) {
+  assert(address != length_in_bytes && address != temp && temp != length_in_bytes, "registers must be different");
+  assert((offset_in_bytes & (BytesPerWord - 1)) == 0, "offset must be a multiple of BytesPerWord");
+  Label done;
+
+  testptr(length_in_bytes, length_in_bytes);
+  jcc(Assembler::zero, done);
+
+  // initialize topmost word, divide index by 2, check if odd and test if zero
+  // note: for the remaining code to work, index must be a multiple of BytesPerWord
+#ifdef ASSERT
+  {
+    Label L;
+    testptr(length_in_bytes, BytesPerWord - 1);
+    jcc(Assembler::zero, L);
+    stop("length must be a multiple of BytesPerWord");
+    bind(L);
+  }
+#endif
+  Register index = length_in_bytes;
+  xorptr(temp, temp);    // use _zero reg to clear memory (shorter code)
+  if (UseIncDec) {
+    shrptr(index, 3);  // divide by 8/16 and set carry flag if bit 2 was set
+  } else {
+    shrptr(index, 2);  // use 2 instructions to avoid partial flag stall
+    shrptr(index, 1);
+  }
+#ifndef _LP64
+  // index could have not been a multiple of 8 (i.e., bit 2 was set)
+  {
+    Label even;
+    // note: if index was a multiple of 8, then it cannot
+    //       be 0 now otherwise it must have been 0 before
+    //       => if it is even, we don't need to check for 0 again
+    jcc(Assembler::carryClear, even);
+    // clear topmost word (no jump would be needed if conditional assignment worked here)
+    movptr(Address(address, index, Address::times_8, offset_in_bytes - 0*BytesPerWord), temp);
+    // index could be 0 now, must check again
+    jcc(Assembler::zero, done);
+    bind(even);
+  }
+#endif // !_LP64
+  // initialize remaining object fields: index is a multiple of 2 now
+  {
+    Label loop;
+    bind(loop);
+    movptr(Address(address, index, Address::times_8, offset_in_bytes - 1*BytesPerWord), temp);
+    NOT_LP64(movptr(Address(address, index, Address::times_8, offset_in_bytes - 2*BytesPerWord), temp);)
+    decrement(index);
+    jcc(Assembler::notZero, loop);
+  }
+
+  bind(done);
+}
+
 void MacroAssembler::incr_allocated_bytes(Register thread,
                                           Register var_size_in_bytes,
                                           int con_size_in_bytes,