Merge
authorcoleenp
Mon, 08 Jan 2018 12:02:48 -0500
changeset 48620 7f97d35fac6e
parent 48619 1703d83b3ffe (current diff)
parent 48618 688e5cbd0b91 (diff)
child 48621 77797298bf36
Merge
src/hotspot/share/classfile/javaClasses.cpp
src/hotspot/share/classfile/javaClasses.hpp
--- a/src/hotspot/share/classfile/javaClasses.cpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Mon Jan 08 12:02:48 2018 -0500
@@ -628,12 +628,12 @@
 bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
   assert(java_string->klass() == SystemDictionary::String_klass(),
          "must be java_string");
-  typeArrayOop value  = java_lang_String::value(java_string);
-  int          length = java_lang_String::length(java_string);
+  typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
+  int length = java_lang_String::length(java_string);
   if (length != len) {
     return false;
   }
-  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  bool is_latin1 = java_lang_String::is_latin1(java_string);
   if (!is_latin1) {
     for (int i = 0; i < len; i++) {
       if (value->char_at(i) != chars[i]) {
@@ -655,12 +655,12 @@
          "must be java String");
   assert(str2->klass() == SystemDictionary::String_klass(),
          "must be java String");
-  typeArrayOop value1  = java_lang_String::value(str1);
-  int          length1 = java_lang_String::length(str1);
-  bool       is_latin1 = java_lang_String::is_latin1(str1);
-  typeArrayOop value2  = java_lang_String::value(str2);
-  int          length2 = java_lang_String::length(str2);
-  bool       is_latin2 = java_lang_String::is_latin1(str2);
+  typeArrayOop value1    = java_lang_String::value_no_keepalive(str1);
+  int          length1   = java_lang_String::length(value1);
+  bool         is_latin1 = java_lang_String::is_latin1(str1);
+  typeArrayOop value2    = java_lang_String::value_no_keepalive(str2);
+  int          length2   = java_lang_String::length(value2);
+  bool         is_latin2 = java_lang_String::is_latin1(str2);
 
   if ((length1 != length2) || (is_latin1 != is_latin2)) {
     // Strings of different size or with different
@@ -668,7 +668,7 @@
     return false;
   }
   int blength1 = value1->length();
-  for (int i = 0; i < value1->length(); i++) {
+  for (int i = 0; i < blength1; i++) {
     if (value1->byte_at(i) != value2->byte_at(i)) {
       return false;
     }
@@ -678,7 +678,7 @@
 
 void java_lang_String::print(oop java_string, outputStream* st) {
   assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string");
-  typeArrayOop value  = java_lang_String::value(java_string);
+  typeArrayOop value  = java_lang_String::value_no_keepalive(java_string);
 
   if (value == NULL) {
     // This can happen if, e.g., printing a String
--- a/src/hotspot/share/classfile/javaClasses.hpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Mon Jan 08 12:02:48 2018 -0500
@@ -102,6 +102,7 @@
 
   // Accessors
   static inline typeArrayOop value(oop java_string);
+  static inline typeArrayOop value_no_keepalive(oop java_string);
   static inline unsigned int hash(oop java_string);
   static inline bool is_latin1(oop java_string);
   static inline int length(oop java_string);
--- a/src/hotspot/share/classfile/javaClasses.inline.hpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/classfile/javaClasses.inline.hpp	Mon Jan 08 12:02:48 2018 -0500
@@ -26,6 +26,7 @@
 #define SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP
 
 #include "classfile/javaClasses.hpp"
+#include "oops/access.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oopsHierarchy.hpp"
 
@@ -53,6 +54,11 @@
   assert(is_instance(java_string), "must be java_string");
   return (typeArrayOop) java_string->obj_field(value_offset);
 }
+typeArrayOop java_lang_String::value_no_keepalive(oop java_string) {
+  assert(initialized && (value_offset > 0), "Must be initialized");
+  assert(is_instance(java_string), "must be java_string");
+  return (typeArrayOop) java_string->obj_field_access<AS_NO_KEEPALIVE>(value_offset);
+}
 unsigned int java_lang_String::hash(oop java_string) {
   assert(initialized && (hash_offset > 0), "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
@@ -68,11 +74,11 @@
 int java_lang_String::length(oop java_string) {
   assert(initialized, "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
-  typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset));
-  if (value_array == NULL) {
+  typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
+  if (value == NULL) {
     return 0;
   }
-  int arr_length = value_array->length();
+  int arr_length = value->length();
   if (!is_latin1(java_string)) {
     assert((arr_length & 1) == 0, "should be even for UTF16 string");
     arr_length >>= 1; // convert number of bytes to number of elements
--- a/src/hotspot/share/classfile/stringTable.cpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/classfile/stringTable.cpp	Mon Jan 08 12:02:48 2018 -0500
@@ -35,6 +35,7 @@
 #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"
@@ -43,7 +44,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1CollectedHeap.hpp"
-#include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc/g1/g1StringDedup.hpp"
 #endif
 
@@ -124,6 +124,22 @@
   }
 }
 
+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");
@@ -131,13 +147,16 @@
 }
 
 oop StringTable::lookup_in_main_table(int index, jchar* name,
-                                int len, unsigned int hash) {
+                                      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);
       }
     }
   }
@@ -192,18 +211,6 @@
   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);
@@ -217,8 +224,6 @@
   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;
 }
 
@@ -238,9 +243,6 @@
 
   // Found
   if (found_string != NULL) {
-    if (found_string != string_or_null()) {
-      ensure_string_alive(found_string);
-    }
     return found_string;
   }
 
@@ -276,10 +278,6 @@
                                   hashValue, CHECK_NULL);
   }
 
-  if (added_or_found != string()) {
-    ensure_string_alive(added_or_found);
-  }
-
   return added_or_found;
 }
 
@@ -388,9 +386,9 @@
     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 {
@@ -429,7 +427,7 @@
   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");
@@ -448,10 +446,10 @@
     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);
+        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);
@@ -484,8 +482,8 @@
                                       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 ") "
@@ -505,12 +503,12 @@
 }
 
 StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
-                                      HashtableEntry<oop, mtSymbol>* e_ptr,
-                                      StringTable::VerifyMesgModes mesg_mode) {
+                                                      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,
@@ -684,7 +682,7 @@
   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;
@@ -708,7 +706,7 @@
   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;
@@ -721,7 +719,7 @@
       }
 
       // 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);
@@ -763,4 +761,3 @@
   _shared_table.oops_do(f);
 }
 #endif //INCLUDE_CDS_JAVA_HEAP
-
--- a/src/hotspot/share/classfile/stringTable.hpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/classfile/stringTable.hpp	Mon Jan 08 12:02:48 2018 -0500
@@ -76,6 +76,13 @@
   static unsigned int hash_string(oop string);
   static unsigned int alt_hash_string(const jchar* s, int len);
 
+  // Accessors for the string roots in the hashtable entries.
+  // Use string_object_no_keepalive() only when the value is not returned
+  // outside of a scope where a thread transition is possible.
+  static oop string_object(HashtableEntry<oop, mtSymbol>* entry);
+  static oop string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry);
+  static void set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string);
+
   StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
                               sizeof (HashtableEntry<oop, mtSymbol>)) {}
 
--- a/src/hotspot/share/oops/oop.hpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/oops/oop.hpp	Mon Jan 08 12:02:48 2018 -0500
@@ -28,6 +28,7 @@
 #include "gc/shared/specialized_oop_closures.hpp"
 #include "memory/iterator.hpp"
 #include "memory/memRegion.hpp"
+#include "oops/access.hpp"
 #include "oops/metadata.hpp"
 #include "utilities/macros.hpp"
 
@@ -178,6 +179,8 @@
   static inline void encode_store_heap_oop(oop* p, oop v);
 
   // Access to fields in a instanceOop through these methods.
+  template <DecoratorSet decorator>
+  oop obj_field_access(int offset) const;
   oop obj_field(int offset) const;
   void obj_field_put(int offset, oop value);
   void obj_field_put_raw(int offset, oop value);
--- a/src/hotspot/share/oops/oop.inline.hpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/oops/oop.inline.hpp	Mon Jan 08 12:02:48 2018 -0500
@@ -326,7 +326,10 @@
   *p = encode_heap_oop(v);
 }
 
+template <DecoratorSet decorators>
+inline oop  oopDesc::obj_field_access(int offset) const             { return HeapAccess<decorators>::oop_load_at(as_oop(), offset); }
 inline oop  oopDesc::obj_field(int offset) const                    { return HeapAccess<>::oop_load_at(as_oop(), offset);  }
+
 inline void oopDesc::obj_field_put(int offset, oop value)           { HeapAccess<>::oop_store_at(as_oop(), offset, value); }
 
 inline jbyte oopDesc::byte_field(int offset) const                  { return HeapAccess<>::load_at(as_oop(), offset);  }
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Mon Jan 08 12:02:48 2018 -0500
@@ -30,6 +30,7 @@
 #include "code/codeCache.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/resourceArea.hpp"
+#include "oops/access.inline.hpp"
 #include "oops/instanceMirrorKlass.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.inline.hpp"
@@ -52,10 +53,6 @@
 #include "runtime/vm_operations.hpp"
 #include "services/serviceUtil.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1SATBCardTableModRefBS.hpp"
-#include "gc/parallel/parallelScavengeHeap.hpp"
-#endif // INCLUDE_ALL_GCS
 
 // JvmtiTagHashmapEntry
 //
@@ -78,22 +75,31 @@
   }
 
   // constructor
-  JvmtiTagHashmapEntry(oop object, jlong tag)         { init(object, tag); }
+  JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); }
 
  public:
 
   // accessor methods
-  inline oop object() const                           { return _object; }
-  inline oop* object_addr()                           { return &_object; }
-  inline jlong tag() const                            { return _tag; }
+  inline oop* object_addr() { return &_object; }
+  inline oop object()       { return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(object_addr()); }
+  // Peek at the object without keeping it alive. The returned object must be
+  // kept alive using a normal access if it leaks out of a thread transition from VM.
+  inline oop object_peek()  {
+    return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(object_addr());
+  }
+  inline jlong tag() const  { return _tag; }
 
   inline void set_tag(jlong tag) {
     assert(tag != 0, "can't be zero");
     _tag = tag;
   }
 
-  inline JvmtiTagHashmapEntry* next() const             { return _next; }
-  inline void set_next(JvmtiTagHashmapEntry* next)      { _next = next; }
+  inline bool equals(oop object) {
+    return object == object_peek();
+  }
+
+  inline JvmtiTagHashmapEntry* next() const        { return _next; }
+  inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; }
 };
 
 
@@ -211,7 +217,7 @@
       JvmtiTagHashmapEntry* entry = _table[i];
       while (entry != NULL) {
         JvmtiTagHashmapEntry* next = entry->next();
-        oop key = entry->object();
+        oop key = entry->object_peek();
         assert(key != NULL, "jni weak reference cleared!!");
         unsigned int h = hash(key, new_size);
         JvmtiTagHashmapEntry* anchor = new_table[h];
@@ -304,7 +310,7 @@
     unsigned int h = hash(key);
     JvmtiTagHashmapEntry* entry = _table[h];
     while (entry != NULL) {
-      if (entry->object() == key) {
+      if (entry->equals(key)) {
          return entry;
       }
       entry = entry->next();
@@ -345,7 +351,7 @@
     JvmtiTagHashmapEntry* entry = _table[h];
     JvmtiTagHashmapEntry* prev = NULL;
     while (entry != NULL) {
-      if (key == entry->object()) {
+      if (entry->equals(key)) {
         break;
       }
       prev = entry;
@@ -1535,16 +1541,12 @@
   void do_entry(JvmtiTagHashmapEntry* entry) {
     for (int i=0; i<_tag_count; i++) {
       if (_tags[i] == entry->tag()) {
+        // The reference in this tag map could be the only (implicitly weak)
+        // reference to that object. If we hand it out, we need to keep it live wrt
+        // SATB marking similar to other j.l.ref.Reference referents. This is
+        // achieved by using a phantom load in the object() accessor.
         oop o = entry->object();
         assert(o != NULL && Universe::heap()->is_in_reserved(o), "sanity check");
-#if INCLUDE_ALL_GCS
-        if (UseG1GC) {
-          // The reference in this tag map could be the only (implicitly weak)
-          // reference to that object. If we hand it out, we need to keep it live wrt
-          // SATB marking similar to other j.l.ref.Reference referents.
-          G1SATBCardTableModRefBS::enqueue(o);
-        }
-#endif
         jobject ref = JNIHandles::make_local(JavaThread::current(), o);
         _object_results->append(ref);
         _tag_results->append((uint64_t)entry->tag());
@@ -3363,10 +3365,8 @@
     while (entry != NULL) {
       JvmtiTagHashmapEntry* next = entry->next();
 
-      oop* obj = entry->object_addr();
-
       // has object been GC'ed
-      if (!is_alive->do_object_b(entry->object())) {
+      if (!is_alive->do_object_b(entry->object_peek())) {
         // grab the tag
         jlong tag = entry->tag();
         guarantee(tag != 0, "checking");
@@ -3384,7 +3384,7 @@
         ++freed;
       } else {
         f->do_oop(entry->object_addr());
-        oop new_oop = entry->object();
+        oop new_oop = entry->object_peek();
 
         // if the object has moved then re-hash it and move its
         // entry to its new location.
@@ -3418,7 +3418,7 @@
   // Re-add all the entries which were kept aside
   while (delayed_add != NULL) {
     JvmtiTagHashmapEntry* next = delayed_add->next();
-    unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size);
+    unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object_peek(), size);
     delayed_add->set_next(table[pos]);
     table[pos] = delayed_add;
     delayed_add = next;
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp	Mon Jan 08 12:02:48 2018 -0500
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "memory/allocation.hpp"
+#include "oops/access.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/method.hpp"
 #include "oops/symbol.hpp"
@@ -33,10 +34,20 @@
 #include "runtime/mutexLocker.hpp"
 #include "utilities/hashtable.inline.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1SATBCardTableModRefBS.hpp"
-#endif
+
+
+oop ResolvedMethodEntry::object() {
+  return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(literal_addr());
+}
 
+oop ResolvedMethodEntry::object_no_keepalive() {
+  // The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
+  // This is dangerous in general but is okay if the loaded oop does
+  // not leak out past a thread transition where a safepoint can happen.
+  // A subsequent oop_load without AS_NO_KEEPALIVE (the object() accessor)
+  // keeps the oop alive before doing so.
+  return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(literal_addr());
+}
 
 ResolvedMethodTable::ResolvedMethodTable()
   : Hashtable<oop, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
@@ -44,13 +55,18 @@
 oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
   for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
     if (p->hash() == hash) {
-      oop target = p->literal();
+
+      // Peek the object to check if it is the right target.
+      oop target = p->object_no_keepalive();
+
       // The method is in the table as a target already
       if (java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
         ResourceMark rm;
         log_debug(membername, table) ("ResolvedMethod entry found for %s index %d",
                                        method->name_and_sig_as_C_string(), index);
-        return target;
+        // The object() accessor makes sure the target object is kept alive before
+        // leaking out.
+        return p->object();
       }
     }
   }
@@ -70,18 +86,6 @@
   return lookup(index, hash, method);
 }
 
-// Tell the GC that this oop was looked up in the table
-static void ensure_oop_alive(oop mname) {
-  // A lookup in the ResolvedMethodTable 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 && mname != NULL) {
-    G1SATBCardTableModRefBS::enqueue(mname);
-  }
-#endif
-}
-
 oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) {
   assert_locked_or_safepoint(ResolvedMethodTable_lock);
 
@@ -91,7 +95,6 @@
   // One was added while aquiring the lock
   oop entry = lookup(index, hash, method);
   if (entry != NULL) {
-    ensure_oop_alive(entry);
     return entry;
   }
 
@@ -100,14 +103,13 @@
   ResourceMark rm;
   log_debug(membername, table) ("ResolvedMethod entry added for %s index %d",
                                  method->name_and_sig_as_C_string(), index);
-  return p->literal();
+  return rmethod_name;
 }
 
 ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;
 
 oop ResolvedMethodTable::find_method(Method* method) {
   oop entry = _the_table->lookup(method);
-  ensure_oop_alive(entry);
   return entry;
 }
 
@@ -147,12 +149,12 @@
     ResolvedMethodEntry* entry = _the_table->bucket(i);
     while (entry != NULL) {
       _oops_counted++;
-      if (is_alive->do_object_b(entry->literal())) {
+      if (is_alive->do_object_b(entry->object_no_keepalive())) {
         p = entry->next_addr();
       } else {
         _oops_removed++;
         if (log_is_enabled(Debug, membername, table)) {
-          Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->literal());
+          Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->object_no_keepalive());
           ResourceMark rm;
           log_debug(membername, table) ("ResolvedMethod entry removed for %s index %d",
                                            m->name_and_sig_as_C_string(), i);
@@ -185,7 +187,7 @@
     ResolvedMethodEntry* entry = bucket(i);
     while (entry != NULL) {
       tty->print("%d : ", i);
-      oop rmethod_name = entry->literal();
+      oop rmethod_name = entry->object_no_keepalive();
       rmethod_name->print();
       Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
       m->print();
@@ -203,8 +205,7 @@
   for (int i = 0; i < _the_table->table_size(); ++i) {
     ResolvedMethodEntry* entry = _the_table->bucket(i);
     while (entry != NULL) {
-
-      oop mem_name = entry->literal();
+      oop mem_name = entry->object_no_keepalive();
       Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
 
       if (old_method->is_old()) {
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp	Mon Jan 08 12:02:48 2018 -0500
@@ -44,6 +44,9 @@
     return (ResolvedMethodEntry**)HashtableEntry<oop, mtClass>::next_addr();
   }
 
+  oop object();
+  oop object_no_keepalive();
+
   void print_on(outputStream* st) const;
 };
 
--- a/src/hotspot/share/utilities/vmError.cpp	Mon Jan 08 09:46:31 2018 -0500
+++ b/src/hotspot/share/utilities/vmError.cpp	Mon Jan 08 12:02:48 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -243,11 +243,12 @@
           RegisterMap map((JavaThread*)t, false); // No update
           fr = fr.sender(&map);
         } else {
+          // is_first_C_frame() does only simple checks for frame pointer,
+          // it will pass if java compiled code has a pointer in EBP.
+          if (os::is_first_C_frame(&fr)) break;
           fr = os::get_sender_for_C_frame(&fr);
         }
       } else {
-        // is_first_C_frame() does only simple checks for frame pointer,
-        // it will pass if java compiled code has a pointer in EBP.
         if (os::is_first_C_frame(&fr)) break;
         fr = os::get_sender_for_C_frame(&fr);
       }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/BadNativeStackInErrorHandlingTest.java	Mon Jan 08 12:02:48 2018 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @bug 8194652
+ * @summary Printing native stack shows an "error occurred during error reporting".
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ */
+
+// This test was adapted from SafeFetchInErrorHandlingTest.java.
+public class BadNativeStackInErrorHandlingTest {
+  public static void main(String[] args) throws Exception {
+    if (!Platform.isDebugBuild() || Platform.isZero()) {
+      return;
+    }
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+UnlockDiagnosticVMOptions",
+        "-Xmx100M",
+        "-XX:ErrorHandlerTest=14",
+        "-XX:-CreateCoredumpOnCrash",
+        "-version");
+
+    OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
+
+    // we should have crashed with a SIGSEGV
+    output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
+    output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*");
+
+    // extract hs-err file
+    String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
+    if (hs_err_file == null) {
+        throw new RuntimeException("Did not find hs-err file in output.\n");
+    }
+
+    File f = new File(hs_err_file);
+    if (!f.exists()) {
+        throw new RuntimeException("hs-err file missing at " +
+                                   f.getAbsolutePath() + ".\n");
+    }
+
+    System.out.println("Found hs_err file. Scanning...");
+
+    FileInputStream fis = new FileInputStream(f);
+    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
+    String line = null;
+
+    // The failing line looks like this:
+    // [error occurred during error reporting (printing native stack), id 0xb]
+    Pattern pattern =
+        Pattern.compile("\\[error occurred during error reporting \\(printing native stack\\), id .*\\]");
+
+    String lastLine = null;
+    while ((line = br.readLine()) != null) {
+        if (pattern.matcher(line).matches()) {
+            System.out.println("Found: " + line + ".");
+            throw new RuntimeException("hs-err file should not contain: '" +
+                                       pattern + "'");
+        }
+        lastLine = line;
+    }
+    br.close();
+
+    if (!lastLine.equals("END.")) {
+        throw new RuntimeException("hs-err file incomplete (missing END marker.)");
+    } else {
+        System.out.println("End marker found.");
+    }
+
+    System.out.println("OK.");
+  }
+}