Skip to content

Commit 5cf01ce

Browse files
author
J. Duke
committed
ZGC: Solaris/SPARC support
1 parent 19efc73 commit 5cf01ce

22 files changed

Lines changed: 1134 additions & 16 deletions

make/autoconf/hotspot.m4

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
328328
fi
329329
fi
330330
331-
# Only enable ZGC on Linux x86_64
331+
# Only enable ZGC on Linux x86_64 and Solaris Sparc
332332
AC_MSG_CHECKING([if zgc should be built])
333333
if HOTSPOT_CHECK_JVM_FEATURE(zgc); then
334-
if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then
334+
if (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64") || \
335+
(test "x$OPENJDK_TARGET_OS" = "xsolaris" && test "x$OPENJDK_TARGET_CPU" = "xsparcv9"); then
335336
AC_MSG_RESULT([yes])
336337
else
337338
DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES zgc"

src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,23 +3202,38 @@ void LIR_Assembler::leal(LIR_Opr addr_opr, LIR_Opr dest, LIR_PatchCode patch_cod
32023202
const Register dest_reg = dest->as_pointer_register();
32033203
const Register base_reg = addr->base()->as_pointer_register();
32043204

3205-
if (Assembler::is_simm13(addr->disp())) {
3206-
if (addr->index()->is_valid()) {
3207-
const Register index_reg = addr->index()->as_pointer_register();
3208-
assert(index_reg != G3_scratch, "invariant");
3209-
__ add(base_reg, addr->disp(), G3_scratch);
3210-
__ add(index_reg, G3_scratch, dest_reg);
3211-
} else {
3212-
__ add(base_reg, addr->disp(), dest_reg);
3213-
}
3214-
} else {
3215-
__ set(addr->disp(), G3_scratch);
3205+
if (patch_code != lir_patch_none) {
3206+
PatchingStub* patch = new PatchingStub(_masm, PatchingStub::access_field_id);
3207+
assert(addr->disp() != 0, "must have");
3208+
assert(base_reg != G3_scratch, "invariant");
3209+
__ patchable_set(0, G3_scratch);
3210+
patching_epilog(patch, patch_code, base_reg, info);
3211+
assert(dest_reg != G3_scratch, "invariant");
32163212
if (addr->index()->is_valid()) {
32173213
const Register index_reg = addr->index()->as_pointer_register();
32183214
assert(index_reg != G3_scratch, "invariant");
32193215
__ add(index_reg, G3_scratch, G3_scratch);
32203216
}
32213217
__ add(base_reg, G3_scratch, dest_reg);
3218+
} else {
3219+
if (Assembler::is_simm13(addr->disp())) {
3220+
if (addr->index()->is_valid()) {
3221+
const Register index_reg = addr->index()->as_pointer_register();
3222+
assert(index_reg != G3_scratch, "invariant");
3223+
__ add(base_reg, addr->disp(), G3_scratch);
3224+
__ add(index_reg, G3_scratch, dest_reg);
3225+
} else {
3226+
__ add(base_reg, addr->disp(), dest_reg);
3227+
}
3228+
} else {
3229+
__ set(addr->disp(), G3_scratch);
3230+
if (addr->index()->is_valid()) {
3231+
const Register index_reg = addr->index()->as_pointer_register();
3232+
assert(index_reg != G3_scratch, "invariant");
3233+
__ add(index_reg, G3_scratch, G3_scratch);
3234+
}
3235+
__ add(base_reg, G3_scratch, dest_reg);
3236+
}
32223237
}
32233238
}
32243239

src/hotspot/cpu/sparc/c2_globals_sparc.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K);
8585

8686
define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed on sparc.
8787

88+
#if INCLUDE_ZGC
89+
define_pd_global(bool, PreventLoadBarrierMatcherAssert, true);
90+
#endif
91+
8892
// Heap related flags
8993
define_pd_global(size_t, MetaspaceSize, ScaleForWordSize(16*M));
9094

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
#include "precompiled.hpp"
25+
#include "asm/macroAssembler.inline.hpp"
26+
#include "gc/z/zBarrier.inline.hpp"
27+
#include "gc/z/zBarrierSet.hpp"
28+
#include "gc/z/zBarrierSetAssembler.hpp"
29+
#include "gc/z/zBarrierSetRuntime.hpp"
30+
#ifdef COMPILER1
31+
#include "c1/c1_LIRAssembler.hpp"
32+
#include "c1/c1_MacroAssembler.hpp"
33+
#include "gc/z/c1/zBarrierSetC1.hpp"
34+
#endif // COMPILER1
35+
36+
#undef __
37+
#define __ masm->
38+
39+
#ifdef PRODUCT
40+
#define BLOCK_COMMENT(str) /* nothing */
41+
#else
42+
#define BLOCK_COMMENT(str) __ block_comment(str)
43+
#endif
44+
45+
#define G6_badmask G6
46+
47+
void ZBarrierSetAssembler::load_at(MacroAssembler* masm,
48+
DecoratorSet decorators,
49+
BasicType type,
50+
Address src,
51+
Register dst,
52+
Register tmp) {
53+
if (!ZBarrierSet::barrier_needed(decorators, type)) {
54+
// Barrier not needed
55+
BarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp);
56+
return;
57+
}
58+
59+
assert_different_registers(src.base(), src.index(), tmp);
60+
assert_different_registers(dst, tmp);
61+
62+
Label done;
63+
64+
BLOCK_COMMENT("ZBarrierSetAssembler::load_at {");
65+
66+
//
67+
// Fast path
68+
//
69+
70+
// Load address
71+
if (Assembler::is_simm13(src.disp())) {
72+
if (src.index()->is_valid()) {
73+
__ add(src.base(), src.disp(), tmp);
74+
__ add(src.index(), tmp, tmp);
75+
} else {
76+
__ add(src.base(), src.disp(), tmp);
77+
}
78+
} else {
79+
__ set(src.disp(), tmp);
80+
if (src.index()->is_valid()) {
81+
__ add(src.index(), tmp, tmp);
82+
}
83+
__ add(src.base(), tmp, tmp);
84+
}
85+
86+
// Load oop at address
87+
__ ld_ptr(Address(tmp, 0), dst);
88+
89+
// Test address bad mask
90+
__ btst(dst, G6_badmask);
91+
__ brx(Assembler::zero, false, Assembler::pt, done);
92+
__ delayed()->nop();
93+
94+
//
95+
// Slow path
96+
//
97+
98+
// Call the slow path
99+
__ save_frame_and_mov(0, dst, O0, tmp, O1);
100+
__ mov(G1, L1);
101+
__ mov(G2, L2);
102+
__ mov(G3, L3);
103+
__ mov(G4, L4);
104+
__ mov(G5, L5);
105+
__ mov(G7, L6);
106+
__ call_VM_leaf(L7_thread_cache, ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators));
107+
__ mov(L1, G1);
108+
__ mov(L2, G2);
109+
__ mov(L3, G3);
110+
__ mov(L4, G4);
111+
__ mov(L5, G5);
112+
__ mov(L6, G7);
113+
114+
// Save result
115+
__ mov(O0, G6);
116+
117+
__ restore();
118+
119+
// Restore result
120+
__ mov(G6, dst);
121+
122+
// Restore address bad mask
123+
__ ld_ptr(address_bad_mask_from_thread(G2_thread), G6_badmask);
124+
125+
__ bind(done);
126+
127+
// Verify result
128+
__ verify_oop(dst);
129+
130+
BLOCK_COMMENT("} ZBarrierSetAssembler::load_at");
131+
}
132+
133+
#ifdef ASSERT
134+
void ZBarrierSetAssembler::store_at(MacroAssembler* masm,
135+
DecoratorSet decorators,
136+
BasicType type,
137+
Register src,
138+
Address dst,
139+
Register tmp) {
140+
BLOCK_COMMENT("ZBarrierSetAssembler::store_at {");
141+
142+
// Verify value
143+
if (type == T_OBJECT || type == T_ARRAY) {
144+
// Note that src could be noreg, which means we
145+
// are storing null and can skip verification.
146+
if (src != noreg) {
147+
Label done;
148+
__ btst(src, G6_badmask);
149+
__ brx(Assembler::zero, false, Assembler::pt, done);
150+
__ stop("Verify oop store failed");
151+
__ should_not_reach_here();
152+
__ bind(done);
153+
}
154+
}
155+
156+
// Store value
157+
BarrierSetAssembler::store_at(masm, decorators, type, src, dst, tmp);
158+
159+
BLOCK_COMMENT("} ZBarrierSetAssembler::store_at");
160+
}
161+
#endif // ASSERT
162+
163+
void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm,
164+
DecoratorSet decorators,
165+
BasicType type,
166+
Register src,
167+
Register dst,
168+
Register count) {
169+
if (!ZBarrierSet::barrier_needed(decorators, type)) {
170+
// Barrier not needed
171+
return;
172+
}
173+
174+
BLOCK_COMMENT("ZBarrierSetAssembler::arraycopy_prologue {");
175+
176+
// Save frame and setup arguments
177+
__ save_frame_and_mov(0, src, O0, count, O1);
178+
179+
// Call barrier
180+
__ call_VM_leaf(L7_thread_cache, ZBarrierSetRuntime::load_barrier_on_oop_array_addr());
181+
182+
// Restore frame
183+
__ restore();
184+
185+
BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue");
186+
}
187+
188+
void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm,
189+
Register jni_env,
190+
Register obj,
191+
Register tmp,
192+
Label& slowpath) {
193+
BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_jobject_in_native {");
194+
195+
// Resolve jobject
196+
BarrierSetAssembler::try_resolve_jobject_in_native(masm, jni_env, obj, tmp, slowpath);
197+
198+
// Load address bad mask
199+
__ ld_ptr(address_bad_mask_from_jni_env(jni_env), tmp);
200+
201+
// Test address bad mask
202+
__ btst(obj, tmp);
203+
__ brx(Assembler::notZero, false, Assembler::pn, slowpath);
204+
__ delayed()->nop();
205+
206+
BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native");
207+
}
208+
209+
#ifdef COMPILER1
210+
211+
#undef __
212+
#define __ ce->masm()->
213+
214+
void ZBarrierSetAssembler::generate_c1_load_barrier_test(LIR_Assembler* ce,
215+
LIR_Opr ref) const {
216+
__ btst(ref->as_register(), G6_badmask);
217+
}
218+
219+
void ZBarrierSetAssembler::generate_c1_load_barrier_stub(LIR_Assembler* ce,
220+
ZLoadBarrierStubC1* stub) const {
221+
// Stub entry
222+
__ bind(*stub->entry());
223+
224+
Register ref = stub->ref()->as_register();
225+
Register ref_addr = noreg;
226+
227+
if (stub->ref_addr()->is_register()) {
228+
// Address already in register
229+
ref_addr = stub->ref_addr()->as_pointer_register();
230+
} else {
231+
// Load address into tmp register
232+
ce->leal(stub->ref_addr(), stub->tmp(), stub->patch_code(), stub->patch_info());
233+
ref_addr = stub->tmp()->as_pointer_register();
234+
}
235+
236+
assert_different_registers(ref, ref_addr, G4, G5, noreg);
237+
238+
// Setup arguments and call runtime stub
239+
__ mov(ref_addr, G5);
240+
__ call(stub->runtime_stub());
241+
__ delayed()->mov(ref, G4);
242+
243+
// Verify result
244+
__ verify_oop(G4);
245+
246+
// Return result and exit stub
247+
__ br(Assembler::always, false, Assembler::pt, *stub->continuation());
248+
__ delayed()->mov(G4, ref);
249+
}
250+
251+
#undef __
252+
#define __ sasm->
253+
254+
void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* sasm,
255+
DecoratorSet decorators) const {
256+
// Save frame
257+
__ save_frame(0);
258+
259+
// Call VM
260+
__ call_VM_leaf(L7_thread_cache,
261+
ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators),
262+
G4, G5);
263+
264+
// Move result to G4
265+
__ mov(O0, G4);
266+
267+
// Restore frame and return
268+
__ ret();
269+
__ delayed()->restore();
270+
}
271+
272+
#endif // COMPILER1

0 commit comments

Comments
 (0)