< 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,19 +33,19 @@
 #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/g1SATBCardTableModRefBS.hpp"
 #include "gc/g1/g1StringDedup.hpp"
 #endif
 
 // the number of buckets a thread claims
 const int ClaimChunkSize = 32;

@@ -122,10 +122,26 @@
     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,12 +150,15 @@
                                 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 (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,22 +209,10 @@
   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) {

@@ -215,12 +222,10 @@
     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) {

@@ -236,13 +241,10 @@
   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),

@@ -274,14 +276,10 @@
     // 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;

@@ -386,13 +384,13 @@
     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 (is_alive->do_object_b(string_object_no_keepalive(entry))) {
         if (f != NULL) {
-          f->do_oop((oop*)entry->literal_addr());
+          f->do_oop(entry->literal_addr());
         }
         p = entry->next_addr();
       } else {
         *p = entry->next();
         context->free_entry(entry);

@@ -427,11 +425,11 @@
 // 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();
+      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,12 +444,12 @@
     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);
+        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,12 +480,12 @@
                                       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();
+  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,11 +506,11 @@
                                       HashtableEntry<oop, mtSymbol>* e_ptr,
                                       StringTable::VerifyMesgModes mesg_mode) {
 
   VerifyRetTypes ret = _verify_pass;  // be optimistic
 
-  oop str = e_ptr->literal();
+  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,11 +680,11 @@
 // 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 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,11 +704,11 @@
   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();
+      oop s = string_object_no_keepalive(bucket);
       unsigned int hash = java_lang_String::hash_code(s);
       if (hash == 0) {
         continue;
       }
 

@@ -719,11 +717,11 @@
       if (new_s == NULL) {
         continue;
       }
 
       // set the archived string in bucket
-      bucket->set_literal(new_s);
+      set_string_object(bucket, new_s);
 
       // add to the compact table
       writer->add(hash, new_s);
     }
   }

@@ -761,6 +759,5 @@
 
 void StringTable::shared_oops_do(OopClosure* f) {
   _shared_table.oops_do(f);
 }
 #endif //INCLUDE_CDS_JAVA_HEAP
-
< prev index next >