Skip to content

Commit fea59e4

Browse files
authored
Fix write barrier parameter type (#1130)
Change the target type of write barrier functions to `Option<ObjectReference>`. This allows VM bindings to use the write barrier API when storing NULL references or non-references values to slots. Fixes: #1129
1 parent a02803b commit fea59e4

File tree

4 files changed

+41
-18
lines changed

4 files changed

+41
-18
lines changed

src/memory_manager.rs

+26-4
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,24 @@ pub fn post_alloc<VM: VMBinding>(
229229
/// * `src`: The modified source object.
230230
/// * `slot`: The location of the field to be modified.
231231
/// * `target`: The target for the write operation.
232+
///
233+
/// # Deprecated
234+
///
235+
/// This function needs to be redesigned. Its current form has multiple issues.
236+
///
237+
/// - It is only able to write non-null object references into the slot. But dynamic language
238+
/// VMs may write non-reference values, such as tagged small integers, special values such as
239+
/// `null`, `undefined`, `true`, `false`, etc. into a field that previous contains an object
240+
/// reference.
241+
/// - It relies on `slot.store` to write `target` into the slot, but `slot.store` is designed for
242+
/// forwarding references when an object is moved by GC, and is supposed to preserve tagged
243+
/// type information, the offset (if it is an interior pointer), etc. A write barrier is
244+
/// associated to an assignment operation, which usually updates such information instead.
245+
///
246+
/// We will redesign a more general subsuming write barrier to address those problems and replace
247+
/// the current `object_reference_write`. Before that happens, VM bindings should use
248+
/// `object_reference_write_pre` and `object_reference_write_post` instead.
249+
#[deprecated = "Use `object_reference_write_pre` and `object_reference_write_post` instead, until this function is redesigned"]
232250
pub fn object_reference_write<VM: VMBinding>(
233251
mutator: &mut Mutator<VM>,
234252
src: ObjectReference,
@@ -252,12 +270,14 @@ pub fn object_reference_write<VM: VMBinding>(
252270
/// * `mutator`: The mutator for the current thread.
253271
/// * `src`: The modified source object.
254272
/// * `slot`: The location of the field to be modified.
255-
/// * `target`: The target for the write operation.
273+
/// * `target`: The target for the write operation. `None` if the slot did not hold an object
274+
/// reference before the write operation. For example, the slot may be holding a `null`
275+
/// reference, a small integer, or special values such as `true`, `false`, `undefined`, etc.
256276
pub fn object_reference_write_pre<VM: VMBinding>(
257277
mutator: &mut Mutator<VM>,
258278
src: ObjectReference,
259279
slot: VM::VMEdge,
260-
target: ObjectReference,
280+
target: Option<ObjectReference>,
261281
) {
262282
mutator
263283
.barrier()
@@ -278,12 +298,14 @@ pub fn object_reference_write_pre<VM: VMBinding>(
278298
/// * `mutator`: The mutator for the current thread.
279299
/// * `src`: The modified source object.
280300
/// * `slot`: The location of the field to be modified.
281-
/// * `target`: The target for the write operation.
301+
/// * `target`: The target for the write operation. `None` if the slot no longer hold an object
302+
/// reference after the write operation. This may happen when writing a `null` reference, a small
303+
/// integers, or a special value such as`true`, `false`, `undefined`, etc., into the slot.
282304
pub fn object_reference_write_post<VM: VMBinding>(
283305
mutator: &mut Mutator<VM>,
284306
src: ObjectReference,
285307
slot: VM::VMEdge,
286-
target: ObjectReference,
308+
target: Option<ObjectReference>,
287309
) {
288310
mutator
289311
.barrier()

src/plan/barriers.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,17 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
5252
slot: VM::VMEdge,
5353
target: ObjectReference,
5454
) {
55-
self.object_reference_write_pre(src, slot, target);
55+
self.object_reference_write_pre(src, slot, Some(target));
5656
slot.store(target);
57-
self.object_reference_write_post(src, slot, target);
57+
self.object_reference_write_post(src, slot, Some(target));
5858
}
5959

6060
/// Full pre-barrier for object reference write
6161
fn object_reference_write_pre(
6262
&mut self,
6363
_src: ObjectReference,
6464
_slot: VM::VMEdge,
65-
_target: ObjectReference,
65+
_target: Option<ObjectReference>,
6666
) {
6767
}
6868

@@ -71,7 +71,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
7171
&mut self,
7272
_src: ObjectReference,
7373
_slot: VM::VMEdge,
74-
_target: ObjectReference,
74+
_target: Option<ObjectReference>,
7575
) {
7676
}
7777

@@ -81,7 +81,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
8181
&mut self,
8282
_src: ObjectReference,
8383
_slot: VM::VMEdge,
84-
_target: ObjectReference,
84+
_target: Option<ObjectReference>,
8585
) {
8686
}
8787

@@ -147,7 +147,7 @@ pub trait BarrierSemantics: 'static + Send {
147147
&mut self,
148148
src: ObjectReference,
149149
slot: <Self::VM as VMBinding>::VMEdge,
150-
target: ObjectReference,
150+
target: Option<ObjectReference>,
151151
);
152152

153153
/// Slow-path call for mempry slice copy operations. For example, array-copy operations.
@@ -217,7 +217,7 @@ impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
217217
&mut self,
218218
src: ObjectReference,
219219
slot: <S::VM as VMBinding>::VMEdge,
220-
target: ObjectReference,
220+
target: Option<ObjectReference>,
221221
) {
222222
if self.object_is_unlogged(src) {
223223
self.object_reference_write_slow(src, slot, target);
@@ -228,7 +228,7 @@ impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
228228
&mut self,
229229
src: ObjectReference,
230230
slot: <S::VM as VMBinding>::VMEdge,
231-
target: ObjectReference,
231+
target: Option<ObjectReference>,
232232
) {
233233
if self.log_object(src) {
234234
self.semantics

src/plan/generational/barrier.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>> BarrierSem
7575
&mut self,
7676
src: ObjectReference,
7777
_slot: VM::VMEdge,
78-
_target: ObjectReference,
78+
_target: Option<ObjectReference>,
7979
) {
8080
// enqueue the object
8181
self.modbuf.push(src);

src/vm/tests/mock_tests/mock_test_barrier_slow_path_assertion.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn test_assertion_barrier_invalid_ref() {
3030
fixture.mutator_mut().barrier.object_reference_write_slow(
3131
invalid_objref,
3232
edge,
33-
objref,
33+
Some(objref),
3434
);
3535
});
3636
},
@@ -51,10 +51,11 @@ fn test_assertion_barrier_valid_ref() {
5151
let edge = Address::from_ref(&slot);
5252

5353
// Invoke barrier slowpath with the valid object ref
54-
fixture
55-
.mutator_mut()
56-
.barrier
57-
.object_reference_write_slow(objref, edge, objref);
54+
fixture.mutator_mut().barrier.object_reference_write_slow(
55+
objref,
56+
edge,
57+
Some(objref),
58+
);
5859
});
5960
},
6061
no_cleanup,

0 commit comments

Comments
 (0)