8138956: Elide more final field's write memory barrier with escape analysis result
authorroland
Thu, 15 Oct 2015 09:40:45 +0200
changeset 33180 34e5004f5acb
parent 33178 f77a432b90f6
child 33181 ea9cb42aa6eb
8138956: Elide more final field's write memory barrier with escape analysis result Summary: membar for final/stable fields eliminated if possible Reviewed-by: roland, mdoerr, enevill, aph Contributed-by: hui.shi@linaro.org
hotspot/src/share/vm/opto/parse.hpp
hotspot/src/share/vm/opto/parse1.cpp
hotspot/src/share/vm/opto/parse3.cpp
--- a/hotspot/src/share/vm/opto/parse.hpp	Wed Oct 14 09:22:21 2015 -1000
+++ b/hotspot/src/share/vm/opto/parse.hpp	Thu Oct 15 09:40:45 2015 +0200
@@ -343,6 +343,7 @@
   bool          _count_invocations;  // update and test invocation counter
   bool          _method_data_update; // update method data oop
   Node*         _alloc_with_final;   // An allocation node with final field
+  Node*         _alloc_with_stable;  // An allocation node with stable field
 
   // Variables which track Java semantics during bytecode parsing:
 
@@ -398,6 +399,25 @@
     _alloc_with_final = n;
   }
 
+  Node*    alloc_with_stable() const  {
+    if (_alloc_with_stable == NodeSentinel) {
+      return NULL;
+    }
+    return _alloc_with_stable;
+  }
+
+  void set_alloc_with_stable(Node* n)  {
+    if (_alloc_with_stable == NodeSentinel) {
+      // uninitialized status, initialize with current input, can be
+      // null or valid node.
+      _alloc_with_stable = n;
+    } else if (_alloc_with_stable != n) {
+      // _alloc_with_stable isn't equal to n
+      _alloc_with_stable = NULL;
+    }
+    // _alloc_with_stable is equal with n, do nothing
+  }
+
   Block*             block()    const { return _block; }
   ciBytecodeStream&  iter()           { return _iter; }
   Bytecodes::Code    bc()       const { return _iter.cur_bc(); }
--- a/hotspot/src/share/vm/opto/parse1.cpp	Wed Oct 14 09:22:21 2015 -1000
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Thu Oct 15 09:40:45 2015 +0200
@@ -397,6 +397,7 @@
   _wrote_stable = false;
   _wrote_fields = false;
   _alloc_with_final = NULL;
+  _alloc_with_stable = NodeSentinel;
   _entry_bci = InvocationEntryBci;
   _tf = NULL;
   _block = NULL;
@@ -970,7 +971,7 @@
   // those also. If there is a predecessor allocation node, bind the
   // barrier there.
   if (wrote_stable()) {
-    _exits.insert_mem_bar(Op_MemBarRelease, alloc_with_final());
+    _exits.insert_mem_bar(Op_MemBarRelease, alloc_with_stable());
 #ifndef PRODUCT
     if (PrintOpto && (Verbose || WizardMode)) {
       method()->print_name();
--- a/hotspot/src/share/vm/opto/parse3.cpp	Wed Oct 14 09:22:21 2015 -1000
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Thu Oct 15 09:40:45 2015 +0200
@@ -313,10 +313,19 @@
 
     // Preserve allocation ptr to create precedent edge to it in membar
     // generated on exit from constructor.
-    if (C->eliminate_boxing() &&
-        adr_type->isa_oopptr() && adr_type->is_oopptr()->is_ptr_to_boxed_value() &&
-        AllocateNode::Ideal_allocation(obj, &_gvn) != NULL) {
-      set_alloc_with_final(obj);
+    if (AllocateNode::Ideal_allocation(obj, &_gvn) != NULL) {
+      if (field->is_final()) {
+        set_alloc_with_final(obj);
+      }
+      if (field->is_stable()) {
+        set_alloc_with_stable(obj);
+      }
+    } else if (field->is_stable()) {
+      // This stable field doesn't have an allocation, set
+      // alloc_with_stable as NULL: its initial value is NodeSentinel,
+      // if it is not set to NULL here, next set_alloc_with_stable
+      // call might set none-NULL value successfully.
+      set_alloc_with_stable(NULL);
     }
   }
 }