changeset 165:437d03ea40b1

6703888: Compressed Oops: use the 32-bits gap after klass in a object Summary: Use the gap also for a narrow oop field and a boxing object value. Reviewed-by: coleenp, never
author kvn
date Wed, 21 May 2008 16:31:35 -0700
parents c436414a719e
children aaa1137c5ef4
files src/cpu/sparc/vm/sharedRuntime_sparc.cpp src/cpu/sparc/vm/sparc.ad src/cpu/x86/vm/sharedRuntime_x86_32.cpp src/cpu/x86/vm/sharedRuntime_x86_64.cpp src/share/vm/ci/ciInstanceKlass.cpp src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/javaClasses.hpp src/share/vm/gc_implementation/includeDB_gc_shared src/share/vm/oops/arrayOop.hpp src/share/vm/oops/instanceKlass.hpp src/share/vm/oops/instanceKlassKlass.cpp src/share/vm/oops/instanceOop.hpp
diffstat 13 files changed, 67 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed May 21 16:31:35 2008 -0700
@@ -2556,7 +2556,6 @@
   int total_strings = 0;
   int first_arg_to_pass = 0;
   int total_c_args = 0;
-  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
 
   // Skip the receiver as dtrace doesn't want to see it
   if( !method->is_static() ) {
@@ -2778,7 +2777,9 @@
             __ br_null(in_reg, true, Assembler::pn, skipUnbox);
             __ delayed()->mov(G0, tmp);
 
-            switch (out_sig_bt[c_arg]) {
+            BasicType bt = out_sig_bt[c_arg];
+            int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
+            switch (bt) {
                 case T_BYTE:
                   __ ldub(in_reg, box_offset, tmp); break;
                 case T_SHORT:
--- a/src/cpu/sparc/vm/sparc.ad	Wed May 21 13:46:23 2008 -0700
+++ b/src/cpu/sparc/vm/sparc.ad	Wed May 21 16:31:35 2008 -0700
@@ -5471,7 +5471,6 @@
 // Load Klass Pointer
 instruct loadKlass(iRegP dst, memory mem) %{
   match(Set dst (LoadKlass mem));
-  predicate(!n->in(MemNode::Address)->bottom_type()->is_ptr_to_narrowoop());
   ins_cost(MEMORY_REF_COST);
   size(4);
 
@@ -5490,6 +5489,7 @@
 instruct loadNKlass(iRegN dst, memory mem) %{
   match(Set dst (LoadNKlass mem));
   ins_cost(MEMORY_REF_COST);
+  size(4);
 
   format %{ "LDUW   $mem,$dst\t! compressed klass ptr" %}
 
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed May 21 16:31:35 2008 -0700
@@ -1920,7 +1920,6 @@
   int total_strings = 0;
   int first_arg_to_pass = 0;
   int total_c_args = 0;
-  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
 
   if( !method->is_static() ) {  // Pass in receiver first
     in_sig_bt[i++] = T_OBJECT;
@@ -2131,7 +2130,10 @@
           assert(dst.first()->is_stack() &&
                  (!dst.second()->is_valid() || dst.second()->is_stack()),
                  "value(s) must go into stack slots");
-          if ( out_sig_bt[c_arg] == T_LONG ) {
+
+          BasicType bt = out_sig_bt[c_arg];
+          int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
+          if ( bt == T_LONG ) {
             __ movl(rbx, Address(in_reg,
                                  box_offset + VMRegImpl::stack_slot_size));
             __ movl(Address(rsp, reg2offset_out(dst.second())), rbx);
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed May 21 16:31:35 2008 -0700
@@ -1950,7 +1950,6 @@
   int total_strings = 0;
   int first_arg_to_pass = 0;
   int total_c_args = 0;
-  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
 
   // Skip the receiver as dtrace doesn't want to see it
   if( !method->is_static() ) {
@@ -2197,8 +2196,10 @@
               __ testq(in_reg, in_reg);
               __ jcc(Assembler::zero, skipUnbox);
 
+              BasicType bt = out_sig_bt[c_arg];
+              int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
               Address src1(in_reg, box_offset);
-              if ( out_sig_bt[c_arg] == T_LONG ) {
+              if ( bt == T_LONG ) {
                 __ movq(in_reg,  src1);
                 __ movq(stack_dst, in_reg);
                 assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
@@ -2460,8 +2461,10 @@
           Label skip;
           __ testq(r, r);
           __ jcc(Assembler::equal, skip);
+          BasicType bt = out_sig_bt[c_arg];
+          int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
           Address src1(r, box_offset);
-          if ( out_sig_bt[c_arg] == T_LONG ) {
+          if ( bt == T_LONG ) {
             __ movq(r, src1);
           } else {
             __ movl(r, src1);
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Wed May 21 16:31:35 2008 -0700
@@ -392,12 +392,12 @@
   assert(!is_java_lang_Object(), "bootstrap OK");
 
   // Size in bytes of my fields, including inherited fields.
-  int fsize = nonstatic_field_size() * wordSize;
+  int fsize = nonstatic_field_size() * heapOopSize;
 
   ciInstanceKlass* super = this->super();
   GrowableArray<ciField*>* super_fields = NULL;
   if (super != NULL && super->has_nonstatic_fields()) {
-    int super_fsize  = super->nonstatic_field_size() * wordSize;
+    int super_fsize  = super->nonstatic_field_size() * heapOopSize;
     int super_flen   = super->nof_nonstatic_fields();
     super_fields = super->_nonstatic_fields;
     assert(super_flen == 0 || super_fields != NULL, "first get nof_fields");
@@ -438,7 +438,7 @@
     // This is a minor inefficiency classFileParser.cpp.
     last_offset = offset + size;
   }
-  assert(last_offset <= (int)sizeof(oopDesc) + fsize, "no overflow");
+  assert(last_offset <= (int)instanceOopDesc::base_offset_in_bytes() + fsize, "no overflow");
 #endif
 
   _nonstatic_fields = fields;
--- a/src/share/vm/classfile/classFileParser.cpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Wed May 21 16:31:35 2008 -0700
@@ -2664,8 +2664,8 @@
                                   fac.static_byte_count ), wordSize );
     static_field_size           = (next_static_type_offset -
                                   next_static_oop_offset) / wordSize;
-    first_nonstatic_field_offset = (instanceOopDesc::header_size() +
-                                    nonstatic_field_size) * wordSize;
+    first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
+                                   nonstatic_field_size * heapOopSize;
     next_nonstatic_field_offset = first_nonstatic_field_offset;
 
     // Add fake fields for java.lang.Class instances (also see below)
@@ -2734,9 +2734,9 @@
       next_nonstatic_byte_offset  = next_nonstatic_short_offset +
                                     (nonstatic_short_count * BytesPerShort);
       next_nonstatic_type_offset  = align_size_up((next_nonstatic_byte_offset +
-                                    nonstatic_byte_count ), wordSize );
+                                    nonstatic_byte_count ), heapOopSize );
       orig_nonstatic_field_size   = nonstatic_field_size +
-        ((next_nonstatic_type_offset - first_nonstatic_field_offset)/wordSize);
+      ((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize);
     }
 #endif
     bool compact_fields   = CompactFields;
@@ -2791,18 +2791,8 @@
     int nonstatic_short_space_offset;
     int nonstatic_byte_space_offset;
 
-    bool compact_into_header = (UseCompressedOops &&
-                                allocation_style == 1 && compact_fields &&
-                                !super_has_nonstatic_fields);
-
-    if( compact_into_header || nonstatic_double_count > 0 ) {
-      int offset;
-      // Pack something in with the header if no super klass has done so.
-      if (compact_into_header) {
-        offset = oopDesc::klass_gap_offset_in_bytes();
-      } else {
-        offset = next_nonstatic_double_offset;
-      }
+    if( nonstatic_double_count > 0 ) {
+      int offset = next_nonstatic_double_offset;
       next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
       if( compact_fields && offset != next_nonstatic_double_offset ) {
         // Allocate available fields into the gap before double field.
@@ -2830,8 +2820,7 @@
         }
         // Allocate oop field in the gap if there are no other fields for that.
         nonstatic_oop_space_offset = offset;
-        if(!compact_into_header && length >= heapOopSize &&
-            nonstatic_oop_count > 0 &&
+        if( length >= heapOopSize && nonstatic_oop_count > 0 &&
             allocation_style != 0 ) { // when oop fields not first
           nonstatic_oop_count      -= 1;
           nonstatic_oop_space_count = 1; // Only one will fit
@@ -2854,14 +2843,13 @@
     } else { // allocation_style == 1
       next_nonstatic_oop_offset = next_nonstatic_byte_offset + nonstatic_byte_count;
       if( nonstatic_oop_count > 0 ) {
-        notaligned_offset = next_nonstatic_oop_offset;
         next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
       }
       notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
     }
-    next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
+    next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize );
     nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset
-                                      - first_nonstatic_field_offset)/wordSize);
+                                   - first_nonstatic_field_offset)/heapOopSize);
 
     // Iterate over fields again and compute correct offsets.
     // The field allocation type was temporarily stored in the offset slot.
@@ -2962,9 +2950,10 @@
     // Size of instances
     int instance_size;
 
+    next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
     instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
 
-    assert(instance_size == align_object_size(instanceOopDesc::header_size() + nonstatic_field_size), "consistent layout helper value");
+    assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value");
 
     // Size of non-static oop map blocks (in words) allocated at end of klass
     int nonstatic_oop_map_size = compute_oop_map_size(super_klass, nonstatic_oop_map_count, first_nonstatic_oop_offset);
@@ -3122,13 +3111,15 @@
 #ifndef PRODUCT
     if( PrintCompactFieldsSavings ) {
       if( nonstatic_field_size < orig_nonstatic_field_size ) {
-        tty->print("[Saved %d of %3d words in %s]\n",
-                 orig_nonstatic_field_size - nonstatic_field_size,
-                 orig_nonstatic_field_size, this_klass->external_name());
+        tty->print("[Saved %d of %d bytes in %s]\n",
+                 (orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
+                 orig_nonstatic_field_size*heapOopSize,
+                 this_klass->external_name());
       } else if( nonstatic_field_size > orig_nonstatic_field_size ) {
-        tty->print("[Wasted %d over %3d words in %s]\n",
-                 nonstatic_field_size - orig_nonstatic_field_size,
-                 orig_nonstatic_field_size, this_klass->external_name());
+        tty->print("[Wasted %d over %d bytes in %s]\n",
+                 (nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize,
+                 orig_nonstatic_field_size*heapOopSize,
+                 this_klass->external_name());
       }
     }
 #endif
--- a/src/share/vm/classfile/javaClasses.cpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/classfile/javaClasses.cpp	Wed May 21 16:31:35 2008 -0700
@@ -1872,7 +1872,7 @@
       box->float_field_put(value_offset, value->f);
       break;
     case T_DOUBLE:
-      box->double_field_put(value_offset, value->d);
+      box->double_field_put(long_value_offset, value->d);
       break;
     case T_BYTE:
       box->byte_field_put(value_offset, value->b);
@@ -1884,7 +1884,7 @@
       box->int_field_put(value_offset, value->i);
       break;
     case T_LONG:
-      box->long_field_put(value_offset, value->j);
+      box->long_field_put(long_value_offset, value->j);
       break;
     default:
       return NULL;
@@ -1915,7 +1915,7 @@
     value->f = box->float_field(value_offset);
     break;
   case T_DOUBLE:
-    value->d = box->double_field(value_offset);
+    value->d = box->double_field(long_value_offset);
     break;
   case T_BYTE:
     value->b = box->byte_field(value_offset);
@@ -1927,7 +1927,7 @@
     value->i = box->int_field(value_offset);
     break;
   case T_LONG:
-    value->j = box->long_field(value_offset);
+    value->j = box->long_field(long_value_offset);
     break;
   default:
     return T_ILLEGAL;
@@ -1949,7 +1949,7 @@
     box->float_field_put(value_offset, value->f);
     break;
   case T_DOUBLE:
-    box->double_field_put(value_offset, value->d);
+    box->double_field_put(long_value_offset, value->d);
     break;
   case T_BYTE:
     box->byte_field_put(value_offset, value->b);
@@ -1961,7 +1961,7 @@
     box->int_field_put(value_offset, value->i);
     break;
   case T_LONG:
-    box->long_field_put(value_offset, value->j);
+    box->long_field_put(long_value_offset, value->j);
     break;
   default:
     return T_ILLEGAL;
@@ -2163,6 +2163,7 @@
 int java_lang_reflect_Field::signature_offset;
 int java_lang_reflect_Field::annotations_offset;
 int java_lang_boxing_object::value_offset;
+int java_lang_boxing_object::long_value_offset;
 int java_lang_ref_Reference::referent_offset;
 int java_lang_ref_Reference::queue_offset;
 int java_lang_ref_Reference::next_offset;
@@ -2282,10 +2283,7 @@
 // are not available to determine the offset_of_static_fields.
 void JavaClasses::compute_hard_coded_offsets() {
   const int x = heapOopSize;
-  // Objects don't get allocated in the gap in the header with compressed oops
-  // for these special classes because hard coded offsets can't be conditional
-  // so base_offset_in_bytes() is wrong here, allocate after the header.
-  const int header = sizeof(instanceOopDesc);
+  const int header = instanceOopDesc::base_offset_in_bytes();
 
   // Do the String Class
   java_lang_String::value_offset  = java_lang_String::hc_value_offset  * x + header;
@@ -2308,7 +2306,8 @@
   java_lang_Throwable::stackTrace_offset = java_lang_Throwable::hc_stackTrace_offset * x + header;
 
   // java_lang_boxing_object
-  java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset * x + header;
+  java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset + header;
+  java_lang_boxing_object::long_value_offset = align_size_up((java_lang_boxing_object::hc_value_offset + header), BytesPerLong);
 
   // java_lang_ref_Reference:
   java_lang_ref_Reference::referent_offset = java_lang_ref_Reference::hc_referent_offset * x + header;
@@ -2322,7 +2321,7 @@
   java_lang_ref_Reference::number_of_fake_oop_fields = 1;
 
   // java_lang_ref_SoftReference Class
-  java_lang_ref_SoftReference::timestamp_offset = java_lang_ref_SoftReference::hc_timestamp_offset * x + header;
+  java_lang_ref_SoftReference::timestamp_offset = align_size_up((java_lang_ref_SoftReference::hc_timestamp_offset * x + header), BytesPerLong);
   // Don't multiply static fields because they are always in wordSize units
   java_lang_ref_SoftReference::static_clock_offset = java_lang_ref_SoftReference::hc_static_clock_offset * x;
 
@@ -2469,6 +2468,9 @@
 #define CHECK_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
   valid &= check_offset(klass_name, cpp_klass_name :: field_name ## _offset, #field_name, field_sig)
 
+#define CHECK_LONG_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
+  valid &= check_offset(klass_name, cpp_klass_name :: long_ ## field_name ## _offset, #field_name, field_sig)
+
 #define CHECK_STATIC_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
   valid &= check_static_offset(klass_name, cpp_klass_name :: static_ ## field_name ## _offset, #field_name, field_sig)
 
@@ -2501,11 +2503,11 @@
   CHECK_OFFSET("java/lang/Boolean",   java_lang_boxing_object, value, "Z");
   CHECK_OFFSET("java/lang/Character", java_lang_boxing_object, value, "C");
   CHECK_OFFSET("java/lang/Float",     java_lang_boxing_object, value, "F");
-  CHECK_OFFSET("java/lang/Double",    java_lang_boxing_object, value, "D");
+  CHECK_LONG_OFFSET("java/lang/Double", java_lang_boxing_object, value, "D");
   CHECK_OFFSET("java/lang/Byte",      java_lang_boxing_object, value, "B");
   CHECK_OFFSET("java/lang/Short",     java_lang_boxing_object, value, "S");
   CHECK_OFFSET("java/lang/Integer",   java_lang_boxing_object, value, "I");
-  CHECK_OFFSET("java/lang/Long",      java_lang_boxing_object, value, "J");
+  CHECK_LONG_OFFSET("java/lang/Long", java_lang_boxing_object, value, "J");
 
   // java.lang.ClassLoader
 
--- a/src/share/vm/classfile/javaClasses.hpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/classfile/javaClasses.hpp	Wed May 21 16:31:35 2008 -0700
@@ -653,6 +653,7 @@
    hc_value_offset = 0
   };
   static int value_offset;
+  static int long_value_offset;
 
   static oop initialize_and_allocate(BasicType type, TRAPS);
  public:
@@ -665,7 +666,10 @@
   static bool is_instance(oop box)                 { return basic_type(box) != T_ILLEGAL; }
   static bool is_instance(oop box, BasicType type) { return basic_type(box) == type; }
 
-  static int value_offset_in_bytes() { return value_offset; }
+  static int value_offset_in_bytes(BasicType type) {
+    return ( type == T_LONG || type == T_DOUBLE ) ? long_value_offset :
+                                                    value_offset;
+  }
 
   // Debugging
   friend class JavaClasses;
@@ -747,7 +751,7 @@
  public:
   enum {
    // The timestamp is a long field and may need to be adjusted for alignment.
-   hc_timestamp_offset    = align_object_offset_(hc_discovered_offset + 1)
+   hc_timestamp_offset  = hc_discovered_offset + 1
   };
   enum {
    hc_static_clock_offset = 0
--- a/src/share/vm/gc_implementation/includeDB_gc_shared	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/gc_implementation/includeDB_gc_shared	Wed May 21 16:31:35 2008 -0700
@@ -54,6 +54,7 @@
 markSweep.inline.hpp                    psParallelCompact.hpp
 
 mutableNUMASpace.cpp                    mutableNUMASpace.hpp
+mutableNUMASpace.cpp                    oop.inline.hpp
 mutableNUMASpace.cpp                    sharedHeap.hpp
 mutableNUMASpace.cpp                    thread_<os_family>.inline.hpp
 
--- a/src/share/vm/oops/arrayOop.hpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/oops/arrayOop.hpp	Wed May 21 16:31:35 2008 -0700
@@ -41,11 +41,10 @@
   // Header size computation.
   // The header is considered the oop part of this type plus the length.
   // Returns the aligned header_size_in_bytes.  This is not equivalent to
-  // sizeof(arrayOopDesc) which should not appear in the code, except here.
+  // sizeof(arrayOopDesc) which should not appear in the code.
   static int header_size_in_bytes() {
-    size_t hs = UseCompressedOops ?
-            sizeof(arrayOopDesc) :
-            align_size_up(sizeof(arrayOopDesc) + sizeof(int), HeapWordSize);
+    size_t hs = align_size_up(length_offset_in_bytes() + sizeof(int),
+                              HeapWordSize);
 #ifdef ASSERT
     // make sure it isn't called before UseCompressedOops is initialized.
     static size_t arrayoopdesc_hs = 0;
--- a/src/share/vm/oops/instanceKlass.hpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/oops/instanceKlass.hpp	Wed May 21 16:31:35 2008 -0700
@@ -180,9 +180,8 @@
   // End of the oop block.
   //
 
-  // number of words used by non-static fields in this klass (including
-  // inherited fields but after header_size()).  If fields are compressed into
-  // header, this can be zero so it's not the same as number of static fields.
+  // Number of heapOopSize words used by non-static fields in this klass
+  // (including inherited fields but after header_size()).
   int             _nonstatic_field_size;
   int             _static_field_size;    // number words used by static fields (oop and non-oop) in this klass
   int             _static_oop_field_size;// number of static oop fields in this klass
--- a/src/share/vm/oops/instanceKlassKlass.cpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/oops/instanceKlassKlass.cpp	Wed May 21 16:31:35 2008 -0700
@@ -581,7 +581,7 @@
   OopMapBlock* map     = ik->start_of_nonstatic_oop_maps();
   OopMapBlock* end_map = map + ik->nonstatic_oop_map_size();
   while (map < end_map) {
-    st->print("%d-%d ", map->offset(), map->offset() + oopSize*(map->length() - 1));
+    st->print("%d-%d ", map->offset(), map->offset() + heapOopSize*(map->length() - 1));
     map++;
   }
   st->cr();
--- a/src/share/vm/oops/instanceOop.hpp	Wed May 21 13:46:23 2008 -0700
+++ b/src/share/vm/oops/instanceOop.hpp	Wed May 21 16:31:35 2008 -0700
@@ -39,14 +39,7 @@
 
   static bool contains_field_offset(int offset, int nonstatic_field_size) {
     int base_in_bytes = base_offset_in_bytes();
-    if (UseCompressedOops) {
-      return (offset >= base_in_bytes &&
-              // field can be embedded in header, or is after header.
-              (offset < (int)sizeof(instanceOopDesc) ||
-              (offset-(int)sizeof(instanceOopDesc))/wordSize < nonstatic_field_size));
-    } else {
-      return (offset >= base_in_bytes &&
-              (offset-base_in_bytes)/wordSize < nonstatic_field_size);
-    }
+    return (offset >= base_in_bytes &&
+            (offset-base_in_bytes) < nonstatic_field_size * heapOopSize);
   }
 };