changeset 4161:b3e39bc817a7

8192025: Less referential references Reviewed-by: coleenp, eosterlund, mchung, ahgross, rhalade
author kbarrett
date Mon, 22 Jan 2018 14:27:46 -0500
parents a74480137e6e
children d2e4c962b08a
files src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/javaClasses.hpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/oops/klass.cpp src/share/vm/oops/klass.hpp src/share/vm/prims/jvm.cpp
diffstat 8 files changed, 116 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/javaClasses.cpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/classfile/javaClasses.cpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -2373,6 +2373,31 @@
   *offset = value;
 }
 
+// Support for java_lang_ref_ReferenceQueue
+
+oop java_lang_ref_ReferenceQueue::NULL_queue() {
+  instanceKlass* ik = instanceKlass::cast(SystemDictionary::ReferenceQueue_klass());
+  oop mirror = ik->java_mirror();
+  return mirror->obj_field(static_NULL_queue_offset);
+}
+
+oop java_lang_ref_ReferenceQueue::ENQUEUED_queue() {
+  instanceKlass* ik = instanceKlass::cast(SystemDictionary::ReferenceQueue_klass());
+  oop mirror = ik->java_mirror();
+  return mirror->obj_field(static_ENQUEUED_queue_offset);
+}
+
+void java_lang_ref_ReferenceQueue::compute_offsets() {
+  klassOop k = SystemDictionary::ReferenceQueue_klass();
+  compute_offset(static_NULL_queue_offset,
+                 k,
+                 vmSymbols::referencequeue_null_name(),
+                 vmSymbols::referencequeue_signature());
+  compute_offset(static_ENQUEUED_queue_offset,
+                 k,
+                 vmSymbols::referencequeue_enqueued_name(),
+                 vmSymbols::referencequeue_signature());
+}
 
 // Support for java_lang_invoke_MethodHandle
 
@@ -2942,6 +2967,8 @@
 int java_lang_ref_Reference::static_lock_offset;
 int java_lang_ref_Reference::static_pending_offset;
 int java_lang_ref_Reference::number_of_fake_oop_fields;
+int java_lang_ref_ReferenceQueue::static_NULL_queue_offset;
+int java_lang_ref_ReferenceQueue::static_ENQUEUED_queue_offset;
 int java_lang_ref_SoftReference::timestamp_offset;
 int java_lang_ref_SoftReference::static_clock_offset;
 int java_lang_ClassLoader::parent_offset;
@@ -3141,6 +3168,8 @@
   }
   sun_misc_AtomicLongCSImpl::compute_offsets();
 
+  java_lang_ref_ReferenceQueue::compute_offsets();
+
   // generated interpreter code wants to know about the offsets we just computed:
   AbstractAssembler::update_delayed_values();
 }
--- a/src/share/vm/classfile/javaClasses.hpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/classfile/javaClasses.hpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -849,6 +849,12 @@
   static HeapWord* discovered_addr(oop ref) {
     return ref->obj_field_addr<HeapWord>(discovered_offset);
   }
+  static inline oop queue(oop ref) {
+    return ref->obj_field(queue_offset);
+  }
+  static inline void set_queue(oop ref, oop value) {
+    return ref->obj_field_put(queue_offset, value);
+  }
   // Accessors for statics
   static oop  pending_list_lock();
   static oop  pending_list();
@@ -881,6 +887,20 @@
 };
 
 
+// Interface to java.lang.ref.ReferenceQueue objects
+
+class java_lang_ref_ReferenceQueue: public AllStatic {
+public:
+  static int static_NULL_queue_offset;
+  static int static_ENQUEUED_queue_offset;
+
+  // Accessors
+  static oop NULL_queue();
+  static oop ENQUEUED_queue();
+
+  static void compute_offsets();
+};
+
 // Interface to java.lang.invoke.MethodHandle objects
 
 #define METHODHANDLE_INJECTED_FIELDS(macro)                               \
--- a/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/classfile/systemDictionary.cpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -2008,6 +2008,8 @@
   instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
   instanceKlass::cast(WK_KLASS(Cleaner_klass))->set_reference_type(REF_CLEANER);
 
+  initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(ReferenceQueue_klass), scan, CHECK);
+
   // JSR 292 classes
   WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
   WKID jsr292_group_end   = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
--- a/src/share/vm/classfile/systemDictionary.hpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/classfile/systemDictionary.hpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -125,6 +125,7 @@
   template(PhantomReference_klass,       java_lang_ref_PhantomReference, Pre) \
   template(Cleaner_klass,                sun_misc_Cleaner,               Pre) \
   template(Finalizer_klass,              java_lang_ref_Finalizer,        Pre) \
+  template(ReferenceQueue_klass,         java_lang_ref_ReferenceQueue,   Pre) \
                                                                               \
   template(Thread_klass,                 java_lang_Thread,               Pre) \
   template(ThreadGroup_klass,            java_lang_ThreadGroup,          Pre) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -82,6 +82,7 @@
   template(java_lang_ref_PhantomReference,            "java/lang/ref/PhantomReference")           \
   template(sun_misc_Cleaner,                          "sun/misc/Cleaner")                         \
   template(java_lang_ref_Finalizer,                   "java/lang/ref/Finalizer")                  \
+  template(java_lang_ref_ReferenceQueue,              "java/lang/ref/ReferenceQueue")             \
   template(java_lang_reflect_AccessibleObject,        "java/lang/reflect/AccessibleObject")       \
   template(java_lang_reflect_Method,                  "java/lang/reflect/Method")                 \
   template(java_lang_reflect_Constructor,             "java/lang/reflect/Constructor")            \
@@ -384,6 +385,8 @@
   template(array_klass_name,                          "array_klass")                              \
   template(oop_size_name,                             "oop_size")                                 \
   template(static_oop_field_count_name,               "static_oop_field_count")                   \
+  template(referencequeue_null_name,                  "NULL")                                     \
+  template(referencequeue_enqueued_name,              "ENQUEUED")                                 \
                                                                                                   \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
@@ -473,6 +476,7 @@
   template(class_signature,                           "Ljava/lang/Class;")                                        \
   template(string_signature,                          "Ljava/lang/String;")                                       \
   template(reference_signature,                       "Ljava/lang/ref/Reference;")                                \
+  template(referencequeue_signature,                  "Ljava/lang/ref/ReferenceQueue;")                           \
   template(concurrenthashmap_signature,               "Ljava/util/concurrent/ConcurrentHashMap;")                 \
   template(String_StringBuilder_signature,            "(Ljava/lang/String;)Ljava/lang/StringBuilder;")            \
   template(int_StringBuilder_signature,               "(I)Ljava/lang/StringBuilder;")                             \
--- a/src/share/vm/oops/klass.cpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/oops/klass.cpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -35,6 +35,19 @@
 #include "oops/oop.inline2.hpp"
 #include "runtime/atomic.hpp"
 
+bool Klass::is_cloneable() const {
+  return _access_flags.is_cloneable() ||
+         is_subtype_of(SystemDictionary::Cloneable_klass());
+}
+
+void Klass::set_is_cloneable() {
+  if (oop_is_instance() && instanceKlass::cast(this->as_klassOop())->reference_type() != REF_NONE) {
+    // Reference cloning should not be intrinsified and always happen in JVM_Clone.
+  } else {
+    _access_flags.set_is_cloneable();
+  }
+}
+
 void Klass::set_name(Symbol* n) {
   _name = n;
   if (_name != NULL) _name->increment_refcount();
--- a/src/share/vm/oops/klass.hpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/oops/klass.hpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -673,8 +673,8 @@
   bool has_final_method() const         { return _access_flags.has_final_method(); }
   void set_has_finalizer()              { _access_flags.set_has_finalizer(); }
   void set_has_final_method()           { _access_flags.set_has_final_method(); }
-  bool is_cloneable() const             { return _access_flags.is_cloneable(); }
-  void set_is_cloneable()               { _access_flags.set_is_cloneable(); }
+  bool is_cloneable() const;
+  void set_is_cloneable();
   bool has_vanilla_constructor() const  { return _access_flags.has_vanilla_constructor(); }
   void set_has_vanilla_constructor()    { _access_flags.set_has_vanilla_constructor(); }
   bool has_miranda_methods () const     { return access_flags().has_miranda_methods(); }
--- a/src/share/vm/prims/jvm.cpp	Thu Mar 15 17:02:56 2018 +0300
+++ b/src/share/vm/prims/jvm.cpp	Mon Jan 22 14:27:46 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -78,6 +78,10 @@
 # include "jvm_bsd.h"
 #endif
 
+#if INCLUDE_ALL_GCS
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#endif // INCLUDE_ALL_GCS
+
 #include <errno.h>
 
 #ifndef USDT2
@@ -543,6 +547,28 @@
 JVM_END
 
 
+static void fixup_cloned_reference(ReferenceType ref_type, oop src, oop clone) {
+  // If G1 is enabled then we need to register a non-null referent
+  // with the SATB barrier.
+#if INCLUDE_ALL_GCS
+  if (UseG1GC) {
+    oop referent = java_lang_ref_Reference::referent(clone);
+    if (referent != NULL) {
+      G1SATBCardTableModRefBS::enqueue(referent);
+    }
+  }
+#endif // INCLUDE_ALL_GCS
+  if ((java_lang_ref_Reference::next(clone) != NULL) ||
+      (java_lang_ref_Reference::queue(clone) == java_lang_ref_ReferenceQueue::ENQUEUED_queue())) {
+    // If the source has been enqueued or is being enqueued, don't
+    // register the clone with a queue.
+    java_lang_ref_Reference::set_queue(clone, java_lang_ref_ReferenceQueue::NULL_queue());
+  }
+  // discovered and next are list links; the clone is not in those lists.
+  java_lang_ref_Reference::set_discovered(clone, NULL);
+  java_lang_ref_Reference::set_next(clone, NULL);
+}
+
 JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
   JVMWrapper("JVM_Clone");
   Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
@@ -569,11 +595,16 @@
 
   // Make shallow object copy
   const int size = obj->size();
+  ReferenceType ref_type = REF_NONE;
   oop new_obj = NULL;
   if (obj->is_javaArray()) {
     const int length = ((arrayOop)obj())->length();
     new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
   } else {
+    ref_type = instanceKlass::cast(klass())->reference_type();
+    assert((ref_type == REF_NONE) ==
+           !klass->is_subclass_of(SystemDictionary::Reference_klass()),
+           "invariant");
     new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
   }
   // 4839641 (4840070): We must do an oop-atomic copy, because if another thread
@@ -596,6 +627,12 @@
   assert(bs->has_write_region_opt(), "Barrier set does not have write_region");
   bs->write_region(MemRegion((HeapWord*)new_obj, size));
 
+  // If cloning a Reference, set Reference fields to a safe state.
+  // Fixup must be completed before any safepoint.
+  if (ref_type != REF_NONE) {
+    fixup_cloned_reference(ref_type, obj(), new_obj);
+  }
+  
   // Caution: this involves a java upcall, so the clone should be
   // "gc-robust" by this stage.
   if (klass->has_finalizer()) {