8202713: Create a MacroAssembler::access_load/store_at wrapper for S390 and PPC
authormdoerr
Thu, 17 May 2018 14:19:54 +0200
changeset 50162 f9fe56417050
parent 50161 e2d9b38630c3
child 50163 268ea94772da
8202713: Create a MacroAssembler::access_load/store_at wrapper for S390 and PPC Reviewed-by: eosterlund, goetz
src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp
src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp
src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp
src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp
src/hotspot/cpu/ppc/interp_masm_ppc.hpp
src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp
src/hotspot/cpu/ppc/methodHandles_ppc.cpp
src/hotspot/cpu/ppc/stubGenerator_ppc.cpp
src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
src/hotspot/cpu/ppc/templateTable_ppc_64.cpp
src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp
src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp
src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp
src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp
src/hotspot/cpu/s390/interp_masm_s390.cpp
src/hotspot/cpu/s390/macroAssembler_s390.cpp
src/hotspot/cpu/s390/macroAssembler_s390.hpp
src/hotspot/cpu/s390/methodHandles_s390.cpp
src/hotspot/cpu/s390/s390.ad
src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
src/hotspot/cpu/s390/templateTable_s390.cpp
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Thu May 17 14:19:54 2018 +0200
@@ -304,15 +304,15 @@
 
 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                     Register base, RegisterOrConstant ind_or_offs, Register dst,
-                                    Register tmp1, Register tmp2, bool needs_frame, Label *is_null) {
+                                    Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null) {
   bool on_oop = type == T_OBJECT || type == T_ARRAY;
   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
   bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
   bool on_reference = on_weak || on_phantom;
   Label done;
-  if (on_oop && on_reference && is_null == NULL) { is_null = &done; }
+  if (on_oop && on_reference && L_handle_null == NULL) { L_handle_null = &done; }
   // Load the value of the referent field.
-  ModRefBarrierSetAssembler::load_at(masm, decorators, type, base, ind_or_offs, dst, tmp1, tmp2, needs_frame, is_null);
+  ModRefBarrierSetAssembler::load_at(masm, decorators, type, base, ind_or_offs, dst, tmp1, tmp2, needs_frame, L_handle_null);
   if (on_oop && on_reference) {
     // Generate the G1 pre-barrier code to log the value of
     // the referent field in an SATB buffer. Note with
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp	Thu May 17 14:19:54 2018 +0200
@@ -61,7 +61,7 @@
 
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                        Register base, RegisterOrConstant ind_or_offs, Register dst,
-                       Register tmp1, Register tmp2, bool needs_frame, Label *is_null = NULL);
+                       Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null = NULL);
 
   virtual void resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2, bool needs_frame);
 };
--- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp	Thu May 17 14:19:54 2018 +0200
@@ -65,9 +65,10 @@
 
 void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register base, RegisterOrConstant ind_or_offs, Register dst,
-                                  Register tmp1, Register tmp2, bool needs_frame, Label *is_null) {
-  bool on_heap = (decorators & IN_HEAP) != 0;
-  bool on_root = (decorators & IN_ROOT) != 0;
+                                  Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null) {
+  bool on_heap  = (decorators & IN_HEAP) != 0;
+  bool on_root  = (decorators & IN_ROOT) != 0;
+  bool not_null = (decorators & OOP_NOT_NULL) != 0;
   assert(on_heap || on_root, "where?");
   assert_different_registers(ind_or_offs.register_or_noreg(), dst, R0);
 
@@ -75,19 +76,24 @@
   case T_ARRAY:
   case T_OBJECT: {
     if (UseCompressedOops && on_heap) {
-      __ lwz(dst, ind_or_offs, base);
-      if (is_null) {
+      if (L_handle_null != NULL) { // Label provided.
+        __ lwz(dst, ind_or_offs, base);
         __ cmpwi(CCR0, dst, 0);
-        __ beq(CCR0, *is_null);
+        __ beq(CCR0, *L_handle_null);
         __ decode_heap_oop_not_null(dst);
-      } else {
+      } else if (not_null) { // Guaranteed to be not null.
+        Register narrowOop = (tmp1 != noreg && Universe::narrow_oop_base_disjoint()) ? tmp1 : dst;
+        __ lwz(narrowOop, ind_or_offs, base);
+        __ decode_heap_oop_not_null(dst, narrowOop);
+      } else { // Any oop.
+        __ lwz(dst, ind_or_offs, base);
         __ decode_heap_oop(dst);
       }
     } else {
       __ ld(dst, ind_or_offs, base);
-      if (is_null) {
+      if (L_handle_null != NULL) {
         __ cmpdi(CCR0, dst, 0);
-        __ beq(CCR0, *is_null);
+        __ beq(CCR0, *L_handle_null);
       }
     }
     break;
--- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp	Thu May 17 14:19:54 2018 +0200
@@ -45,7 +45,7 @@
 
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                        Register base, RegisterOrConstant ind_or_offs, Register dst,
-                       Register tmp1, Register tmp2, bool needs_frame, Label *is_null = NULL);
+                       Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null = NULL);
 
   virtual void resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2, bool needs_frame);
 
--- a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp	Thu May 17 14:19:54 2018 +0200
@@ -77,7 +77,7 @@
                          Register tmp1, Register tmp2, Register tmp3, Label &ok_is_subtype);
 
   // Load object from cpool->resolved_references(index).
-  void load_resolved_reference_at_index(Register result, Register index, Label *is_null = NULL);
+  void load_resolved_reference_at_index(Register result, Register index, Label *L_handle_null = NULL);
 
   // load cpool->resolved_klass_at(index)
   void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass);
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp	Thu May 17 14:19:54 2018 +0200
@@ -471,7 +471,7 @@
 }
 
 // Load object from cpool->resolved_references(index).
-void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index, Label *is_null) {
+void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index, Label *L_handle_null) {
   assert_different_registers(result, index);
   get_constant_pool(result);
 
@@ -494,8 +494,7 @@
 #endif
   // Add in the index.
   add(result, tmp, result);
-  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->load_at(this, IN_HEAP, T_OBJECT, result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, tmp, R0, false, is_null);
+  load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, tmp, R0, false, 0, L_handle_null);
 }
 
 // load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp	Thu May 17 14:19:54 2018 +0200
@@ -2045,7 +2045,8 @@
                                               Label& wrong_method_type) {
   assert_different_registers(mtype_reg, mh_reg, temp_reg);
   // Compare method type against that of the receiver.
-  load_heap_oop_not_null(temp_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg), mh_reg);
+  load_heap_oop(temp_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg), mh_reg,
+                noreg, noreg, false, OOP_NOT_NULL);
   cmpd(CCR0, temp_reg, mtype_reg);
   bne(CCR0, wrong_method_type);
 }
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp	Thu May 17 14:19:54 2018 +0200
@@ -27,6 +27,7 @@
 #define CPU_PPC_VM_MACROASSEMBLER_PPC_HPP
 
 #include "asm/assembler.hpp"
+#include "oops/accessDecorators.hpp"
 #include "runtime/rtmLocking.hpp"
 #include "utilities/macros.hpp"
 
@@ -691,17 +692,26 @@
   inline void null_check_throw(Register a, int offset, Register temp_reg, address exception_entry);
   inline void null_check(Register a, int offset, Label *Lis_null); // implicit only if Lis_null not provided
 
-  // Load heap oop and decompress. Loaded oop may not be null.
-  // Specify tmp to save one cycle.
-  inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg,
-                                     Register tmp = noreg);
-  // Store heap oop and decompress.  Decompressed oop may not be null.
-  // Specify tmp register if d should not be changed.
-  inline void store_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1,
-                                      Register tmp = noreg);
+  // Access heap oop, handle encoding and GC barriers.
+  // Some GC barriers call C so use needs_frame = true if an extra frame is needed at the current call site.
+ private:
+  inline void access_store_at(BasicType type, DecoratorSet decorators,
+                              Register base, RegisterOrConstant ind_or_offs, Register val,
+                              Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
+  inline void access_load_at(BasicType type, DecoratorSet decorators,
+                             Register base, RegisterOrConstant ind_or_offs, Register dst,
+                             Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null = NULL);
 
-  // Null allowed.
-  inline void load_heap_oop(Register d, RegisterOrConstant offs, Register s1 = noreg, Label *is_null = NULL);
+ public:
+  // Specify tmp1 for better code in certain compressed oops cases. Specify Label to bail out on null oop.
+  // tmp1, tmp2 and needs_frame are used with decorators ON_PHANTOM_OOP_REF or ON_WEAK_OOP_REF.
+  inline void load_heap_oop(Register d, RegisterOrConstant offs, Register s1,
+                            Register tmp1, Register tmp2, bool needs_frame,
+                            DecoratorSet decorators = 0, Label *L_handle_null = NULL);
+
+  inline void store_heap_oop(Register d, RegisterOrConstant offs, Register s1,
+                             Register tmp1, Register tmp2, Register tmp3, bool needs_frame,
+                             DecoratorSet decorators = 0);
 
   // Encode/decode heap oop. Oop may not be null, else en/decoding goes wrong.
   // src == d allowed.
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp	Thu May 17 14:19:54 2018 +0200
@@ -30,6 +30,8 @@
 #include "asm/macroAssembler.hpp"
 #include "asm/codeBuffer.hpp"
 #include "code/codeCache.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "runtime/safepointMechanism.hpp"
 
 inline bool MacroAssembler::is_ld_largeoffset(address a) {
@@ -323,45 +325,52 @@
   }
 }
 
-inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1, Register tmp) {
-  if (UseCompressedOops) {
-    // In disjoint mode decoding can save a cycle if src != dst.
-    Register narrowOop = (tmp != noreg && Universe::narrow_oop_base_disjoint()) ? tmp : d;
-    lwz(narrowOop, offs, s1);
-    // Attention: no null check here!
-    Register res = decode_heap_oop_not_null(d, narrowOop);
-    assert(res == d, "caller will not consume loaded value");
+inline void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators,
+                                            Register base, RegisterOrConstant ind_or_offs, Register val,
+                                            Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
+  assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL |
+                         ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator");
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::store_at(this, decorators, type,
+                                      base, ind_or_offs, val,
+                                      tmp1, tmp2, tmp3, needs_frame);
   } else {
-    ld(d, offs, s1);
+    bs->store_at(this, decorators, type,
+                 base, ind_or_offs, val,
+                 tmp1, tmp2, tmp3, needs_frame);
   }
 }
 
-inline void MacroAssembler::store_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1, Register tmp) {
-  if (UseCompressedOops) {
-    Register compressedOop = encode_heap_oop_not_null((tmp != noreg) ? tmp : d, d);
-    stw(compressedOop, offs, s1);
+inline void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators,
+                                           Register base, RegisterOrConstant ind_or_offs, Register dst,
+                                           Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null) {
+  assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL |
+                         ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator");
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::load_at(this, decorators, type,
+                                     base, ind_or_offs, dst,
+                                     tmp1, tmp2, needs_frame, L_handle_null);
   } else {
-    std(d, offs, s1);
+    bs->load_at(this, decorators, type,
+                base, ind_or_offs, dst,
+                tmp1, tmp2, needs_frame, L_handle_null);
   }
 }
 
-inline void MacroAssembler::load_heap_oop(Register d, RegisterOrConstant offs, Register s1, Label *is_null) {
-  if (UseCompressedOops) {
-    lwz(d, offs, s1);
-    if (is_null != NULL) {
-      cmpwi(CCR0, d, 0);
-      beq(CCR0, *is_null);
-      decode_heap_oop_not_null(d);
-    } else {
-      decode_heap_oop(d);
-    }
-  } else {
-    ld(d, offs, s1);
-    if (is_null != NULL) {
-      cmpdi(CCR0, d, 0);
-      beq(CCR0, *is_null);
-    }
-  }
+inline void MacroAssembler::load_heap_oop(Register d, RegisterOrConstant offs, Register s1,
+                                          Register tmp1, Register tmp2,
+                                          bool needs_frame, DecoratorSet decorators, Label *L_handle_null) {
+  access_load_at(T_OBJECT, IN_HEAP | decorators, s1, offs, d, tmp1, tmp2, needs_frame, L_handle_null);
+}
+
+inline void MacroAssembler::store_heap_oop(Register d, RegisterOrConstant offs, Register s1,
+                                           Register tmp1, Register tmp2, Register tmp3,
+                                           bool needs_frame, DecoratorSet decorators) {
+  access_store_at(T_OBJECT, IN_HEAP | decorators, s1, offs, d, tmp1, tmp2, tmp3, needs_frame);
 }
 
 inline Register MacroAssembler::encode_heap_oop_not_null(Register d, Register src) {
--- a/src/hotspot/cpu/ppc/methodHandles_ppc.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/methodHandles_ppc.cpp	Thu May 17 14:19:54 2018 +0200
@@ -173,11 +173,14 @@
 
   // Load the invoker, as MH -> MH.form -> LF.vmentry
   __ verify_oop(recv);
-  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv, temp2);
+  __ load_heap_oop(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv,
+                   temp2, noreg, false, OOP_NOT_NULL);
   __ verify_oop(method_temp);
-  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2);
+  __ load_heap_oop(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp,
+                   temp2, noreg, false, OOP_NOT_NULL);
   __ verify_oop(method_temp);
-  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), method_temp);
+  __ load_heap_oop(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), method_temp,
+                   temp2, noreg, false, OOP_NOT_NULL);
   __ verify_oop(method_temp);
   __ ld(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), method_temp);
 
@@ -338,7 +341,8 @@
       if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {
         Label L_ok;
         Register temp2_defc = temp2;
-        __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
+        __ load_heap_oop(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg,
+                         temp3, noreg, false, OOP_NOT_NULL);
         load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
         __ verify_klass_ptr(temp2_defc);
         __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -365,7 +369,8 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2);
       }
-      __ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg);
+      __ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg,
+                       temp3, noreg, false, OOP_NOT_NULL);
       __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), R19_method);
       break;
 
@@ -373,7 +378,8 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2);
       }
-      __ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg);
+      __ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg,
+                       temp3, noreg, false, OOP_NOT_NULL);
       __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), R19_method);
       break;
 
@@ -415,7 +421,8 @@
       }
 
       Register temp2_intf = temp2;
-      __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
+      __ load_heap_oop(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg,
+                       temp3, noreg, false, OOP_NOT_NULL);
       load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
       __ verify_klass_ptr(temp2_intf);
 
--- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp	Thu May 17 14:19:54 2018 +0200
@@ -2198,7 +2198,7 @@
 
     // ======== loop entry is here ========
     __ bind(load_element);
-    __ load_heap_oop(R10_oop, R8_offset, R3_from, &store_null);  // Load the oop.
+    __ load_heap_oop(R10_oop, R8_offset, R3_from, R12_tmp, noreg, false, AS_RAW, &store_null);
 
     __ load_klass(R11_klass, R10_oop); // Query the object klass.
 
--- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp	Thu May 17 14:19:54 2018 +0200
@@ -524,11 +524,8 @@
   __ cmpdi(CCR0, R3_RET, 0);
   __ beq(CCR0, slow_path);
 
-  // Load the value of the referent field.
-  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT,
-                    R3_RET, referent_offset, R3_RET,
-                    /* non-volatile temp */ R31, R11_scratch1, true);
+  __ load_heap_oop(R3_RET, referent_offset, R3_RET,
+                   /* non-volatile temp */ R31, R11_scratch1, true, ON_WEAK_OOP_REF);
 
   // Generate the G1 pre-barrier code to log the value of
   // the referent field in an SATB buffer. Note with
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Thu May 17 14:19:54 2018 +0200
@@ -62,8 +62,7 @@
                          Register           tmp3,
                          DecoratorSet       decorators) {
   assert_different_registers(tmp1, tmp2, tmp3, val, base);
-  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->store_at(_masm, decorators, T_OBJECT, base, offset, val, tmp1, tmp2, tmp3, false);
+  __ store_heap_oop(val, offset, base, tmp1, tmp2, tmp3, false, decorators);
 }
 
 static void do_oop_load(InterpreterMacroAssembler* _masm,
@@ -75,8 +74,7 @@
                         DecoratorSet decorators) {
   assert_different_registers(base, tmp1, tmp2);
   assert_different_registers(dst, tmp1, tmp2);
-  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->load_at(_masm, decorators, T_OBJECT, base, offset, dst, tmp1, tmp2, false);
+  __ load_heap_oop(dst, offset, base, tmp1, tmp2, false, decorators);
 }
 
 // ============================================================================
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Thu May 17 14:19:54 2018 +0200
@@ -96,14 +96,14 @@
 }
 
 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
-                                    const Address& src, Register dst, Register tmp1, Register tmp2, Label *is_null) {
+                                    const Address& src, Register dst, Register tmp1, Register tmp2, Label *L_handle_null) {
   bool on_oop = type == T_OBJECT || type == T_ARRAY;
   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
   bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
   bool on_reference = on_weak || on_phantom;
   Label done;
-  if (on_oop && on_reference && is_null == NULL) { is_null = &done; }
-  ModRefBarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp1, tmp2, is_null);
+  if (on_oop && on_reference && L_handle_null == NULL) { L_handle_null = &done; }
+  ModRefBarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp1, tmp2, L_handle_null);
   if (on_oop && on_reference) {
     // Generate the G1 pre-barrier code to log the value of
     // the referent field in an SATB buffer.
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp	Thu May 17 14:19:54 2018 +0200
@@ -65,7 +65,7 @@
 #endif
 
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
-                       const Address& src, Register dst, Register tmp1, Register tmp2, Label *is_null = NULL);
+                       const Address& src, Register dst, Register tmp1, Register tmp2, Label *L_handle_null = NULL);
 
   virtual void resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2);
 };
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp	Thu May 17 14:19:54 2018 +0200
@@ -36,9 +36,10 @@
 }
 
 void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
-                                  const Address& addr, Register dst, Register tmp1, Register tmp2, Label *is_null) {
-  bool on_heap = (decorators & IN_HEAP) != 0;
-  bool on_root = (decorators & IN_ROOT) != 0;
+                                  const Address& addr, Register dst, Register tmp1, Register tmp2, Label *L_handle_null) {
+  bool on_heap  = (decorators & IN_HEAP) != 0;
+  bool on_root  = (decorators & IN_ROOT) != 0;
+  bool not_null = (decorators & OOP_NOT_NULL) != 0;
   assert(on_heap || on_root, "where?");
 
   switch (type) {
@@ -46,16 +47,16 @@
   case T_OBJECT: {
     if (UseCompressedOops && on_heap) {
       __ z_llgf(dst, addr);
-      if (is_null) {
-        __ compareU32_and_branch(dst, (intptr_t)0, Assembler::bcondEqual, *is_null);
+      if (L_handle_null != NULL) { // Label provided.
+        __ compareU32_and_branch(dst, (intptr_t)0, Assembler::bcondEqual, *L_handle_null);
         __ oop_decoder(dst, dst, false);
       } else {
-        __ oop_decoder(dst, dst, true);
+        __ oop_decoder(dst, dst, !not_null);
       }
     } else {
       __ z_lg(dst, addr);
-      if (is_null) {
-        __ compareU64_and_branch(dst, (intptr_t)0, Assembler::bcondEqual, *is_null);
+      if (L_handle_null != NULL) {
+        __ compareU64_and_branch(dst, (intptr_t)0, Assembler::bcondEqual, *L_handle_null);
       }
     }
     break;
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp	Thu May 17 14:19:54 2018 +0200
@@ -40,7 +40,7 @@
                                   Register dst, Register count, bool do_return = false);
 
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
-                       const Address& addr, Register dst, Register tmp1, Register tmp2, Label *is_null = NULL);
+                       const Address& addr, Register dst, Register tmp1, Register tmp2, Label *L_handle_null = NULL);
   virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                         const Address& addr, Register val, Register tmp1, Register tmp2, Register tmp3);
 
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp	Thu May 17 14:19:54 2018 +0200
@@ -391,8 +391,7 @@
   bind(index_ok);
 #endif
   z_agr(result, index);    // Address of indexed array element.
-  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->load_at(this, IN_HEAP, T_OBJECT, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), result, tmp, noreg);
+  load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), tmp, noreg);
 }
 
 // load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Thu May 17 14:19:54 2018 +0200
@@ -4047,68 +4047,52 @@
   BLOCK_COMMENT("} compare heap oop");
 }
 
-// Load heap oop and decompress, if necessary.
-void  MacroAssembler::load_heap_oop(Register dest, const Address &a) {
-  if (UseCompressedOops) {
-    z_llgf(dest, a.disp(), a.indexOrR0(), a.baseOrR0());
-    oop_decoder(dest, dest, true);
-  } else {
-    z_lg(dest, a.disp(), a.indexOrR0(), a.baseOrR0());
-  }
-}
-
-// Load heap oop and decompress, if necessary.
-void MacroAssembler::load_heap_oop(Register dest, int64_t disp, Register base) {
-  if (UseCompressedOops) {
-    z_llgf(dest, disp, base);
-    oop_decoder(dest, dest, true);
-  } else {
-    z_lg(dest, disp, base);
-  }
-}
-
-// Load heap oop and decompress, if necessary.
-void MacroAssembler::load_heap_oop_not_null(Register dest, int64_t disp, Register base) {
-  if (UseCompressedOops) {
-    z_llgf(dest, disp, base);
-    oop_decoder(dest, dest, false);
+void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators,
+                                     const Address& addr, Register val,
+                                     Register tmp1, Register tmp2, Register tmp3) {
+  assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL |
+                         ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator");
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::store_at(this, decorators, type,
+                                      addr, val,
+                                      tmp1, tmp2, tmp3);
   } else {
-    z_lg(dest, disp, base);
-  }
-}
-
-// Compress, if necessary, and store oop to heap.
-void MacroAssembler::store_heap_oop(Register Roop, RegisterOrConstant offset, Register base) {
-  Register Ridx = offset.is_register() ? offset.register_or_noreg() : Z_R0;
-  if (UseCompressedOops) {
-    assert_different_registers(Roop, offset.register_or_noreg(), base);
-    encode_heap_oop(Roop);
-    z_st(Roop, offset.constant_or_zero(), Ridx, base);
+    bs->store_at(this, decorators, type,
+                 addr, val,
+                 tmp1, tmp2, tmp3);
+  }
+}
+
+void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators,
+                                    const Address& addr, Register dst,
+                                    Register tmp1, Register tmp2, Label *is_null) {
+  assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL |
+                         ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator");
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::load_at(this, decorators, type,
+                                     addr, dst,
+                                     tmp1, tmp2, is_null);
   } else {
-    z_stg(Roop, offset.constant_or_zero(), Ridx, base);
-  }
-}
-
-// Compress, if necessary, and store oop to heap. Oop is guaranteed to be not NULL.
-void MacroAssembler::store_heap_oop_not_null(Register Roop, RegisterOrConstant offset, Register base) {
-  Register Ridx = offset.is_register() ? offset.register_or_noreg() : Z_R0;
-  if (UseCompressedOops) {
-    assert_different_registers(Roop, offset.register_or_noreg(), base);
-    encode_heap_oop_not_null(Roop);
-    z_st(Roop, offset.constant_or_zero(), Ridx, base);
-  } else {
-    z_stg(Roop, offset.constant_or_zero(), Ridx, base);
-  }
-}
-
-// Store NULL oop to heap.
-void MacroAssembler::store_heap_oop_null(Register zero, RegisterOrConstant offset, Register base) {
-  Register Ridx = offset.is_register() ? offset.register_or_noreg() : Z_R0;
-  if (UseCompressedOops) {
-    z_st(zero, offset.constant_or_zero(), Ridx, base);
-  } else {
-    z_stg(zero, offset.constant_or_zero(), Ridx, base);
-  }
+    bs->load_at(this, decorators, type,
+                addr, dst,
+                tmp1, tmp2, is_null);
+  }
+}
+
+void MacroAssembler::load_heap_oop(Register dest, const Address &a,
+                                   Register tmp1, Register tmp2,
+                                   DecoratorSet decorators, Label *is_null) {
+  access_load_at(T_OBJECT, IN_HEAP | decorators, a, dest, tmp1, tmp2, is_null);
+}
+
+void MacroAssembler::store_heap_oop(Register Roop, const Address &a,
+                                    Register tmp1, Register tmp2, Register tmp3,
+                                    DecoratorSet decorators) {
+  access_store_at(T_OBJECT, IN_HEAP | decorators, a, Roop, tmp1, tmp2, tmp3);
 }
 
 //-------------------------------------------------
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Thu May 17 14:19:54 2018 +0200
@@ -27,6 +27,7 @@
 #define CPU_S390_VM_MACROASSEMBLER_S390_HPP
 
 #include "asm/assembler.hpp"
+#include "oops/accessDecorators.hpp"
 
 #define MODERN_IFUN(name)  ((void (MacroAssembler::*)(Register, int64_t, Register, Register))&MacroAssembler::name)
 #define CLASSIC_IFUN(name) ((void (MacroAssembler::*)(Register, int64_t, Register, Register))&MacroAssembler::name)
@@ -804,12 +805,25 @@
   int  get_oop_base_complement(Register Rbase, uint64_t oop_base);
   void compare_heap_oop(Register Rop1, Address mem, bool maybeNULL);
   void compare_klass_ptr(Register Rop1, int64_t disp, Register Rbase, bool maybeNULL);
-  void load_heap_oop(Register dest, const Address &a);
-  void load_heap_oop(Register d, int64_t si16, Register s1);
-  void load_heap_oop_not_null(Register d, int64_t si16, Register s1);
-  void store_heap_oop(Register Roop, RegisterOrConstant offset, Register base);
-  void store_heap_oop_not_null(Register Roop, RegisterOrConstant offset, Register base);
-  void store_heap_oop_null(Register zero, RegisterOrConstant offset, Register base);
+
+  // Access heap oop, handle encoding and GC barriers.
+ private:
+  void access_store_at(BasicType type, DecoratorSet decorators,
+                       const Address& addr, Register val,
+                       Register tmp1, Register tmp2, Register tmp3);
+  void access_load_at(BasicType type, DecoratorSet decorators,
+                      const Address& addr, Register dst,
+                      Register tmp1, Register tmp2, Label *is_null = NULL);
+
+ public:
+  // tmp1 and tmp2 are used with decorators ON_PHANTOM_OOP_REF or ON_WEAK_OOP_REF.
+  void load_heap_oop(Register dest, const Address &a,
+                     Register tmp1, Register tmp2,
+                     DecoratorSet decorators = 0, Label *is_null = NULL);
+  void store_heap_oop(Register Roop, const Address &a,
+                      Register tmp1, Register tmp2, Register tmp3,
+                      DecoratorSet decorators = 0);
+
   void oop_encoder(Register Rdst, Register Rsrc, bool maybeNULL,
                    Register Rbase = Z_R1, int pow2_offset = -1, bool only32bitValid = false);
   void oop_decoder(Register Rdst, Register Rsrc, bool maybeNULL,
--- a/src/hotspot/cpu/s390/methodHandles_s390.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/methodHandles_s390.cpp	Thu May 17 14:19:54 2018 +0200
@@ -196,16 +196,19 @@
   // Load the invoker, as MH -> MH.form -> LF.vmentry
   __ verify_oop(recv);
   __ load_heap_oop(method_temp,
-                     Address(recv,
-                             NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())));
+                   Address(recv,
+                           NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())),
+                   noreg, noreg, OOP_NOT_NULL);
   __ verify_oop(method_temp);
   __ load_heap_oop(method_temp,
-                     Address(method_temp,
-                             NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())));
+                   Address(method_temp,
+                           NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())),
+                   noreg, noreg, OOP_NOT_NULL);
   __ verify_oop(method_temp);
   __ load_heap_oop(method_temp,
-          Address(method_temp,
-                  NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())));
+                   Address(method_temp,
+                           NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())),
+                   noreg, noreg, OOP_NOT_NULL);
   __ verify_oop(method_temp);
   __ z_lg(method_temp,
           Address(method_temp,
@@ -405,7 +408,8 @@
       NearLabel L_ok;
       Register temp2_defc = temp2;
 
-      __ load_heap_oop(temp2_defc, member_clazz);
+      __ load_heap_oop(temp2_defc, member_clazz,
+                       noreg, noreg, OOP_NOT_NULL);
       load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
       __ verify_klass_ptr(temp2_defc);
       __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -431,7 +435,8 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
       }
-      __ load_heap_oop(Z_method, member_vmtarget);
+      __ load_heap_oop(Z_method, member_vmtarget,
+                       noreg, noreg, OOP_NOT_NULL);
       __ z_lg(Z_method, vmtarget_method);
       method_is_live = true;
       break;
@@ -440,7 +445,8 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
       }
-      __ load_heap_oop(Z_method, member_vmtarget);
+      __ load_heap_oop(Z_method, member_vmtarget,
+                       noreg, noreg, OOP_NOT_NULL);
       __ z_lg(Z_method, vmtarget_method);
       method_is_live = true;
       break;
@@ -481,7 +487,8 @@
 
       Register temp3_intf = temp3;
 
-      __ load_heap_oop(temp3_intf, member_clazz);
+      __ load_heap_oop(temp3_intf, member_clazz,
+                       noreg, noreg, OOP_NOT_NULL);
       load_klass_from_Class(_masm, temp3_intf, temp2, temp4);
 
       Register Z_index = Z_method;
--- a/src/hotspot/cpu/s390/s390.ad	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/s390.ad	Thu May 17 14:19:54 2018 +0200
@@ -2239,8 +2239,8 @@
       // Go through the vtable. Get receiver klass. Receiver already
       // checked for non-null. If we'll go thru a C2I adapter, the
       // interpreter expects method in Z_method.
-      // Use Z_method to temporarily hold the klass oop. Z_R1_scratch is destroyed
-      // by load_heap_oop_not_null.
+      // Use Z_method to temporarily hold the klass oop.
+      // Z_R1_scratch is destroyed.
       __ load_klass(Z_method, Z_R2);
 
       int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index * vtableEntry::size_in_bytes();
--- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp	Thu May 17 14:19:54 2018 +0200
@@ -512,9 +512,7 @@
   __ z_bre(slow_path);
 
   //  Load the value of the referent field.
- BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
- bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT,
-                   Address(pre_val, referent_offset), pre_val, scratch1, scratch2);
+  __ load_heap_oop(pre_val, Address(pre_val, referent_offset), scratch1, scratch2, ON_WEAK_OOP_REF);
 
   // Restore caller sp for c2i case.
   __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp	Wed May 16 11:11:03 2018 -0400
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp	Thu May 17 14:19:54 2018 +0200
@@ -200,8 +200,7 @@
                          Register           tmp3,
                          DecoratorSet       decorators) {
   assert_different_registers(tmp1, tmp2, tmp3, val, addr.base());
-  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->store_at(_masm, decorators, T_OBJECT, addr, val, tmp1, tmp2, tmp3);
+  __ store_heap_oop(val, addr, tmp1, tmp2, tmp3, decorators);
 }
 
 static void do_oop_load(InterpreterMacroAssembler* _masm,
@@ -212,8 +211,7 @@
                         DecoratorSet decorators) {
   assert_different_registers(addr.base(), tmp1, tmp2);
   assert_different_registers(dst, tmp1, tmp2);
-  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->load_at(_masm, decorators, T_OBJECT, addr, dst, tmp1, tmp2);
+  __ load_heap_oop(dst, addr, tmp1, tmp2, decorators);
 }
 
 Address TemplateTable::at_bcp(int offset) {