# HG changeset patch # User kvn # Date 1211412695 25200 # Node ID 437d03ea40b15504113acc482831c589004c55f6 # Parent c436414a719efa0661d9a22688402e6784c02657 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 diff -r c436414a719e -r 437d03ea40b1 src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- 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: diff -r c436414a719e -r 437d03ea40b1 src/cpu/sparc/vm/sparc.ad --- 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" %} diff -r c436414a719e -r 437d03ea40b1 src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- 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); diff -r c436414a719e -r 437d03ea40b1 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- 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); diff -r c436414a719e -r 437d03ea40b1 src/share/vm/ci/ciInstanceKlass.cpp --- 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* 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; diff -r c436414a719e -r 437d03ea40b1 src/share/vm/classfile/classFileParser.cpp --- 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 diff -r c436414a719e -r 437d03ea40b1 src/share/vm/classfile/javaClasses.cpp --- 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 diff -r c436414a719e -r 437d03ea40b1 src/share/vm/classfile/javaClasses.hpp --- 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 diff -r c436414a719e -r 437d03ea40b1 src/share/vm/gc_implementation/includeDB_gc_shared --- 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_.inline.hpp diff -r c436414a719e -r 437d03ea40b1 src/share/vm/oops/arrayOop.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; diff -r c436414a719e -r 437d03ea40b1 src/share/vm/oops/instanceKlass.hpp --- 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 diff -r c436414a719e -r 437d03ea40b1 src/share/vm/oops/instanceKlassKlass.cpp --- 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(); diff -r c436414a719e -r 437d03ea40b1 src/share/vm/oops/instanceOop.hpp --- 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); } };