--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Dec 16 17:33:08 2011 -0500
@@ -63,6 +63,8 @@
private static int CLASS_STATE_FULLY_INITIALIZED;
private static int CLASS_STATE_INITIALIZATION_ERROR;
+ private static int IS_MARKED_DEPENDENT_MASK;
+
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("instanceKlass");
arrayKlasses = new OopField(type.getOopField("_array_klasses"), Oop.getHeaderSize());
@@ -90,7 +92,7 @@
staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), Oop.getHeaderSize());
staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), Oop.getHeaderSize());
nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), Oop.getHeaderSize());
- isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), Oop.getHeaderSize());
+ miscFlags = new CIntField(type.getCIntegerField("_misc_flags"), Oop.getHeaderSize());
initState = new CIntField(type.getCIntegerField("_init_state"), Oop.getHeaderSize());
vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), Oop.getHeaderSize());
itableLen = new CIntField(type.getCIntegerField("_itable_len"), Oop.getHeaderSize());
@@ -118,6 +120,8 @@
CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("instanceKlass::fully_initialized").intValue();
CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("instanceKlass::initialization_error").intValue();
+ IS_MARKED_DEPENDENT_MASK = db.lookupIntConstant("instanceKlass::IS_MARKED_DEPENDENT").intValue();
+
}
InstanceKlass(OopHandle handle, ObjectHeap heap) {
@@ -151,7 +155,7 @@
private static CIntField staticFieldSize;
private static CIntField staticOopFieldCount;
private static CIntField nonstaticOopMapSize;
- private static CIntField isMarkedDependent;
+ private static CIntField miscFlags;
private static CIntField initState;
private static CIntField vtableLen;
private static CIntField itableLen;
@@ -333,7 +337,7 @@
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
- public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
+ public boolean getIsMarkedDependent() { return (miscFlags.getValue(this) & IS_MARKED_DEPENDENT_MASK) != 0; }
public long getVtableLen() { return vtableLen.getValue(this); }
public long getItableLen() { return itableLen.getValue(this); }
public Symbol getGenericSignature() { return getSymbol(genericSignature); }
@@ -524,7 +528,7 @@
visitor.doCInt(staticFieldSize, true);
visitor.doCInt(staticOopFieldCount, true);
visitor.doCInt(nonstaticOopMapSize, true);
- visitor.doCInt(isMarkedDependent, true);
+ visitor.doCInt(miscFlags, true);
visitor.doCInt(initState, true);
visitor.doCInt(vtableLen, true);
visitor.doCInt(itableLen, true);
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -2455,7 +2455,7 @@
op->obj()->as_register() == O0 &&
op->klass()->as_register() == G5, "must be");
if (op->init_check()) {
- __ ld(op->klass()->as_register(),
+ __ ldub(op->klass()->as_register(),
instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc),
op->tmp1()->as_register());
add_debug_info_for_null_check_here(op->stub()->info());
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -398,7 +398,7 @@
if (id == fast_new_instance_init_check_id) {
// make sure the klass is initialized
- __ ld(G5_klass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc), G3_t1);
+ __ ldub(G5_klass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc), G3_t1);
__ cmp_and_br_short(G3_t1, instanceKlass::fully_initialized, Assembler::notEqual, Assembler::pn, slow_path);
}
#ifdef ASSERT
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -3350,7 +3350,7 @@
__ ld_ptr(Rscratch, Roffset, RinstanceKlass);
// make sure klass is fully initialized:
- __ ld(RinstanceKlass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc), G3_scratch);
+ __ ldub(RinstanceKlass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc), G3_scratch);
__ cmp(G3_scratch, instanceKlass::fully_initialized);
__ br(Assembler::notEqual, false, Assembler::pn, slow_case);
__ delayed()->ld(RinstanceKlass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc), Roffset);
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -1557,7 +1557,7 @@
void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) {
if (op->init_check()) {
- __ cmpl(Address(op->klass()->as_register(),
+ __ cmpb(Address(op->klass()->as_register(),
instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)),
instanceKlass::fully_initialized);
add_debug_info_for_null_check_here(op->stub()->info());
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -1011,7 +1011,7 @@
if (id == fast_new_instance_init_check_id) {
// make sure the klass is initialized
- __ cmpl(Address(klass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)), instanceKlass::fully_initialized);
+ __ cmpb(Address(klass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)), instanceKlass::fully_initialized);
__ jcc(Assembler::notEqual, slow_path);
}
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -3188,7 +3188,7 @@
// make sure klass is initialized & doesn't have finalizer
// make sure klass is fully initialized
- __ cmpl(Address(rcx, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)), instanceKlass::fully_initialized);
+ __ cmpb(Address(rcx, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)), instanceKlass::fully_initialized);
__ jcc(Assembler::notEqual, slow_case);
// get instance_size in instanceKlass (scaled to a count of bytes)
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -3235,7 +3235,7 @@
// make sure klass is initialized & doesn't have finalizer
// make sure klass is fully initialized
- __ cmpl(Address(rsi,
+ __ cmpb(Address(rsi,
instanceKlass::init_state_offset_in_bytes() +
sizeof(oopDesc)),
instanceKlass::fully_initialized);
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -54,7 +54,7 @@
_flags = ciFlags(access_flags);
_has_finalizer = access_flags.has_finalizer();
_has_subklass = ik->subklass() != NULL;
- _init_state = (instanceKlass::ClassState)ik->get_init_state();
+ _init_state = ik->init_state();
_nonstatic_field_size = ik->nonstatic_field_size();
_has_nonstatic_fields = ik->has_nonstatic_fields();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
@@ -118,7 +118,7 @@
void ciInstanceKlass::compute_shared_init_state() {
GUARDED_VM_ENTRY(
instanceKlass* ik = get_instanceKlass();
- _init_state = (instanceKlass::ClassState)ik->get_init_state();
+ _init_state = ik->init_state();
)
}
--- a/hotspot/src/share/vm/code/dependencies.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/code/dependencies.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -1631,7 +1631,7 @@
for (ContextStream str(*this); str.next(); ) {
klassOop d = str.klass();
assert(!instanceKlass::cast(d)->is_marked_dependent(), "checking");
- instanceKlass::cast(d)->set_is_marked_dependent(true);
+ instanceKlass::cast(d)->set_is_marked_dependent();
}
}
@@ -1640,7 +1640,7 @@
// Unmark transitive interfaces
for (ContextStream str(*this); str.next(); ) {
klassOop d = str.klass();
- instanceKlass::cast(d)->set_is_marked_dependent(false);
+ instanceKlass::cast(d)->clear_is_marked_dependent();
}
}
--- a/hotspot/src/share/vm/memory/dump.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/memory/dump.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -1402,7 +1402,7 @@
instanceKlass* ik = (instanceKlass*) k;
// Link the class to cause the bytecodes to be rewritten and the
// cpcache to be created.
- if (ik->get_init_state() < instanceKlass::linked) {
+ if (ik->init_state() < instanceKlass::linked) {
ik->link_class(THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "exception in class rewriting");
}
@@ -1535,7 +1535,7 @@
// are loaded in order that the related data structures (klass,
// cpCache, Sting constants) are located together.
- if (ik->get_init_state() < instanceKlass::linked) {
+ if (ik->init_state() < instanceKlass::linked) {
ik->link_class(THREAD);
guarantee(!(HAS_PENDING_EXCEPTION), "exception in class rewriting");
}
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -208,7 +208,7 @@
// abort if someone beat us to the initialization
if (!this_oop->is_not_initialized()) return; // note: not equivalent to is_initialized()
- ClassState old_state = this_oop->_init_state;
+ ClassState old_state = this_oop->init_state();
link_class_impl(this_oop, true, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
@@ -2479,7 +2479,7 @@
bool good_state = as_klassOop()->is_shared() ? (_init_state <= state)
: (_init_state < state);
assert(good_state || state == allocated, "illegal state transition");
- _init_state = state;
+ _init_state = (u1)state;
}
#endif
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Dec 16 17:33:08 2011 -0500
@@ -230,13 +230,9 @@
int _static_oop_field_count;// number of static oop fields in this klass
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
int _java_fields_count; // The number of declared Java fields
- bool _is_marked_dependent; // used for marking during flushing and deoptimization
- bool _rewritten; // methods rewritten.
- bool _has_nonstatic_fields; // for sizing with UseCompressedOops
- bool _should_verify_class; // allow caching of preverification
+
u2 _minor_version; // minor version number of class file
u2 _major_version; // major version number of class file
- ClassState _init_state; // state of class
Thread* _init_thread; // Pointer to current thread doing initialization (to handle recusive initialization)
int _vtable_len; // length of Java vtable (in words)
int _itable_len; // length of Java itable (in words)
@@ -260,6 +256,24 @@
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
+ // Class states are defined as ClassState (see above).
+ // Place the _init_state here to utilize the unused 2-byte after
+ // _idnum_allocated_count.
+ u1 _init_state; // state of class
+
+ // Compact the following four boolean flags into 1-bit each. These four flags
+ // were defined as separate boolean fields and each was 1-byte before. Since
+ // there are 2 bytes unused after the _idnum_allocated_count field, place the
+ // _misc_flags field after _idnum_allocated_count to utilize the unused bits
+ // and save total 4-bytes.
+ enum {
+ IS_MARKED_DEPENDENT = 0x1, // used for marking during flushing and deoptimization
+ REWRITTEN = 0x2, // methods rewritten.
+ HAS_NONSTATIC_FIELDS = 0x4, // for sizing with UseCompressedOops
+ SHOULD_VERIFY_CLASS = 0x8 // allow caching of preverification
+ };
+ u1 _misc_flags;
+
// embedded Java vtable follows here
// embedded Java itables follows here
// embedded static fields follows here
@@ -269,8 +283,14 @@
friend class SystemDictionary;
public:
- bool has_nonstatic_fields() const { return _has_nonstatic_fields; }
- void set_has_nonstatic_fields(bool b) { _has_nonstatic_fields = b; }
+ bool has_nonstatic_fields() const { return (_misc_flags & HAS_NONSTATIC_FIELDS) != 0; }
+ void set_has_nonstatic_fields(bool b) {
+ if (b) {
+ _misc_flags |= HAS_NONSTATIC_FIELDS;
+ } else {
+ _misc_flags &= ~HAS_NONSTATIC_FIELDS;
+ }
+ }
// field sizes
int nonstatic_field_size() const { return _nonstatic_field_size; }
@@ -377,16 +397,24 @@
bool is_being_initialized() const { return _init_state == being_initialized; }
bool is_in_error_state() const { return _init_state == initialization_error; }
bool is_reentrant_initialization(Thread *thread) { return thread == _init_thread; }
- int get_init_state() { return _init_state; } // Useful for debugging
- bool is_rewritten() const { return _rewritten; }
+ ClassState init_state() { return (ClassState)_init_state; }
+ bool is_rewritten() const { return (_misc_flags & REWRITTEN) != 0; }
// defineClass specified verification
- bool should_verify_class() const { return _should_verify_class; }
- void set_should_verify_class(bool value) { _should_verify_class = value; }
+ bool should_verify_class() const { return (_misc_flags & SHOULD_VERIFY_CLASS) != 0; }
+ void set_should_verify_class(bool value) {
+ if (value) {
+ _misc_flags |= SHOULD_VERIFY_CLASS;
+ } else {
+ _misc_flags &= ~SHOULD_VERIFY_CLASS;
+ }
+ }
+
// marking
- bool is_marked_dependent() const { return _is_marked_dependent; }
- void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
+ bool is_marked_dependent() const { return (_misc_flags & IS_MARKED_DEPENDENT) != 0; }
+ void set_is_marked_dependent() { _misc_flags |= IS_MARKED_DEPENDENT; }
+ void clear_is_marked_dependent() { _misc_flags &= ~IS_MARKED_DEPENDENT; }
// initialization (virtuals from Klass)
bool should_be_initialized() const; // means that initialize should be called
@@ -754,9 +782,9 @@
#ifdef ASSERT
void set_init_state(ClassState state);
#else
- void set_init_state(ClassState state) { _init_state = state; }
+ void set_init_state(ClassState state) { _init_state = (u1)state; }
#endif
- void set_rewritten() { _rewritten = true; }
+ void set_rewritten() { _misc_flags |= REWRITTEN; }
void set_init_thread(Thread *thread) { _init_thread = thread; }
u2 idnum_allocated_count() const { return _idnum_allocated_count; }
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -399,7 +399,7 @@
ik->set_inner_classes(NULL);
ik->set_static_oop_field_count(0);
ik->set_nonstatic_field_size(0);
- ik->set_is_marked_dependent(false);
+ ik->clear_is_marked_dependent();
ik->set_init_state(instanceKlass::allocated);
ik->set_init_thread(NULL);
ik->set_reference_type(rt);
--- a/hotspot/src/share/vm/opto/library_call.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -2807,7 +2807,9 @@
// Serializable.class or Object[].class. The runtime will handle it.
// But we must make an explicit check for initialization.
Node* insp = basic_plus_adr(kls, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc));
- Node* inst = make_load(NULL, insp, TypeInt::INT, T_INT);
+ // Use T_BOOLEAN for instanceKlass::_init_state so the compiler
+ // can generate code to load it as unsigned byte.
+ Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN);
Node* bits = intcon(instanceKlass::fully_initialized);
Node* test = _gvn.transform( new (C, 3) SubINode(inst, bits) );
// The 'test' is non-zero if we need to take a slow path.
--- a/hotspot/src/share/vm/opto/parseHelper.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -230,7 +230,9 @@
Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
adr_node = basic_plus_adr(kls, kls, init_state_offset);
- Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT);
+ // Use T_BOOLEAN for instanceKlass::_init_state so the compiler
+ // can generate code to load it as unsigned byte.
+ Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN);
Node* being_init = _gvn.intcon(instanceKlass::being_initialized);
tst = Bool( CmpI( init_state, being_init), BoolTest::eq);
iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
--- a/hotspot/src/share/vm/runtime/mutex.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/runtime/mutex.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -527,7 +527,21 @@
void Monitor::IUnlock (bool RelaxAssert) {
assert (ILocked(), "invariant") ;
- _LockWord.Bytes[_LSBINDEX] = 0 ; // drop outer lock
+ // Conceptually we need a MEMBAR #storestore|#loadstore barrier or fence immediately
+ // before the store that releases the lock. Crucially, all the stores and loads in the
+ // critical section must be globally visible before the store of 0 into the lock-word
+ // that releases the lock becomes globally visible. That is, memory accesses in the
+ // critical section should not be allowed to bypass or overtake the following ST that
+ // releases the lock. As such, to prevent accesses within the critical section
+ // from "leaking" out, we need a release fence between the critical section and the
+ // store that releases the lock. In practice that release barrier is elided on
+ // platforms with strong memory models such as TSO.
+ //
+ // Note that the OrderAccess::storeload() fence that appears after unlock store
+ // provides for progress conditions and succession and is _not related to exclusion
+ // safety or lock release consistency.
+ OrderAccess::release_store(&_LockWord.Bytes[_LSBINDEX], 0); // drop outer lock
+
OrderAccess::storeload ();
ParkEvent * const w = _OnDeck ;
assert (RelaxAssert || w != Thread::current()->_MutexEvent, "invariant") ;
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Dec 14 20:06:21 2011 -0500
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Dec 16 17:33:08 2011 -0500
@@ -307,10 +307,10 @@
nonstatic_field(instanceKlass, _static_field_size, int) \
nonstatic_field(instanceKlass, _static_oop_field_count, int) \
nonstatic_field(instanceKlass, _nonstatic_oop_map_size, int) \
- nonstatic_field(instanceKlass, _is_marked_dependent, bool) \
+ nonstatic_field(instanceKlass, _misc_flags, u1) \
nonstatic_field(instanceKlass, _minor_version, u2) \
nonstatic_field(instanceKlass, _major_version, u2) \
- nonstatic_field(instanceKlass, _init_state, instanceKlass::ClassState) \
+ nonstatic_field(instanceKlass, _init_state, u1) \
nonstatic_field(instanceKlass, _init_thread, Thread*) \
nonstatic_field(instanceKlass, _vtable_len, int) \
nonstatic_field(instanceKlass, _itable_len, int) \
@@ -1362,6 +1362,7 @@
/* The compiler thinks this is a different type than */ \
/* unsigned short on Win32 */ \
declare_unsigned_integer_type(u2) \
+ declare_unsigned_integer_type(u1) \
declare_unsigned_integer_type(unsigned) \
\
/*****************************/ \
@@ -2385,6 +2386,7 @@
declare_constant(instanceKlass::being_initialized) \
declare_constant(instanceKlass::fully_initialized) \
declare_constant(instanceKlass::initialization_error) \
+ declare_constant(instanceKlass::IS_MARKED_DEPENDENT) \
\
/*********************************/ \
/* Symbol* - symbol max length */ \