summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yjit_codegen.c19
-rw-r--r--yjit_core.c7
-rw-r--r--yjit_core.h1
3 files changed, 20 insertions, 7 deletions
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 0d90cdeb43..b91af9bba7 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -527,8 +527,8 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx)
mov(cb, REG0, mem_opnd(64, REG0, offs));
// Write the local at SP
- //x86opnd_t stack_top = ctx_stack_push_local(ctx, local_idx);
- x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_UNKNOWN);
+ x86opnd_t stack_top = ctx_stack_push_local(ctx, local_idx);
+ //x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_UNKNOWN);
mov(cb, stack_top, REG0);
return YJIT_KEEP_COMPILING;
@@ -592,12 +592,9 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx)
// if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
jnz_ptr(cb, side_exit);
- // NOTE: disabled for now since we don't have a good strategy
- // for dealing with how blocks/closures can affect local types
- //
// Set the type of the local variable in the context
- //val_type_t temp_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
- //ctx_set_local_type(ctx, local_idx, temp_type);
+ val_type_t temp_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
+ ctx_set_local_type(ctx, local_idx, temp_type);
// Pop the value to write from the stack
x86opnd_t stack_top = ctx_stack_pop(ctx, 1);
@@ -616,6 +613,8 @@ guard_self_is_heap(codeblock_t *cb, x86opnd_t self_opnd, uint8_t *side_exit, ctx
{
// `self` is constant throughout the entire region, so we only need to do this check once.
if (!ctx->self_type.is_heap) {
+ // FIXME: use two-comparison test
+ ADD_COMMENT(cb, "guard self is heap");
test(cb, self_opnd, imm_opnd(RUBY_IMMEDIATE_MASK));
jnz_ptr(cb, side_exit);
cmp(cb, self_opnd, imm_opnd(Qfalse));
@@ -1399,6 +1398,8 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_
// Check that the receiver is a heap object
if (!val_type.is_heap)
{
+ // FIXME: use two comparisons instead of 3 here
+ ADD_COMMENT(cb, "guard not immediate");
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
jnz_ptr(cb, side_exit);
cmp(cb, REG0, imm_opnd(Qfalse));
@@ -1413,6 +1414,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
// Bail if receiver class is different from compile-time call cache class
+ ADD_COMMENT(cb, "guard known class");
jit_mov_gc_ptr(jit, cb, REG1, known_klass);
cmp(cb, klass_opnd, REG1);
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
@@ -1851,6 +1853,9 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx)
RUBY_ASSERT(cme->called_id == mid);
assume_method_lookup_stable(comptime_recv_klass, cme, jit->block);
+ // Method calls may corrupt types
+ ctx_clear_local_types(ctx);
+
switch (cme->def->type) {
case VM_METHOD_TYPE_ISEQ:
return gen_oswb_iseq(jit, ctx, ci, cme, argc);
diff --git a/yjit_core.c b/yjit_core.c
index 64a87b5d8a..9469616947 100644
--- a/yjit_core.c
+++ b/yjit_core.c
@@ -208,6 +208,13 @@ void ctx_set_local_type(ctx_t* ctx, size_t idx, val_type_t type)
ctx->local_types[idx] = type;
}
+// Erase local variable type information
+// eg: because of a call we can't track
+void ctx_clear_local_types(ctx_t* ctx)
+{
+ memset(&ctx->local_types, 0, sizeof(ctx->local_types));
+}
+
/*
Compute a difference between two value types
Returns 0 if the two are the same
diff --git a/yjit_core.h b/yjit_core.h
index ab849b9414..2297caebcd 100644
--- a/yjit_core.h
+++ b/yjit_core.h
@@ -240,6 +240,7 @@ x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
val_type_t ctx_get_opnd_type(const ctx_t* ctx, insn_opnd_t opnd);
void ctx_set_opnd_type(ctx_t* ctx, insn_opnd_t opnd, val_type_t type);
void ctx_set_local_type(ctx_t* ctx, size_t idx, val_type_t type);
+void ctx_clear_local_types(ctx_t* ctx);
int ctx_diff(const ctx_t* src, const ctx_t* dst);
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx);