Skip to content

Commit 75296ac

Browse files
authored
Select barrier based on active plan (#44)
1 parent 08b91f1 commit 75296ac

18 files changed

+473
-523
lines changed

mmtk/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ lazy_static = "1.1"
2121
# - change branch
2222
# - change repo name
2323
# But other changes including adding/removing whitespaces in commented lines may break the CI.
24-
mmtk = { git = "ssh://[email protected]/mmtk/mmtk-core.git", rev = "4bc6d859fb6828d876aa7d1b0973fc2dda297850" }
24+
mmtk = { git = "ssh://[email protected]/mmtk/mmtk-core.git", rev = "1c7d7abb8e2adc5a9f64326af2f5af6a5d335497" }
2525
# Uncomment the following to build locally
2626
# mmtk = { path = "../repos/mmtk-core" }
2727

@@ -31,7 +31,7 @@ nogc_lock_free = ["mmtk/nogc_lock_free"]
3131
nogc_no_zeroing = ["mmtk/nogc_no_zeroing"]
3232

3333
# We can select plan at runtime. So no need to use any of these features.
34-
# However, if any of these is provided during build-time, we will ignore any runtime flag and
34+
# However, if any of these is provided during build-time, we will ignore any runtime flag and
3535
# always run this plan. Performance-wise there is no difference. The main reason for these features
3636
# is to temporarily allow running performance tests without changing performance scripts.
3737
nogc = []

mmtk/src/api.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use libc::{c_char, c_void};
2-
use std::ffi::CStr;
3-
2+
use std::ffi::{CStr, CString};
3+
use std::lazy::SyncLazy;
44
use mmtk::memory_manager;
55
use mmtk::scheduler::GCWorker;
66
use mmtk::util::alloc::allocators::AllocatorSelector;
@@ -10,12 +10,26 @@ use mmtk::AllocationSemantics;
1010
use mmtk::MutatorContext;
1111
use mmtk::Mutator;
1212
use mmtk::{Plan, MMTK};
13-
13+
use mmtk::util::options::PlanSelector;
14+
use mmtk::plan::barriers::BarrierSelector;
1415
use crate::OpenJDK;
1516
use crate::OpenJDK_Upcalls;
1617
use crate::SINGLETON;
1718
use crate::UPCALLS;
1819

20+
// Supported barriers:
21+
static NO_BARRIER: SyncLazy<CString> = SyncLazy::new(|| CString::new("NoBarrier").unwrap());
22+
static OBJECT_BARRIER: SyncLazy<CString> = SyncLazy::new(|| CString::new("ObjectBarrier").unwrap());
23+
24+
#[no_mangle]
25+
pub extern "C" fn mmtk_active_barrier() -> *const c_char {
26+
match SINGLETON.plan.constraints().barrier {
27+
BarrierSelector::NoBarrier => NO_BARRIER.as_ptr(),
28+
BarrierSelector::ObjectBarrier => OBJECT_BARRIER.as_ptr(),
29+
_ => unimplemented!()
30+
}
31+
}
32+
1933
#[no_mangle]
2034
pub extern "C" fn release_buffer(ptr: *mut Address, length: usize, capacity: usize) {
2135
let _vec = unsafe { Vec::<Address>::from_raw_parts(ptr, length, capacity) };
@@ -30,11 +44,6 @@ pub extern "C" fn openjdk_gc_init(calls: *const OpenJDK_Upcalls, heap_size: usiz
3044
memory_manager::gc_init(singleton_mut, heap_size);
3145
}
3246

33-
#[no_mangle]
34-
pub extern "C" fn openjdk_needs_write_barrier() -> bool {
35-
SINGLETON.plan.constraints().needs_write_barrier
36-
}
37-
3847
#[no_mangle]
3948
pub extern "C" fn start_control_collector(tls: OpaquePointer) {
4049
memory_manager::start_control_collector(&SINGLETON, tls);

mmtk/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(const_fn)]
33
#![feature(box_syntax)]
44
#![feature(vec_into_raw_parts)]
5+
#![feature(once_cell)]
56

67
extern crate libc;
78
extern crate mmtk;

openjdk/CompileThirdPartyHeap.gmk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ JVM_LDFLAGS += '-Wl,-rpath,$$ORIGIN'
3131
FORCE:
3232

3333
TARGETS += $(LIB_MMTK)
34-
JVM_SRC_DIRS += $(MMTK_CPP_ROOT)
34+
JVM_SRC_DIRS += $(MMTK_CPP_ROOT) $(MMTK_CPP_ROOT)/barriers
3535
JVM_CFLAGS += -DINCLUDE_THIRD_PARTY_HEAP -DTHIRD_PARTY_HEAP_SRC=$(MMTK_CPP_ROOT)
3636

3737
$(BUILD_LIBJVM): $(LIB_MMTK)

openjdk/barriers/mmtkNoBarrier.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef MMTK_BARRIERS_NO_BARRIER
2+
#define MMTK_BARRIERS_NO_BARRIER
3+
4+
#include "../mmtkBarrierSet.hpp"
5+
#include "../mmtkBarrierSetAssembler_x86.hpp"
6+
#include "../mmtkBarrierSetC1.hpp"
7+
#include "../mmtkBarrierSetC2.hpp"
8+
9+
class MMTkNoBarrierSetRuntime: public MMTkBarrierSetRuntime {};
10+
11+
class MMTkNoBarrierSetAssembler: public MMTkBarrierSetAssembler {};
12+
13+
class MMTkNoBarrierSetC1: public MMTkBarrierSetC1 {};
14+
15+
class MMTkNoBarrierSetC2: public MMTkBarrierSetC2 {};
16+
17+
struct MMTkNoBarrier: MMTkBarrierImpl<
18+
MMTkNoBarrierSetRuntime,
19+
MMTkNoBarrierSetAssembler,
20+
MMTkNoBarrierSetC1,
21+
MMTkNoBarrierSetC2
22+
> {};
23+
24+
#endif
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include "mmtkObjectBarrier.hpp"
2+
#include "runtime/interfaceSupport.inline.hpp"
3+
4+
void MMTkObjectBarrierSetRuntime::record_modified_node_slow(void* obj) {
5+
::record_modified_node((MMTk_Mutator) &Thread::current()->third_party_heap_mutator, (void*) obj);
6+
}
7+
8+
void MMTkObjectBarrierSetRuntime::record_modified_node(oop src) {
9+
record_modified_node_slow((void*) src);
10+
}
11+
12+
#define __ masm->
13+
14+
void MMTkObjectBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2) {
15+
bool in_heap = (decorators & IN_HEAP) != 0;
16+
bool as_normal = (decorators & AS_NORMAL) != 0;
17+
assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
18+
19+
if (!in_heap || val == noreg) {
20+
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2);
21+
return;
22+
}
23+
24+
assert_different_registers(tmp1, noreg);
25+
assert_different_registers(tmp2, noreg);
26+
assert_different_registers(tmp1, tmp2);
27+
28+
__ push(dst.base());
29+
30+
if (dst.index() == noreg && dst.disp() == 0) {
31+
if (dst.base() != tmp1) {
32+
__ movptr(tmp1, dst.base());
33+
}
34+
} else {
35+
__ lea(tmp1, dst);
36+
}
37+
38+
BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg);
39+
40+
__ pop(tmp2);
41+
42+
record_modified_node(masm, tmp2);
43+
}
44+
45+
void MMTkObjectBarrierSetAssembler::record_modified_node(MacroAssembler* masm, Register obj) {
46+
__ pusha();
47+
__ movptr(c_rarg0, obj);
48+
__ call_VM_leaf_base(CAST_FROM_FN_PTR(address, MMTkObjectBarrierSetRuntime::record_modified_node_slow), 1);
49+
__ popa();
50+
}
51+
52+
#undef __
53+
54+
#ifdef ASSERT
55+
#define __ gen->lir(__FILE__, __LINE__)->
56+
#else
57+
#define __ gen->lir()->
58+
#endif
59+
60+
void MMTkObjectBarrierSetC1::record_modified_node(LIRAccess& access, LIR_Opr src, LIR_Opr slot, LIR_Opr new_val) {
61+
LIRGenerator* gen = access.gen();
62+
DecoratorSet decorators = access.decorators();
63+
if ((decorators & IN_HEAP) == 0) return;
64+
if (!src->is_register()) {
65+
LIR_Opr reg = gen->new_pointer_register();
66+
if (src->is_constant()) {
67+
__ move(src, reg);
68+
} else {
69+
__ leal(src, reg);
70+
}
71+
src = reg;
72+
}
73+
assert(src->is_register(), "must be a register at this point");
74+
if (!slot->is_register()) {
75+
LIR_Opr reg = gen->new_pointer_register();
76+
if (slot->is_constant()) {
77+
__ move(slot, reg);
78+
} else {
79+
__ leal(slot, reg);
80+
}
81+
slot = reg;
82+
}
83+
assert(slot->is_register(), "must be a register at this point");
84+
if (!new_val->is_register()) {
85+
LIR_Opr new_val_reg = gen->new_register(T_OBJECT);
86+
if (new_val->is_constant()) {
87+
__ move(new_val, new_val_reg);
88+
} else {
89+
__ leal(new_val, new_val_reg);
90+
}
91+
new_val = new_val_reg;
92+
}
93+
assert(new_val->is_register(), "must be a register at this point");
94+
CodeStub* slow = new MMTkObjectBarrierStub(src, slot, new_val);
95+
__ jump(slow);
96+
__ branch_destination(slow->continuation());
97+
}
98+
99+
#undef __
100+
101+
#define __ ideal.
102+
103+
const TypeFunc* record_modified_node_entry_Type() {
104+
const Type **fields = TypeTuple::fields(1);
105+
fields[TypeFunc::Parms+0] = TypeOopPtr::BOTTOM; // oop src
106+
const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
107+
fields = TypeTuple::fields(0);
108+
const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
109+
return TypeFunc::make(domain, range);
110+
}
111+
112+
void MMTkObjectBarrierSetC2::record_modified_node(GraphKit* kit, Node* node) const {
113+
IdealKit ideal(kit, true);
114+
const TypeFunc *tf = record_modified_node_entry_Type();
115+
Node* x = __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, MMTkObjectBarrierSetRuntime::record_modified_node_slow), "record_modified_node", node);
116+
kit->final_sync(ideal); // Final sync IdealKit and GraphKit.
117+
}
118+
119+
#undef __

0 commit comments

Comments
 (0)