changeset 50877:2dff159158c5

ZGC: Solaris/SPARC support
author duke
date Fri, 08 Jun 2018 18:24:45 +0200
parents e95f45dc3927
children f63ee2ebf86c
files make/autoconf/hotspot.m4 src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp src/hotspot/cpu/sparc/c2_globals_sparc.hpp src/hotspot/cpu/sparc/gc/z/zBarrierSetAssembler_sparc.cpp src/hotspot/cpu/sparc/gc/z/zBarrierSetAssembler_sparc.hpp src/hotspot/cpu/sparc/macroAssembler_sparc.cpp src/hotspot/cpu/sparc/nativeInst_sparc.cpp src/hotspot/cpu/sparc/sparc.ad src/hotspot/os/solaris/globals_solaris.hpp src/hotspot/os_cpu/solaris_sparc/gc/z/zAddress_solaris_sparc.inline.hpp src/hotspot/os_cpu/solaris_sparc/gc/z/zGlobals_solaris_sparc.cpp src/hotspot/os_cpu/solaris_sparc/gc/z/zGlobals_solaris_sparc.hpp src/hotspot/os_cpu/solaris_sparc/gc/z/zLargePages_solaris_sparc.cpp src/hotspot/os_cpu/solaris_sparc/gc/z/zNUMA_solaris_sparc.cpp src/hotspot/os_cpu/solaris_sparc/gc/z/zPhysicalMemoryBacking_solaris_sparc.cpp src/hotspot/os_cpu/solaris_sparc/gc/z/zPhysicalMemoryBacking_solaris_sparc.hpp src/hotspot/os_cpu/solaris_sparc/gc/z/zVirtualMemory_solaris_sparc.cpp src/hotspot/share/adlc/formssel.cpp src/hotspot/share/adlc/formssel.hpp src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp src/hotspot/share/opto/classes.hpp src/hotspot/share/opto/connode.hpp
diffstat 22 files changed, 1134 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/make/autoconf/hotspot.m4	Fri Jun 08 18:24:45 2018 +0200
+++ b/make/autoconf/hotspot.m4	Fri Jun 08 18:24:45 2018 +0200
@@ -328,10 +328,11 @@
     fi
   fi
 
-  # Only enable ZGC on Linux x86_64
+  # Only enable ZGC on Linux x86_64 and Solaris Sparc
   AC_MSG_CHECKING([if zgc should be built])
   if HOTSPOT_CHECK_JVM_FEATURE(zgc); then
-    if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then
+    if (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64") || \
+       (test "x$OPENJDK_TARGET_OS" = "xsolaris" && test "x$OPENJDK_TARGET_CPU" = "xsparcv9"); then
       AC_MSG_RESULT([yes])
     else
       DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES zgc"
--- a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -3202,23 +3202,38 @@
   const Register dest_reg = dest->as_pointer_register();
   const Register base_reg = addr->base()->as_pointer_register();
 
-  if (Assembler::is_simm13(addr->disp())) {
-    if (addr->index()->is_valid()) {
-      const Register index_reg = addr->index()->as_pointer_register();
-      assert(index_reg != G3_scratch, "invariant");
-      __ add(base_reg, addr->disp(), G3_scratch);
-      __ add(index_reg, G3_scratch, dest_reg);
-    } else {
-      __ add(base_reg, addr->disp(), dest_reg);
-    }
-  } else {
-    __ set(addr->disp(), G3_scratch);
+  if (patch_code != lir_patch_none) {
+    PatchingStub* patch = new PatchingStub(_masm, PatchingStub::access_field_id);
+    assert(addr->disp() != 0, "must have");
+    assert(base_reg != G3_scratch, "invariant");
+    __ patchable_set(0, G3_scratch);
+    patching_epilog(patch, patch_code, base_reg, info);
+    assert(dest_reg != G3_scratch, "invariant");
     if (addr->index()->is_valid()) {
       const Register index_reg = addr->index()->as_pointer_register();
       assert(index_reg != G3_scratch, "invariant");
       __ add(index_reg, G3_scratch, G3_scratch);
     }
     __ add(base_reg, G3_scratch, dest_reg);
+  } else {
+    if (Assembler::is_simm13(addr->disp())) {
+      if (addr->index()->is_valid()) {
+        const Register index_reg = addr->index()->as_pointer_register();
+        assert(index_reg != G3_scratch, "invariant");
+        __ add(base_reg, addr->disp(), G3_scratch);
+        __ add(index_reg, G3_scratch, dest_reg);
+      } else {
+        __ add(base_reg, addr->disp(), dest_reg);
+      }
+    } else {
+      __ set(addr->disp(), G3_scratch);
+      if (addr->index()->is_valid()) {
+        const Register index_reg = addr->index()->as_pointer_register();
+        assert(index_reg != G3_scratch, "invariant");
+        __ add(index_reg, G3_scratch, G3_scratch);
+      }
+      __ add(base_reg, G3_scratch, dest_reg);
+    }
   }
 }
 
--- a/src/hotspot/cpu/sparc/c2_globals_sparc.hpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/cpu/sparc/c2_globals_sparc.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -85,6 +85,10 @@
 
 define_pd_global(bool,  TrapBasedRangeChecks,        false); // Not needed on sparc.
 
+#if INCLUDE_ZGC
+define_pd_global(bool,  PreventLoadBarrierMatcherAssert, true);
+#endif
+
 // Heap related flags
 define_pd_global(size_t, MetaspaceSize,              ScaleForWordSize(16*M));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/z/zBarrierSetAssembler_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/z/zBarrier.inline.hpp"
+#include "gc/z/zBarrierSet.hpp"
+#include "gc/z/zBarrierSetAssembler.hpp"
+#include "gc/z/zBarrierSetRuntime.hpp"
+#ifdef COMPILER1
+#include "c1/c1_LIRAssembler.hpp"
+#include "c1/c1_MacroAssembler.hpp"
+#include "gc/z/c1/zBarrierSetC1.hpp"
+#endif // COMPILER1
+
+#undef __
+#define __ masm->
+
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) __ block_comment(str)
+#endif
+
+#define G6_badmask G6
+
+void ZBarrierSetAssembler::load_at(MacroAssembler* masm,
+                                   DecoratorSet decorators,
+                                   BasicType type,
+                                   Address src,
+                                   Register dst,
+                                   Register tmp) {
+  if (!ZBarrierSet::barrier_needed(decorators, type)) {
+    // Barrier not needed
+    BarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp);
+    return;
+  }
+
+  assert_different_registers(src.base(), src.index(), tmp);
+  assert_different_registers(dst, tmp);
+
+  Label done;
+
+  BLOCK_COMMENT("ZBarrierSetAssembler::load_at {");
+
+  //
+  // Fast path
+  //
+
+  // Load address
+  if (Assembler::is_simm13(src.disp())) {
+    if (src.index()->is_valid()) {
+      __ add(src.base(), src.disp(), tmp);
+      __ add(src.index(), tmp, tmp);
+    } else {
+      __ add(src.base(), src.disp(), tmp);
+    }
+  } else {
+    __ set(src.disp(), tmp);
+    if (src.index()->is_valid()) {
+      __ add(src.index(), tmp, tmp);
+    }
+    __ add(src.base(), tmp, tmp);
+  }
+
+  // Load oop at address
+  __ ld_ptr(Address(tmp, 0), dst);
+
+  // Test address bad mask
+  __ btst(dst, G6_badmask);
+  __ brx(Assembler::zero, false, Assembler::pt, done);
+  __ delayed()->nop();
+
+  //
+  // Slow path
+  //
+
+  // Call the slow path
+  __ save_frame_and_mov(0, dst, O0, tmp, O1);
+  __ mov(G1, L1);
+  __ mov(G2, L2);
+  __ mov(G3, L3);
+  __ mov(G4, L4);
+  __ mov(G5, L5);
+  __ mov(G7, L6);
+  __ call_VM_leaf(L7_thread_cache, ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators));
+  __ mov(L1, G1);
+  __ mov(L2, G2);
+  __ mov(L3, G3);
+  __ mov(L4, G4);
+  __ mov(L5, G5);
+  __ mov(L6, G7);
+
+  // Save result
+  __ mov(O0, G6);
+
+  __ restore();
+
+  // Restore result
+  __ mov(G6, dst);
+
+  // Restore address bad mask
+  __ ld_ptr(address_bad_mask_from_thread(G2_thread), G6_badmask);
+
+  __ bind(done);
+
+  // Verify result
+  __ verify_oop(dst);
+
+  BLOCK_COMMENT("} ZBarrierSetAssembler::load_at");
+}
+
+#ifdef ASSERT
+void ZBarrierSetAssembler::store_at(MacroAssembler* masm,
+                                    DecoratorSet decorators,
+                                    BasicType type,
+                                    Register src,
+                                    Address dst,
+                                    Register tmp) {
+  BLOCK_COMMENT("ZBarrierSetAssembler::store_at {");
+
+  // Verify value
+  if (type == T_OBJECT || type == T_ARRAY) {
+    // Note that src could be noreg, which means we
+    // are storing null and can skip verification.
+    if (src != noreg) {
+      Label done;
+      __ btst(src, G6_badmask);
+      __ brx(Assembler::zero, false, Assembler::pt, done);
+      __ stop("Verify oop store failed");
+      __ should_not_reach_here();
+      __ bind(done);
+    }
+  }
+
+  // Store value
+  BarrierSetAssembler::store_at(masm, decorators, type, src, dst, tmp);
+
+  BLOCK_COMMENT("} ZBarrierSetAssembler::store_at");
+}
+#endif // ASSERT
+
+void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm,
+                                              DecoratorSet decorators,
+                                              BasicType type,
+                                              Register src,
+                                              Register dst,
+                                              Register count) {
+  if (!ZBarrierSet::barrier_needed(decorators, type)) {
+    // Barrier not needed
+    return;
+  }
+
+  BLOCK_COMMENT("ZBarrierSetAssembler::arraycopy_prologue {");
+
+  // Save frame and setup arguments
+  __ save_frame_and_mov(0, src, O0, count, O1);
+
+  // Call barrier
+  __ call_VM_leaf(L7_thread_cache, ZBarrierSetRuntime::load_barrier_on_oop_array_addr());
+
+  // Restore frame
+  __ restore();
+
+  BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue");
+}
+
+void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm,
+                                                         Register jni_env,
+                                                         Register obj,
+                                                         Register tmp,
+                                                         Label& slowpath) {
+  BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_jobject_in_native {");
+
+  // Resolve jobject
+  BarrierSetAssembler::try_resolve_jobject_in_native(masm, jni_env, obj, tmp, slowpath);
+
+  // Load address bad mask
+  __ ld_ptr(address_bad_mask_from_jni_env(jni_env), tmp);
+
+  // Test address bad mask
+  __ btst(obj, tmp);
+  __ brx(Assembler::notZero, false, Assembler::pn, slowpath);
+  __ delayed()->nop();
+
+  BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native");
+}
+
+#ifdef COMPILER1
+
+#undef __
+#define __ ce->masm()->
+
+void ZBarrierSetAssembler::generate_c1_load_barrier_test(LIR_Assembler* ce,
+                                                         LIR_Opr ref) const {
+  __ btst(ref->as_register(), G6_badmask);
+}
+
+void ZBarrierSetAssembler::generate_c1_load_barrier_stub(LIR_Assembler* ce,
+                                                         ZLoadBarrierStubC1* stub) const {
+  // Stub entry
+  __ bind(*stub->entry());
+
+  Register ref = stub->ref()->as_register();
+  Register ref_addr = noreg;
+
+  if (stub->ref_addr()->is_register()) {
+    // Address already in register
+    ref_addr = stub->ref_addr()->as_pointer_register();
+  } else {
+    // Load address into tmp register
+    ce->leal(stub->ref_addr(), stub->tmp(), stub->patch_code(), stub->patch_info());
+    ref_addr = stub->tmp()->as_pointer_register();
+  }
+
+  assert_different_registers(ref, ref_addr, G4, G5, noreg);
+
+  // Setup arguments and call runtime stub
+  __ mov(ref_addr, G5);
+  __ call(stub->runtime_stub());
+  __ delayed()->mov(ref, G4);
+
+  // Verify result
+  __ verify_oop(G4);
+
+  // Return result and exit stub
+  __ br(Assembler::always, false, Assembler::pt, *stub->continuation());
+  __ delayed()->mov(G4, ref);
+}
+
+#undef __
+#define __ sasm->
+
+void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* sasm,
+                                                                 DecoratorSet decorators) const {
+  // Save frame
+  __ save_frame(0);
+
+  // Call VM
+  __ call_VM_leaf(L7_thread_cache,
+                  ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators),
+                  G4, G5);
+
+  // Move result to G4
+  __ mov(O0, G4);
+
+  // Restore frame and return
+  __ ret();
+  __ delayed()->restore();
+}
+
+#endif // COMPILER1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/z/zBarrierSetAssembler_sparc.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef CPU_SPARC_GC_Z_ZBARRIERSETASSEMBLER_SPARC_HPP
+#define CPU_SPARC_GC_Z_ZBARRIERSETASSEMBLER_SPARC_HPP
+
+#ifdef COMPILER1
+class LIR_Assembler;
+class LIR_OprDesc;
+typedef LIR_OprDesc* LIR_Opr;
+class StubAssembler;
+class ZLoadBarrierStubC1;
+#endif // COMPILER1
+
+class ZBarrierSetAssembler : public ZBarrierSetAssemblerBase {
+public:
+  virtual void load_at(MacroAssembler* masm,
+                       DecoratorSet decorators,
+                       BasicType type,
+                       Address src,
+                       Register dst,
+                       Register tmp);
+
+#ifdef ASSERT
+  virtual void store_at(MacroAssembler* masm,
+                        DecoratorSet decorators,
+                        BasicType type,
+                        Register src,
+                        Address dst,
+                        Register tmp);
+#endif // ASSERT
+
+  virtual void arraycopy_prologue(MacroAssembler* masm,
+                                  DecoratorSet decorators,
+                                  BasicType type,
+                                  Register src,
+                                  Register dst,
+                                  Register count);
+
+  virtual void try_resolve_jobject_in_native(MacroAssembler* masm,
+                                             Register jni_env,
+                                             Register obj,
+                                             Register tmp,
+                                             Label& slowpath);
+
+#ifdef COMPILER1
+  void generate_c1_load_barrier_test(LIR_Assembler* ce,
+                                     LIR_Opr ref) const;
+
+  void generate_c1_load_barrier_stub(LIR_Assembler* ce,
+                                     ZLoadBarrierStubC1* stub) const;
+
+  void generate_c1_load_barrier_runtime_stub(StubAssembler* sasm,
+                                             DecoratorSet decorators) const;
+#endif // COMPILER1
+};
+
+#endif // CPU_SPARC_GC_Z_ZBARRIERSETASSEMBLER_SPARC_HPP
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -358,6 +358,12 @@
 
 
 void MacroAssembler::restore_thread(const Register thread_cache) {
+#if INCLUDE_ZGC
+  if (UseZGC) {
+    AddressLiteral bad_mask((intptr_t)&ZAddressBadMask);
+    load_ptr_contents(bad_mask, G6);
+  }
+#endif // INCLUDE_ZGC
   if (thread_cache->is_valid()) {
     assert(thread_cache->is_local() || thread_cache->is_in(), "bad volatile");
     mov(thread_cache, G2_thread);
@@ -1289,6 +1295,17 @@
   assert(_verify_oop_implicit_branch[0] == NULL, "set once");
   _verify_oop_implicit_branch[0] = pc();
 
+#if INCLUDE_ZGC
+  if (UseZGC) {
+    // Check if mask is good
+    AddressLiteral bad_mask((intptr_t)&ZAddressBadMask);
+    load_ptr_contents(bad_mask, O2);
+    btst(O0_obj, O2);
+    brx(notZero, false, pn, null_or_fail);
+    delayed()->nop();
+  }
+#endif // INCLUDE_ZGCC
+
   // We can't check the mark oop because it could be in the process of
   // locking or unlocking while this is running.
   set(Universe::verify_oop_mask (), O2_mask);
@@ -3695,6 +3712,12 @@
 }
 
 void MacroAssembler::reinit_heapbase() {
+#if INCLUDE_ZGC
+  if (UseZGC) {
+    AddressLiteral bad_mask((intptr_t)&ZAddressBadMask);
+    load_ptr_contents(bad_mask, G6);
+  } else
+#endif // INCLUDE_ZGC
   if (UseCompressedOops || UseCompressedClassPointers) {
     if (Universe::heap() != NULL) {
       set((intptr_t)Universe::narrow_ptrs_base(), G6_heapbase);
--- a/src/hotspot/cpu/sparc/nativeInst_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/cpu/sparc/nativeInst_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -585,10 +585,21 @@
   NativeInstruction::verify();
   // make sure code pattern is actually a "ld" or "st" of some sort.
   int i0 = long_at(0);
+  int i1 = long_at(add_offset);
   int op3 = inv_op3(i0);
 
   assert((int)add_offset == NativeMovConstReg::add_offset, "sethi size ok");
 
+  // verify the pattern "sethi %hi22(imm), reg ;  add reg, %lo10(imm), reg"
+  Register rd = inv_rd(i0);
+  if ((is_op2(i0, Assembler::sethi_op2) && rd != G0 &&
+        is_op3(i1, Assembler::add_op3, Assembler::arith_op) &&
+        inv_immed(i1) && (unsigned)get_simm13(i1) < (1 << 10) &&
+        rd == inv_rs1(i1) && rd == inv_rd(i1))) {
+    // Offset for patchable lea
+    return;
+  }
+
   if (!(is_op(i0, Assembler::ldst_op) &&
         inv_immed(i0) &&
         0 != (op3 < op3_ldst_int_limit
--- a/src/hotspot/cpu/sparc/sparc.ad	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/cpu/sparc/sparc.ad	Fri Jun 08 18:24:45 2018 +0200
@@ -358,6 +358,7 @@
 
 reg_class g1_regL(R_G1H,R_G1);
 reg_class g3_regL(R_G3H,R_G3);
+reg_class g6_regL(R_G6H,R_G6);
 reg_class o2_regL(R_O2H,R_O2);
 reg_class o7_regL(R_O7H,R_O7);
 
@@ -978,6 +979,13 @@
 
   if (preserve_g2)   __ mov(L7, G2);
 
+#if INCLUDE_ZGC
+  if (preserve_g2 && UseZGC) {
+    AddressLiteral bad_base((intptr_t)&ZAddressBadMask);
+    __ load_ptr_contents(bad_base, G6);
+  }
+#endif // INCLUDE_ZGC
+
 #ifdef ASSERT
   if (preserve_g2 && (VerifyCompiledCode || VerifyOops)) {
     // Trash argument dump slots.
@@ -2829,6 +2837,43 @@
     __ casx(Rmem, Rold, Rnew);
   %}
 
+  enc_class enc_leal(memory addr_opr, iRegP dest_opr) %{
+    Address addr = $addr_opr$$Address;
+    Register dest = $dest_opr$$Register;
+    MacroAssembler _masm(&cbuf);
+    if (addr.has_index()) {
+      assert(!addr.has_disp(), "sanity");
+      __ add(addr.base(), addr.index(), dest);
+    } else if (Assembler::is_simm13(addr.disp())) {
+      __ add(addr.base(), addr.disp(), dest);
+    } else {
+      __ set(addr.disp(), dest);
+      __ add(addr.base(), addr.disp(), dest);
+    }
+  %}
+
+  enc_class enc_casi_val(iRegI cmp_val_opr, iRegI new_val_opr, iRegP addr_reg_opr, iRegI res_opr) %{
+    Register cmp_val = $cmp_val_opr$$Register;
+    Register new_val = $new_val_opr$$Register;
+    Register addr_reg = $addr_reg_opr$$Register;
+    Register res = $res_opr$$Register;
+
+    MacroAssembler _masm(&cbuf);
+    __ mov(new_val, res);
+    __ cas(addr_reg, cmp_val, res);
+  %}
+
+  enc_class enc_casl_val(iRegL cmp_val_opr, iRegL new_val_opr, iRegP addr_reg_opr, iRegL res_opr) %{
+    Register cmp_val = $cmp_val_opr$$Register;
+    Register new_val = $new_val_opr$$Register;
+    Register addr_reg = $addr_reg_opr$$Register;
+    Register res = $res_opr$$Register;
+
+    MacroAssembler _masm(&cbuf);
+    __ mov(new_val, res);
+    __ casx(addr_reg, cmp_val, res);
+  %}
+
   enc_class enc_lflags_ne_to_boolean( iRegI res ) %{
     Register Rres = reg_to_register_object($res$$reg);
 
@@ -3744,6 +3789,14 @@
   interface(REG_INTER);
 %}
 
+operand g6RegL() %{
+  constraint(ALLOC_IN_RC(g6_regL));
+  match(iRegL);
+
+  format %{ %}
+  interface(REG_INTER);
+%}
+
 // Int Register safe
 // This is 64bit safe
 operand iRegIsafe() %{
@@ -6927,6 +6980,28 @@
 
 // No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
 
+instruct addr_bad_bit(g6RegL dst) %{
+  match(Set dst (AddrBadBit));
+  effect(DEF dst);
+
+  size(0);
+  format %{ "# addr_bad_bit in G6" %}
+  ins_encode( /*empty encoding*/ );
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct g6_testL_reg_reg(flagsRegL ccr, iRegP src, g6RegL other, immL0 zero)
+%{
+  match(Set ccr (CmpL (AndL (CastP2X src) other) zero));
+  effect(DEF ccr, USE src, USE other);
+
+  size(4);
+  format %{ "btst   $src, $other\t# long" %}
+  opcode(Assembler::andcc_op3, Assembler::arith_op);
+  ins_encode( form3_rs1_rs2_rd( src, other, R_G0 ) );
+  ins_pipe(ialu_cconly_reg_reg_zero);
+%}
+
 instruct compareAndSwapL_bool(iRegP mem_ptr, iRegL oldval, iRegL newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{
   predicate(VM_Version::supports_cx8());
   match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
--- a/src/hotspot/os/solaris/globals_solaris.hpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/os/solaris/globals_solaris.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -40,7 +40,9 @@
                          writeable) \
                                                                                \
   product(bool, UseExtendedFileIO, true,                                       \
-          "Enable workaround for limitations of stdio FILE structure")
+          "Enable workaround for limitations of stdio FILE structure")         \
+  product(bool, UseOSMHeap, false,                                             \
+          "Use Optimized Shared Memory for the Java heap")
 
 //
 // Defines Solaris-specific default values. The flags are available on all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zAddress_solaris_sparc.inline.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+
+#ifndef OS_CPU_SOLARIS_SPARC_ZADDRESS_SOLARIS_SPARC_INLINE_HPP
+#define OS_CPU_SOLARIS_SPARC_ZADDRESS_SOLARIS_SPARC_INLINE_HPP
+
+inline uintptr_t ZAddress::address(uintptr_t value) {
+  return value | ZAddressSpaceStart;
+}
+
+#endif // OS_CPU_SOLARIS_SPARC_ZADDRESS_SOLARIS_SPARC_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zGlobals_solaris_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zGlobals.hpp"
+
+uintptr_t ZAddressReservedStart() {
+  return ZAddressMetadataMarked0 + ZAddressSpaceStart;
+}
+
+uintptr_t ZAddressReservedEnd() {
+  return ZAddressMetadataRemapped + ZAddressSpaceEnd;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zGlobals_solaris_sparc.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#ifndef OS_CPU_SOLARIS_SPARC_ZGLOBALS_SOLARIS_SPARC_HPP
+#define OS_CPU_SOLARIS_SPARC_ZGLOBALS_SOLARIS_SPARC_HPP
+
+//
+// Page Allocation Tiers
+// ---------------------
+//
+//  Page Type     Page Size     Object Size Limit     Object Alignment
+//  ------------------------------------------------------------------
+//  Small         4M            <= 512K               <MinObjAlignmentInBytes>
+//  Medium        64M           <= 8M                 8K
+//  Large         X*M           > 8M                  4M
+//  ------------------------------------------------------------------
+//
+//
+// Address Space & Pointer Layout
+// ------------------------------
+//
+//  +--------------------------------+ 0xFFFFFFFFFFFFFFFF (16EB)
+//  .                                .
+//  .                                .
+//  .                                .
+//  +--------------------------------+ 0x0000080000000000 (8TB)
+//  |              Heap              |
+//  +--------------------------------+ 0x0000040000000000 (4TB)
+//  .                                .
+//  +--------------------------------+ 0x0000000000000000
+//
+//
+//  * 63-60 ADI bits (4-bits)
+//  |
+//  |    * 59-56 VA Masking Bits (4-bits)
+//  |    |
+//  |    |
+//  |6  6|5  5 5            4 4 4                                             0
+//  |3  0|9  6 5            3 2 1                                             0
+//  +----+----+--------------+-+-----------------------------------------------+
+//  |0000|1111|00000000 00000|1|11 11111111 11111111 11111111 11111111 11111111|
+//  +----+----+--------------+-+-----------------------------------------------+
+//  |    |    |              | |
+//  |    |    |              | * 41-0 Object Offset (42-bits, 4TB address space)
+//  |    |    |              |
+//  |    |    |              * 42-42 Address Base (1-bit)
+//  |    |    |
+//  |    |    * 55-43 Unused (13-bits, always zero)
+//  |    |
+//  |    * 59-56 Metadata Bits (4-bits)  0001 = Marked0
+//  |                                    0010 = Marked1
+//  |                                    0100 = Remapped
+//  |                                    1000 = Finalizable
+//  * 63-60 Fixed (4-bits, always zero)
+//
+
+const size_t    ZPlatformPageSizeSmallShift   = 22; // 4M
+
+const size_t    ZPlatformAddressOffsetBits    = 42; // 4TB
+
+const uintptr_t ZPlatformAddressMetadataShift = BitsPerWord - BitsPerByte; // 1 byte allocated for VA masking
+
+const uintptr_t ZPlatformAddressSpaceStart    = (uintptr_t)1 << ZPlatformAddressOffsetBits;
+const uintptr_t ZPlatformAddressSpaceSize     = (uintptr_t)1 << ZPlatformAddressOffsetBits;
+
+const size_t    ZPlatformCacheLineSize        = 64;
+
+const int       ZPlatformADIBits              = 4; // Always assume 4 ADI bits
+const int       ZPlatformVAMaskBits           = 4;
+
+#endif // OS_CPU_SOLARIS_SPARC_ZGLOBALS_SOLARIS_SPARC_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zLargePages_solaris_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zLargePages.hpp"
+#include "runtime/globals.hpp"
+
+void ZLargePages::initialize_platform() {
+  // Large pages are always transparent when enabled
+  if (UseLargePages && !UseOSMHeap) {
+    _state = Transparent;
+  } else {
+    _state = Disabled;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zNUMA_solaris_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, 2017, 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.
+ */
+
+#include "gc/z/zNUMA.hpp"
+#include "logging/log.hpp"
+
+void ZNUMA::initialize_platform() {
+  // NUMA support not implemented
+  if (UseNUMA) {
+    log_warning(gc, init)("NUMA support not available");
+  }
+  _enabled = false;
+}
+
+uint32_t ZNUMA::count() {
+  return 1;
+}
+
+uint32_t ZNUMA::id() {
+  return 0;
+}
+
+uint32_t ZNUMA::memory_id(uintptr_t addr) {
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zPhysicalMemoryBacking_solaris_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2015, 2017, 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.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zErrno.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zLargePages.inline.hpp"
+#include "gc/z/zPhysicalMemory.inline.hpp"
+#include "gc/z/zPhysicalMemoryBacking_solaris_sparc.hpp"
+#include "logging/log.hpp"
+#include "runtime/os.hpp"
+#include "utilities/align.hpp"
+#include "utilities/debug.hpp"
+
+#include <dlfcn.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+// Support for building on Solaris systems older than 11.3
+#ifndef VA_MASK_OVERLAP
+#define VA_MASK_OVERLAP      1
+#endif
+
+#ifndef _SC_OSM_PAGESIZE_MIN
+#define _SC_OSM_PAGESIZE_MIN 519
+#endif
+
+#ifndef MC_LOCK_GRANULE
+#define MC_LOCK_GRANULE      8
+#endif
+
+#ifndef MC_UNLOCK_GRANULE
+#define MC_UNLOCK_GRANULE    9
+#endif
+
+typedef int (*shmget_osm_func_t)(key_t, size_t, int, size_t);
+typedef int (*va_mask_alloc_func_t)(int, int, int*);
+
+static shmget_osm_func_t shmget_osm_func = NULL;
+static va_mask_alloc_func_t va_mask_alloc_func = NULL;
+
+static bool initialize_symbols() {
+  va_mask_alloc_func = (va_mask_alloc_func_t)dlsym(RTLD_DEFAULT, "va_mask_alloc");
+  if (va_mask_alloc_func == NULL) {
+    log_error(gc, init)("System does not support VA masking");
+    return false;
+  }
+
+  if (UseOSMHeap) {
+    shmget_osm_func = (shmget_osm_func_t)dlsym(RTLD_DEFAULT, "shmget_osm");
+    if (shmget_osm_func == NULL) {
+      log_error(gc, init)("System does not support OSM");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity, size_t granule_size) :
+    _granule_size(granule_size),
+    _initialized(false) {
+
+  if (!initialize_symbols()) {
+    return;
+  }
+
+  if (!initialize_vamask()) {
+    return;
+  }
+
+  if (UseOSMHeap) {
+    _initialized = initialize_osm();
+  } else {
+    _initialized = initialize_anonymous();
+  }
+}
+
+bool ZPhysicalMemoryBacking::initialize_vamask() const {
+  const int total_vamask_bits = align_up_(ZPlatformADIBits + ZPlatformVAMaskBits, BitsPerByte);
+  const int alloc_vamask_bits = total_vamask_bits - ZPlatformADIBits;
+  int lsb;
+
+  if (va_mask_alloc_func(alloc_vamask_bits, VA_MASK_OVERLAP, &lsb) == -1) {
+    log_error(gc, init)("Failed to allocate VA mask");
+    return false;
+  }
+
+  if (lsb != ZAddressMetadataShift) {
+    log_error(gc, init)("Failed to allocate expected VA mask");
+    return false;
+  }
+
+  return true;
+}
+
+bool ZPhysicalMemoryBacking::initialize_osm() const {
+  const uintptr_t start = ZAddressSpaceStart;
+  const size_t size = ZAddressSpaceSize;
+  const size_t min_page_size = sysconf(_SC_OSM_PAGESIZE_MIN);
+
+  if (!is_aligned(_granule_size, min_page_size)) {
+    log_error(gc, init)("OSM page size not supported");
+    return false;
+  }
+
+  const int osm = shmget_osm_func(IPC_PRIVATE, size, IPC_CREAT | 0600, _granule_size);
+  if (osm == -1) {
+    log_error(gc, init)("Failed to create OSM for Java heap");
+    return false;
+  }
+
+  const uintptr_t actual_start = (uintptr_t)shmat(osm, (void*)start, 0);
+
+  if (shmctl(osm, IPC_RMID, NULL) == -1) {
+    log_error(gc, init)("Failed to destroy OSM for Java heap");
+    return false;
+  }
+
+  if (actual_start == (uintptr_t)-1) {
+    log_error(gc, init)("Failed to attach OSM for Java heap");
+    return false;
+  }
+
+  if (actual_start != start) {
+    log_error(gc, init)("Failed to reserve address space for Java heap");
+    return false;
+  }
+
+  if (madvise((char*)start, size, MADV_ACCESS_DEFAULT) == -1) {
+    log_error(gc, init)("Failed to set NUMA policy for Java heap");
+    return false;
+  }
+
+  return true;
+}
+
+bool ZPhysicalMemoryBacking::initialize_anonymous() const {
+  if (ZLargePages::is_enabled()) {
+    // Check if granule size is a supported large page size (we always ignore LargePageSizeInBytes)
+    if (os::page_size_for_region_aligned(_granule_size, 1) != _granule_size) {
+      log_error(gc, init)("Page size " SIZE_FORMAT " not supported", _granule_size);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool ZPhysicalMemoryBacking::is_initialized() const {
+  return _initialized;
+}
+
+bool ZPhysicalMemoryBacking::expand(size_t from, size_t to) {
+  assert(is_aligned(to - from, _granule_size), "Invalid size");
+  return true;
+}
+
+ZPhysicalMemory ZPhysicalMemoryBacking::alloc(size_t size) {
+  assert(is_aligned(size, _granule_size), "Invalid size");
+  return ZPhysicalMemory(size);
+}
+
+void ZPhysicalMemoryBacking::free(ZPhysicalMemory pmem) {
+  assert(pmem.nsegments() == 1, "Invalid number of segments");
+}
+
+void ZPhysicalMemoryBacking::map_osm(ZPhysicalMemory pmem, uintptr_t offset) const {
+  const uintptr_t addr = ZAddress::address(offset);
+  if (memcntl((char*)addr, pmem.size(), MC_LOCK_GRANULE, 0, 0, 0) == -1) {
+    fatal("Failed to lock OSM granule");
+  }
+  // No need to pre-touch OSM mappings
+}
+
+void ZPhysicalMemoryBacking::unmap_osm(ZPhysicalMemory pmem, uintptr_t offset) const {
+  const uintptr_t addr = ZAddress::address(offset);
+  if (memcntl((char*)addr, pmem.size(), MC_UNLOCK_GRANULE, 0, 0, 0) == -1) {
+    fatal("Failed to unlock OSM granule");
+  }
+}
+
+void ZPhysicalMemoryBacking::advise_anonymous(uintptr_t addr, size_t size) const {
+  memcntl_mha mha;
+  mha.mha_cmd = MHA_MAPSIZE_VA;
+  mha.mha_pagesize = _granule_size;
+  mha.mha_flags = 0;
+
+  if (memcntl((char*)addr, size, MC_HAT_ADVISE, (caddr_t)&mha, 0, 0) == -1) {
+    ZErrno err;
+    log_error(gc)("Failed to advise use of large pages (%s)", err.to_string());
+  }
+}
+
+void ZPhysicalMemoryBacking::map_anonymous(ZPhysicalMemory pmem, uintptr_t offset) const {
+  const uintptr_t addr = ZAddress::address(offset);
+  const size_t size = pmem.size();
+  void* const res = mmap((void*)addr, size, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+  if (res == MAP_FAILED) {
+    ZErrno err;
+    fatal("Failed to map memory (%s)", err.to_string());
+  }
+
+  if (ZLargePages::is_transparent()) {
+    advise_anonymous(addr, size);
+  }
+
+  if (AlwaysPreTouch) {
+    os::pretouch_memory((void*)addr, (void*)(addr + size));
+  }
+}
+
+void ZPhysicalMemoryBacking::unmap_anonymous(ZPhysicalMemory pmem, uintptr_t offset) const {
+  const uintptr_t addr = ZAddress::address(offset);
+  if (munmap((char*)addr, pmem.size()) == -1) {
+    ZErrno err;
+    fatal("Failed to unmap memory (%s)", err.to_string());
+  }
+}
+
+uintptr_t ZPhysicalMemoryBacking::nmt_address(uintptr_t offset) const {
+  // We only have one heap mapping, so just convert the offset to a heap address
+  return ZAddress::address(offset);
+}
+
+void ZPhysicalMemoryBacking::map(ZPhysicalMemory pmem, uintptr_t offset) const {
+  if (UseOSMHeap) {
+    map_osm(pmem, offset);
+  } else {
+    map_anonymous(pmem, offset);
+  }
+}
+
+void ZPhysicalMemoryBacking::unmap(ZPhysicalMemory pmem, uintptr_t offset) const {
+  if (UseOSMHeap) {
+    unmap_osm(pmem, offset);
+  } else {
+    unmap_anonymous(pmem, offset);
+  }
+}
+
+void ZPhysicalMemoryBacking::flip(ZPhysicalMemory pmem, uintptr_t offset) const {
+  // Does nothing when using VA-masking
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zPhysicalMemoryBacking_solaris_sparc.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, 2017, 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.
+ */
+
+#ifndef OS_CPU_SOLARIS_SPARC_ZPHYSICALMEMORYBACKING_SOLARIS_SPARC_HPP
+#define OS_CPU_SOLARIS_SPARC_ZPHYSICALMEMORYBACKING_SOLARIS_SPARC_HPP
+
+#include "gc/z/zMemory.hpp"
+
+class ZErrno;
+class ZPhysicalMemory;
+
+class ZPhysicalMemoryBacking {
+private:
+  const size_t _granule_size;
+  bool         _initialized;
+
+  bool initialize_vamask() const;
+  bool initialize_osm() const;
+  bool initialize_anonymous() const;
+
+  void map_osm(ZPhysicalMemory pmem, uintptr_t offset) const;
+  void unmap_osm(ZPhysicalMemory pmem, uintptr_t offset) const;
+
+  void advise_anonymous(uintptr_t addr, size_t size) const;
+  void map_anonymous(ZPhysicalMemory pmem, uintptr_t offset) const;
+  void unmap_anonymous(ZPhysicalMemory pmem, uintptr_t offset) const;
+
+public:
+  ZPhysicalMemoryBacking(size_t max_capacity, size_t granule_size);
+
+  bool is_initialized() const;
+
+  bool expand(size_t from, size_t to);
+  ZPhysicalMemory alloc(size_t size);
+  void free(ZPhysicalMemory pmem);
+
+  uintptr_t nmt_address(uintptr_t offset) const;
+
+  void map(ZPhysicalMemory pmem, uintptr_t offset) const;
+  void unmap(ZPhysicalMemory pmem, uintptr_t offset) const;
+  void flip(ZPhysicalMemory pmem, uintptr_t offset) const;
+};
+
+#endif // OS_CPU_SOLARIS_SPARC_ZPHYSICALMEMORYBACKING_SOLARIS_SPARC_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os_cpu/solaris_sparc/gc/z/zVirtualMemory_solaris_sparc.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 2017, 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.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zVirtualMemory.hpp"
+#include "logging/log.hpp"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#ifndef MC_RESERVE_AS
+#define MC_RESERVE_AS 12
+#endif
+
+bool ZVirtualMemoryManager::reserve(uintptr_t start, size_t size) {
+  // Reserve address space
+  const int res = memcntl((char*)start, size, MC_RESERVE_AS, NULL, 0, 0);
+  if (res == -1) {
+    log_error(gc)("Failed to reserve address space for Java heap");
+    return false;
+  }
+
+  return true;
+}
--- a/src/hotspot/share/adlc/formssel.cpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/share/adlc/formssel.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -304,6 +304,14 @@
   return 0;
 }
 
+int InstructForm::is_addr_bad_bits_instruction() const {
+  if (_ident != NULL &&
+      ( ! strcmp( _ident,"addr_bad_bits") ) ) {
+    return 1;
+  }
+  return 0;
+}
+
 
 // Return 'true' if this instruction matches an ideal 'If' node
 bool InstructForm::is_ideal_if() const {
@@ -550,7 +558,7 @@
     rematerialize = true;
 
   // Pseudo-constants (values easily available to the runtime)
-  if (is_empty_encoding() && is_tls_instruction())
+  if (is_empty_encoding() && (is_tls_instruction() || is_addr_bad_bits_instruction()))
     rematerialize = true;
 
   // 1-input, 1-output, such as copies or increments.
--- a/src/hotspot/share/adlc/formssel.hpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/share/adlc/formssel.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -152,6 +152,7 @@
   virtual int         is_expensive() const;     // node matches ideal 'CosD'
   virtual int         is_empty_encoding() const; // _size=0 and/or _insencode empty
   virtual int         is_tls_instruction() const; // tlsLoadP rule or ideal ThreadLocal
+  virtual int         is_addr_bad_bits_instruction() const; // ZGC address bad bits in register
   virtual int         is_ideal_copy() const;    // node matches ideal 'Copy*'
   virtual bool        is_ideal_negD() const;    // node matches ideal 'NegD'
   virtual bool        is_ideal_if()   const;    // node matches ideal 'If'
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Fri Jun 08 18:24:45 2018 +0200
@@ -796,7 +796,13 @@
     assert(!barrier->oop_reload_allowed(), "writeback barriers should be marked as requires oop");
   }
 
-  if (!barrier->oop_reload_allowed()) {
+#ifdef SPARC
+  bool basic_load_barrier = true;
+#else
+  bool basic_load_barrier = !barrier->oop_reload_allowed();
+#endif
+
+  if (basic_load_barrier) {
     expand_loadbarrier_basic(phase, barrier);
   } else {
     expand_loadbarrier_optimized(phase, barrier);
@@ -818,9 +824,13 @@
   float unlikely  = PROB_UNLIKELY(0.999);
   const Type* in_val_maybe_null_t = igvn.type(in_val);
 
+#ifdef SPARC
+  Node* bad_mask = igvn.transform(new AddrBadBitNode());
+#else
   Node* jthread = igvn.transform(new ThreadLocalNode());
   Node* adr = phase->basic_plus_adr(jthread, in_bytes(ZThreadLocalData::address_bad_mask_offset()));
   Node* bad_mask = igvn.transform(LoadNode::make(igvn, in_ctrl, in_mem, adr, TypeRawPtr::BOTTOM, TypeX_X, TypeX_X->basic_type(), MemNode::unordered));
+#endif
   Node* cast = igvn.transform(new CastP2XNode(in_ctrl, in_val));
   Node* obj_masked = igvn.transform(new AndXNode(cast, bad_mask));
   Node* cmp = igvn.transform(new CmpXNode(obj_masked, igvn.zerocon(TypeX_X->basic_type())));
--- a/src/hotspot/share/opto/classes.hpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/share/opto/classes.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -35,6 +35,7 @@
 macro(AddI)
 macro(AddL)
 macro(AddP)
+macro(AddrBadBit)
 macro(Allocate)
 macro(AllocateArray)
 macro(AndI)
--- a/src/hotspot/share/opto/connode.hpp	Fri Jun 08 18:24:45 2018 +0200
+++ b/src/hotspot/share/opto/connode.hpp	Fri Jun 08 18:24:45 2018 +0200
@@ -149,6 +149,13 @@
     virtual uint ideal_reg() const { return Op_RegP; }
 };
 
+class AddrBadBitNode : public Node {
+public:
+    AddrBadBitNode() : Node((Node*)Compile::current()->root()) {}
+    virtual int Opcode() const;
+    virtual const Type *bottom_type() const { return TypeX_X;}
+    virtual uint ideal_reg() const { return Op_RegX; }
+};
 
 
 #endif // SHARE_VM_OPTO_CONNODE_HPP