diff options
author | Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> | 2021-03-31 15:54:46 -0400 |
---|---|---|
committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:32 -0400 |
commit | aee44e4f2bcd795b5a81c72cb75d742103bb070b (patch) | |
tree | bded8242c24efc33da06cea490dbefc75334ff15 /yjit_core.c | |
parent | e47dd8bb88a10eb20afb8dc37f19ae6ee8e56f4b (diff) |
Part 1 of improved type tracking logic
Diffstat (limited to 'yjit_core.c')
-rw-r--r-- | yjit_core.c | 119 |
1 files changed, 93 insertions, 26 deletions
diff --git a/yjit_core.c b/yjit_core.c index 4d710b7499..23bddfb573 100644 --- a/yjit_core.c +++ b/yjit_core.c @@ -34,12 +34,33 @@ Push one new value on the temp stack Return a pointer to the new stack top */ x86opnd_t -ctx_stack_push(ctx_t* ctx, int type) +ctx_stack_push(ctx_t* ctx, val_type_t type) { // Keep track of the type of the value - RUBY_ASSERT(type <= RUBY_T_MASK); - if (ctx->stack_size < MAX_TEMP_TYPES) + if (ctx->stack_size < MAX_TEMP_TYPES) { + ctx->temp_mapping[ctx->stack_size] = MAP_STACK; ctx->temp_types[ctx->stack_size] = type; + } + + ctx->stack_size += 1; + ctx->sp_offset += 1; + + // SP points just above the topmost value + int32_t offset = (ctx->sp_offset - 1) * sizeof(VALUE); + return mem_opnd(64, REG_SP, offset); +} + +/* +Push the self value on the stack +*/ +x86opnd_t +ctx_stack_push_self(ctx_t* ctx) +{ + // Keep track of the type of the value + if (ctx->stack_size < MAX_TEMP_TYPES) { + ctx->temp_mapping[ctx->stack_size] = MAP_SELF; + ctx->temp_types[ctx->stack_size] = ctx->self_type; + } ctx->stack_size += 1; ctx->sp_offset += 1; @@ -66,8 +87,10 @@ ctx_stack_pop(ctx_t* ctx, size_t n) for (size_t i = 0; i < n; ++i) { size_t idx = ctx->stack_size - i - 1; - if (idx < MAX_TEMP_TYPES) - ctx->temp_types[idx] = T_NONE; + if (idx < MAX_TEMP_TYPES) { + ctx->temp_types[idx] = TYPE_UNKNOWN; + ctx->temp_mapping[idx] = MAP_STACK; + } } ctx->stack_size -= n; @@ -90,18 +113,58 @@ ctx_stack_opnd(ctx_t* ctx, int32_t idx) } /** -Get the type of the topmost value on the temp stack +Get the type of a value on the temp stack Returns T_NONE if unknown */ -int -ctx_get_top_type(ctx_t* ctx) +val_type_t +ctx_get_temp_type(const ctx_t* ctx, size_t idx) { - RUBY_ASSERT(ctx->stack_size > 0); + RUBY_ASSERT(idx < ctx->stack_size); if (ctx->stack_size > MAX_TEMP_TYPES) - return T_NONE; + return TYPE_UNKNOWN; + + temp_mapping_t mapping = ctx->temp_mapping[ctx->stack_size - 1 - idx]; + + if (mapping.kind == TEMP_SELF) + return ctx->self_type; + else if (mapping.kind == TEMP_STACK) + return ctx->temp_types[ctx->stack_size - 1 - idx]; + + RUBY_ASSERT(false); + return TYPE_UNKNOWN; +} + +/* +Compute a difference between two value types +Returns 0 if the two are the same +Returns > 0 if different but compatible +Returns INT_MAX if incompatible +*/ +int type_diff(val_type_t src, val_type_t dst) +{ + RUBY_ASSERT(!src.is_heap || !src.is_imm); + RUBY_ASSERT(!dst.is_heap || !dst.is_imm); + + if (src.type != dst.type && dst.type != ETYPE_UNKNOWN) + return INT_MAX; + + if (src.is_heap && !dst.is_heap) + return INT_MAX; + + if (src.is_imm && !dst.is_imm) + return INT_MAX; + + if (src.is_heap != dst.is_heap) + return 1; + + if (src.is_imm != dst.is_imm) + return 1; - return ctx->temp_types[ctx->stack_size - 1]; + if (src.type != dst.type) + return 1; + + return 0; } /** @@ -127,26 +190,30 @@ int ctx_diff(const ctx_t* src, const ctx_t* dst) if (dst->sp_offset != src->sp_offset) return INT_MAX; - if (dst->self_is_object != src->self_is_object) - return INT_MAX; - // Difference sum int diff = 0; - // For each temporary variable - for (size_t i = 0; i < MAX_TEMP_TYPES; ++i) + // Check the type of self + int self_diff = type_diff(src->self_type, dst->self_type); + + if (self_diff == INT_MAX) + return INT_MAX; + + diff += self_diff; + + // TODO: when we track local types, need to check them too + + // For each value on the temp stack + for (size_t i = 0; i < src->stack_size; ++i) { - int t_src = src->temp_types[i]; - int t_dst = dst->temp_types[i]; + val_type_t t_src = ctx_get_temp_type(src, i); + val_type_t t_dst = ctx_get_temp_type(dst, i); + int temp_diff = type_diff(t_src, t_dst); - if (t_dst != t_src) - { - // It's OK to lose some type information - if (t_dst == T_NONE) - diff += 1; - else - return INT_MAX; - } + if (temp_diff == INT_MAX) + return INT_MAX; + + diff += temp_diff; } return diff; |