8213791: StringTable: Use get and insert
Reviewed-by: eosterlund, gziemski
This commit is contained in:
parent
0f0b8626fc
commit
7e0040c384
src/hotspot/share
@ -206,6 +206,12 @@ StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0),
|
||||
_local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
|
||||
}
|
||||
|
||||
void StringTable::update_needs_rehash(bool rehash) {
|
||||
if (rehash) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
}
|
||||
|
||||
size_t StringTable::item_added() {
|
||||
return Atomic::add((size_t)1, &(the_table()->_items_count));
|
||||
}
|
||||
@ -281,9 +287,7 @@ oop StringTable::do_lookup(const jchar* name, int len, uintx hash) {
|
||||
StringTableGet stg(thread);
|
||||
bool rehash_warning;
|
||||
_local_table->get(thread, lookup, stg, &rehash_warning);
|
||||
if (rehash_warning) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
update_needs_rehash(rehash_warning);
|
||||
return stg.get_res_oop();
|
||||
}
|
||||
|
||||
@ -334,30 +338,6 @@ oop StringTable::intern(Handle string_or_null_h, const jchar* name, int len, TRA
|
||||
hash, CHECK_NULL);
|
||||
}
|
||||
|
||||
class StringTableCreateEntry : public StackObj {
|
||||
private:
|
||||
Thread* _thread;
|
||||
Handle _return;
|
||||
Handle _store;
|
||||
public:
|
||||
StringTableCreateEntry(Thread* thread, Handle store)
|
||||
: _thread(thread), _store(store) {}
|
||||
|
||||
WeakHandle<vm_string_table_data> operator()() { // No dups found
|
||||
WeakHandle<vm_string_table_data> wh =
|
||||
WeakHandle<vm_string_table_data>::create(_store);
|
||||
return wh;
|
||||
}
|
||||
void operator()(bool inserted, WeakHandle<vm_string_table_data>* val) {
|
||||
oop result = val->resolve();
|
||||
assert(result != NULL, "Result should be reachable");
|
||||
_return = Handle(_thread, result);
|
||||
}
|
||||
oop get_return() const {
|
||||
return _return();
|
||||
}
|
||||
};
|
||||
|
||||
oop StringTable::do_intern(Handle string_or_null_h, const jchar* name,
|
||||
int len, uintx hash, TRAPS) {
|
||||
HandleMark hm(THREAD); // cleanup strings created
|
||||
@ -377,15 +357,23 @@ oop StringTable::do_intern(Handle string_or_null_h, const jchar* name,
|
||||
assert(java_lang_String::equals(string_h(), name, len),
|
||||
"string must be properly initialized");
|
||||
assert(len == java_lang_String::length(string_h()), "Must be same length");
|
||||
|
||||
StringTableLookupOop lookup(THREAD, hash, string_h);
|
||||
StringTableCreateEntry stc(THREAD, string_h);
|
||||
StringTableGet stg(THREAD);
|
||||
|
||||
bool rehash_warning;
|
||||
_local_table->get_insert_lazy(THREAD, lookup, stc, stc, &rehash_warning);
|
||||
if (rehash_warning) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
return stc.get_return();
|
||||
do {
|
||||
if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) {
|
||||
update_needs_rehash(rehash_warning);
|
||||
return stg.get_res_oop();
|
||||
}
|
||||
WeakHandle<vm_string_table_data> wh = WeakHandle<vm_string_table_data>::create(string_h);
|
||||
// The hash table takes ownership of the WeakHandle, even if it's not inserted.
|
||||
if (_local_table->insert(THREAD, lookup, wh, &rehash_warning)) {
|
||||
update_needs_rehash(rehash_warning);
|
||||
return wh.resolve();
|
||||
}
|
||||
} while(true);
|
||||
}
|
||||
|
||||
// GC support
|
||||
|
@ -93,6 +93,7 @@ private:
|
||||
|
||||
void try_rehash_table();
|
||||
bool do_rehash();
|
||||
inline void update_needs_rehash(bool rehash);
|
||||
|
||||
public:
|
||||
// The string table
|
||||
|
@ -313,8 +313,13 @@ class ConcurrentHashTable : public CHeapObj<F> {
|
||||
|
||||
// Insert which handles a number of cases.
|
||||
template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
|
||||
bool internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
|
||||
CALLBACK_FUNC& callback, bool* grow_hint = NULL, bool* clean_hint = NULL);
|
||||
bool internal_get_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
|
||||
CALLBACK_FUNC& callback_f, bool* grow_hint = NULL, bool* clean_hint = NULL);
|
||||
|
||||
// Plain insert.
|
||||
template <typename LOOKUP_FUNC>
|
||||
bool internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
|
||||
bool* grow_hint, bool* clean_hint);
|
||||
|
||||
// Returns true if an item matching LOOKUP_FUNC is removed.
|
||||
// Calls DELETE_FUNC before destroying the node.
|
||||
@ -402,7 +407,7 @@ class ConcurrentHashTable : public CHeapObj<F> {
|
||||
template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
|
||||
bool get_insert_lazy(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& val_f,
|
||||
CALLBACK_FUNC& callback_f, bool* grow_hint = NULL, bool* clean_hint = NULL) {
|
||||
return !internal_insert(thread, lookup_f, val_f, callback_f, grow_hint, clean_hint);
|
||||
return !internal_get_insert(thread, lookup_f, val_f, callback_f, grow_hint, clean_hint);
|
||||
}
|
||||
|
||||
// Same without CALLBACK_FUNC.
|
||||
@ -442,8 +447,7 @@ class ConcurrentHashTable : public CHeapObj<F> {
|
||||
template <typename LOOKUP_FUNC>
|
||||
bool insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
|
||||
bool* grow_hint = NULL, bool* clean_hint = NULL) {
|
||||
LazyValueRetrieve vp(value);
|
||||
return internal_insert(thread, lookup_f, vp, noOp, grow_hint, clean_hint);
|
||||
return internal_insert(thread, lookup_f, value, grow_hint, clean_hint);
|
||||
}
|
||||
|
||||
// This does a fast unsafe insert and can thus only be used when there is no
|
||||
|
@ -876,8 +876,8 @@ inline VALUE* ConcurrentHashTable<VALUE, CONFIG, F>::
|
||||
template <typename VALUE, typename CONFIG, MEMFLAGS F>
|
||||
template <typename LOOKUP_FUNC, typename VALUE_FUNC, typename CALLBACK_FUNC>
|
||||
inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
|
||||
internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
|
||||
CALLBACK_FUNC& callback, bool* grow_hint, bool* clean_hint)
|
||||
internal_get_insert(Thread* thread, LOOKUP_FUNC& lookup_f, VALUE_FUNC& value_f,
|
||||
CALLBACK_FUNC& callback_f, bool* grow_hint, bool* clean_hint)
|
||||
{
|
||||
bool ret = false;
|
||||
bool clean = false;
|
||||
@ -901,7 +901,7 @@ inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
|
||||
new_node->set_next(first_at_start);
|
||||
}
|
||||
if (bucket->cas_first(new_node, first_at_start)) {
|
||||
callback(true, new_node->value());
|
||||
callback_f(true, new_node->value());
|
||||
new_node = NULL;
|
||||
ret = true;
|
||||
break; /* leave critical section */
|
||||
@ -910,7 +910,7 @@ inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
|
||||
locked = bucket->is_locked();
|
||||
} else {
|
||||
// There is a duplicate.
|
||||
callback(false, old->value());
|
||||
callback_f(false, old->value());
|
||||
break; /* leave critical section */
|
||||
}
|
||||
} /* leave critical section */
|
||||
@ -945,6 +945,70 @@ inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename VALUE, typename CONFIG, MEMFLAGS F>
|
||||
template <typename LOOKUP_FUNC>
|
||||
inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
|
||||
internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value,
|
||||
bool* grow_hint, bool* clean_hint)
|
||||
{
|
||||
bool ret = false;
|
||||
bool clean = false;
|
||||
bool locked;
|
||||
size_t loops = 0;
|
||||
size_t i = 0;
|
||||
uintx hash = lookup_f.get_hash();
|
||||
Node* new_node = Node::create_node(value, NULL);
|
||||
|
||||
while (true) {
|
||||
{
|
||||
ScopedCS cs(thread, this); /* protected the table/bucket */
|
||||
Bucket* bucket = get_bucket(hash);
|
||||
Node* first_at_start = bucket->first();
|
||||
Node* old = get_node(bucket, lookup_f, &clean, &loops);
|
||||
if (old == NULL) {
|
||||
new_node->set_next(first_at_start);
|
||||
if (bucket->cas_first(new_node, first_at_start)) {
|
||||
new_node = NULL;
|
||||
ret = true;
|
||||
break; /* leave critical section */
|
||||
}
|
||||
// CAS failed we must leave critical section and retry.
|
||||
locked = bucket->is_locked();
|
||||
} else {
|
||||
// There is a duplicate.
|
||||
break; /* leave critical section */
|
||||
}
|
||||
} /* leave critical section */
|
||||
i++;
|
||||
if (locked) {
|
||||
os::naked_yield();
|
||||
} else {
|
||||
SpinPause();
|
||||
}
|
||||
}
|
||||
|
||||
if (new_node != NULL) {
|
||||
// CAS failed and a duplicate was inserted, we must free this node.
|
||||
Node::destroy_node(new_node);
|
||||
} else if (i == 0 && clean) {
|
||||
// We only do cleaning on fast inserts.
|
||||
Bucket* bucket = get_bucket_locked(thread, lookup_f.get_hash());
|
||||
delete_in_bucket(thread, bucket, lookup_f);
|
||||
bucket->unlock();
|
||||
clean = false;
|
||||
}
|
||||
|
||||
if (grow_hint != NULL) {
|
||||
*grow_hint = loops > _grow_hint;
|
||||
}
|
||||
|
||||
if (clean_hint != NULL) {
|
||||
*clean_hint = clean;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename VALUE, typename CONFIG, MEMFLAGS F>
|
||||
template <typename FUNC>
|
||||
inline bool ConcurrentHashTable<VALUE, CONFIG, F>::
|
||||
|
Loading…
x
Reference in New Issue
Block a user