diff src/cpu/x86/vm/assembler_x86.cpp @ 6725:da91efe96a93

6964458: Reimplement class meta-data storage to use native memory Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author coleenp
date Sat, 01 Sep 2012 13:25:18 -0400
parents 006050192a5a
children 137868b7aa6f
line wrap: on
line diff
--- a/src/cpu/x86/vm/assembler_x86.cpp	Fri Aug 31 16:39:35 2012 -0700
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Sat Sep 01 13:25:18 2012 -0400
@@ -57,6 +57,7 @@
   _target = target;
   switch (rtype) {
   case relocInfo::oop_type:
+  case relocInfo::metadata_type:
     // Oops are a special case. Normally they would be their own section
     // but in cases like icBuffer they are literals in the code stream that
     // we don't have a section for. We use none so that we get a literal address
@@ -154,10 +155,10 @@
 // Convert the raw encoding form into the form expected by the constructor for
 // Address.  An index of 4 (rsp) corresponds to having no index, so convert
 // that to noreg for the Address constructor.
-Address Address::make_raw(int base, int index, int scale, int disp, bool disp_is_oop) {
+Address Address::make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc) {
   RelocationHolder rspec;
-  if (disp_is_oop) {
-    rspec = Relocation::spec_simple(relocInfo::oop_type);
+  if (disp_reloc != relocInfo::none) {
+    rspec = Relocation::spec_simple(disp_reloc);
   }
   bool valid_index = index != rsp->encoding();
   if (valid_index) {
@@ -270,17 +271,6 @@
   }
 }
 
-void Assembler::emit_arith(int op1, int op2, Register dst, jobject obj) {
-  LP64_ONLY(ShouldNotReachHere());
-  assert(isByte(op1) && isByte(op2), "wrong opcode");
-  assert((op1 & 0x01) == 1, "should be 32bit operation");
-  assert((op1 & 0x02) == 0, "sign-extension bit should not be set");
-  InstructionMark im(this);
-  emit_byte(op1);
-  emit_byte(op2 | encode(dst));
-  emit_data((intptr_t)obj, relocInfo::oop_type, 0);
-}
-
 
 void Assembler::emit_arith(int op1, int op2, Register dst, Register src) {
   assert(isByte(op1) && isByte(op2), "wrong opcode");
@@ -5572,6 +5562,14 @@
   increment(rsp, number_of_arguments * wordSize);
 }
 
+void MacroAssembler::cmpklass(Address src1, Metadata* obj) {
+  cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate());
+}
+
+void MacroAssembler::cmpklass(Register src1, Metadata* obj) {
+  cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate());
+}
+
 void MacroAssembler::cmpoop(Address src1, jobject obj) {
   cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate());
 }
@@ -5753,6 +5751,14 @@
   mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate());
 }
 
+void MacroAssembler::mov_metadata(Register dst, Metadata* obj) {
+  mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate());
+}
+
+void MacroAssembler::mov_metadata(Address dst, Metadata* obj) {
+  mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate());
+}
+
 void MacroAssembler::movptr(Register dst, AddressLiteral src) {
   if (src.is_lval()) {
     mov_literal32(dst, (intptr_t)src.target(), src.rspec());
@@ -5804,6 +5810,9 @@
   push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate());
 }
 
+void MacroAssembler::pushklass(Metadata* obj) {
+  push_literal32((int32_t)obj, metadata_Relocation::spec_for_immediate());
+}
 
 void MacroAssembler::pushptr(AddressLiteral src) {
   if (src.is_lval()) {
@@ -5856,13 +5865,13 @@
     if (os::message_box(msg, "Execution stopped, print registers?")) {
       print_state32(rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax, eip);
       BREAKPOINT;
-      assert(false, "start up GDB");
     }
   } else {
     ttyLocker ttyl;
     ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg);
+  }
+  // Don't assert holding the ttyLock
     assert(false, err_msg("DEBUG MESSAGE: %s", msg));
-  }
   ThreadStateTransition::transition(thread, _thread_in_vm, saved_state);
 }
 
@@ -6280,6 +6289,15 @@
   movq(dst, rscratch1);
 }
 
+void MacroAssembler::mov_metadata(Register dst, Metadata* obj) {
+  mov_literal64(dst, (intptr_t)obj, metadata_Relocation::spec_for_immediate());
+}
+
+void MacroAssembler::mov_metadata(Address dst, Metadata* obj) {
+  mov_literal64(rscratch1, (intptr_t)obj, metadata_Relocation::spec_for_immediate());
+  movq(dst, rscratch1);
+}
+
 void MacroAssembler::movptr(Register dst, AddressLiteral src) {
   if (src.is_lval()) {
     mov_literal64(dst, (intptr_t)src.target(), src.rspec());
@@ -6321,6 +6339,11 @@
   push(rscratch1);
 }
 
+void MacroAssembler::pushklass(Metadata* obj) {
+  mov_metadata(rscratch1, obj);
+  push(rscratch1);
+}
+
 void MacroAssembler::pushptr(AddressLiteral src) {
   lea(rscratch1, src);
   if (src.is_lval()) {
@@ -6655,6 +6678,12 @@
   }
 }
 
+void MacroAssembler::ic_call(address entry) {
+  RelocationHolder rh = virtual_call_Relocation::spec(pc());
+  movptr(rax, (intptr_t)Universe::non_oop_word());
+  call(AddressLiteral(entry, rh));
+}
+
 // Implementation of call_VM versions
 
 void MacroAssembler::call_VM(Register oop_result,
@@ -6923,9 +6952,7 @@
 
   // get oop result if there is one and reset the value in the thread
   if (oop_result->is_valid()) {
-    movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset()));
-    movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD);
-    verify_oop(oop_result, "broken oop in call_VM_base");
+    get_vm_result(oop_result, java_thread);
   }
 }
 
@@ -7016,6 +7043,17 @@
   MacroAssembler::call_VM_leaf_base(entry_point, 4);
 }
 
+void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) {
+  movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset()));
+  movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD);
+  verify_oop(oop_result, "broken oop in call_VM_base");
+}
+
+void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) {
+  movptr(metadata_result, Address(java_thread, JavaThread::vm_result_2_offset()));
+  movptr(Address(java_thread, JavaThread::vm_result_2_offset()), NULL_WORD);
+}
+
 void MacroAssembler::check_and_handle_earlyret(Register java_thread) {
 }
 
@@ -9097,20 +9135,20 @@
          "caller must use same register for non-constant itable index as for method");
 
   // Compute start of first itableOffsetEntry (which is at the end of the vtable)
-  int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
+  int vtable_base = InstanceKlass::vtable_start_offset() * wordSize;
   int itentry_off = itableMethodEntry::method_offset_in_bytes();
   int scan_step   = itableOffsetEntry::size() * wordSize;
   int vte_size    = vtableEntry::size() * wordSize;
   Address::ScaleFactor times_vte_scale = Address::times_ptr;
   assert(vte_size == wordSize, "else adjust times_vte_scale");
 
-  movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize));
+  movl(scan_temp, Address(recv_klass, InstanceKlass::vtable_length_offset() * wordSize));
 
   // %%% Could store the aligned, prescaled offset in the klassoop.
   lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
   if (HeapWordsPerLong > 1) {
     // Round up to align_object_offset boundary
-    // see code for instanceKlass::start_of_itable!
+    // see code for InstanceKlass::start_of_itable!
     round_to(scan_temp, BytesPerLong);
   }
 
@@ -9160,7 +9198,7 @@
 void MacroAssembler::lookup_virtual_method(Register recv_klass,
                                            RegisterOrConstant vtable_index,
                                            Register method_result) {
-  const int base = instanceKlass::vtable_start_offset() * wordSize;
+  const int base = InstanceKlass::vtable_start_offset() * wordSize;
   assert(vtableEntry::size() * wordSize == wordSize, "else adjust the scaling in the code below");
   Address vtable_entry_addr(recv_klass,
                             vtable_index, Address::times_ptr,
@@ -9335,33 +9373,19 @@
   // We will consult the secondary-super array.
   movptr(rdi, secondary_supers_addr);
   // Load the array length.  (Positive movl does right thing on LP64.)
-  movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
+  movl(rcx, Address(rdi, Array<Klass*>::length_offset_in_bytes()));
   // Skip to start of data.
-  addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
+  addptr(rdi, Array<Klass*>::base_offset_in_bytes());
 
   // Scan RCX words at [RDI] for an occurrence of RAX.
   // Set NZ/Z based on last compare.
   // Z flag value will not be set by 'repne' if RCX == 0 since 'repne' does
   // not change flags (only scas instruction which is repeated sets flags).
   // Set Z = 0 (not equal) before 'repne' to indicate that class was not found.
-#ifdef _LP64
-  // This part is tricky, as values in supers array could be 32 or 64 bit wide
-  // and we store values in objArrays always encoded, thus we need to encode
-  // the value of rax before repne.  Note that rax is dead after the repne.
-  if (UseCompressedOops) {
-    encode_heap_oop_not_null(rax); // Changes flags.
-    // The superclass is never null; it would be a basic system error if a null
-    // pointer were to sneak in here.  Note that we have already loaded the
-    // Klass::super_check_offset from the super_klass in the fast path,
-    // so if there is a null in that register, we are already in the afterlife.
-    testl(rax,rax); // Set Z = 0
-    repne_scanl();
-  } else
-#endif // _LP64
-  {
+
     testptr(rax,rax); // Set Z = 0
     repne_scan();
-  }
+
   // Unspill the temp. registers:
   if (pushed_rdi)  pop(rdi);
   if (pushed_rcx)  pop(rcx);
@@ -9907,7 +9931,7 @@
 
 void MacroAssembler::load_klass(Register dst, Register src) {
 #ifdef _LP64
-  if (UseCompressedOops) {
+  if (UseCompressedKlassPointers) {
     movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
     decode_heap_oop_not_null(dst);
   } else
@@ -9917,7 +9941,7 @@
 
 void MacroAssembler::load_prototype_header(Register dst, Register src) {
 #ifdef _LP64
-  if (UseCompressedOops) {
+  if (UseCompressedKlassPointers) {
     assert (Universe::heap() != NULL, "java heap should be initialized");
     movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
     if (Universe::narrow_oop_shift() != 0) {
@@ -9942,7 +9966,7 @@
 
 void MacroAssembler::store_klass(Register dst, Register src) {
 #ifdef _LP64
-  if (UseCompressedOops) {
+  if (UseCompressedKlassPointers) {
     encode_heap_oop_not_null(src);
     movl(Address(dst, oopDesc::klass_offset_in_bytes()), src);
   } else
@@ -9952,6 +9976,7 @@
 
 void MacroAssembler::load_heap_oop(Register dst, Address src) {
 #ifdef _LP64
+  // FIXME: Must change all places where we try to load the klass.
   if (UseCompressedOops) {
     movl(dst, src);
     decode_heap_oop(dst);
@@ -10016,7 +10041,7 @@
 
 #ifdef _LP64
 void MacroAssembler::store_klass_gap(Register dst, Register src) {
-  if (UseCompressedOops) {
+  if (UseCompressedKlassPointers) {
     // Store to klass gap in destination
     movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src);
   }