8000 Merge pull request #4 from github/jamesgolick-method-cache-patches · github/ruby@d151f4e · GitHub
[go: up one dir, main page]

Skip to content

Commit d151f4e

Browse files
author
Charlie Somerville
committed
Merge pull request #4 from github/jamesgolick-method-cache-patches
James Golick method cache patches
2 parents 540c52d + da97620 commit d151f4e

19 files changed

+976
-180
lines changed

class.c

Lines changed: 153 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,136 @@
2828
#include "method.h"
2929
#include "constant.h"
3030
#include "vm_core.h"
31+
#include "vm_insnhelper.h"
3132
#include "internal.h"
3233
#include <ctype.h>
3334

3435
extern st_table *rb_class_tbl;
3536
static ID id_attached;
3637

38+
static void
39+
rb_class_subclass_add(VALUE super, VALUE klass)
40+
{
41+
rb_subclass_entry_t *entry, *head;
42+
43+
if (super && super != Qundef) {
44+
entry = malloc(sizeof(rb_subclass_entry_t));
45+
entry->klass = klass;
46+
entry->next = NULL;
47+
48+
head = RCLASS_SUBCLASSES(super);
49+
if (head) {
50+
entry->next = head;
51+
RCLASS_PARENT_SUBCLASSES(head->klass) = &entry->next;
52+
}
53+
54+
RCLASS_SUBCLASSES(super) = entry;
55+
RCLASS_PARENT_SUBCLASSES(klass) = &RCLASS_SUBCLASSES(super);
56+
}
57+
}
58+
59+
static void
60+
rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
61+
{
62+
rb_subclass_entry_t *entry, *head;
63+
64+
entry = malloc(sizeof(rb_subclass_entry_t));
65+
entry->klass = iclass;
66+
entry->next = NULL;
67+
68+
head = RCLASS_SUBCLASSES(module);
69+
if (head) {
70+
entry->next = head;
71+
RCLASS_MODULE_SUBCLASSES(head->klass) = &entry->next;
72+
}
73+
74+
RCLASS_SUBCLASSES(module) = entry;
75+
RCLASS_MODULE_SUBCLASSES(iclass) = &RCLASS_SUBCLASSES(module);
76+
}
77+
78+
void
79+
rb_class_remove_from_super_subclasses(VALUE klass)
80+
{
81+
rb_subclass_entry_t *entry;
82+
83+
84+
if (RCLASS_PARENT_SUBCLASSES(klass)) {
85+
entry = *RCLASS_PARENT_SUBCLASSES(klass);
86+
87+
*RCLASS_PARENT_SUBCLASSES(klass) = entry->next;
88+
if (entry->next) {
89+
RCLASS_PARENT_SUBCLASSES(entry->next->klass) = RCLASS_PARENT_SUBCLASSES(klass);
90+
}
91+
free(entry);
92+
}
93+
94+
RCLASS_PARENT_SUBCLASSES(klass) = NULL;
95+
}
96+
97+
void
98+
rb_class_remove_from_module_subclasses(VALUE klass)
99+
{
100+
rb_subclass_entry_t *entry;
101+
102+
if (RCLASS_MODULE_SUBCLASSES(klass)) {
103+
entry = *RCLASS_MODULE_SUBCLASSES(klass);
104+
*RCLASS_MODULE_SUBCLASSES(klass) = entry->next;
105+
if (entry->next) {
106+
RCLASS_MODULE_SUBCLASSES(entry->next->klass) = RCLASS_MODULE_SUBCLASSES(klass);
107+
}
108+
free(entry);
109+
}
110+
111+
RCLASS_MODULE_SUBCLASSES(klass) = NULL;
112+
}
113+
114+
static int
115+
rb_class_foreach_iter_wrapper(st_data_t key, st_data_t unused, st_data_t rf)
116+
{
117+
int (*f)(VALUE);
118+
119+
f = (int (*)(VALUE)) rf;
120+
return f((VALUE)key);
121+
}
122+
123+
void
124+
rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE))
125+
{
126+
rb_subclass_entry_t *cur;
127+
VALUE curklass;
128+
129+
cur = RCLASS_SUBCLASSES(klass);
130+
while(cur)
131+
{
132+
curklass = cur->klass;
133+
cur = cur->next;
134+
f(curklass);
135+
}
136+
}
137+
138+
VALUE
139+
rb_class_set_superclass(VALUE klass, VALUE super)
140+
{
141+
rb_class_remove_from_super_subclasses(klass);
142+
143+
rb_class_subclass_add(super, klass);
144+
RCLASS_SUPER(klass) = super;
145+
146+
return super;
147+
}
148+
149+
void
150+
rb_class_detatch_subclasses(VALUE klass)
151+
{
152+
rb_class_foreach_subclass(klass, rb_class_remove_from_super_subclasses);
153+
}
154+
155+
void
156+
rb_class_detatch_module_subclasses(VALUE klass)
157+
{
158+
rb_class_foreach_subclass(klass, rb_class_remove_from_module_subclasses);
159+
}
160+
37161
/**
38162
* Allocates a struct RClass for a new class.
39163
*
@@ -58,6 +182,13 @@ class_alloc(VALUE flags, VALUE klass)
58182
RCLASS_M_TBL(obj) = 0;
59183
RCLASS_SUPER(obj) = 0;
60184
RCLASS_IV_INDEX_TBL(obj) = 0;
185+
RCLASS_SUBCLASSES(obj) = NULL;
186+
RCLASS_PARENT_SUBCLASSES(obj) = NULL;
187+
RCLASS_MODULE_SUBCLASSES(obj) = NULL;
188+
RCLASS_SEQ(obj) = rb_next_seq();
189+
RCLASS_ICLASSTARGET(obj) = 0;
190+
RCLASS_MC_TBL(obj) = NULL;
191+
61192
return (VALUE)obj;
62193
}
63194

@@ -76,7 +207,7 @@ rb_class_boot(VALUE super)
76207
{
77208
VALUE klass = class_alloc(T_CLASS, rb_cClass);
78209

79-
RCLASS_SUPER(klass) = super;
210+
rb_class_set_superclass(klass, super);
80211
RCLASS_M_TBL(klass) = st_init_numtable();
81212

82213
OBJ_INFECT(klass, super);
@@ -168,7 +299,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
168299
RBASIC(clone)->klass = rb_singleton_class_clone(orig);
169300
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
170301
}
171-
RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
302+
rb_class_set_superclass(clone, RCLASS_SUPER(orig));
172303
if (RCLASS_IV_TBL(orig)) {
173304
st_data_t id;
174305

@@ -238,7 +369,7 @@ rb_singleton_class_clone(VALUE obj)
238369
RBASIC(clone)->klass = rb_singleton_class_clone(klass);
239370
}
240371

241-
RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
372+
rb_class_set_superclass(clone, RCLASS_SUPER(klass));
242373
if (RCLASS_IV_TBL(klass)) {
243374
RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
244375
}
@@ -324,7 +455,7 @@ make_metaclass(VALUE klass)
324455

325456
super = RCLASS_SUPER(klass);
326457
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
327-
RCLASS_SUPER(metaclass) = super ? ENSURE_EIGENCLASS(super) : rb_cClass;
458+
rb_class_set_superclass(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
328459

329460
OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
330461

@@ -644,13 +775,14 @@ include_class_new(VALUE module, VALUE super)
644775
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
645776
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
646777
RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
647-
RCLASS_SUPER(klass) = super;
778+
rb_class_set_superclass(klass, super);
648779
if (TYPE(module) == T_ICLASS) {
649780
RBASIC(klass)->klass = RBASIC(module)->klass;
650781
}
651782
else {
652783
RBASIC(klass)->klass = module;
653784
}
785+
654786
OBJ_INFECT(klass, module);
655787
OBJ_INFECT(klass, super);
656788

@@ -660,7 +792,7 @@ include_class_new(VALUE module, VALUE super)
660792
void
661793
rb_include_module(VALUE klass, VALUE module)
662794
{
663-
VALUE p, c;
795+
VALUE p, c, iclass;
664796
int changed = 0;
665797

666798
rb_frozen_class_p(klass);
@@ -695,13 +827,26 @@ rb_include_module(VALUE klass, VALUE module)
695827
break;
696828
}
697829
}
698-
c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
830+
iclass = include_class_new(module, RCLASS_SUPER(c));
831+
RCLASS_ICLASSTARGET(iclass) = klass;
832+
833+
c = rb_class_set_superclass(c, iclass);
834+
835+
if (BUILTIN_TYPE(module) == T_ICLASS) {
836+
rb_module_add_to_subclasses_list(RBASIC(module)->klass, iclass);
837+
} else {
838+
rb_module_add_to_subclasses_list(module, iclass);
839+
}
840+
699841
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
700842
changed = 1;
701843
skip:
702844
module = RCLASS_SUPER(module);
703845
}
704-
if (changed) rb_clear_cache();
846+
if (changed) {
847+
rb_clear_method_cache_by_class(klass);
848+
rb_clear_constant_cache();
849+
}
705850
}
706851

707852
/*

common.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \
7979
safe.$(OBJEXT) \
8080
signal.$(OBJEXT) \
8181
sprintf.$(OBJEXT) \
82+
sp_ar.$(OBJEXT) \
8283
st.$(OBJEXT) \
8384
strftime.$(OBJEXT) \
8485
string.$(OBJEXT) \
@@ -702,6 +703,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \
702703
$(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
703704
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
704705
{$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES)
706+
sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES)
705707
st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h
706708
strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \
707709
{$(VPATH)}timev.h

0 commit comments

Comments
 (0)
0