summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2021-06-22 19:22:30 -0700
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:37 -0400
commitdfc5e5e35b927bcfc26af0b59d4952e97bdfb0f7 (patch)
tree3ff236a27d603e97c5245fdaceae536b241a2edf
parentc3f264b62cfee09a90fd3f75de9eaa36bc06645d (diff)
Support guards against symbols and integers
This adds guards
-rw-r--r--bootstraptest/test_yjit.rb52
-rw-r--r--yjit_codegen.c26
-rw-r--r--yjit_core.h1
3 files changed, 76 insertions, 3 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index fc0b693ec2..db494b7911 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -1295,3 +1295,55 @@ assert_equal '[:B, [:B, :m]]', %q{
ins.singleton_class.define_method(:bar, B.instance_method(:foo))
ins.bar
}
+
+# Call to fixnum
+assert_equal '[true, false]', %q{
+ def is_odd(obj)
+ obj.odd?
+ end
+
+ is_odd(1)
+ is_odd(1)
+
+ [is_odd(123), is_odd(456)]
+}
+
+# Call to bignum
+assert_equal '[true, false]', %q{
+ def is_odd(obj)
+ obj.odd?
+ end
+
+ bignum = 99999999999999999999
+ is_odd(bignum)
+ is_odd(bignum)
+
+ [is_odd(bignum), is_odd(bignum+1)]
+}
+
+# Call to fixnum and bignum
+assert_equal '[true, false, true, false]', %q{
+ def is_odd(obj)
+ obj.odd?
+ end
+
+ bignum = 99999999999999999999
+ is_odd(bignum)
+ is_odd(bignum)
+ is_odd(123)
+ is_odd(123)
+
+ [is_odd(123), is_odd(456), is_odd(bignum), is_odd(bignum+1)]
+}
+
+# Call to static and dynamic symbol
+assert_equal 'bar', %q{
+ def to_string(obj)
+ obj.to_s
+ end
+
+ to_string(:foo)
+ to_string(:foo)
+ to_string((-"bar").to_sym)
+ to_string((-"bar").to_sym)
+}
diff --git a/yjit_codegen.c b/yjit_codegen.c
index b5edf86460..0def2f9402 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -2250,9 +2250,29 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t *ctx, VALUE known_klass, insn_opnd_
ctx_set_opnd_type(ctx, insn_opnd, TYPE_FALSE);
}
}
- else if (known_klass == rb_cInteger ||
- known_klass == rb_cSymbol ||
- known_klass == rb_cFloat) {
+ else if (known_klass == rb_cInteger && FIXNUM_P(sample_instance)) {
+ // We will guard FIXNUM and BIGNUM as though they were separate classes
+ // BIGNUM can be handled by the general else case below
+ if (val_type.type != ETYPE_FIXNUM || !val_type.is_imm) {
+ ADD_COMMENT(cb, "guard object is fixnum");
+ test(cb, REG0, imm_opnd(RUBY_FIXNUM_FLAG));
+ jit_chain_guard(JCC_JZ, jit, ctx, max_chain_depth, side_exit);
+ ctx_set_opnd_type(ctx, insn_opnd, TYPE_FIXNUM);
+ }
+ }
+ else if (known_klass == rb_cSymbol && STATIC_SYM_P(sample_instance)) {
+ // We will guard STATIC vs DYNAMIC as though they were separate classes
+ // DYNAMIC symbols can be handled by the general else case below
+ if (val_type.type != ETYPE_SYMBOL || !val_type.is_imm) {
+ ADD_COMMENT(cb, "guard object is static symbol");
+ STATIC_ASSERT(special_shift_is_8, RUBY_SPECIAL_SHIFT == 8);
+ cmp(cb, REG0_8, imm_opnd(RUBY_SYMBOL_FLAG));
+ jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
+
+ ctx_set_opnd_type(ctx, insn_opnd, TYPE_STATIC_SYMBOL);
+ }
+ }
+ else if (known_klass == rb_cFloat) {
// Can't guard for for these classes because they can have both
// immediate (special const) instances and instances on the heap. Can
// remove this by adding appropriate dynamic checks.
diff --git a/yjit_core.h b/yjit_core.h
index a2436e6eb3..5939f5b74b 100644
--- a/yjit_core.h
+++ b/yjit_core.h
@@ -69,6 +69,7 @@ STATIC_ASSERT(val_type_size, sizeof(val_type_t) == 1);
#define TYPE_TRUE ( (val_type_t){ .is_imm = 1, .type = ETYPE_TRUE } )
#define TYPE_FALSE ( (val_type_t){ .is_imm = 1, .type = ETYPE_FALSE } )
#define TYPE_FIXNUM ( (val_type_t){ .is_imm = 1, .type = ETYPE_FIXNUM } )
+#define TYPE_STATIC_SYMBOL ( (val_type_t){ .is_imm = 1, .type = ETYPE_SYMBOL } )
#define TYPE_ARRAY ( (val_type_t){ .is_heap = 1, .type = ETYPE_ARRAY } )
#define TYPE_HASH ( (val_type_t){ .is_heap = 1, .type = ETYPE_HASH } )
#define TYPE_STRING ( (val_type_t){ .is_heap = 1, .type = ETYPE_STRING } )