Let execution context local storage be an ID table

This commit is contained in:
Lourens Naudé 2020-01-04 00:45:58 +00:00 committed by Samuel Williams
parent b53d8230f1
commit 40c57ad4a1
Notes: git 2020-01-11 10:41:09 +09:00
6 changed files with 42 additions and 22 deletions

View File

@ -0,0 +1,8 @@
prelude: |
th = Thread.current
th[:key] = :val
benchmark:
key?: th.key?(:key)
[]: th[:key]
keys: th.keys
loop_count: 1_000_000

View File

@ -1919,6 +1919,7 @@ cont.$(OBJEXT): {$(VPATH)}defines.h
cont.$(OBJEXT): {$(VPATH)}eval_intern.h cont.$(OBJEXT): {$(VPATH)}eval_intern.h
cont.$(OBJEXT): {$(VPATH)}gc.h cont.$(OBJEXT): {$(VPATH)}gc.h
cont.$(OBJEXT): {$(VPATH)}id.h cont.$(OBJEXT): {$(VPATH)}id.h
cont.$(OBJEXT): {$(VPATH)}id_table.h
cont.$(OBJEXT): {$(VPATH)}intern.h cont.$(OBJEXT): {$(VPATH)}intern.h
cont.$(OBJEXT): {$(VPATH)}internal.h cont.$(OBJEXT): {$(VPATH)}internal.h
cont.$(OBJEXT): {$(VPATH)}method.h cont.$(OBJEXT): {$(VPATH)}method.h

5
cont.c
View File

@ -27,6 +27,7 @@
#include "internal/warnings.h" #include "internal/warnings.h"
#include "mjit.h" #include "mjit.h"
#include "vm_core.h" #include "vm_core.h"
#include "id_table.h"
static const int DEBUG = 0; static const int DEBUG = 0;
@ -1018,7 +1019,7 @@ fiber_free(void *ptr)
//if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", fiber, fiber->stack.base); //if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", fiber, fiber->stack.base);
if (fiber->cont.saved_ec.local_storage) { if (fiber->cont.saved_ec.local_storage) {
st_free_table(fiber->cont.saved_ec.local_storage); rb_id_table_free(fiber->cont.saved_ec.local_storage);
} }
cont_free(&fiber->cont); cont_free(&fiber->cont);
@ -1037,7 +1038,7 @@ fiber_memsize(const void *ptr)
* vm.c::thread_memsize already counts th->ec->local_storage * vm.c::thread_memsize already counts th->ec->local_storage
*/ */
if (saved_ec->local_storage && fiber != th->root_fiber) { if (saved_ec->local_storage && fiber != th->root_fiber) {
size += st_memsize(saved_ec->local_storage); size += rb_id_table_memsize(saved_ec->local_storage);
} }
size += cont_memsize(&fiber->cont); size += cont_memsize(&fiber->cont);
return size; return size;

View File

@ -3219,11 +3219,11 @@ threadptr_local_aref(rb_thread_t *th, ID id)
return th->ec->local_storage_recursive_hash; return th->ec->local_storage_recursive_hash;
} }
else { else {
st_data_t val; VALUE val;
st_table *local_storage = th->ec->local_storage; struct rb_id_table *local_storage = th->ec->local_storage;
if (local_storage != NULL && st_lookup(local_storage, id, &val)) { if (local_storage != NULL && rb_id_table_lookup(local_storage, id, &val)) {
return (VALUE)val; return val;
} }
else { else {
return Qnil; return Qnil;
@ -3340,7 +3340,7 @@ rb_thread_fetch(int argc, VALUE *argv, VALUE self)
return target_th->ec->local_storage_recursive_hash; return target_th->ec->local_storage_recursive_hash;
} }
else if (id && target_th->ec->local_storage && else if (id && target_th->ec->local_storage &&
st_lookup(target_th->ec->local_storage, id, &val)) { rb_id_table_lookup(target_th->ec->local_storage, id, &val)) {
return val; return val;
} }
else if (block_given) { else if (block_given) {
@ -3362,18 +3362,18 @@ threadptr_local_aset(rb_thread_t *th, ID id, VALUE val)
return val; return val;
} }
else { else {
st_table *local_storage = th->ec->local_storage; struct rb_id_table *local_storage = th->ec->local_storage;
if (NIL_P(val)) { if (NIL_P(val)) {
if (!local_storage) return Qnil; if (!local_storage) return Qnil;
st_delete_wrap(local_storage, id); rb_id_table_delete(local_storage, id);
return Qnil; return Qnil;
} }
else { else {
if (local_storage == NULL) { if (local_storage == NULL) {
th->ec->local_storage = local_storage = st_init_numtable(); th->ec->local_storage = local_storage = rb_id_table_create(0);
} }
st_insert(local_storage, id, val); rb_id_table_insert(local_storage, id, val);
return val; return val;
} }
} }
@ -3486,13 +3486,14 @@ rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
static VALUE static VALUE
rb_thread_key_p(VALUE self, VALUE key) rb_thread_key_p(VALUE self, VALUE key)
{ {
VALUE val;
ID id = rb_check_id(&key); ID id = rb_check_id(&key);
st_table *local_storage = rb_thread_ptr(self)->ec->local_storage; struct rb_id_table *local_storage = rb_thread_ptr(self)->ec->local_storage;
if (!id || local_storage == NULL) { if (!id || local_storage == NULL) {
return Qfalse; return Qfalse;
} }
else if (st_is_member(local_storage, id)) { else if (rb_id_table_lookup(local_storage, id, &val)) {
return Qtrue; return Qtrue;
} }
else { else {
@ -3500,11 +3501,11 @@ rb_thread_key_p(VALUE self, VALUE key)
} }
} }
static int static enum rb_id_table_iterator_result
thread_keys_i(ID key, VALUE value, VALUE ary) thread_keys_i(ID key, VALUE value, void *ary)
{ {
rb_ary_push(ary, ID2SYM(key)); rb_ary_push((VALUE)ary, ID2SYM(key));
return ST_CONTINUE; return ID_TABLE_CONTINUE;
} }
int int
@ -3530,11 +3531,11 @@ rb_thread_alone(void)
static VALUE static VALUE
rb_thread_keys(VALUE self) rb_thread_keys(VALUE self)
{ {
st_table *local_storage = rb_thread_ptr(self)->ec->local_storage; struct rb_id_table *local_storage = rb_thread_ptr(self)->ec->local_storage;
VALUE ary = rb_ary_new(); VALUE ary = rb_ary_new();
if (local_storage) { if (local_storage) {
st_foreach(local_storage, thread_keys_i, ary); rb_id_table_foreach(local_storage, thread_keys_i, (void *)ary);
} }
return ary; return ary;
} }

13
vm.c
View File

@ -2501,6 +2501,13 @@ rb_execution_context_update(const rb_execution_context_t *ec)
} }
} }
static enum rb_id_table_iterator_result
mark_local_storage_i(VALUE local, void *data)
{
rb_gc_mark(local);
return ID_TABLE_CONTINUE;
}
void void
rb_execution_context_mark(const rb_execution_context_t *ec) rb_execution_context_mark(const rb_execution_context_t *ec)
{ {
@ -2544,7 +2551,9 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
RUBY_MARK_UNLESS_NULL(ec->errinfo); RUBY_MARK_UNLESS_NULL(ec->errinfo);
RUBY_MARK_UNLESS_NULL(ec->root_svar); RUBY_MARK_UNLESS_NULL(ec->root_svar);
rb_mark_tbl(ec->local_storage); if (ec->local_storage) {
rb_id_table_foreach_values(ec->local_storage, mark_local_storage_i, NULL);
}
RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash); RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash);
RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash_for_trace); RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash_for_trace);
RUBY_MARK_UNLESS_NULL(ec->private_const_reference); RUBY_MARK_UNLESS_NULL(ec->private_const_reference);
@ -2639,7 +2648,7 @@ thread_memsize(const void *ptr)
size += th->ec->vm_stack_size * sizeof(VALUE); size += th->ec->vm_stack_size * sizeof(VALUE);
} }
if (th->ec->local_storage) { if (th->ec->local_storage) {
size += st_memsize(th->ec->local_storage); size += rb_id_table_memsize(th->ec->local_storage);
} }
return size; return size;
} }

View File

@ -865,7 +865,7 @@ typedef struct rb_execution_context_struct {
struct rb_thread_struct *thread_ptr; struct rb_thread_struct *thread_ptr;
/* storage (ec (fiber) local) */ /* storage (ec (fiber) local) */
st_table *local_storage; struct rb_id_table *local_storage;
VALUE local_storage_recursive_hash; VALUE local_storage_recursive_hash;
VALUE local_storage_recursive_hash_for_trace; VALUE local_storage_recursive_hash_for_trace;