@@ -2170,6 +2170,7 @@ static bool
2170
2170
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 )
2171
2171
{
2172
2172
val_type_t val_type = ctx_get_opnd_type (ctx , insn_opnd );
2173
+ bool singleton_klass = FL_TEST (known_klass , FL_SINGLETON );
2173
2174
2174
2175
if (known_klass == rb_cNilClass ) {
2175
2176
if (val_type .type != ETYPE_NIL ) {
@@ -2188,7 +2189,6 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_
2188
2189
2189
2190
ctx_set_opnd_type (ctx , insn_opnd , TYPE_TRUE );
2190
2191
}
2191
-
2192
2192
}
2193
2193
else if (known_klass == rb_cFalseClass ) {
2194
2194
if (val_type .type != ETYPE_FALSE ) {
@@ -2200,15 +2200,26 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_
2200
2200
ctx_set_opnd_type (ctx , insn_opnd , TYPE_FALSE );
2201
2201
}
2202
2202
}
2203
- else {
2204
- // Can't guard for for these classes because some of they are sometimes immediate (special const).
2205
- // Can remove this by adding appropriate dynamic checks.
2206
- if (known_klass == rb_cInteger ||
2203
+ else if (known_klass == rb_cInteger ||
2207
2204
known_klass == rb_cSymbol ||
2208
2205
known_klass == rb_cFloat ) {
2209
- return false;
2210
- }
2211
-
2206
+ // Can't guard for for these classes because some of they are sometimes
2207
+ // immediate (special const). Can remove this by adding appropriate
2208
+ // dynamic checks.
2209
+ return false;
2210
+ }
2211
+ else if (singleton_klass ) {
2212
+ // Singleton classes are attached to one specific object, so we can
2213
+ // avoid one memory access (and potentially the is_heap check) by
2214
+ // looking for the expected object directly.
2215
+ ADD_COMMENT (cb , "guard known object with singleton class" );
2216
+ VALUE known_obj = rb_attr_get (known_klass , id__attached__ );
2217
+ // TODO: jit_mov_gc_ptr keeps a strong reference, which leaks the object.
2218
+ jit_mov_gc_ptr (jit , cb , REG1 , known_obj );
2219
+ cmp (cb , REG0 , REG1 );
2220
+ jit_chain_guard (JCC_JNE , jit , ctx , max_chain_depth , side_exit );
2221
+ }
2222
+ else {
2212
2223
// Check that the receiver is a heap object
2213
2224
// Note: if we get here, the class doesn't have immediate instances.
2214
2225
if (!val_type .is_heap ) {
@@ -2232,7 +2243,6 @@ jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_
2232
2243
jit_chain_guard (JCC_JNE , jit , ctx , max_chain_depth , side_exit );
2233
2244
}
2234
2245
2235
- // Pointer to the klass field of the receiver &(recv->klass)
2236
2246
return true;
2237
2247
}
2238
2248
0 commit comments