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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy