< 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 >