mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Revert "Filling cache values on cvar write"
This reverts commit08de37f9fa
. This reverts commite8ae922b62
.
This commit is contained in:
parent
08de37f9fa
commit
07f055bb13
15 changed files with 26 additions and 275 deletions
|
@ -1,20 +0,0 @@
|
||||||
prelude: |
|
|
||||||
class A
|
|
||||||
@@foo = 1
|
|
||||||
|
|
||||||
def self.foo
|
|
||||||
@@foo
|
|
||||||
end
|
|
||||||
|
|
||||||
("A".."Z").each do |module_name|
|
|
||||||
eval <<-EOM
|
|
||||||
module #{module_name}
|
|
||||||
end
|
|
||||||
|
|
||||||
include #{module_name}
|
|
||||||
EOM
|
|
||||||
end
|
|
||||||
end
|
|
||||||
benchmark:
|
|
||||||
vm_cvar: A.foo
|
|
||||||
loop_count: 600000
|
|
6
class.c
6
class.c
|
@ -27,7 +27,6 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "constant.h"
|
#include "constant.h"
|
||||||
#include "debug_counter.h"
|
|
||||||
#include "id_table.h"
|
#include "id_table.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "internal/class.h"
|
#include "internal/class.h"
|
||||||
|
@ -44,8 +43,6 @@
|
||||||
#define METACLASS_OF(k) RBASIC(k)->klass
|
#define METACLASS_OF(k) RBASIC(k)->klass
|
||||||
#define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls)
|
#define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls)
|
||||||
|
|
||||||
RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_class_subclass_add(VALUE super, VALUE klass)
|
rb_class_subclass_add(VALUE super, VALUE klass)
|
||||||
{
|
{
|
||||||
|
@ -960,7 +957,6 @@ rb_include_class_new(VALUE module, VALUE super)
|
||||||
RCLASS_CONST_TBL(module) = rb_id_table_create(0);
|
RCLASS_CONST_TBL(module) = rb_id_table_create(0);
|
||||||
}
|
}
|
||||||
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
|
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
|
||||||
RCLASS_CVC_TBL(klass) = RCLASS_CVC_TBL(module);
|
|
||||||
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
|
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
|
||||||
|
|
||||||
RCLASS_SET_SUPER(klass, super);
|
RCLASS_SET_SUPER(klass, super);
|
||||||
|
@ -1089,8 +1085,6 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
|
||||||
VALUE super_class = RCLASS_SUPER(c);
|
VALUE super_class = RCLASS_SUPER(c);
|
||||||
|
|
||||||
// invalidate inline method cache
|
// invalidate inline method cache
|
||||||
RB_DEBUG_COUNTER_INC(cvar_include_invalidate);
|
|
||||||
ruby_vm_global_cvar_state++;
|
|
||||||
tbl = RCLASS_M_TBL(module);
|
tbl = RCLASS_M_TBL(module);
|
||||||
if (tbl && rb_id_table_size(tbl)) {
|
if (tbl && rb_id_table_size(tbl)) {
|
||||||
if (search_super) { // include
|
if (search_super) { // include
|
||||||
|
|
|
@ -2458,7 +2458,6 @@ class.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
|
||||||
class.$(OBJEXT): {$(VPATH)}class.c
|
class.$(OBJEXT): {$(VPATH)}class.c
|
||||||
class.$(OBJEXT): {$(VPATH)}config.h
|
class.$(OBJEXT): {$(VPATH)}config.h
|
||||||
class.$(OBJEXT): {$(VPATH)}constant.h
|
class.$(OBJEXT): {$(VPATH)}constant.h
|
||||||
class.$(OBJEXT): {$(VPATH)}debug_counter.h
|
|
||||||
class.$(OBJEXT): {$(VPATH)}defines.h
|
class.$(OBJEXT): {$(VPATH)}defines.h
|
||||||
class.$(OBJEXT): {$(VPATH)}encoding.h
|
class.$(OBJEXT): {$(VPATH)}encoding.h
|
||||||
class.$(OBJEXT): {$(VPATH)}id.h
|
class.$(OBJEXT): {$(VPATH)}id.h
|
||||||
|
|
10
compile.c
10
compile.c
|
@ -8044,9 +8044,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
|
||||||
if (!popped) {
|
if (!popped) {
|
||||||
ADD_INSN(ret, line_node, dup);
|
ADD_INSN(ret, line_node, dup);
|
||||||
}
|
}
|
||||||
ADD_INSN2(ret, line_node, setclassvariable,
|
ADD_INSN1(ret, line_node, setclassvariable,
|
||||||
ID2SYM(node->nd_vid),
|
ID2SYM(node->nd_vid));
|
||||||
get_ivar_ic_value(iseq,node->nd_vid));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NODE_OP_ASGN1: {
|
case NODE_OP_ASGN1: {
|
||||||
|
@ -8669,9 +8668,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
|
||||||
}
|
}
|
||||||
case NODE_CVAR:{
|
case NODE_CVAR:{
|
||||||
if (!popped) {
|
if (!popped) {
|
||||||
ADD_INSN2(ret, line_node, getclassvariable,
|
ADD_INSN1(ret, line_node, getclassvariable,
|
||||||
ID2SYM(node->nd_vid),
|
ID2SYM(node->nd_vid));
|
||||||
get_ivar_ic_value(iseq,node->nd_vid));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,6 @@ RB_DEBUG_COUNTER(mc_inline_miss_same_cme) // IMC miss, but same CME
|
||||||
RB_DEBUG_COUNTER(mc_inline_miss_same_def) // IMC miss, but same definition
|
RB_DEBUG_COUNTER(mc_inline_miss_same_def) // IMC miss, but same definition
|
||||||
RB_DEBUG_COUNTER(mc_inline_miss_diff) // IMC miss, different methods
|
RB_DEBUG_COUNTER(mc_inline_miss_diff) // IMC miss, different methods
|
||||||
|
|
||||||
RB_DEBUG_COUNTER(cvar_write_inline_hit) // cvar cache hit on write
|
|
||||||
RB_DEBUG_COUNTER(cvar_read_inline_hit) // cvar cache hit on read
|
|
||||||
RB_DEBUG_COUNTER(cvar_inline_miss) // miss inline cache
|
|
||||||
RB_DEBUG_COUNTER(cvar_class_invalidate) // invalidate cvar cache when define a cvar that's defined on a subclass
|
|
||||||
RB_DEBUG_COUNTER(cvar_include_invalidate) // invalidate cvar cache on module include or prepend
|
|
||||||
|
|
||||||
RB_DEBUG_COUNTER(mc_cme_complement) // number of acquiring complement CME
|
RB_DEBUG_COUNTER(mc_cme_complement) // number of acquiring complement CME
|
||||||
RB_DEBUG_COUNTER(mc_cme_complement_hit) // number of cache hit for complemented CME
|
RB_DEBUG_COUNTER(mc_cme_complement_hit) // number of cache hit for complemented CME
|
||||||
|
|
||||||
|
|
36
gc.c
36
gc.c
|
@ -3003,13 +3003,6 @@ cc_table_free(rb_objspace_t *objspace, VALUE klass, bool alive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum rb_id_table_iterator_result
|
|
||||||
cvar_table_free_i(VALUE value, void * ctx)
|
|
||||||
{
|
|
||||||
xfree((void *) value);
|
|
||||||
return ID_TABLE_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_cc_table_free(VALUE klass)
|
rb_cc_table_free(VALUE klass)
|
||||||
{
|
{
|
||||||
|
@ -3121,10 +3114,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
|
||||||
if (RCLASS_IV_INDEX_TBL(obj)) {
|
if (RCLASS_IV_INDEX_TBL(obj)) {
|
||||||
iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj));
|
iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj));
|
||||||
}
|
}
|
||||||
if (RCLASS_CVC_TBL(obj)) {
|
|
||||||
rb_id_table_foreach_values(RCLASS_CVC_TBL(obj), cvar_table_free_i, NULL);
|
|
||||||
rb_id_table_free(RCLASS_CVC_TBL(obj));
|
|
||||||
}
|
|
||||||
if (RCLASS_SUBCLASSES(obj)) {
|
if (RCLASS_SUBCLASSES(obj)) {
|
||||||
if (BUILTIN_TYPE(obj) == T_MODULE) {
|
if (BUILTIN_TYPE(obj) == T_MODULE) {
|
||||||
rb_class_detach_module_subclasses(obj);
|
rb_class_detach_module_subclasses(obj);
|
||||||
|
@ -4568,9 +4557,6 @@ obj_memsize_of(VALUE obj, int use_all_types)
|
||||||
if (RCLASS_IV_TBL(obj)) {
|
if (RCLASS_IV_TBL(obj)) {
|
||||||
size += st_memsize(RCLASS_IV_TBL(obj));
|
size += st_memsize(RCLASS_IV_TBL(obj));
|
||||||
}
|
}
|
||||||
if (RCLASS_CVC_TBL(obj)) {
|
|
||||||
size += rb_id_table_memsize(RCLASS_CVC_TBL(obj));
|
|
||||||
}
|
|
||||||
if (RCLASS_IV_INDEX_TBL(obj)) {
|
if (RCLASS_IV_INDEX_TBL(obj)) {
|
||||||
// TODO: more correct value
|
// TODO: more correct value
|
||||||
size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
|
size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
|
||||||
|
@ -9617,27 +9603,6 @@ update_cc_tbl(rb_objspace_t *objspace, VALUE klass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum rb_id_table_iterator_result
|
|
||||||
update_cvc_tbl_i(ID id, VALUE cvc_entry, void *data)
|
|
||||||
{
|
|
||||||
struct rb_cvar_class_tbl_entry *entry;
|
|
||||||
|
|
||||||
entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
|
|
||||||
|
|
||||||
entry->class_value = rb_gc_location(entry->class_value);
|
|
||||||
|
|
||||||
return ID_TABLE_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_cvc_tbl(rb_objspace_t *objspace, VALUE klass)
|
|
||||||
{
|
|
||||||
struct rb_id_table *tbl = RCLASS_CVC_TBL(klass);
|
|
||||||
if (tbl) {
|
|
||||||
rb_id_table_foreach_with_replace(tbl, update_cvc_tbl_i, 0, objspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum rb_id_table_iterator_result
|
static enum rb_id_table_iterator_result
|
||||||
update_const_table(VALUE value, void *data)
|
update_const_table(VALUE value, void *data)
|
||||||
{
|
{
|
||||||
|
@ -9709,7 +9674,6 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
|
||||||
if (!RCLASS_EXT(obj)) break;
|
if (!RCLASS_EXT(obj)) break;
|
||||||
update_m_tbl(objspace, RCLASS_M_TBL(obj));
|
update_m_tbl(objspace, RCLASS_M_TBL(obj));
|
||||||
update_cc_tbl(objspace, obj);
|
update_cc_tbl(objspace, obj);
|
||||||
update_cvc_tbl(objspace, obj);
|
|
||||||
|
|
||||||
gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj));
|
gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj));
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ rb_id_table_init(struct rb_id_table *tbl, int capa)
|
||||||
return tbl;
|
return tbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
MJIT_FUNC_EXPORTED struct rb_id_table *
|
struct rb_id_table *
|
||||||
rb_id_table_create(size_t capa)
|
rb_id_table_create(size_t capa)
|
||||||
{
|
{
|
||||||
struct rb_id_table *tbl = ALLOC(struct rb_id_table);
|
struct rb_id_table *tbl = ALLOC(struct rb_id_table);
|
||||||
|
@ -223,7 +223,7 @@ hash_table_show(struct rb_id_table *tbl)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MJIT_FUNC_EXPORTED int
|
int
|
||||||
rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
|
rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
|
||||||
{
|
{
|
||||||
id_key_t key = id2key(id);
|
id_key_t key = id2key(id);
|
||||||
|
@ -253,7 +253,7 @@ rb_id_table_insert_key(struct rb_id_table *tbl, const id_key_t key, const VALUE
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MJIT_FUNC_EXPORTED int
|
int
|
||||||
rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
|
rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
|
||||||
{
|
{
|
||||||
return rb_id_table_insert_key(tbl, id2key(id), val);
|
return rb_id_table_insert_key(tbl, id2key(id), val);
|
||||||
|
|
|
@ -72,7 +72,6 @@ VALUE rb_mod_const_missing(VALUE,VALUE);
|
||||||
VALUE rb_cvar_defined(VALUE, ID);
|
VALUE rb_cvar_defined(VALUE, ID);
|
||||||
void rb_cvar_set(VALUE, ID, VALUE);
|
void rb_cvar_set(VALUE, ID, VALUE);
|
||||||
VALUE rb_cvar_get(VALUE, ID);
|
VALUE rb_cvar_get(VALUE, ID);
|
||||||
VALUE rb_cvar_find(VALUE, ID, VALUE*);
|
|
||||||
void rb_cv_set(VALUE, const char*, VALUE);
|
void rb_cv_set(VALUE, const char*, VALUE);
|
||||||
VALUE rb_cv_get(VALUE, const char*);
|
VALUE rb_cv_get(VALUE, const char*);
|
||||||
void rb_define_class_variable(VALUE, const char*, VALUE);
|
void rb_define_class_variable(VALUE, const char*, VALUE);
|
||||||
|
|
10
insns.def
10
insns.def
|
@ -230,28 +230,26 @@ setinstancevariable
|
||||||
/* Get value of class variable id of klass as val. */
|
/* Get value of class variable id of klass as val. */
|
||||||
DEFINE_INSN
|
DEFINE_INSN
|
||||||
getclassvariable
|
getclassvariable
|
||||||
(ID id, IVC ic)
|
(ID id)
|
||||||
()
|
()
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
/* "class variable access from toplevel" warning can be hooked. */
|
/* "class variable access from toplevel" warning can be hooked. */
|
||||||
// attr bool leaf = false; /* has rb_warning() */
|
// attr bool leaf = false; /* has rb_warning() */
|
||||||
{
|
{
|
||||||
rb_cref_t * cref = vm_get_cref(GET_EP());
|
val = rb_cvar_get(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP(), 1), id);
|
||||||
rb_control_frame_t *cfp = GET_CFP();
|
|
||||||
val = vm_getclassvariable(GET_ISEQ(), cref, cfp, id, (ICVARC)ic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set value of class variable id of klass as val. */
|
/* Set value of class variable id of klass as val. */
|
||||||
DEFINE_INSN
|
DEFINE_INSN
|
||||||
setclassvariable
|
setclassvariable
|
||||||
(ID id, IVC ic)
|
(ID id)
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
()
|
()
|
||||||
/* "class variable access from toplevel" warning can be hooked. */
|
/* "class variable access from toplevel" warning can be hooked. */
|
||||||
// attr bool leaf = false; /* has rb_warning() */
|
// attr bool leaf = false; /* has rb_warning() */
|
||||||
{
|
{
|
||||||
vm_ensure_not_refinement_module(GET_SELF());
|
vm_ensure_not_refinement_module(GET_SELF());
|
||||||
vm_setclassvariable(GET_ISEQ(), vm_get_cref(GET_EP()), GET_CFP(), id, val, (ICVARC)ic);
|
rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP(), 1), id, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants
|
/* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants
|
||||||
|
|
|
@ -31,12 +31,6 @@ struct rb_iv_index_tbl_entry {
|
||||||
VALUE class_value;
|
VALUE class_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rb_cvar_class_tbl_entry {
|
|
||||||
uint32_t index;
|
|
||||||
rb_serial_t global_cvar_state;
|
|
||||||
VALUE class_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rb_classext_struct {
|
struct rb_classext_struct {
|
||||||
struct st_table *iv_index_tbl; // ID -> struct rb_iv_index_tbl_entry
|
struct st_table *iv_index_tbl; // ID -> struct rb_iv_index_tbl_entry
|
||||||
struct st_table *iv_tbl;
|
struct st_table *iv_tbl;
|
||||||
|
@ -46,7 +40,6 @@ struct rb_classext_struct {
|
||||||
struct rb_id_table *const_tbl;
|
struct rb_id_table *const_tbl;
|
||||||
struct rb_id_table *callable_m_tbl;
|
struct rb_id_table *callable_m_tbl;
|
||||||
struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */
|
struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */
|
||||||
struct rb_id_table *cvc_tbl;
|
|
||||||
struct rb_subclass_entry *subclasses;
|
struct rb_subclass_entry *subclasses;
|
||||||
struct rb_subclass_entry **parent_subclasses;
|
struct rb_subclass_entry **parent_subclasses;
|
||||||
/**
|
/**
|
||||||
|
@ -90,7 +83,6 @@ typedef struct rb_classext_struct rb_classext_t;
|
||||||
#endif
|
#endif
|
||||||
#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl)
|
#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl)
|
||||||
#define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl)
|
#define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl)
|
||||||
#define RCLASS_CVC_TBL(c) (RCLASS_EXT(c)->cvc_tbl)
|
|
||||||
#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl)
|
#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl)
|
||||||
#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_)
|
#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_)
|
||||||
#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
|
#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
|
||||||
|
|
100
variable.c
100
variable.c
|
@ -39,9 +39,6 @@
|
||||||
#include "ractor_core.h"
|
#include "ractor_core.h"
|
||||||
#include "vm_sync.h"
|
#include "vm_sync.h"
|
||||||
|
|
||||||
RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
|
|
||||||
#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
|
|
||||||
|
|
||||||
typedef void rb_gvar_compact_t(void *var);
|
typedef void rb_gvar_compact_t(void *var);
|
||||||
|
|
||||||
static struct rb_id_table *rb_global_tbl;
|
static struct rb_id_table *rb_global_tbl;
|
||||||
|
@ -3328,30 +3325,6 @@ cvar_overtaken(VALUE front, VALUE target, ID id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
|
||||||
find_cvar(VALUE klass, VALUE * front, VALUE * target, ID id)
|
|
||||||
{
|
|
||||||
VALUE v = Qundef;
|
|
||||||
CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR();
|
|
||||||
if (cvar_lookup_at(klass, id, (&v))) {
|
|
||||||
if (!*front) {
|
|
||||||
*front = klass;
|
|
||||||
}
|
|
||||||
*target = klass;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) {
|
|
||||||
if (cvar_lookup_at(klass, id, (&v))) {
|
|
||||||
if (!*front) {
|
|
||||||
*front = klass;
|
|
||||||
}
|
|
||||||
*target = klass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
|
#define CVAR_FOREACH_ANCESTORS(klass, v, r) \
|
||||||
for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
|
for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
|
||||||
if (cvar_lookup_at(klass, id, (v))) { \
|
if (cvar_lookup_at(klass, id, (v))) { \
|
||||||
|
@ -3365,20 +3338,6 @@ find_cvar(VALUE klass, VALUE * front, VALUE * target, ID id)
|
||||||
CVAR_FOREACH_ANCESTORS(klass, v, r);\
|
CVAR_FOREACH_ANCESTORS(klass, v, r);\
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static void
|
|
||||||
check_for_cvar_table(VALUE subclass, VALUE key)
|
|
||||||
{
|
|
||||||
st_table *tbl = RCLASS_IV_TBL(subclass);
|
|
||||||
|
|
||||||
if (tbl && st_lookup(tbl, key, NULL)) {
|
|
||||||
RB_DEBUG_COUNTER_INC(cvar_class_invalidate);
|
|
||||||
ruby_vm_global_cvar_state++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_class_foreach_subclass(subclass, check_for_cvar_table, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_cvar_set(VALUE klass, ID id, VALUE val)
|
rb_cvar_set(VALUE klass, ID id, VALUE val)
|
||||||
{
|
{
|
||||||
|
@ -3398,58 +3357,23 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
|
||||||
}
|
}
|
||||||
check_before_mod_set(target, id, val, "class variable");
|
check_before_mod_set(target, id, val, "class variable");
|
||||||
|
|
||||||
int result = rb_class_ivar_set(target, id, val);
|
rb_class_ivar_set(target, id, val);
|
||||||
|
|
||||||
struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(target);
|
|
||||||
|
|
||||||
if (!rb_cvc_tbl) {
|
|
||||||
rb_cvc_tbl = RCLASS_CVC_TBL(target) = rb_id_table_create(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_cvar_class_tbl_entry *ent;
|
|
||||||
|
|
||||||
if (!rb_id_table_lookup(rb_cvc_tbl, id, (VALUE*)&ent)) {
|
|
||||||
ent = ALLOC(struct rb_cvar_class_tbl_entry);
|
|
||||||
ent->class_value = target;
|
|
||||||
ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
|
|
||||||
rb_id_table_insert(rb_cvc_tbl, id, (VALUE)ent);
|
|
||||||
RB_DEBUG_COUNTER_INC(cvar_inline_miss);
|
|
||||||
} else {
|
|
||||||
ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Break the cvar cache if this is a new class variable
|
|
||||||
// and target is a module or a subclass with the same
|
|
||||||
// cvar in this lookup.
|
|
||||||
if (result == 0) {
|
|
||||||
if (RB_TYPE_P(target, T_CLASS)) {
|
|
||||||
if (RCLASS_SUBCLASSES(target)) {
|
|
||||||
rb_class_foreach_subclass(target, check_for_cvar_table, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE
|
|
||||||
rb_cvar_find(VALUE klass, ID id, VALUE *front)
|
|
||||||
{
|
|
||||||
VALUE target = 0;
|
|
||||||
VALUE value;
|
|
||||||
|
|
||||||
value = find_cvar(klass, front, &target, id);
|
|
||||||
if (!target) {
|
|
||||||
rb_name_err_raise("uninitialized class variable %1$s in %2$s",
|
|
||||||
klass, ID2SYM(id));
|
|
||||||
}
|
|
||||||
cvar_overtaken(*front, target, id);
|
|
||||||
return (VALUE)value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_cvar_get(VALUE klass, ID id)
|
rb_cvar_get(VALUE klass, ID id)
|
||||||
{
|
{
|
||||||
VALUE front = 0;
|
VALUE tmp, front = 0, target = 0;
|
||||||
return rb_cvar_find(klass, id, &front);
|
st_data_t value;
|
||||||
|
|
||||||
|
tmp = klass;
|
||||||
|
CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
|
||||||
|
if (!target) {
|
||||||
|
rb_name_err_raise("uninitialized class variable %1$s in %2$s",
|
||||||
|
tmp, ID2SYM(id));
|
||||||
|
}
|
||||||
|
cvar_overtaken(front, target, id);
|
||||||
|
return (VALUE)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
|
5
vm.c
5
vm.c
|
@ -405,7 +405,6 @@ unsigned int ruby_vm_event_local_num;
|
||||||
|
|
||||||
rb_serial_t ruby_vm_global_constant_state = 1;
|
rb_serial_t ruby_vm_global_constant_state = 1;
|
||||||
rb_serial_t ruby_vm_class_serial = 1;
|
rb_serial_t ruby_vm_class_serial = 1;
|
||||||
rb_serial_t ruby_vm_global_cvar_state = 1;
|
|
||||||
|
|
||||||
static const struct rb_callcache vm_empty_cc = {
|
static const struct rb_callcache vm_empty_cc = {
|
||||||
.flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE,
|
.flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE,
|
||||||
|
@ -485,7 +484,7 @@ rb_dtrace_setup(rb_execution_context_t *ec, VALUE klass, ID id,
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_stat(int argc, VALUE *argv, VALUE self)
|
vm_stat(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
static VALUE sym_global_constant_state, sym_class_serial, sym_global_cvar_state;
|
static VALUE sym_global_constant_state, sym_class_serial;
|
||||||
VALUE arg = Qnil;
|
VALUE arg = Qnil;
|
||||||
VALUE hash = Qnil, key = Qnil;
|
VALUE hash = Qnil, key = Qnil;
|
||||||
|
|
||||||
|
@ -506,7 +505,6 @@ vm_stat(int argc, VALUE *argv, VALUE self)
|
||||||
#define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
|
#define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
|
||||||
S(global_constant_state);
|
S(global_constant_state);
|
||||||
S(class_serial);
|
S(class_serial);
|
||||||
S(global_cvar_state);
|
|
||||||
#undef S
|
#undef S
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +516,6 @@ vm_stat(int argc, VALUE *argv, VALUE self)
|
||||||
|
|
||||||
SET(global_constant_state, ruby_vm_global_constant_state);
|
SET(global_constant_state, ruby_vm_global_constant_state);
|
||||||
SET(class_serial, ruby_vm_class_serial);
|
SET(class_serial, ruby_vm_class_serial);
|
||||||
SET(global_cvar_state, ruby_vm_global_cvar_state);
|
|
||||||
#undef SET
|
#undef SET
|
||||||
|
|
||||||
if (!NIL_P(key)) { /* matched key should return above */
|
if (!NIL_P(key)) { /* matched key should return above */
|
||||||
|
|
|
@ -244,10 +244,6 @@ struct iseq_inline_iv_cache_entry {
|
||||||
struct rb_iv_index_tbl_entry *entry;
|
struct rb_iv_index_tbl_entry *entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iseq_inline_cvar_cache_entry {
|
|
||||||
struct rb_cvar_class_tbl_entry *entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
union iseq_inline_storage_entry {
|
union iseq_inline_storage_entry {
|
||||||
struct {
|
struct {
|
||||||
struct rb_thread_struct *running_thread;
|
struct rb_thread_struct *running_thread;
|
||||||
|
@ -1154,7 +1150,6 @@ enum vm_svar_index {
|
||||||
/* inline cache */
|
/* inline cache */
|
||||||
typedef struct iseq_inline_constant_cache *IC;
|
typedef struct iseq_inline_constant_cache *IC;
|
||||||
typedef struct iseq_inline_iv_cache_entry *IVC;
|
typedef struct iseq_inline_iv_cache_entry *IVC;
|
||||||
typedef struct iseq_inline_cvar_cache_entry *ICVARC;
|
|
||||||
typedef union iseq_inline_storage_entry *ISE;
|
typedef union iseq_inline_storage_entry *ISE;
|
||||||
typedef const struct rb_callinfo *CALL_INFO;
|
typedef const struct rb_callinfo *CALL_INFO;
|
||||||
typedef const struct rb_callcache *CALL_CACHE;
|
typedef const struct rb_callcache *CALL_CACHE;
|
||||||
|
|
|
@ -951,7 +951,7 @@ vm_ensure_not_refinement_module(VALUE self)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_get_iclass(const rb_control_frame_t *cfp, VALUE klass)
|
vm_get_iclass(rb_control_frame_t *cfp, VALUE klass)
|
||||||
{
|
{
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1041,7 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, bool allow_
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_get_cvar_base(const rb_cref_t *cref, const rb_control_frame_t *cfp, int top_level_raise)
|
vm_get_cvar_base(const rb_cref_t *cref, rb_control_frame_t *cfp, int top_level_raise)
|
||||||
{
|
{
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
|
|
||||||
|
@ -1281,86 +1281,6 @@ vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
|
||||||
vm_getclassvariable(const rb_iseq_t *iseq, const rb_cref_t *cref, const rb_control_frame_t *cfp, ID id, ICVARC ic)
|
|
||||||
{
|
|
||||||
if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE()) {
|
|
||||||
VALUE v = Qundef;
|
|
||||||
RB_DEBUG_COUNTER_INC(cvar_read_inline_hit);
|
|
||||||
|
|
||||||
if (st_lookup(RCLASS_IV_TBL(ic->entry->class_value), (st_data_t)id, &v)) {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE klass = vm_get_cvar_base(cref, cfp, 1);
|
|
||||||
VALUE defined_class = 0;
|
|
||||||
|
|
||||||
VALUE cvar_value = rb_cvar_find(klass, id, &defined_class);
|
|
||||||
|
|
||||||
if (RB_TYPE_P(defined_class, T_ICLASS)) {
|
|
||||||
defined_class = RBASIC(defined_class)->klass;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
|
|
||||||
|
|
||||||
if (!rb_cvc_tbl) {
|
|
||||||
rb_cvc_tbl = RCLASS_CVC_TBL(defined_class) = rb_id_table_create(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_cvar_class_tbl_entry *ent;
|
|
||||||
|
|
||||||
if (!rb_id_table_lookup(rb_cvc_tbl, id, (VALUE*)&ent)) {
|
|
||||||
rb_bug("should have cvar cache entry");
|
|
||||||
} else {
|
|
||||||
ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ic->entry = ent;
|
|
||||||
RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value);
|
|
||||||
|
|
||||||
return cvar_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
vm_setclassvariable(const rb_iseq_t *iseq, const rb_cref_t *cref, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic)
|
|
||||||
{
|
|
||||||
if (ic->entry && ic->entry->global_cvar_state == GET_GLOBAL_CVAR_STATE()) {
|
|
||||||
RB_DEBUG_COUNTER_INC(cvar_write_inline_hit);
|
|
||||||
|
|
||||||
rb_class_ivar_set(ic->entry->class_value, id, val);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE klass = vm_get_cvar_base(cref, cfp, 1);
|
|
||||||
|
|
||||||
rb_cvar_set(klass, id, val);
|
|
||||||
|
|
||||||
VALUE defined_class = 0;
|
|
||||||
rb_cvar_find(klass, id, &defined_class);
|
|
||||||
|
|
||||||
if (RB_TYPE_P(defined_class, T_ICLASS)) {
|
|
||||||
defined_class = RBASIC(defined_class)->klass;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(defined_class);
|
|
||||||
|
|
||||||
if (!rb_cvc_tbl) {
|
|
||||||
rb_bug("the cvc table should be set");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rb_cvar_class_tbl_entry *ent;
|
|
||||||
|
|
||||||
if (!rb_id_table_lookup(rb_cvc_tbl, id, (VALUE*)&ent)) {
|
|
||||||
rb_bug("should have cvar cache entry");
|
|
||||||
} else {
|
|
||||||
ent->global_cvar_state = GET_GLOBAL_CVAR_STATE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ic->entry = ent;
|
|
||||||
RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_getinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, IVC ic)
|
vm_getinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, IVC ic)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,6 @@ RUBY_SYMBOL_EXPORT_BEGIN
|
||||||
RUBY_EXTERN VALUE ruby_vm_const_missing_count;
|
RUBY_EXTERN VALUE ruby_vm_const_missing_count;
|
||||||
RUBY_EXTERN rb_serial_t ruby_vm_global_constant_state;
|
RUBY_EXTERN rb_serial_t ruby_vm_global_constant_state;
|
||||||
RUBY_EXTERN rb_serial_t ruby_vm_class_serial;
|
RUBY_EXTERN rb_serial_t ruby_vm_class_serial;
|
||||||
RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
|
|
||||||
|
|
||||||
RUBY_SYMBOL_EXPORT_END
|
RUBY_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
|
@ -180,8 +179,6 @@ CC_SET_FASTPATH(const struct rb_callcache *cc, vm_call_handler func, bool enable
|
||||||
#define NEXT_CLASS_SERIAL() (++ruby_vm_class_serial)
|
#define NEXT_CLASS_SERIAL() (++ruby_vm_class_serial)
|
||||||
#define GET_GLOBAL_CONSTANT_STATE() (ruby_vm_global_constant_state)
|
#define GET_GLOBAL_CONSTANT_STATE() (ruby_vm_global_constant_state)
|
||||||
#define INC_GLOBAL_CONSTANT_STATE() (++ruby_vm_global_constant_state)
|
#define INC_GLOBAL_CONSTANT_STATE() (++ruby_vm_global_constant_state)
|
||||||
#define GET_GLOBAL_CVAR_STATE() (ruby_vm_global_cvar_state)
|
|
||||||
#define INC_GLOBAL_CVAR_STATE() (++ruby_vm_global_cvar_state)
|
|
||||||
|
|
||||||
static inline struct vm_throw_data *
|
static inline struct vm_throw_data *
|
||||||
THROW_DATA_NEW(VALUE val, const rb_control_frame_t *cf, int st)
|
THROW_DATA_NEW(VALUE val, const rb_control_frame_t *cf, int st)
|
||||||
|
|
Loading…
Reference in a new issue