Skip to content

Commit e4e30f4

Browse files
Add armv8 support in the binding for mmtk/jdk:jdk-21%2B24-mmtk (#249)
Signed-off-by: ArberSephirotheca <[email protected]>
1 parent 776baab commit e4e30f4

6 files changed

+341
-4
lines changed

openjdk/CompileThirdPartyHeap.gmk

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,25 @@ CARGO_TARGET_FLAG =
7474

7575
ifeq ($(COMPILE_TYPE), cross)
7676
ifneq ($(CREATING_BUILDJDK), true)
77+
# Set the CARGO_TARGET based on the architecture
78+
ifeq ($(HOTSPOT_TARGET_CPU_ARCH), riscv64)
79+
CARGO_TARGET = riscv64gc-unknown-linux-gnu
80+
endif
81+
ifeq ($(HOTSPOT_TARGET_CPU_ARCH), aarch64)
82+
CARGO_TARGET = aarch64-unknown-linux-gnu
83+
endif
7784
CARGO_EXECUTABLE = cross
78-
CARGO_TARGET = riscv64gc-unknown-linux-gnu
7985
CARGO_TARGET_FLAG = --target $(CARGO_TARGET)
8086
endif
8187
endif
82-
8388
$(LIB_MMTK): FORCE
8489
if [[ "$(OPENJDK_VERSION)" != "$(OPENJDK_LOCAL_VERSION)" ]]; then \
8590
echo -e $(YELLOW)WARNING: Local OpenJDK version does not match version specified in mmtk/Cargo.toml$(NC); \
8691
echo -e $(YELLOW)Local OpenJDK version $(OPENJDK_LOCAL_VERSION)$(NC); \
8792
echo -e $(YELLOW)mmtk/Cargo.toml OpenJDK version $(OPENJDK_VERSION)$(NC); \
8893
fi
89-
if [[ "$(OPENJDK_TARGET_CPU)" != "riscv64" ]] && [[ $(CARGO_EXECUTABLE) == "cross" ]]; then \
90-
echo -e "Only cross compiling to riscv64 is supported"; \
94+
if [[ "$(OPENJDK_TARGET_CPU)" != "riscv64" ]] && [[ "$(OPENJDK_TARGET_CPU)" != "aarch64" ]] && [[ $(CARGO_EXECUTABLE) == "cross" ]]; then \
95+
echo -e "Only cross compiling to riscv64/aarch64 are supported"; \
9196
exit 1; \
9297
fi
9398
echo "cd $(MMTK_RUST_ROOT) && $(CARGO_EXECUTABLE) --version && $(CARGO_EXECUTABLE) build $(CARGO_TARGET_FLAG) $(CARGO_PROFILE_FLAG) $(GC_FEATURES)"
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
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 "interpreter/interp_masm.hpp"
27+
#include "mmtkBarrierSet.hpp"
28+
#include "mmtkBarrierSetAssembler_aarch64.hpp"
29+
#include "mmtkBarrierSetC1.hpp"
30+
#include "mmtkMutator.hpp"
31+
#include "runtime/sharedRuntime.hpp"
32+
#include "utilities/macros.hpp"
33+
#include "c1/c1_LIRAssembler.hpp"
34+
#include "c1/c1_MacroAssembler.hpp"
35+
36+
#define __ masm->
37+
38+
void MMTkBarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register tmp1, Register tmp2, Label& slow_case) {
39+
// XXX tmp1 seems to be -1
40+
assert_different_registers(obj, tmp2);
41+
assert_different_registers(obj, var_size_in_bytes);
42+
assert(tmp2->is_valid(), "need temp reg");
43+
44+
if (!MMTK_ENABLE_ALLOCATION_FASTPATH) {
45+
__ b(slow_case);
46+
} else {
47+
// printf("generating mmtk allocation fast path\n");
48+
// MMTk size check. If the alloc size is larger than the allowed max size for non los,
49+
// we jump to slow path and allodate with LOS in slowpath.
50+
// Note that OpenJDK has a slow path check. Search for layout_helper_needs_slow_path and FastAllocateSizeLimit.
51+
// I tried to set FastAllocateSizeLimit in MMTkHeap::initialize(). But there are still large objects allocated into the
52+
// default space.
53+
assert(MMTkMutatorContext::max_non_los_default_alloc_bytes != 0, "max_non_los_default_alloc_bytes hasn't been initialized");
54+
size_t max_non_los_bytes = MMTkMutatorContext::max_non_los_default_alloc_bytes;
55+
size_t extra_header = 0;
56+
// fastpath, we only use default allocator
57+
Allocator allocator = AllocatorDefault;
58+
// We need to figure out which allocator we are using by querying MMTk.
59+
AllocatorSelector selector = get_allocator_mapping(allocator);
60+
61+
// XXX riscv: disallow markcompact and global alloc bit for now
62+
assert(selector.tag != TAG_MARK_COMPACT, "mark compact not supported for now");
63+
64+
if (var_size_in_bytes == noreg) {
65+
// constant alloc size. If it is larger than max_non_los_bytes, we directly go to slowpath.
66+
if ((size_t)con_size_in_bytes > max_non_los_bytes - extra_header) {
67+
__ b(slow_case);
68+
return;
69+
}
70+
} else {
71+
// var alloc size. We compare with max_non_los_bytes and conditionally jump to slowpath.
72+
// printf("max_non_los_bytes %lu\n",max_non_los_bytes);
73+
__ movi(rscratch1, max_non_los_bytes - extra_header);
74+
__ cmp(rscratch1, var_size_in_bytes);
75+
__ br(Assembler::LT, slow_case);
76+
}
77+
78+
if (selector.tag == TAG_MALLOC || selector.tag == TAG_LARGE_OBJECT) {
79+
__ b(slow_case);
80+
return;
81+
}
82+
83+
// Calculate offsets of TLAB top and end
84+
Address cursor, limit;
85+
MMTkAllocatorOffsets alloc_offsets = get_tlab_top_and_end_offsets(selector);
86+
87+
cursor = Address(rthread, alloc_offsets.tlab_top_offset);
88+
limit = Address(rthread, alloc_offsets.tlab_end_offset);
89+
90+
// XXX disassembly
91+
// 0x7fffe85597e0: ld a0,688(s7)
92+
// 0x7fffe85597e4: add a1,a0,a3
93+
// 0x7fffe85597e8: bltu a1,a0,0x7fffe8559878
94+
// 0x7fffe85597ec: ld t0,696(s7)
95+
// 0x7fffe85597f0: bltu t0,a1,0x7fffe8559878
96+
// 0x7fffe85597f4: sd a1,688(s7)
97+
98+
__ ldr(obj, cursor);
99+
Register end = tmp2;
100+
if (var_size_in_bytes == noreg) {
101+
__ adr(end, Address(obj, con_size_in_bytes));
102+
} else {
103+
__ add(end, obj, var_size_in_bytes);
104+
}
105+
// slowpath if end < obj
106+
__ cmp(end, obj);
107+
__ br(Assembler::LT, slow_case);
108+
// slowpath if end > lab.limit
109+
__ ldr(tmp1, limit);
110+
// XXX debug use, force slow path
111+
__ cmp(end, tmp1);
112+
__ br(Assembler::GT, slow_case);
113+
114+
// lab.cursor = end
115+
__ str(end, cursor);
116+
117+
// recover var_size_in_bytes if necessary
118+
if (var_size_in_bytes == end) {
119+
__ sub(var_size_in_bytes, var_size_in_bytes, obj);
120+
}
121+
// if the above is removed, and the register holding the object size is
122+
// clobbered, operations that rely on the size, such as array copy will
123+
// crash
124+
125+
// XXX debug use, force segfault to disassemble in gdb
126+
// __ ld(t0, zr);
127+
128+
// XXX debug use, force double allocation
129+
// __ j(slow_case);
130+
131+
#ifdef MMTK_ENABLE_GLOBAL_ALLOC_BIT
132+
assert(false, "global alloc bit not supported");
133+
#endif
134+
}
135+
}
136+
137+
#undef __
138+
139+
#define __ sasm->
140+
141+
void MMTkBarrierSetAssembler::generate_c1_write_barrier_runtime_stub(StubAssembler* sasm) const {
142+
// printf("xxx MMTkBarrierSetAssembler::generate_c1_write_barrier_runtime_stub\n");
143+
// See also void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm)
144+
__ prologue("mmtk_write_barrier", false);
145+
146+
Label done, runtime;
147+
148+
// void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg)
149+
// ld(reg, Address(fp, offset_in_words * BytesPerWord));
150+
// ra is free to use here, because call prologue/epilogue handles it
151+
// Zheyuan: Code works by swaping rscratch2 and rscratch1, and I dont know why
152+
const Register src = rscratch2;
153+
const Register slot = rscratch1;
154+
const Register new_val = lr;
155+
__ load_parameter(0, src);
156+
__ load_parameter(1, slot);
157+
__ load_parameter(2, new_val);
158+
159+
__ bind(runtime);
160+
161+
// Push integer registers x7, x10-x17, x28-x31.
162+
// t2, a0-a7, t3-t6
163+
__ push_call_clobbered_registers();
164+
165+
#if MMTK_ENABLE_BARRIER_FASTPATH
166+
__ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), src, slot, new_val);
167+
#else
168+
__ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), src, slot, new_val);
169+
#endif
170+
171+
__ pop_call_clobbered_registers();
172+
173+
__ bind(done);
174+
175+
__ epilogue();
176+
}
177+
178+
#undef __
179+
180+
#define __ ce->masm()->
181+
182+
void MMTkBarrierSetAssembler::generate_c1_write_barrier_stub_call(LIR_Assembler* ce, MMTkC1BarrierStub* stub) {
183+
// printf("xxx MMTkBarrierSetAssembler::generate_c1_write_barrier_stub_call\n");
184+
// See also void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub)
185+
MMTkBarrierSetC1* bs = (MMTkBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
186+
__ bind(*stub->entry());
187+
assert(stub->src->is_register(), "Precondition");
188+
assert(stub->slot->is_register(), "Precondition");
189+
assert(stub->new_val->is_register(), "Precondition");
190+
ce->store_parameter(stub->src->as_pointer_register(), 0);
191+
ce->store_parameter(stub->slot->as_pointer_register(), 1);
192+
ce->store_parameter(stub->new_val->as_pointer_register(), 2);
193+
__ far_call(RuntimeAddress(bs->_write_barrier_c1_runtime_code_blob->code_begin()));
194+
__ b(*stub->continuation());
195+
}
196+
197+
#undef __
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#ifndef MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_AARCH64_HPP
2+
#define MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_AARCH64_HPP
3+
4+
#include "asm/macroAssembler.hpp"
5+
#include "gc/shared/barrierSetAssembler.hpp"
6+
7+
class MMTkBarrierSetC1;
8+
class MMTkC1BarrierStub;
9+
class LIR_Assembler;
10+
class StubAssembler;
11+
12+
class MMTkBarrierSetAssembler: public BarrierSetAssembler {
13+
friend class MMTkBarrierSetC1;
14+
15+
protected:
16+
/// Full pre-barrier
17+
virtual void object_reference_write_pre(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const {}
18+
/// Full post-barrier
19+
virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const {}
20+
21+
/// Barrier elision test
22+
virtual bool can_remove_barrier(DecoratorSet decorators, Register val, bool skip_const_null) const {
23+
bool in_heap = (decorators & IN_HEAP) != 0;
24+
bool as_normal = (decorators & AS_NORMAL) != 0;
25+
assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
26+
return !in_heap || (skip_const_null && val == noreg);
27+
}
28+
29+
/// Generate C1 write barrier slow-call assembly code
30+
virtual void generate_c1_write_barrier_runtime_stub(StubAssembler* sasm) const;
31+
32+
public:
33+
virtual void eden_allocate(MacroAssembler* masm,
34+
Register obj, // result: pointer to object after successful allocation
35+
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
36+
int con_size_in_bytes, // object size in bytes if known at compile time
37+
Register tmp1, // temp register
38+
Register tmp2, // temp register
39+
Label& slow_case // continuation point if fast allocation fails
40+
);
41+
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
42+
if (type == T_OBJECT || type == T_ARRAY) object_reference_write_pre(masm, decorators, dst, val, tmp1, tmp2);
43+
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
44+
if (type == T_OBJECT || type == T_ARRAY) object_reference_write_post(masm, decorators, dst, val, tmp1, tmp2);
45+
}
46+
47+
/// Generate C1 write barrier slow-call stub
48+
static void generate_c1_write_barrier_stub_call(LIR_Assembler* ce, MMTkC1BarrierStub* stub);
49+
};
50+
#endif // MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_AARCH64_HPP
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#ifndef MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_AARCH64_HPP
2+
#define MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_AARCH64_HPP
3+
4+
class MMTkNoBarrierSetAssembler: public MMTkBarrierSetAssembler {};
5+
#endif // MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_AARCH64_HPP
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "precompiled.hpp"
2+
#include "mmtkObjectBarrier.hpp"
3+
#include "runtime/interfaceSupport.inline.hpp"
4+
5+
#define __ masm->
6+
7+
void MMTkObjectBarrierSetAssembler::object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const {
8+
// tmp1 and tmp2 is from MacroAssembler::access_store_at
9+
// For do_oop_store, we have three tmps, x28/t3, x29/t4, x13/a3
10+
// printf("object_reference_write_post\n");
11+
// if (can_remove_barrier(decorators, val, /* skip_const_null */ true)) return;
12+
if (can_remove_barrier(decorators, val, /* skip_const_null */ true)) return;
13+
Register obj = dst.base();
14+
15+
#if MMTK_ENABLE_BARRIER_FASTPATH
16+
Label done;
17+
18+
assert_different_registers(obj, tmp1, tmp2);
19+
assert_different_registers(val, tmp1, tmp2);
20+
assert(tmp1->is_valid(), "need temp reg");
21+
assert(tmp2->is_valid(), "need temp reg");
22+
// tmp1 = load-byte (SIDE_METADATA_BASE_ADDRESS + (obj >> 6));
23+
__ mov(tmp1, obj);
24+
__ lsr(tmp1, tmp1, 6); // tmp1 = obj >> 6;
25+
__ mov(tmp2, SIDE_METADATA_BASE_ADDRESS);
26+
__ add(tmp1, tmp1, tmp2); // tmp1 = SIDE_METADATA_BASE_ADDRESS + (obj >> 6);
27+
__ ldrb(tmp1, Address(tmp1, 0));
28+
// tmp2 = (obj >> 3) & 7
29+
__ mov(tmp2, obj);
30+
__ lsr(tmp2, tmp2, 3);
31+
__ andr(tmp2, tmp2, 7);
32+
// tmp1 = tmp1 >> tmp2
33+
__ lsrv(tmp1, tmp1, tmp2);
34+
// if ((tmp1 & 1) == 1) fall through to slowpath;
35+
// equivalently ((tmp1 & 1) == 0) go to done
36+
__ andr(tmp1, tmp1, 1);
37+
__ cbz(tmp1, done);
38+
// setup calling convention
39+
__ mov(c_rarg0, obj);
40+
__ lea(c_rarg1, dst);
41+
__ mov(c_rarg2, val == noreg ? zr : val);
42+
__ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), 3);
43+
44+
__ bind(done);
45+
#else
46+
__ mov(c_rarg0, obj);
47+
__ lea(c_rarg1, dst);
48+
__ mov(c_rarg2, val == noreg ? zr : val);
49+
__ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), 3);
50+
#endif
51+
}
52+
53+
void MMTkObjectBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
54+
Register src, Register dst, Register count, Register tmp, RegSet saved_regs) {
55+
// see also void G1BarrierSetAssembler::gen_write_ref_array_post_barrier
56+
assert_different_registers(src, dst, count);
57+
// const bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
58+
// if (is_oop && !dest_uninitialized) {
59+
if (is_oop){
60+
__ push(saved_regs, sp);
61+
__ mov(c_rarg1, dst);
62+
__ mov(c_rarg2, count);
63+
__ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_array_copy_post_call), 3);
64+
__ pop(saved_regs, sp);
65+
}
66+
}
67+
68+
69+
#undef __
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_AARCH64_HPP
2+
#define MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_AARCH64_HPP
3+
4+
class MMTkObjectBarrierSetAssembler: public MMTkBarrierSetAssembler {
5+
protected:
6+
virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const override;
7+
public:
8+
virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
9+
Register src, Register dst, Register count, Register tmp, RegSet saved_regs) override;
10+
};
11+
#endif // MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_AARCH64_HPP

0 commit comments

Comments
 (0)