Skip to content
Permalink
Browse files
ZGC: Solaris/SPARC support
  • Loading branch information
J. Duke committed Jun 12, 2018
1 parent 19efc73 commit 5cf01ce95b3ade3710c578b473edfe0404128e9e
Show file tree
Hide file tree
Showing 22 changed files with 1,134 additions and 16 deletions.
@@ -328,10 +328,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
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"
@@ -3202,23 +3202,38 @@ void LIR_Assembler::leal(LIR_Opr addr_opr, LIR_Opr dest, LIR_PatchCode patch_cod
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);
}
}
}

@@ -85,6 +85,10 @@ define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K);

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));

@@ -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

0 comments on commit 5cf01ce

Please sign in to comment.