mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Simplify known class check for singletons
Singleton classes should only ever be attached to one object. This means that checking for the object should be the same as checking for the class. This should be slightly faster by avoiding one memory acccess as well as allowing us to skip checking if the receiver is a heap object. This will be most common for calling class methods.
This commit is contained in:
parent
8c68f112d8
commit
7d252186fe
2 changed files with 50 additions and 16 deletions
|
@ -1153,3 +1153,34 @@ assert_equal '7', %q{
|
|||
foo(5,2)
|
||||
foo(5,2)
|
||||
}
|
||||
|
||||
# Call to object with singleton
|
||||
assert_equal '123', %q{
|
||||
obj = Object.new
|
||||
def obj.foo
|
||||
123
|
||||
end
|
||||
|
||||
def foo(obj)
|
||||
obj.foo()
|
||||
end
|
||||
|
||||
foo(obj)
|
||||
foo(obj)
|
||||
}
|
||||
|
||||
# Call to singleton class
|
||||
assert_equal '123', %q{
|
||||
class Foo
|
||||
def self.foo
|
||||
123
|
||||
end
|
||||
end
|
||||
|
||||
def foo(obj)
|
||||
obj.foo()
|
||||
end
|
||||
|
||||
foo(Foo)
|
||||
foo(Foo)
|
||||
}
|
||||
|
|
|
@ -2172,6 +2172,7 @@ static bool
|
|||
jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_t insn_opnd, const int max_chain_depth, uint8_t *side_exit)
|
||||
{
|
||||
val_type_t val_type = ctx_get_opnd_type(ctx, insn_opnd);
|
||||
bool singleton_klass = FL_TEST(known_klass, FL_SINGLETON);
|
||||
|
||||
if (known_klass == rb_cNilClass) {
|
||||
if (val_type.type != ETYPE_NIL) {
|
||||
|
@ -2190,7 +2191,6 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_
|
|||
|
||||
ctx_set_opnd_type(ctx, insn_opnd, TYPE_TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
else if (known_klass == rb_cFalseClass) {
|
||||
if (val_type.type != ETYPE_FALSE) {
|
||||
|
@ -2202,15 +2202,26 @@ 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 {
|
||||
// Can't guard for for these classes because some of they are sometimes immediate (special const).
|
||||
// Can remove this by adding appropriate dynamic checks.
|
||||
if (known_klass == rb_cInteger ||
|
||||
else if (known_klass == rb_cInteger ||
|
||||
known_klass == rb_cSymbol ||
|
||||
known_klass == rb_cFloat) {
|
||||
// Can't guard for for these classes because some of they are sometimes
|
||||
// immediate (special const). Can remove this by adding appropriate
|
||||
// dynamic checks.
|
||||
return false;
|
||||
}
|
||||
|
||||
else if (singleton_klass) {
|
||||
// Singleton classes are attached to one specific object, so we can
|
||||
// avoid one memory access (and potentially the is_heap check) by
|
||||
// looking for the expected object directly.
|
||||
ADD_COMMENT(cb, "guard known object with singleton class");
|
||||
VALUE known_obj = rb_attr_get(known_klass, id__attached__);
|
||||
// TODO: jit_mov_gc_ptr keeps a strong reference, which leaks the object.
|
||||
jit_mov_gc_ptr(jit, cb, REG1, known_obj);
|
||||
cmp(cb, REG0, REG1);
|
||||
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
|
||||
}
|
||||
else {
|
||||
// Check that the receiver is a heap object
|
||||
// Note: if we get here, the class doesn't have immediate instances.
|
||||
if (!val_type.is_heap) {
|
||||
|
@ -2234,14 +2245,6 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_
|
|||
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
|
||||
}
|
||||
|
||||
// Pointer to the klass field of the receiver &(recv->klass)
|
||||
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
|
||||
|
||||
// Bail if receiver class is different from known_klass
|
||||
// TODO: jit_mov_gc_ptr keeps a strong reference, which leaks the class.
|
||||
jit_mov_gc_ptr(jit, cb, REG1, known_klass);
|
||||
cmp(cb, klass_opnd, REG1);
|
||||
jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue