< prev index next > src/hotspot/share/runtime/synchronizer.cpp
Print this page
#include "utilities/align.hpp"
#include "utilities/concurrentHashTable.inline.hpp"
#include "utilities/concurrentHashTableTasks.inline.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
+ #include "utilities/fastHash.hpp"
#include "utilities/globalCounter.inline.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/linkedlist.hpp"
#include "utilities/preserveException.hpp"
// (objects allocated back-to-back, in particular). This could potentially
// result in hashtable collisions and reduced hashtable efficiency.
// There are simple ways to "diffuse" the middle address bits over the
// generated hashCode values:
- static intptr_t get_next_hash(Thread* current, oop obj) {
+ intptr_t ObjectSynchronizer::get_next_hash(Thread* current, oop obj) {
intptr_t value = 0;
if (hashCode == 0) {
// This form uses global Park-Miller RNG.
// On MP system we'll have lots of RW access to a global, so the
// mechanism induces lots of coherency traffic.
value = 1; // for sensitivity testing
} else if (hashCode == 3) {
value = ++GVars.hc_sequence;
} else if (hashCode == 4) {
value = cast_from_oop<intptr_t>(obj);
- } else {
+ } else if (hashCode == 5) {
// Marsaglia's xor-shift scheme with thread-specific state
// This is probably the best overall implementation -- we'll
// likely make this the default in future releases.
unsigned t = current->_hashStateX;
t ^= (t << 11);
current->_hashStateZ = current->_hashStateW;
unsigned v = current->_hashStateW;
v = (v ^ (v >> 19)) ^ (t ^ (t >> 8));
current->_hashStateW = v;
value = v;
+ } else {
+ assert(UseCompactObjectHeaders, "Only with compact i-hash");
+ #ifdef _LP64
+ uint64_t val = cast_from_oop<uint64_t>(obj);
+ uint32_t hash = FastHash::get_hash32((uint32_t)val, (uint32_t)(val >> 32));
+ #else
+ uint32_t val = cast_from_oop<uint32_t>(obj);
+ uint32_t hash = FastHash::get_hash32(val, UCONST64(0xAAAAAAAA));
+ #endif
+ value= static_cast<intptr_t>(hash);
}
value &= markWord::hash_mask;
- if (value == 0) value = 0xBAD;
- assert(value != markWord::no_hash, "invariant");
+ if (hashCode != 6 && value == 0) value = 0xBAD;
+ assert(value != markWord::no_hash || hashCode == 6, "invariant");
return value;
}
intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) {
while (true) {
ObjectMonitor* monitor = nullptr;
markWord temp, test;
intptr_t hash;
markWord mark = obj->mark_acquire();
- // If UseObjectMonitorTable is set the hash can simply be installed in the
- // object header, since the monitor isn't in the object header.
- if (UseObjectMonitorTable || !mark.has_monitor()) {
+ if (UseCompactObjectHeaders) {
+ if (mark.is_hashed()) {
+ return get_hash(mark, obj);
+ }
+ intptr_t hash = get_next_hash(current, obj); // get a new hash
+ markWord new_mark;
+ if (mark.is_not_hashed_expanded()) {
+ new_mark = mark.set_hashed_expanded();
+ int offset = mark.klass()->hash_offset_in_bytes(obj, mark);
+ obj->int_field_put(offset, (jint) hash);
+ } else {
+ new_mark = mark.set_hashed_not_expanded();
+ }
+ markWord old_mark = obj->cas_set_mark(new_mark, mark);
+ if (old_mark == mark) {
+ return hash;
+ }
+ // CAS failed, retry.
+ continue;
+ } else if (UseObjectMonitorTable || !mark.has_monitor()) {
+ // If UseObjectMonitorTable is set the hash can simply be installed in the
+ // object header, since the monitor isn't in the object header.
hash = mark.hash();
if (hash != 0) { // if it has a hash, just return it
return hash;
}
hash = get_next_hash(current, obj); // get a new hash
// We finally get the hash.
return hash;
}
}
+
+ uint32_t ObjectSynchronizer::get_hash(markWord mark, oop obj, Klass* klass) {
+ assert(UseCompactObjectHeaders, "Only with compact i-hash");
+ //assert(mark.is_neutral() | mark.is_fast_locked(), "only from neutral or fast-locked mark: " INTPTR_FORMAT, mark.value());
+ assert(mark.is_hashed(), "only from hashed or copied object");
+ if (mark.is_hashed_expanded()) {
+ return obj->int_field(klass->hash_offset_in_bytes(obj, mark));
+ } else {
+ assert(mark.is_hashed_not_expanded(), "must be hashed");
+ assert(hashCode == 6 || hashCode == 2, "must have idempotent hashCode");
+ // Already marked as hashed, but not yet copied. Recompute hash and return it.
+ return ObjectSynchronizer::get_next_hash(nullptr, obj); // recompute hash
+ }
+ }
+
+ uint32_t ObjectSynchronizer::get_hash(markWord mark, oop obj) {
+ return get_hash(mark, obj, mark.klass());
+ }
+
bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
Handle h_obj) {
assert(current == JavaThread::current(), "Can only be called on current thread");
oop obj = h_obj();
}
out->flush();
}
+ static uintx objhash(oop obj) {
+ if (UseCompactObjectHeaders) {
+ uintx hash = ObjectSynchronizer::get_hash(obj->mark(), obj);
+ assert(hash != 0, "should have a hash");
+ return hash;
+ } else {
+ uintx hash = obj->mark().hash();
+ assert(hash != 0, "should have a hash");
+ return hash;
+ }
+ }
+
// -----------------------------------------------------------------------------
// ConcurrentHashTable storing links from objects to ObjectMonitors
class ObjectMonitorTable : AllStatic {
struct Config {
using Value = ObjectMonitor*;
public:
explicit Lookup(oop obj) : _obj(obj) {}
uintx get_hash() const {
- uintx hash = _obj->mark().hash();
- assert(hash != 0, "should have a hash");
- return hash;
+ return objhash(_obj);
}
bool equals(ObjectMonitor** value) {
assert(*value != nullptr, "must be");
return (*value)->object_refers_to(_obj);
static ObjectMonitor* monitor_get(Thread* current, oop obj) {
ObjectMonitor* result = nullptr;
Lookup lookup_f(obj);
auto found_f = [&](ObjectMonitor** found) {
assert((*found)->object_peek() == obj, "must be");
+ assert(objhash(obj) == (uintx)(*found)->hash(), "hash must match");
result = *found;
};
_table->get(current, lookup_f, found_f);
verify_monitor_get_result(obj, result);
return result;
auto printer = [&] (ObjectMonitor** entry) {
ObjectMonitor* om = *entry;
oop obj = om->object_peek();
st->print("monitor=" PTR_FORMAT ", ", p2i(om));
st->print("object=" PTR_FORMAT, p2i(obj));
- assert(obj->mark().hash() == om->hash(), "hash must match");
+ assert(objhash(obj) == (uintx)om->hash(), "hash must match");
st->cr();
return true;
};
if (SafepointSynchronize::is_at_safepoint()) {
_table->do_safepoint_scan(printer);
// Add the hashcode to the monitor to match the object and put it in the hashtable.
ObjectMonitor* ObjectSynchronizer::add_monitor(JavaThread* current, ObjectMonitor* monitor, oop obj) {
assert(UseObjectMonitorTable, "must be");
assert(obj == monitor->object(), "must be");
- intptr_t hash = obj->mark().hash();
+ intptr_t hash = objhash(obj);
assert(hash != 0, "must be set when claiming the object monitor");
monitor->set_hash(hash);
return ObjectMonitorTable::monitor_put_get(current, monitor, obj);
}
< prev index next >