hotspot/src/cpu/x86/vm/assembler_x86_64.cpp
changeset 360 21d113ecbf6a
parent 249 8a8601fb5571
child 365 01d8c42b8e6d
--- a/hotspot/src/cpu/x86/vm/assembler_x86_64.cpp	Fri Apr 11 09:56:35 2008 -0400
+++ b/hotspot/src/cpu/x86/vm/assembler_x86_64.cpp	Sun Apr 13 17:43:42 2008 -0400
@@ -127,6 +127,7 @@
 
 bool Assembler::reachable(AddressLiteral adr) {
   int64_t disp;
+
   // None will force a 64bit literal to the code stream. Likely a placeholder
   // for something that will be patched later and we need to certain it will
   // always be reachable.
@@ -636,7 +637,7 @@
   case 0x8A: // movb r, a
   case 0x8B: // movl r, a
   case 0x8F: // popl a
-    debug_only(has_disp32 = true);
+    debug_only(has_disp32 = true;)
     break;
 
   case 0x68: // pushq #32
@@ -2891,7 +2892,7 @@
 }
 
 // scans rcx double words (m64) at [rdi] for occurance of rax
-void Assembler::repne_scan() {
+void Assembler::repne_scanq() {
   // REPNE/REPNZ
   emit_byte(0xF2);
   // SCASQ
@@ -2899,6 +2900,14 @@
   emit_byte(0xAF);
 }
 
+void Assembler::repne_scanl() {
+  // REPNE/REPNZ
+  emit_byte(0xF2);
+  // SCASL
+  emit_byte(0xAF);
+}
+
+
 void Assembler::setb(Condition cc, Register dst) {
   assert(0 <= cc && cc < 16, "illegal cc");
   int encode = prefix_and_encode(dst->encoding(), true);
@@ -4597,7 +4606,6 @@
 
   // pass args on stack, only touch rax
   pushq(reg);
-
   // avoid using pushptr, as it modifies scratch registers
   // and our contract is not to modify anything
   ExternalAddress buffer((address)b);
@@ -4664,9 +4672,9 @@
     JavaThread* thread = JavaThread::current();
     JavaThreadState saved_state = thread->thread_state();
     thread->set_thread_state(_thread_in_vm);
-    ttyLocker ttyl;
 #ifndef PRODUCT
     if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
+      ttyLocker ttyl;
       BytecodeCounter::print();
     }
 #endif
@@ -4674,6 +4682,7 @@
     // XXX correct this offset for amd64
     // This is the value of eip which points to where verify_oop will return.
     if (os::message_box(msg, "Execution stopped, print registers?")) {
+      ttyLocker ttyl;
       tty->print_cr("rip = 0x%016lx", pc);
       tty->print_cr("rax = 0x%016lx", regs[15]);
       tty->print_cr("rbx = 0x%016lx", regs[12]);
@@ -4695,6 +4704,7 @@
     }
     ThreadStateTransition::transition(thread, _thread_in_vm, saved_state);
   } else {
+    ttyLocker ttyl;
     ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n",
                     msg);
   }
@@ -4891,7 +4901,7 @@
   movq(Address(top, arrayOopDesc::length_offset_in_bytes()), t1);
   // set klass to intArrayKlass
   movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr()));
-  movq(Address(top, oopDesc::klass_offset_in_bytes()), t1);
+  store_klass(top, t1);
 
   // refill the tlab with an eden allocation
   bind(do_refill);
@@ -4938,7 +4948,6 @@
   assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg);
   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);
 
   if (PrintBiasedLockingStatistics && counters == NULL)
@@ -4962,7 +4971,7 @@
   jcc(Assembler::notEqual, cas_label);
   // The bias pattern is present in the object's header. Need to check
   // whether the bias owner and the epoch are both still current.
-  movq(tmp_reg, klass_addr);
+  load_klass(tmp_reg, obj_reg);
   movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
   orq(tmp_reg, r15_thread);
   xorq(tmp_reg, swap_reg);
@@ -5037,7 +5046,7 @@
   //
   // FIXME: due to a lack of registers we currently blow away the age
   // bits in this situation. Should attempt to preserve them.
-  movq(tmp_reg, klass_addr);
+  load_klass(tmp_reg, obj_reg);
   movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
   orq(tmp_reg, r15_thread);
   if (os::is_MP()) {
@@ -5068,7 +5077,7 @@
   //
   // FIXME: due to a lack of registers we currently blow away the age
   // bits in this situation. Should attempt to preserve them.
-  movq(tmp_reg, klass_addr);
+  load_klass(tmp_reg, obj_reg);
   movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
   if (os::is_MP()) {
     lock();
@@ -5104,6 +5113,113 @@
 }
 
 
+void MacroAssembler::load_klass(Register dst, Register src) {
+  if (UseCompressedOops) {
+    movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
+    decode_heap_oop_not_null(dst);
+  } else {
+    movq(dst, Address(src, oopDesc::klass_offset_in_bytes()));
+  }
+}
+
+void MacroAssembler::store_klass(Register dst, Register src) {
+  if (UseCompressedOops) {
+    encode_heap_oop_not_null(src);
+    // zero the entire klass field first as the gap needs to be zeroed too.
+    movptr(Address(dst, oopDesc::klass_offset_in_bytes()), NULL_WORD);
+    movl(Address(dst, oopDesc::klass_offset_in_bytes()), src);
+  } else {
+    movq(Address(dst, oopDesc::klass_offset_in_bytes()), src);
+  }
+}
+
+void MacroAssembler::load_heap_oop(Register dst, Address src) {
+  if (UseCompressedOops) {
+    movl(dst, src);
+    decode_heap_oop(dst);
+  } else {
+    movq(dst, src);
+  }
+}
+
+void MacroAssembler::store_heap_oop(Address dst, Register src) {
+  if (UseCompressedOops) {
+    assert(!dst.uses(src), "not enough registers");
+    encode_heap_oop(src);
+    movl(dst, src);
+  } else {
+    movq(dst, src);
+  }
+}
+
+// Algorithm must match oop.inline.hpp encode_heap_oop.
+void MacroAssembler::encode_heap_oop(Register r) {
+  assert (UseCompressedOops, "should be compressed");
+#ifdef ASSERT
+  Label ok;
+  pushq(rscratch1); // cmpptr trashes rscratch1
+  cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr()));
+  jcc(Assembler::equal, ok);
+  stop("MacroAssembler::encode_heap_oop: heap base corrupted?");
+  bind(ok);
+  popq(rscratch1);
+#endif
+  verify_oop(r);
+  testq(r, r);
+  cmovq(Assembler::equal, r, r12_heapbase);
+  subq(r, r12_heapbase);
+  shrq(r, LogMinObjAlignmentInBytes);
+}
+
+void MacroAssembler::encode_heap_oop_not_null(Register r) {
+  assert (UseCompressedOops, "should be compressed");
+#ifdef ASSERT
+  Label ok;
+  testq(r, r);
+  jcc(Assembler::notEqual, ok);
+  stop("null oop passed to encode_heap_oop_not_null");
+  bind(ok);
+#endif
+  verify_oop(r);
+  subq(r, r12_heapbase);
+  shrq(r, LogMinObjAlignmentInBytes);
+}
+
+void  MacroAssembler::decode_heap_oop(Register r) {
+  assert (UseCompressedOops, "should be compressed");
+#ifdef ASSERT
+  Label ok;
+  pushq(rscratch1);
+  cmpptr(r12_heapbase,
+         ExternalAddress((address)Universe::heap_base_addr()));
+  jcc(Assembler::equal, ok);
+  stop("MacroAssembler::decode_heap_oop: heap base corrupted?");
+  bind(ok);
+  popq(rscratch1);
+#endif
+
+  Label done;
+  shlq(r, LogMinObjAlignmentInBytes);
+  jccb(Assembler::equal, done);
+  addq(r, r12_heapbase);
+#if 0
+   // alternate decoding probably a wash.
+   testq(r, r);
+   jccb(Assembler::equal, done);
+   leaq(r, Address(r12_heapbase, r, Address::times_8, 0));
+#endif
+  bind(done);
+  verify_oop(r);
+}
+
+void  MacroAssembler::decode_heap_oop_not_null(Register r) {
+  assert (UseCompressedOops, "should only be used for compressed headers");
+  // Cannot assert, unverified entry point counts instructions (see .ad file)
+  // vtableStubs also counts instructions in pd_code_size_limit.
+  assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong");
+  leaq(r, Address(r12_heapbase, r, Address::times_8, 0));
+}
+
 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
   switch (cond) {
     // Note some conditions are synonyms for others
@@ -5173,3 +5289,9 @@
     movq(Address(tmp, (-i*os::vm_page_size())), size );
   }
 }
+
+void MacroAssembler::reinit_heapbase() {
+  if (UseCompressedOops) {
+    movptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr()));
+  }
+}