< prev index next >
src/hotspot/share/classfile/stringTable.cpp
Print this page
rev 48032 : imported patch Access_strings
rev 48033 : [mq]: Access_strings_v2
*** 33,51 ****
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
#include "services/diagnosticCommand.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1CollectedHeap.hpp"
- #include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/g1StringDedup.hpp"
#endif
// the number of buckets a thread claims
const int ClaimChunkSize = 32;
--- 33,51 ----
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
+ #include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
#include "services/diagnosticCommand.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1StringDedup.hpp"
#endif
// the number of buckets a thread claims
const int ClaimChunkSize = 32;
*** 122,131 ****
--- 122,147 ----
vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
return 0;
}
}
+ oop StringTable::string_object(HashtableEntry<oop, mtSymbol>* entry) {
+ return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(entry->literal_addr());
+ }
+
+ oop StringTable::string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry) {
+ // The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
+ // This is *very dangerous* in general but is okay in this specific
+ // case. The subsequent oop_load keeps the oop alive if it it matched
+ // the jchar* string.
+ return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(entry->literal_addr());
+ }
+
+ void StringTable::set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string) {
+ RootAccess<ON_PHANTOM_OOP_REF>::oop_store(entry->literal_addr(), string);
+ }
+
oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
assert(hash == java_lang_String::hash_code(name, len),
"hash must be computed using java_lang_String::hash_code");
return _shared_table.lookup((const char*)name, hash, len);
}
*** 134,145 ****
int len, unsigned int hash) {
int count = 0;
for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
count++;
if (l->hash() == hash) {
! if (java_lang_String::equals(l->literal(), name, len)) {
! return l->literal();
}
}
}
// If the bucket size is too deep check if this hash code is insufficient.
if (count >= rehash_count && !needs_rehashing()) {
--- 150,164 ----
int len, unsigned int hash) {
int count = 0;
for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
count++;
if (l->hash() == hash) {
! if (java_lang_String::equals(string_object_no_keepalive(l), name, len)) {
! // We must perform a new load with string_object() that keeps the string
! // alive as we must expose the oop as strongly reachable when exiting
! // this context, in case the oop gets published.
! return string_object(l);
}
}
}
// If the bucket size is too deep check if this hash code is insufficient.
if (count >= rehash_count && !needs_rehashing()) {
*** 190,211 ****
int length;
jchar* chars = symbol->as_unicode(length);
return lookup(chars, length);
}
- // Tell the GC that this string was looked up in the StringTable.
- static void ensure_string_alive(oop string) {
- // A lookup in the StringTable could return an object that was previously
- // considered dead. The SATB part of G1 needs to get notified about this
- // potential resurrection, otherwise the marking might not find the object.
- #if INCLUDE_ALL_GCS
- if (UseG1GC && string != NULL) {
- G1SATBCardTableModRefBS::enqueue(string);
- }
- #endif
- }
-
oop StringTable::lookup(jchar* name, int len) {
// shared table always uses java_lang_String::hash_code
unsigned int hash = java_lang_String::hash_code(name, len);
oop string = lookup_shared(name, len, hash);
if (string != NULL) {
--- 209,218 ----
*** 215,226 ****
hash = alt_hash_string(name, len);
}
int index = the_table()->hash_to_index(hash);
string = the_table()->lookup_in_main_table(index, name, len, hash);
- ensure_string_alive(string);
-
return string;
}
oop StringTable::intern(Handle string_or_null, jchar* name,
int len, TRAPS) {
--- 222,231 ----
*** 236,248 ****
int index = the_table()->hash_to_index(hashValue);
found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
// Found
if (found_string != NULL) {
- if (found_string != string_or_null()) {
- ensure_string_alive(found_string);
- }
return found_string;
}
debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
assert(!Universe::heap()->is_in_reserved(name),
--- 241,250 ----
*** 274,287 ****
// Otherwise, add to symbol to table
added_or_found = the_table()->basic_add(index, string, name, len,
hashValue, CHECK_NULL);
}
- if (added_or_found != string()) {
- ensure_string_alive(added_or_found);
- }
-
return added_or_found;
}
oop StringTable::intern(Symbol* symbol, TRAPS) {
if (symbol == NULL) return NULL;
--- 276,285 ----
*** 386,398 ****
HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
while (entry != NULL) {
assert(!entry->is_shared(), "CDS not used for the StringTable");
! if (is_alive->do_object_b(entry->literal())) {
if (f != NULL) {
! f->do_oop((oop*)entry->literal_addr());
}
p = entry->next_addr();
} else {
*p = entry->next();
context->free_entry(entry);
--- 384,396 ----
HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
while (entry != NULL) {
assert(!entry->is_shared(), "CDS not used for the StringTable");
! if (is_alive->do_object_b(string_object_no_keepalive(entry))) {
if (f != NULL) {
! f->do_oop(entry->literal_addr());
}
p = entry->next_addr();
} else {
*p = entry->next();
context->free_entry(entry);
*** 427,437 ****
// See StringTable::verify_and_compare() below for exhaustive verification.
void StringTable::verify() {
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
! oop s = p->literal();
guarantee(s != NULL, "interned string is NULL");
unsigned int h = hash_string(s);
guarantee(p->hash() == h, "broken hash in string table entry");
guarantee(the_table()->hash_to_index(h) == i,
"wrong index in string table");
--- 425,435 ----
// See StringTable::verify_and_compare() below for exhaustive verification.
void StringTable::verify() {
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
! oop s = string_object_no_keepalive(p);
guarantee(s != NULL, "interned string is NULL");
unsigned int h = hash_string(s);
guarantee(p->hash() == h, "broken hash in string table entry");
guarantee(the_table()->hash_to_index(h) == i,
"wrong index in string table");
*** 446,457 ****
Thread* THREAD = Thread::current();
st->print_cr("VERSION: 1.1");
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
! oop s = p->literal();
! typeArrayOop value = java_lang_String::value(s);
int length = java_lang_String::length(s);
bool is_latin1 = java_lang_String::is_latin1(s);
if (length <= 0) {
st->print("%d: ", length);
--- 444,455 ----
Thread* THREAD = Thread::current();
st->print_cr("VERSION: 1.1");
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
! oop s = string_object_no_keepalive(p);
! typeArrayOop value = java_lang_String::value_no_keepalive(s);
int length = java_lang_String::length(s);
bool is_latin1 = java_lang_String::is_latin1(s);
if (length <= 0) {
st->print("%d: ", length);
*** 482,493 ****
HashtableEntry<oop, mtSymbol>* e_ptr1,
int bkt2, int e_cnt2,
HashtableEntry<oop, mtSymbol>* e_ptr2) {
// These entries are sanity checked by verify_and_compare_entries()
// before this function is called.
! oop str1 = e_ptr1->literal();
! oop str2 = e_ptr2->literal();
if (str1 == str2) {
tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
"in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]",
p2i(str1), bkt1, e_cnt1, bkt2, e_cnt2);
--- 480,491 ----
HashtableEntry<oop, mtSymbol>* e_ptr1,
int bkt2, int e_cnt2,
HashtableEntry<oop, mtSymbol>* e_ptr2) {
// These entries are sanity checked by verify_and_compare_entries()
// before this function is called.
! oop str1 = string_object_no_keepalive(e_ptr1);
! oop str2 = string_object_no_keepalive(e_ptr2);
if (str1 == str2) {
tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
"in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]",
p2i(str1), bkt1, e_cnt1, bkt2, e_cnt2);
*** 508,518 ****
HashtableEntry<oop, mtSymbol>* e_ptr,
StringTable::VerifyMesgModes mesg_mode) {
VerifyRetTypes ret = _verify_pass; // be optimistic
! oop str = e_ptr->literal();
if (str == NULL) {
if (mesg_mode == _verify_with_mesgs) {
tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
e_cnt);
}
--- 506,516 ----
HashtableEntry<oop, mtSymbol>* e_ptr,
StringTable::VerifyMesgModes mesg_mode) {
VerifyRetTypes ret = _verify_pass; // be optimistic
! oop str = string_object_no_keepalive(e_ptr);
if (str == NULL) {
if (mesg_mode == _verify_with_mesgs) {
tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
e_cnt);
}
*** 682,692 ****
// Sharing
oop StringTable::create_archived_string(oop s, Thread* THREAD) {
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
oop new_s = NULL;
! typeArrayOop v = java_lang_String::value(s);
typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
if (new_v == NULL) {
return NULL;
}
new_s = MetaspaceShared::archive_heap_object(s, THREAD);
--- 680,690 ----
// Sharing
oop StringTable::create_archived_string(oop s, Thread* THREAD) {
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
oop new_s = NULL;
! typeArrayOop v = java_lang_String::value_no_keepalive(s);
typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
if (new_v == NULL) {
return NULL;
}
new_s = MetaspaceShared::archive_heap_object(s, THREAD);
*** 706,716 ****
Thread* THREAD = Thread::current();
G1CollectedHeap::heap()->begin_archive_alloc_range();
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
for ( ; bucket != NULL; bucket = bucket->next()) {
! oop s = bucket->literal();
unsigned int hash = java_lang_String::hash_code(s);
if (hash == 0) {
continue;
}
--- 704,714 ----
Thread* THREAD = Thread::current();
G1CollectedHeap::heap()->begin_archive_alloc_range();
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
for ( ; bucket != NULL; bucket = bucket->next()) {
! oop s = string_object_no_keepalive(bucket);
unsigned int hash = java_lang_String::hash_code(s);
if (hash == 0) {
continue;
}
*** 719,729 ****
if (new_s == NULL) {
continue;
}
// set the archived string in bucket
! bucket->set_literal(new_s);
// add to the compact table
writer->add(hash, new_s);
}
}
--- 717,727 ----
if (new_s == NULL) {
continue;
}
// set the archived string in bucket
! set_string_object(bucket, new_s);
// add to the compact table
writer->add(hash, new_s);
}
}
*** 761,766 ****
void StringTable::shared_oops_do(OopClosure* f) {
_shared_table.oops_do(f);
}
#endif //INCLUDE_CDS_JAVA_HEAP
-
--- 759,763 ----
< prev index next >