summaryrefslogtreecommitdiff
path: root/yjit_core.c
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2021-07-12 13:35:09 -0700
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:37 -0400
commitcb5571eece818b33d2f6a33b892e7cda31231e69 (patch)
treee320cfb64a30f1c5b3b1ca6adb038aee5b3ca197 /yjit_core.c
parentd5f18f7845f0f0fb3024ada63a552deac9c11ad7 (diff)
Flatten mappings when clearing locals
We clear locals when we know their values might change (ex. when performing a method call). However previously values on the stack which were originally pushed from a local would still point back to that local. With this commit, when clearing locals, we'll now iterate over the mappings of the stack and copy the known type from the local to the stack mapping, removing the association to the local. This should mean both that we'll retain any information we already know about the local type, and that if a local is modified we won't incorrectly infer it's new type from the existing value on the stack.
Diffstat (limited to 'yjit_core.c')
-rw-r--r--yjit_core.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/yjit_core.c b/yjit_core.c
index c4f18e872f..ae771fb7c4 100644
--- a/yjit_core.c
+++ b/yjit_core.c
@@ -201,6 +201,16 @@ void ctx_set_local_type(ctx_t* ctx, size_t idx, val_type_t type)
// eg: because of a call we can't track
void ctx_clear_local_types(ctx_t* ctx)
{
+ // When clearing local types we must detach any stack mappings to those
+ // locals. Even if local values may have changed, stack values will not.
+ for (int i = 0; i < ctx->stack_size && i < MAX_LOCAL_TYPES; i++) {
+ temp_mapping_t *mapping = &ctx->temp_mapping[i];
+ if (mapping->kind == TEMP_LOCAL) {
+ RUBY_ASSERT(mapping->idx < MAX_LOCAL_TYPES);
+ ctx->temp_types[i] = ctx->local_types[mapping->idx];
+ *mapping = MAP_STACK;
+ }
+ }
memset(&ctx->local_types, 0, sizeof(ctx->local_types));
}