Skip to content

Commit e250a0b

Browse files
authored
Merge pull request ruby#139 from jhawthorn/keep_mappings
Preserve type mappings when manipulating the stack
2 parents 09e5897 + 9cd04b0 commit e250a0b

File tree

4 files changed

+196
-74
lines changed

4 files changed

+196
-74
lines changed

test/ruby/test_yjit.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,24 @@ def fib(n)
141141
RUBY
142142
end
143143

144+
def test_ctx_different_mappings
145+
# regression test simplified from URI::Generic#hostname=
146+
assert_compiles(<<~'RUBY', frozen_string_literal: true)
147+
def foo(v)
148+
!(v&.start_with?('[')) && v&.index(':')
149+
end
150+
151+
foo(nil)
152+
foo("example.com")
153+
RUBY
154+
end
155+
144156
def assert_no_exits(script)
145157
assert_compiles(script)
146158
end
147159

148160
ANY = Object.new
149-
def assert_compiles(test_script, insns: [], min_calls: 1, stdout: nil, exits: {}, result: ANY)
161+
def assert_compiles(test_script, insns: [], min_calls: 1, stdout: nil, exits: {}, result: ANY, frozen_string_literal: nil)
150162
reset_stats = <<~RUBY
151163
YJIT.runtime_stats
152164
YJIT.reset_stats!
@@ -183,6 +195,7 @@ def collect_iseqs(iseq)
183195
RUBY
184196

185197
script = <<~RUBY
198+
#{"# frozen_string_literal: true" if frozen_string_literal}
186199
_test_proc = proc {
187200
#{test_script}
188201
}

yjit_codegen.c

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -551,11 +551,11 @@ static codegen_status_t
551551
gen_dup(jitstate_t* jit, ctx_t* ctx)
552552
{
553553
// Get the top value and its type
554-
val_type_t dup_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
555554
x86opnd_t dup_val = ctx_stack_pop(ctx, 0);
555+
temp_type_mapping_t mapping = ctx_get_opnd_mapping(ctx, OPND_STACK(0));
556556

557557
// Push the same value on top
558-
x86opnd_t loc0 = ctx_stack_push(ctx, dup_type);
558+
x86opnd_t loc0 = ctx_stack_push_mapping(ctx, mapping);
559559
mov(cb, REG0, dup_val);
560560
mov(cb, loc0, REG0);
561561

@@ -573,17 +573,16 @@ gen_dupn(jitstate_t* jit, ctx_t* ctx)
573573
return YJIT_CANT_COMPILE;
574574
}
575575

576-
val_type_t type1 = ctx_get_opnd_type(ctx, OPND_STACK(1));
577576
x86opnd_t opnd1 = ctx_stack_opnd(ctx, 1);
578-
579-
val_type_t type0 = ctx_get_opnd_type(ctx, OPND_STACK(0));
580577
x86opnd_t opnd0 = ctx_stack_opnd(ctx, 0);
578+
temp_type_mapping_t mapping1 = ctx_get_opnd_mapping(ctx, OPND_STACK(1));
579+
temp_type_mapping_t mapping0 = ctx_get_opnd_mapping(ctx, OPND_STACK(0));
581580

582-
x86opnd_t dst1 = ctx_stack_push(ctx, type1);
581+
x86opnd_t dst1 = ctx_stack_push_mapping(ctx, mapping1);
583582
mov(cb, REG0, opnd1);
584583
mov(cb, dst1, REG0);
585584

586-
x86opnd_t dst0 = ctx_stack_push(ctx, type0);
585+
x86opnd_t dst0 = ctx_stack_push_mapping(ctx, mapping0);
587586
mov(cb, REG0, opnd0);
588587
mov(cb, dst0, REG0);
589588

@@ -594,21 +593,19 @@ gen_dupn(jitstate_t* jit, ctx_t* ctx)
594593
static codegen_status_t
595594
gen_swap(jitstate_t* jit, ctx_t* ctx)
596595
{
597-
val_type_t type0 = ctx_get_opnd_type(ctx, OPND_STACK(0));
598596
x86opnd_t opnd0 = ctx_stack_opnd(ctx, 0);
599-
600-
val_type_t type1 = ctx_get_opnd_type(ctx, OPND_STACK(1));
601597
x86opnd_t opnd1 = ctx_stack_opnd(ctx, 1);
598+
temp_type_mapping_t mapping0 = ctx_get_opnd_mapping(ctx, OPND_STACK(0));
599+
temp_type_mapping_t mapping1 = ctx_get_opnd_mapping(ctx, OPND_STACK(1));
602600

603601
mov(cb, REG0, opnd0);
604602
mov(cb, REG1, opnd1);
605-
606-
ctx_set_opnd_type(ctx, OPND_STACK(0), type1);
607-
ctx_set_opnd_type(ctx, OPND_STACK(1), type0);
608-
609603
mov(cb, opnd0, REG1);
610604
mov(cb, opnd1, REG0);
611605

606+
ctx_set_opnd_mapping(ctx, OPND_STACK(0), mapping1);
607+
ctx_set_opnd_mapping(ctx, OPND_STACK(1), mapping0);
608+
612609
return YJIT_KEEP_COMPILING;
613610
}
614611

@@ -618,16 +615,15 @@ gen_setn(jitstate_t* jit, ctx_t* ctx)
618615
{
619616
rb_num_t n = (rb_num_t)jit_get_arg(jit, 0);
620617

621-
// Get the top value and its type
622-
val_type_t top_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
618+
// Set the destination
623619
x86opnd_t top_val = ctx_stack_pop(ctx, 0);
624-
625-
// Set the destination and its type
626-
ctx_set_opnd_type(ctx, OPND_STACK(n), top_type);
627620
x86opnd_t dst_opnd = ctx_stack_opnd(ctx, (int32_t)n);
628621
mov(cb, REG0, top_val);
629622
mov(cb, dst_opnd, REG0);
630623

624+
temp_type_mapping_t mapping = ctx_get_opnd_mapping(ctx, OPND_STACK(0));
625+
ctx_set_opnd_mapping(ctx, OPND_STACK(n), mapping);
626+
631627
return YJIT_KEEP_COMPILING;
632628
}
633629

@@ -638,10 +634,10 @@ gen_topn(jitstate_t* jit, ctx_t* ctx)
638634
int32_t n = (int32_t)jit_get_arg(jit, 0);
639635

640636
// Get top n type / operand
641-
val_type_t top_n_type = ctx_get_opnd_type(ctx, OPND_STACK(n));
642637
x86opnd_t top_n_val = ctx_stack_opnd(ctx, n);
638+
temp_type_mapping_t mapping = ctx_get_opnd_mapping(ctx, OPND_STACK(n));
643639

644-
x86opnd_t loc0 = ctx_stack_push(ctx, top_n_type);
640+
x86opnd_t loc0 = ctx_stack_push_mapping(ctx, mapping);
645641
mov(cb, REG0, top_n_val);
646642
mov(cb, loc0, REG0);
647643

@@ -1235,7 +1231,7 @@ gen_set_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt
12351231
ADD_COMMENT(cb, "guard value is immediate");
12361232
test(cb, REG1, imm_opnd(RUBY_IMMEDIATE_MASK));
12371233
jz_ptr(cb, COUNTED_EXIT(side_exit, setivar_val_heapobject));
1238-
ctx_set_opnd_type(ctx, OPND_STACK(0), TYPE_IMM);
1234+
ctx_upgrade_opnd_type(ctx, OPND_STACK(0), TYPE_IMM);
12391235
}
12401236
12411237
// Pop the value to write
@@ -1665,6 +1661,26 @@ guard_two_fixnums(ctx_t* ctx, uint8_t* side_exit)
16651661
val_type_t arg1_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
16661662
val_type_t arg0_type = ctx_get_opnd_type(ctx, OPND_STACK(1));
16671663

1664+
if (arg0_type.is_heap || arg1_type.is_heap) {
1665+
jmp_ptr(cb, side_exit);
1666+
return;
1667+
}
1668+
1669+
if (arg0_type.type != ETYPE_FIXNUM && arg0_type.type != ETYPE_UNKNOWN) {
1670+
jmp_ptr(cb, side_exit);
1671+
return;
1672+
}
1673+
1674+
if (arg1_type.type != ETYPE_FIXNUM && arg1_type.type != ETYPE_UNKNOWN) {
1675+
jmp_ptr(cb, side_exit);
1676+
return;
1677+
}
1678+
1679+
RUBY_ASSERT(!arg0_type.is_heap);
1680+
RUBY_ASSERT(!arg1_type.is_heap);
1681+
RUBY_ASSERT(arg0_type.type == ETYPE_FIXNUM || arg0_type.type == ETYPE_UNKNOWN);
1682+
RUBY_ASSERT(arg1_type.type == ETYPE_FIXNUM || arg1_type.type == ETYPE_UNKNOWN);
1683+
16681684
// Get stack operands without popping them
16691685
x86opnd_t arg1 = ctx_stack_opnd(ctx, 0);
16701686
x86opnd_t arg0 = ctx_stack_opnd(ctx, 1);
@@ -1682,8 +1698,8 @@ guard_two_fixnums(ctx_t* ctx, uint8_t* side_exit)
16821698
}
16831699

16841700
// Set stack types in context
1685-
ctx_set_opnd_type(ctx, OPND_STACK(0), TYPE_FIXNUM);
1686-
ctx_set_opnd_type(ctx, OPND_STACK(1), TYPE_FIXNUM);
1701+
ctx_upgrade_opnd_type(ctx, OPND_STACK(0), TYPE_FIXNUM);
1702+
ctx_upgrade_opnd_type(ctx, OPND_STACK(1), TYPE_FIXNUM);
16871703
}
16881704

16891705
// Conditional move operation used by comparison operators
@@ -2419,7 +2435,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
24192435
cmp(cb, REG0, imm_opnd(Qnil));
24202436
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
24212437

2422-
ctx_set_opnd_type(ctx, insn_opnd, TYPE_NIL);
2438+
ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_NIL);
24232439
}
24242440
}
24252441
else if (known_klass == rb_cTrueClass) {
@@ -2431,7 +2447,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
24312447
cmp(cb, REG0, imm_opnd(Qtrue));
24322448
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
24332449

2434-
ctx_set_opnd_type(ctx, insn_opnd, TYPE_TRUE);
2450+
ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_TRUE);
24352451
}
24362452
}
24372453
else if (known_klass == rb_cFalseClass) {
@@ -2444,7 +2460,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
24442460
test(cb, REG0, REG0);
24452461
jit_chain_guard(JCC_JNZ, jit, ctx, max_chain_depth, side_exit);
24462462

2447-
ctx_set_opnd_type(ctx, insn_opnd, TYPE_FALSE);
2463+
ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_FALSE);
24482464
}
24492465
}
24502466
else if (known_klass == rb_cInteger && FIXNUM_P(sample_instance)) {
@@ -2457,7 +2473,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
24572473
ADD_COMMENT(cb, "guard object is fixnum");
24582474
test(cb, REG0, imm_opnd(RUBY_FIXNUM_FLAG));
24592475
jit_chain_guard(JCC_JZ, jit, ctx, max_chain_depth, side_exit);
2460-
ctx_set_opnd_type(ctx, insn_opnd, TYPE_FIXNUM);
2476+
ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_FIXNUM);
24612477
}
24622478
}
24632479
else if (known_klass == rb_cSymbol && STATIC_SYM_P(sample_instance)) {
@@ -2471,7 +2487,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
24712487
STATIC_ASSERT(special_shift_is_8, RUBY_SPECIAL_SHIFT == 8);
24722488
cmp(cb, REG0_8, imm_opnd(RUBY_SYMBOL_FLAG));
24732489
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
2474-
ctx_set_opnd_type(ctx, insn_opnd, TYPE_STATIC_SYMBOL);
2490+
ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_STATIC_SYMBOL);
24752491
}
24762492
}
24772493
else if (known_klass == rb_cFloat && FLONUM_P(sample_instance)) {
@@ -2485,7 +2501,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
24852501
and(cb, REG1, imm_opnd(RUBY_FLONUM_MASK));
24862502
cmp(cb, REG1, imm_opnd(RUBY_FLONUM_FLAG));
24872503
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
2488-
ctx_set_opnd_type(ctx, insn_opnd, TYPE_FLONUM);
2504+
ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_FLONUM);
24892505
}
24902506
}
24912507
else if (FL_TEST(known_klass, FL_SINGLETON) && sample_instance == rb_attr_get(known_klass, id__attached__)) {
@@ -2518,7 +2534,7 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
25182534
cmp(cb, REG0, imm_opnd(Qnil));
25192535
jit_chain_guard(JCC_JBE, jit, ctx, max_chain_depth, side_exit);
25202536

2521-
ctx_set_opnd_type(ctx, insn_opnd, TYPE_HEAP);
2537+
ctx_upgrade_opnd_type(ctx, insn_opnd, TYPE_HEAP);
25222538
}
25232539

25242540
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
@@ -3063,7 +3079,7 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r
30633079
ctx_set_local_type(&callee_ctx, arg_idx, arg_type);
30643080
}
30653081
val_type_t recv_type = ctx_get_opnd_type(ctx, OPND_STACK(argc));
3066-
ctx_set_opnd_type(&callee_ctx, OPND_SELF, recv_type);
3082+
ctx_upgrade_opnd_type(&callee_ctx, OPND_SELF, recv_type);
30673083

30683084
// The callee might change locals through Kernel#binding and other means.
30693085
ctx_clear_local_types(ctx);

0 commit comments

Comments
 (0)