Skip to content

Commit ea33b0a

Browse files
jhawthornXrXr
authored andcommitted
Add concatstrings to yjit codegen (#58)
* Add ETYPE_TRUE and ETYPE_FALSE * Implement checktype * Implement concatstrings * Update deps
1 parent eb6e5be commit ea33b0a

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

bootstraptest/test_yjit.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,3 +977,47 @@ def build_hash(val)
977977
build_hash(:bar)
978978
build_hash(:bar)
979979
}
980+
981+
# test string interpolation with known types
982+
assert_equal 'foobar', %q{
983+
def make_str
984+
foo = -"foo"
985+
bar = -"bar"
986+
"#{foo}#{bar}"
987+
end
988+
989+
make_str
990+
make_str
991+
}
992+
993+
# test string interpolation with unknown types
994+
assert_equal 'foobar', %q{
995+
def make_str(foo, bar)
996+
"#{foo}#{bar}"
997+
end
998+
999+
make_str("foo", "bar")
1000+
make_str("foo", "bar")
1001+
}
1002+
1003+
# test string interpolation with known non-strings
1004+
assert_equal 'foo123', %q{
1005+
def make_str
1006+
foo = -"foo"
1007+
bar = 123
1008+
"#{foo}#{bar}"
1009+
end
1010+
1011+
make_str
1012+
make_str
1013+
}
1014+
1015+
# test string interpolation with unknown non-strings
1016+
assert_equal 'foo123', %q{
1017+
def make_str(foo, bar)
1018+
"#{foo}#{bar}"
1019+
end
1020+
1021+
make_str("foo", 123)
1022+
make_str("foo", 123)
1023+
}

common.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16712,6 +16712,7 @@ yjit_codegen.$(OBJEXT): $(top_srcdir)/internal/imemo.h
1671216712
yjit_codegen.$(OBJEXT): $(top_srcdir)/internal/object.h
1671316713
yjit_codegen.$(OBJEXT): $(top_srcdir)/internal/serial.h
1671416714
yjit_codegen.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
16715+
yjit_codegen.$(OBJEXT): $(top_srcdir)/internal/string.h
1671516716
yjit_codegen.$(OBJEXT): $(top_srcdir)/internal/vm.h
1671616717
yjit_codegen.$(OBJEXT): $(top_srcdir)/internal/warnings.h
1671716718
yjit_codegen.$(OBJEXT): {$(VPATH)}assert.h
@@ -16730,6 +16731,7 @@ yjit_codegen.$(OBJEXT): {$(VPATH)}config.h
1673016731
yjit_codegen.$(OBJEXT): {$(VPATH)}darray.h
1673116732
yjit_codegen.$(OBJEXT): {$(VPATH)}debug_counter.h
1673216733
yjit_codegen.$(OBJEXT): {$(VPATH)}defines.h
16734+
yjit_codegen.$(OBJEXT): {$(VPATH)}encoding.h
1673316735
yjit_codegen.$(OBJEXT): {$(VPATH)}id.h
1673416736
yjit_codegen.$(OBJEXT): {$(VPATH)}id_table.h
1673516737
yjit_codegen.$(OBJEXT): {$(VPATH)}insns.def
@@ -16880,6 +16882,8 @@ yjit_codegen.$(OBJEXT): {$(VPATH)}iseq.h
1688016882
yjit_codegen.$(OBJEXT): {$(VPATH)}method.h
1688116883
yjit_codegen.$(OBJEXT): {$(VPATH)}missing.h
1688216884
yjit_codegen.$(OBJEXT): {$(VPATH)}node.h
16885+
yjit_codegen.$(OBJEXT): {$(VPATH)}onigmo.h
16886+
yjit_codegen.$(OBJEXT): {$(VPATH)}oniguruma.h
1688316887
yjit_codegen.$(OBJEXT): {$(VPATH)}ruby_assert.h
1688416888
yjit_codegen.$(OBJEXT): {$(VPATH)}ruby_atomic.h
1688516889
yjit_codegen.$(OBJEXT): {$(VPATH)}st.h

yjit_codegen.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "internal/compile.h"
99
#include "internal/class.h"
1010
#include "internal/object.h"
11+
#include "internal/string.h"
1112
#include "insns_info.inc"
1213
#include "yjit.h"
1314
#include "yjit_iface.h"
@@ -1317,6 +1318,89 @@ gen_defined(jitstate_t* jit, ctx_t* ctx)
13171318
return YJIT_KEEP_COMPILING;
13181319
}
13191320

1321+
static codegen_status_t
1322+
gen_checktype(jitstate_t* jit, ctx_t* ctx)
1323+
{
1324+
// TODO: could we specialize on the type we detect
1325+
uint8_t* side_exit = yjit_side_exit(jit, ctx);
1326+
1327+
enum ruby_value_type type_val = (enum ruby_value_type)jit_get_arg(jit, 0);
1328+
// Only three types are emitted by compile.c
1329+
if (type_val == T_STRING || type_val == T_ARRAY || type_val == T_HASH) {
1330+
val_type_t val_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
1331+
x86opnd_t val = ctx_stack_pop(ctx, 1);
1332+
1333+
x86opnd_t stack_ret;
1334+
1335+
// Check if we know from type information
1336+
if ((type_val == T_STRING && val_type.type == ETYPE_STRING) ||
1337+
(type_val == T_ARRAY && val_type.type == ETYPE_ARRAY) ||
1338+
(type_val == T_HASH && val_type.type == ETYPE_HASH)) {
1339+
// guaranteed type match
1340+
stack_ret = ctx_stack_push(ctx, TYPE_TRUE);
1341+
mov(cb, stack_ret, imm_opnd(Qtrue));
1342+
return YJIT_KEEP_COMPILING;
1343+
} else if (val_type.is_imm || val_type.type != ETYPE_UNKNOWN) {
1344+
// guaranteed not to match T_STRING/T_ARRAY/T_HASH
1345+
stack_ret = ctx_stack_push(ctx, TYPE_FALSE);
1346+
mov(cb, stack_ret, imm_opnd(Qfalse));
1347+
return YJIT_KEEP_COMPILING;
1348+
}
1349+
1350+
mov(cb, REG0, val);
1351+
1352+
if (!val_type.is_heap) {
1353+
// if (SPECIAL_CONST_P(val)) {
1354+
// Bail if receiver is not a heap object
1355+
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
1356+
jnz_ptr(cb, side_exit);
1357+
cmp(cb, REG0, imm_opnd(Qfalse));
1358+
je_ptr(cb, side_exit);
1359+
cmp(cb, REG0, imm_opnd(Qnil));
1360+
je_ptr(cb, side_exit);
1361+
}
1362+
1363+
// Check type on object
1364+
mov(cb, REG0, mem_opnd(64, REG0, offsetof(struct RBasic, flags)));
1365+
and(cb, REG0, imm_opnd(RUBY_T_MASK));
1366+
cmp(cb, REG0, imm_opnd(type_val));
1367+
mov(cb, REG1, imm_opnd(Qfalse));
1368+
cmovne(cb, REG0, REG1);
1369+
1370+
stack_ret = ctx_stack_push(ctx, TYPE_IMM);
1371+
mov(cb, stack_ret, REG0);
1372+
1373+
return YJIT_KEEP_COMPILING;
1374+
} else {
1375+
return YJIT_CANT_COMPILE;
1376+
}
1377+
}
1378+
1379+
static codegen_status_t
1380+
gen_concatstrings(jitstate_t* jit, ctx_t* ctx)
1381+
{
1382+
rb_num_t n = (rb_num_t)jit_get_arg(jit, 0);
1383+
1384+
// Save the PC and SP because we are allocating
1385+
jit_save_pc(jit, REG0);
1386+
jit_save_sp(jit, ctx);
1387+
1388+
x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)n));
1389+
1390+
// call rb_str_concat_literals(long n, const VALUE *strings);
1391+
yjit_save_regs(cb);
1392+
mov(cb, C_ARG_REGS[0], imm_opnd(n));
1393+
lea(cb, C_ARG_REGS[1], values_ptr);
1394+
call_ptr(cb, REG0, (void *)rb_str_concat_literals);
1395+
yjit_load_regs(cb);
1396+
1397+
ctx_stack_pop(ctx, n);
1398+
x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_STRING);
1399+
mov(cb, stack_ret, RAX);
1400+
1401+
return YJIT_KEEP_COMPILING;
1402+
}
1403+
13201404
static void
13211405
guard_two_fixnums(ctx_t* ctx, uint8_t* side_exit)
13221406
{
@@ -2902,6 +2986,7 @@ yjit_init_codegen(void)
29022986
yjit_reg_op(BIN(adjuststack), gen_adjuststack);
29032987
yjit_reg_op(BIN(newarray), gen_newarray);
29042988
yjit_reg_op(BIN(newhash), gen_newhash);
2989+
yjit_reg_op(BIN(concatstrings), gen_concatstrings);
29052990
yjit_reg_op(BIN(putnil), gen_putnil);
29062991
yjit_reg_op(BIN(putobject), gen_putobject);
29072992
yjit_reg_op(BIN(putobject_INT2FIX_0_), gen_putobject_int2fix);
@@ -2913,6 +2998,7 @@ yjit_init_codegen(void)
29132998
yjit_reg_op(BIN(getinstancevariable), gen_getinstancevariable);
29142999
yjit_reg_op(BIN(setinstancevariable), gen_setinstancevariable);
29153000
yjit_reg_op(BIN(defined), gen_defined);
3001+
yjit_reg_op(BIN(checktype), gen_checktype);
29163002
yjit_reg_op(BIN(opt_lt), gen_opt_lt);
29173003
yjit_reg_op(BIN(opt_le), gen_opt_le);
29183004
yjit_reg_op(BIN(opt_ge), gen_opt_ge);

yjit_core.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ enum yjit_type_enum
3232
{
3333
ETYPE_UNKNOWN = 0,
3434
ETYPE_NIL,
35+
ETYPE_TRUE,
36+
ETYPE_FALSE,
3537
ETYPE_FIXNUM,
3638
ETYPE_ARRAY,
3739
ETYPE_HASH,
@@ -49,7 +51,7 @@ typedef struct yjit_type_struct
4951
uint8_t is_imm : 1;
5052

5153
// Specific value type, if known
52-
uint8_t type : 3;
54+
uint8_t type : 4;
5355

5456
} val_type_t;
5557
STATIC_ASSERT(val_type_size, sizeof(val_type_t) == 1);
@@ -64,6 +66,8 @@ STATIC_ASSERT(val_type_size, sizeof(val_type_t) == 1);
6466
#define TYPE_IMM ( (val_type_t){ .is_imm = 1 } )
6567

6668
#define TYPE_NIL ( (val_type_t){ .is_imm = 1, .type = ETYPE_NIL } )
69+
#define TYPE_TRUE ( (val_type_t){ .is_imm = 1, .type = ETYPE_TRUE } )
70+
#define TYPE_FALSE ( (val_type_t){ .is_imm = 1, .type = ETYPE_FALSE } )
6771
#define TYPE_FIXNUM ( (val_type_t){ .is_imm = 1, .type = ETYPE_FIXNUM } )
6872
#define TYPE_ARRAY ( (val_type_t){ .is_heap = 1, .type = ETYPE_ARRAY } )
6973
#define TYPE_HASH ( (val_type_t){ .is_heap = 1, .type = ETYPE_HASH } )

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy