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
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/cpu/sparc/vm/sparc.ad Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/classfile/classFileParser.cpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/classfile/javaClasses.cpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/classfile/javaClasses.hpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/oops/arrayOop.hpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/oops/instanceKlass.hpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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/hotspot/src/share/vm/oops/instanceOop.hpp Wed May 21 13:46:23 2008 -0700
+++ b/hotspot/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);
}
};