|
24 | 24 | #include "internal/box.h" |
25 | 25 | #include "internal/class.h" |
26 | 26 | #include "internal/eval.h" |
| 27 | +#include "internal/error.h" |
27 | 28 | #include "internal/hash.h" |
28 | 29 | #include "internal/object.h" |
29 | 30 | #include "internal/string.h" |
|
55 | 56 | * 2: RCLASS_PRIME_CLASSEXT_WRITABLE |
56 | 57 | * This module's prime classext is the only classext and writable from any boxes. |
57 | 58 | * If unset, the prime classext is writable only from the root box. |
| 59 | + * 3: RICLASS_IS_SINGLETON_ANCESTOR |
| 60 | + * This iclass is in the singleton class portion of an ancestry chain. |
| 61 | + * Set when a module is included/prepended into a singleton class. |
58 | 62 | * 4: RCLASS_BOXABLE |
59 | 63 | * Is a builtin class that may be boxed. It larger than a normal class. |
60 | 64 | */ |
@@ -1422,7 +1426,6 @@ make_singleton_class(VALUE obj) |
1422 | 1426 | RBASIC_SET_CLASS(obj, klass); |
1423 | 1427 | rb_singleton_class_attached(klass, obj); |
1424 | 1428 | rb_yjit_invalidate_no_singleton_class(orig_class); |
1425 | | - rb_zjit_invalidate_no_singleton_class(orig_class); |
1426 | 1429 |
|
1427 | 1430 | SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class))); |
1428 | 1431 | return klass; |
@@ -1855,6 +1858,18 @@ clear_module_cache_i(ID id, VALUE val, void *data) |
1855 | 1858 | return ID_TABLE_CONTINUE; |
1856 | 1859 | } |
1857 | 1860 |
|
| 1861 | +static enum rb_id_table_iterator_result |
| 1862 | +zjit_invalid_no_singleton_override_i(ID method_id, VALUE val, void *data) |
| 1863 | +{ |
| 1864 | + VALUE insertion_point = (VALUE)data; |
| 1865 | + // If this method is an override, bust invariant and stop iterating |
| 1866 | + if (rb_method_entry(insertion_point, method_id)) { |
| 1867 | + rb_zjit_invalidate_no_singleton_class(rb_class_real(insertion_point)); |
| 1868 | + return ID_TABLE_STOP; |
| 1869 | + } |
| 1870 | + return ID_TABLE_CONTINUE; |
| 1871 | +} |
| 1872 | + |
1858 | 1873 | static bool |
1859 | 1874 | module_in_super_chain(const VALUE klass, VALUE module) |
1860 | 1875 | { |
@@ -1944,6 +1959,15 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super |
1944 | 1959 |
|
1945 | 1960 | // setup T_ICLASS for the include/prepend module |
1946 | 1961 | iclass = rb_include_class_new(module, super_class); |
| 1962 | + // Mark the iclass as being in the singleton portion of the chain. |
| 1963 | + // c is the insertion point; if it's a singleton class or already in |
| 1964 | + // the singleton portion, the new iclass is too. |
| 1965 | + if (rb_zjit_enabled_p && (RCLASS_SINGLETON_P(c) || (RB_TYPE_P(c, T_ICLASS) && RICLASS_SINGLETON_ANCESTOR_P(c)))) { |
| 1966 | + FL_SET(iclass, RICLASS_IS_SINGLETON_ANCESTOR); |
| 1967 | + if (method_changed && tbl && rb_id_table_size(tbl)) { |
| 1968 | + rb_id_table_foreach(tbl, zjit_invalid_no_singleton_override_i, (void *)c); |
| 1969 | + } |
| 1970 | + } |
1947 | 1971 | c = rb_class_set_super(c, iclass); |
1948 | 1972 | RCLASS_SET_INCLUDER(iclass, klass); |
1949 | 1973 | if (module != RCLASS_ORIGIN(module)) { |
@@ -2082,6 +2106,10 @@ rb_prepend_module(VALUE klass, VALUE module) |
2082 | 2106 | rb_id_table_foreach(RCLASS_M_TBL(subclass), clear_module_cache_i, (void *)subclass); |
2083 | 2107 | RCLASS_WRITE_M_TBL(subclass, klass_m_tbl); |
2084 | 2108 | VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(subclass)); |
| 2109 | + if (rb_zjit_enabled_p && RICLASS_SINGLETON_ANCESTOR_P(subclass)) { |
| 2110 | + RUBY_ASSERT_BUILTIN_TYPE(subclass, T_ICLASS); |
| 2111 | + FL_SET(origin, RICLASS_IS_SINGLETON_ANCESTOR); |
| 2112 | + } |
2085 | 2113 | rb_class_set_super(subclass, origin); |
2086 | 2114 | RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(subclass)); |
2087 | 2115 | RCLASS_WRITE_ORIGIN(subclass, origin); |
|
0 commit comments