< prev index next >

src/hotspot/share/opto/memnode.cpp

Print this page

        

@@ -47,10 +47,13 @@
 #include "utilities/macros.hpp"
 #include "utilities/vmError.hpp"
 #if INCLUDE_ZGC
 #include "gc/z/c2/zBarrierSetC2.hpp"
 #endif
+#if INCLUDE_SHENANDOAHGC
+#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
+#endif
 
 // Portions of code courtesy of Clifford Click
 
 // Optimization - Graph Style
 

@@ -920,12 +923,15 @@
     LoadNode* ld = clone()->as_Load();
     Node* addp = in(MemNode::Address)->clone();
     if (ac->as_ArrayCopy()->is_clonebasic()) {
       assert(ld_alloc != NULL, "need an alloc");
       assert(addp->is_AddP(), "address must be addp");
-      assert(addp->in(AddPNode::Base) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base), "strange pattern");
-      assert(addp->in(AddPNode::Address) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address), "strange pattern");
+      assert(ac->in(ArrayCopyNode::Dest)->is_AddP(), "dest must be an address");
+#if INCLUDE_SHENANDOAHGC
+      assert(ShenandoahBarrierNode::skip_through_barrier(addp->in(AddPNode::Base)) == ShenandoahBarrierNode::skip_through_barrier(ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base)), "strange pattern");
+      assert(ShenandoahBarrierNode::skip_through_barrier(addp->in(AddPNode::Address)) == ShenandoahBarrierNode::skip_through_barrier(ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address)), "strange pattern");
+#endif
       addp->set_req(AddPNode::Base, src->in(AddPNode::Base));
       addp->set_req(AddPNode::Address, src->in(AddPNode::Address));
     } else {
       assert(ac->as_ArrayCopy()->is_arraycopy_validated() ||
              ac->as_ArrayCopy()->is_copyof_validated() ||

@@ -1077,10 +1083,13 @@
     // Load boxed value from result of valueOf() call is input parameter.
     if (this->is_Load() && ld_adr->is_AddP() &&
         (tp != NULL) && tp->is_ptr_to_boxed_value()) {
       intptr_t ignore = 0;
       Node* base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ignore);
+#if INCLUDE_SHENANDOAHGC
+      base = ShenandoahBarrierNode::skip_through_barrier(base);
+#endif
       if (base != NULL && base->is_Proj() &&
           base->as_Proj()->_con == TypeFunc::Parms &&
           base->in(0)->is_CallStaticJava() &&
           base->in(0)->as_CallStaticJava()->is_boxing_method()) {
         return base->in(0)->in(TypeFunc::Parms);

@@ -1126,12 +1135,47 @@
       // If the input to the store does not fit with the load's result type,
       // it must be truncated via an Ideal call.
       if (!phase->type(value)->higher_equal(phase->type(this)))
         return this;
     }
+
+#if INCLUDE_SHENANDOAHGC
+    PhaseIterGVN* igvn = phase->is_IterGVN();
+    if (UseShenandoahGC &&
+        igvn != NULL &&
+        value->is_Phi() &&
+        value->req() > 2 &&
+        value->in(1) != NULL &&
+        value->in(1)->is_ShenandoahBarrier()) {
+      if (igvn->_worklist.member(value) ||
+          igvn->_worklist.member(value->in(0)) ||
+          (value->in(0)->in(1) != NULL &&
+           value->in(0)->in(1)->is_IfProj() &&
+           (igvn->_worklist.member(value->in(0)->in(1)) ||
+            (value->in(0)->in(1)->in(0) != NULL &&
+             igvn->_worklist.member(value->in(0)->in(1)->in(0)))))) {
+        igvn->_worklist.push(this);
+        return this;
+      }
+    }
     // (This works even when value is a Con, but LoadNode::Value
     // usually runs first, producing the singleton type of the Con.)
+    if (UseShenandoahGC) {
+      Node* value_no_barrier = ShenandoahBarrierNode::skip_through_barrier(value->Opcode() == Op_EncodeP ? value->in(1) : value);
+      if (value->Opcode() == Op_EncodeP) {
+        if (value_no_barrier != value->in(1)) {
+          Node* encode = value->clone();
+          encode->set_req(1, value_no_barrier);
+          encode = phase->transform(encode);
+          return encode;
+        }
+      } else {
+        return value_no_barrier;
+      }
+    }
+#endif
+
     return value;
   }
 
   // Search for an existing data phi which was generated before for the same
   // instance's field to avoid infinite generation of phis in a loop.

@@ -1229,10 +1273,13 @@
     if (!base->in(Address)->is_AddP()) {
       return NULL; // Complex address
     }
     AddPNode* address = base->in(Address)->as_AddP();
     Node* cache_base = address->in(AddPNode::Base);
+#if INCLUDE_SHENANDOAHGC
+    cache_base = ShenandoahBarrierNode::skip_through_barrier(cache_base);
+#endif
     if ((cache_base != NULL) && cache_base->is_DecodeN()) {
       // Get ConP node which is static 'cache' field.
       cache_base = cache_base->in(1);
     }
     if ((cache_base != NULL) && cache_base->is_Con()) {

@@ -1693,16 +1740,28 @@
     // Different array types begin at slightly different offsets (12 vs. 16).
     // We choose T_BYTE as an example base type that is least restrictive
     // as to alignment, which will therefore produce the smallest
     // possible base offset.
     const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE);
-    const bool off_beyond_header = ((uint)off >= (uint)min_base_off);
+    const bool off_beyond_header = SHENANDOAHGC_ONLY((off != ShenandoahBrooksPointer::byte_offset() || !UseShenandoahGC) &&)
+                                    ((uint)off >= (uint)min_base_off);
 
     // Try to constant-fold a stable array element.
     if (FoldStableValues && !is_mismatched_access() && ary->is_stable()) {
       // Make sure the reference is not into the header and the offset is constant
-      ciObject* aobj = ary->const_oop();
+      ciObject* aobj = NULL;
+#if INCLUDE_SHENANDOAHGC
+      if (UseShenandoahGC && adr->is_AddP() && !adr->in(AddPNode::Base)->is_top()) {
+        Node* base = ShenandoahBarrierNode::skip_through_barrier(adr->in(AddPNode::Base));
+        if (!base->is_top()) {
+          aobj = phase->type(base)->is_aryptr()->const_oop();
+        }
+      } else
+#endif
+      {
+        aobj = ary->const_oop();
+      }
       if (aobj != NULL && off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) {
         int stable_dimension = (ary->stable_dimension() > 0 ? ary->stable_dimension() - 1 : 0);
         const Type* con_type = Type::make_constant_from_array_element(aobj->as_array(), off,
                                                                       stable_dimension,
                                                                       memory_type(), is_unsigned());

@@ -1768,11 +1827,25 @@
             "Field accesses must be precise" );
     // For oop loads, we expect the _type to be precise.
 
     // Optimize loads from constant fields.
     const TypeInstPtr* tinst = tp->is_instptr();
-    ciObject* const_oop = tinst->const_oop();
+    ciObject* const_oop = NULL;
+#if INCLUDE_SHENANDOAHGC
+    if (UseShenandoahGC && adr->is_AddP() && !adr->in(AddPNode::Base)->is_top()) {
+      Node* base = ShenandoahBarrierNode::skip_through_barrier(adr->in(AddPNode::Base));
+      if (!base->is_top()) {
+        const TypePtr* base_t = phase->type(base)->is_ptr();
+        if (base_t != TypePtr::NULL_PTR) {
+          const_oop = base_t->is_instptr()->const_oop();
+        }
+      }
+    } else
+#endif
+    {
+      const_oop = tinst->const_oop();
+    }
     if (!is_mismatched_access() && off != Type::OffsetBot && const_oop != NULL && const_oop->is_instance()) {
       const Type* con_type = Type::make_constant_from_field(const_oop->as_instance(), off, is_unsigned(), memory_type());
       if (con_type != NULL) {
         return con_type;
       }
< prev index next >