summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--class.c1
-rw-r--r--gc.c4
-rw-r--r--internal.h1
-rw-r--r--method.h2
-rw-r--r--vm_method.c45
6 files changed, 40 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index fbc3ccb189..65273e7423 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Tue Sep 24 14:01:00 2013 Charlie Somerville <charliesome@ruby-lang.org>
+
+ * class.c (class_alloc): remove mc_tbl
+
+ * gc.c (obj_free): ditto
+
+ * internal.h (struct rb_classext_struct): ditto
+
+ * method.h (rb_method_entry): remove ent param
+
+ * vm_method.c: restore the global method cache. Per class cache tables
+ turned out to be far too slow.
+
+ [ruby-core:57289] [Bug #8930]
+
Tue Sep 24 12:51:07 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/win32/lib/win32/registry.rb (Win32::Registry::API): need
diff --git a/class.c b/class.c
index 8a77d1285f..2573bd916a 100644
--- a/class.c
+++ b/class.c
@@ -165,7 +165,6 @@ class_alloc(VALUE flags, VALUE klass)
RCLASS_EXT(obj)->parent_subclasses = NULL;
RCLASS_EXT(obj)->module_subclasses = NULL;
RCLASS_EXT(obj)->seq = rb_next_class_sequence();
- RCLASS_EXT(obj)->mc_tbl = NULL;
RCLASS_REFINED_CLASS(obj) = Qnil;
RCLASS_EXT(obj)->allocator = 0;
diff --git a/gc.c b/gc.c
index e323a5005c..8fea5318f8 100644
--- a/gc.c
+++ b/gc.c
@@ -1261,10 +1261,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
}
RCLASS_EXT(obj)->subclasses = NULL;
}
- if (RCLASS_EXT(obj)->mc_tbl) {
- rb_free_mc_table(RCLASS_EXT(obj)->mc_tbl);
- RCLASS_EXT(obj)->mc_tbl = NULL;
- }
rb_class_remove_from_module_subclasses(obj);
rb_class_remove_from_super_subclasses(obj);
if (RANY(obj)->as.klass.ptr)
diff --git a/internal.h b/internal.h
index 7036398bc7..567100c75f 100644
--- a/internal.h
+++ b/internal.h
@@ -266,7 +266,6 @@ struct rb_classext_struct {
VALUE super;
struct st_table *iv_tbl;
struct st_table *const_tbl;
- struct st_table *mc_tbl;
rb_subclass_entry_t *subclasses;
rb_subclass_entry_t **parent_subclasses;
/**
diff --git a/method.h b/method.h
index 25d3b0b1f9..c89df88bd2 100644
--- a/method.h
+++ b/method.h
@@ -122,7 +122,7 @@ rb_method_entry_t *rb_method_entry_with_refinements(VALUE klass, ID id,
rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id,
VALUE *defined_class_ptr);
-rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *define_class_ptr, method_cache_entry_t *ent);
+rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *define_class_ptr);
rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex);
int rb_method_entry_arity(const rb_method_entry_t *me);
diff --git a/vm_method.c b/vm_method.c
index a986ebec7f..606f9604ed 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -2,6 +2,10 @@
* This file is included by vm.c
*/
+#define GLOBAL_METHOD_CACHE_SIZE 0x800
+#define GLOBAL_METHOD_CACHE_MASK 0x7ff
+#define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&GLOBAL_METHOD_CACHE_MASK)
+#define GLOBAL_METHOD_CACHE(c,m) (global_method_cache + GLOBAL_METHOD_CACHE_KEY(c,m))
#include "method.h"
#define NOEX_NOREDEF 0
@@ -20,6 +24,15 @@ static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VAL
#define singleton_undefined idSingleton_method_undefined
#define attached id__attached__
+struct cache_entry {
+ vm_state_version_t vm_state;
+ vm_state_version_t seq;
+ ID mid;
+ rb_method_entry_t* me;
+ VALUE defined_class;
+};
+
+static struct cache_entry global_method_cache[GLOBAL_METHOD_CACHE_SIZE];
#define ruby_running (GET_VM()->running)
/* int ruby_running = 0; */
@@ -520,26 +533,25 @@ rb_method_entry_at(VALUE klass, ID id)
*/
rb_method_entry_t *
rb_method_entry_get_without_cache(VALUE klass, ID id,
- VALUE *defined_class_ptr,
- method_cache_entry_t *ent)
+ VALUE *defined_class_ptr)
{
VALUE defined_class;
rb_method_entry_t *me = search_method(klass, id, &defined_class);
if (ruby_running) {
+ struct cache_entry *ent;
+ ent = GLOBAL_METHOD_CACHE(klass, id);
ent->seq = RCLASS_EXT(klass)->seq;
ent->vm_state = GET_VM_STATE_VERSION();
+ ent->defined_class = defined_class;
+ ent->mid = id;
if (UNDEFINED_METHOD_ENTRY_P(me)) {
- ent->mid = id;
ent->me = 0;
- ent->defined_class = defined_class;
me = 0;
}
else {
- ent->mid = id;
ent->me = me;
- ent->defined_class = defined_class;
}
}
@@ -555,7 +567,7 @@ verify_method_cache(VALUE klass, ID id, VALUE defined_class, rb_method_entry_t *
VALUE actual_defined_class;
method_cache_entry_t ent;
rb_method_entry_t *actual_me =
- rb_method_entry_get_without_cache(klass, id, &actual_defined_class, &ent);
+ rb_method_entry_get_without_cache(klass, id, &actual_defined_class);
if (me != actual_me || defined_class != actual_defined_class) {
rb_bug("method cache verification failed");
@@ -567,19 +579,10 @@ rb_method_entry_t *
rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
{
#if OPT_GLOBAL_METHOD_CACHE
- method_cache_entry_t *ent;
-
- if (RCLASS_EXT(klass)->mc_tbl == NULL) {
- RCLASS_EXT(klass)->mc_tbl = st_init_numtable();
- }
-
- if (!st_lookup(RCLASS_EXT(klass)->mc_tbl, (st_index_t)id, (st_data_t *)&ent)) {
- ent = calloc(1, sizeof(*ent));
- st_insert(RCLASS_EXT(klass)->mc_tbl, (st_index_t)id, (st_data_t)ent);
- }
-
- if (ent->seq == RCLASS_EXT(klass)->seq &&
- ent->vm_state == GET_VM_STATE_VERSION() &&
+ struct cache_entry *ent;
+ ent = GLOBAL_METHOD_CACHE(klass, id);
+ if (ent->vm_state == GET_VM_STATE_VERSION() &&
+ ent->seq == RCLASS_EXT(klass)->seq &&
ent->mid == id) {
if (defined_class_ptr)
*defined_class_ptr = ent->defined_class;
@@ -593,7 +596,7 @@ rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
method_cache_entry_t* ent = &ent_;
#endif
- return rb_method_entry_get_without_cache(klass, id, defined_class_ptr, ent);
+ return rb_method_entry_get_without_cache(klass, id, defined_class_ptr);
}
static rb_method_entry_t *