6703888: Compressed Oops: use the 32-bits gap after klass in a object

Use the gap also for a narrow oop field and a boxing object value.

Reviewed-by: coleenp, never
This commit is contained in:
Vladimir Kozlov 2008-05-21 16:31:35 -07:00
parent 76035424de
commit e53e767d88
13 changed files with 67 additions and 72 deletions

View File

@ -2556,7 +2556,6 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(
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 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(
__ 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:

View File

@ -5471,7 +5471,6 @@ instruct loadN(iRegN dst, memory mem) %{
// 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 loadKlass(iRegP dst, memory mem) %{
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" %}

View File

@ -1920,7 +1920,6 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(
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 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(
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);

View File

@ -1950,7 +1950,6 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(MacroAssembler *masm,
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 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(MacroAssembler *masm,
__ 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 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(MacroAssembler *masm,
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);

View File

@ -392,12 +392,12 @@ int ciInstanceKlass::compute_nonstatic_fields() {
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 @@ int ciInstanceKlass::compute_nonstatic_fields() {
// 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;

View File

@ -2664,8 +2664,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
}
// 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
} 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
// 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
#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

View File

@ -1872,7 +1872,7 @@ oop java_lang_boxing_object::create(BasicType type, jvalue* value, TRAPS) {
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 @@ oop java_lang_boxing_object::create(BasicType type, jvalue* value, TRAPS) {
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 @@ BasicType java_lang_boxing_object::get_value(oop box, jvalue* value) {
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 @@ BasicType java_lang_boxing_object::get_value(oop box, jvalue* value) {
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 @@ BasicType java_lang_boxing_object::set_value(oop box, jvalue* value) {
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 @@ BasicType java_lang_boxing_object::set_value(oop box, jvalue* value) {
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::modifiers_offset;
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 @@ oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(
// 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 @@ void JavaClasses::compute_hard_coded_offsets() {
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 @@ void JavaClasses::compute_hard_coded_offsets() {
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 @@ void JavaClasses::check_offsets() {
#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 @@ void JavaClasses::check_offsets() {
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

View File

@ -653,6 +653,7 @@ class java_lang_boxing_object: AllStatic {
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 @@ class java_lang_boxing_object: AllStatic {
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 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
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

View File

@ -54,6 +54,7 @@ isGCActiveMark.hpp parallelScavengeHeap.hpp
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

View File

@ -41,11 +41,10 @@ class arrayOopDesc : public oopDesc {
// 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;

View File

@ -180,9 +180,8 @@ class instanceKlass: public Klass {
// 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

View File

@ -581,7 +581,7 @@ void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) {
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();

View File

@ -39,14 +39,7 @@ class instanceOopDesc : public oopDesc {
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);
}
};