Skip to content

Commit eb6e5be

Browse files
jhawthornmaximecb
authored andcommitted
Add newhash and newarray instructions to yjit codegen (#48)
* Implement gen_newarray * Implement newhash for n=0 * Add yjit tests for newhash/newarray * Fix integer size warning on clang * Save PC and SP in newhash and newarray Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
1 parent d01204a commit eb6e5be

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

bootstraptest/test_yjit.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,3 +927,53 @@ def use_zero
927927
928928
[use_zero] + use_three
929929
}
930+
931+
# test building empty array
932+
assert_equal '[]', %q{
933+
def build_arr
934+
[]
935+
end
936+
937+
build_arr
938+
build_arr
939+
}
940+
941+
# test building array of one element
942+
assert_equal '[5]', %q{
943+
def build_arr(val)
944+
[val]
945+
end
946+
947+
build_arr(5)
948+
build_arr(5)
949+
}
950+
951+
# test building array of several element
952+
assert_equal '[5, 5, 5, 5, 5]', %q{
953+
def build_arr(val)
954+
[val, val, val, val, val]
955+
end
956+
957+
build_arr(5)
958+
build_arr(5)
959+
}
960+
961+
# test building empty hash
962+
assert_equal '{}', %q{
963+
def build_hash
964+
{}
965+
end
966+
967+
build_hash
968+
build_hash
969+
}
970+
971+
# test building hash with values
972+
assert_equal '{:foo=>:bar}', %q{
973+
def build_hash(val)
974+
{ foo: val }
975+
end
976+
977+
build_hash(:bar)
978+
build_hash(:bar)
979+
}

yjit_codegen.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,58 @@ gen_adjuststack(jitstate_t* jit, ctx_t* ctx)
595595
return YJIT_KEEP_COMPILING;
596596
}
597597

598+
// new array initialized from top N values
599+
static codegen_status_t
600+
gen_newarray(jitstate_t* jit, ctx_t* ctx)
601+
{
602+
rb_num_t n = (rb_num_t)jit_get_arg(jit, 0);
603+
604+
// Save the PC and SP because we are allocating
605+
jit_save_pc(jit, REG0);
606+
jit_save_sp(jit, ctx);
607+
608+
x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)n));
609+
610+
// call rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts);
611+
yjit_save_regs(cb);
612+
mov(cb, C_ARG_REGS[0], REG_EC);
613+
mov(cb, C_ARG_REGS[1], imm_opnd(n));
614+
lea(cb, C_ARG_REGS[2], values_ptr);
615+
call_ptr(cb, REG0, (void *)rb_ec_ary_new_from_values);
616+
yjit_load_regs(cb);
617+
618+
ctx_stack_pop(ctx, n);
619+
x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_ARRAY);
620+
mov(cb, stack_ret, RAX);
621+
622+
return YJIT_KEEP_COMPILING;
623+
}
624+
625+
// new hash initialized from top N values
626+
static codegen_status_t
627+
gen_newhash(jitstate_t* jit, ctx_t* ctx)
628+
{
629+
rb_num_t n = (rb_num_t)jit_get_arg(jit, 0);
630+
631+
if (n == 0) {
632+
// Save the PC and SP because we are allocating
633+
jit_save_pc(jit, REG0);
634+
jit_save_sp(jit, ctx);
635+
636+
// val = rb_hash_new();
637+
yjit_save_regs(cb);
638+
call_ptr(cb, REG0, (void *)rb_hash_new);
639+
yjit_load_regs(cb);
640+
641+
x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_HASH);
642+
mov(cb, stack_ret, RAX);
643+
644+
return YJIT_KEEP_COMPILING;
645+
} else {
646+
return YJIT_CANT_COMPILE;
647+
}
648+
}
649+
598650
static codegen_status_t
599651
gen_putnil(jitstate_t* jit, ctx_t* ctx)
600652
{
@@ -2848,6 +2900,8 @@ yjit_init_codegen(void)
28482900
yjit_reg_op(BIN(setn), gen_setn);
28492901
yjit_reg_op(BIN(pop), gen_pop);
28502902
yjit_reg_op(BIN(adjuststack), gen_adjuststack);
2903+
yjit_reg_op(BIN(newarray), gen_newarray);
2904+
yjit_reg_op(BIN(newhash), gen_newhash);
28512905
yjit_reg_op(BIN(putnil), gen_putnil);
28522906
yjit_reg_op(BIN(putobject), gen_putobject);
28532907
yjit_reg_op(BIN(putobject_INT2FIX_0_), gen_putobject_int2fix);

0 commit comments

Comments
 (0)