summaryrefslogtreecommitdiff
path: root/yjit_codegen.c
diff options
context:
space:
mode:
authorAaron Patterson <[email protected]>2021-09-02 17:03:08 -0700
committerAlan Wu <[email protected]>2021-10-20 18:19:39 -0400
commit376f5ec1a1c744ca6a78726dbf9886e30b3400fa (patch)
treeaadb5b554f08407ae560c75b4362d3c19eb16daf /yjit_codegen.c
parent307a4369e15b65665b1245bc97f465e962543803 (diff)
Add a write barrier to ivar set
We need to fire the write barrier during ivar set. This function extracts the write barrier function then calls it. Co-Authored-By: John Hawthorn <[email protected]>
Diffstat (limited to 'yjit_codegen.c')
-rw-r--r--yjit_codegen.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 60cd08f456..2d31fd03de 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -1424,6 +1424,12 @@ jit_chain_guard(enum jcc_kinds jcc, jitstate_t *jit, const ctx_t *ctx, uint8_t d
bool rb_iv_index_tbl_lookup(struct st_table *iv_index_tbl, ID id, struct rb_iv_index_tbl_entry **ent); // vm_insnhelper.c
+static VALUE
+yjit_obj_written(VALUE a, VALUE b)
+{
+ return RB_OBJ_WRITTEN(a, Qundef, b);
+}
+
enum {
GETIVAR_MAX_DEPTH = 10, // up to 5 different classes, and embedded or not for each
OPT_AREF_MAX_CHAIN_DEPTH = 2, // hashes and arrays
@@ -1495,15 +1501,18 @@ gen_set_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt
mov(cb, REG1, ctx_stack_pop(ctx, 1));
mov(cb, ivar_opnd, REG1);
+ mov(cb, C_ARG_REGS[0], REG0);
+ mov(cb, C_ARG_REGS[1], REG1);
+ call_ptr(cb, REG1, (void *)yjit_obj_written);
+
// Pop receiver if it's on the temp stack
// ie. this is an attribute method
if (!reg0_opnd.is_self) {
ctx_stack_pop(ctx, 1);
}
- // Push the ivar on the stack
- x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN);
- mov(cb, out_opnd, REG1);
+ // Increment the stack
+ ctx_stack_push(ctx, TYPE_UNKNOWN);
}
else {
// Compile time value is *not* embeded.
@@ -1523,6 +1532,9 @@ gen_set_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt
jle_ptr(cb, COUNTED_EXIT(side_exit, getivar_idx_out_of_range));
}
+ // Save recv for write barrier later
+ mov(cb, C_ARG_REGS[0], REG0);
+
// Get a pointer to the extended table
x86opnd_t tbl_opnd = mem_opnd(64, REG0, offsetof(struct RObject, as.heap.ivptr));
mov(cb, REG0, tbl_opnd);
@@ -1532,15 +1544,17 @@ gen_set_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt
mov(cb, REG1, ctx_stack_pop(ctx, 1));
mov(cb, ivar_opnd, REG1);
+ mov(cb, C_ARG_REGS[1], REG1);
+ call_ptr(cb, REG1, (void *)yjit_obj_written);
+
// Pop receiver if it's on the temp stack
// ie. this is an attribute method
if (!reg0_opnd.is_self) {
ctx_stack_pop(ctx, 1);
}
- // Push the ivar on the stack
- x86opnd_t out_opnd = ctx_stack_push(ctx, TYPE_UNKNOWN);
- mov(cb, out_opnd, REG1);
+ // Increment the stack
+ ctx_stack_push(ctx, TYPE_UNKNOWN);
}
// Jump to next instruction. This allows guard chains to share the same successor.