summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Valentine-House <matt@eightbitraptor.com>2023-02-17 13:32:51 +0000
committerMatt Valentine-House <matt@eightbitraptor.com>2023-04-06 11:07:16 +0100
commitd91a82850ac337c80807743bc0841369a8a1748c (patch)
tree6895a67099d8e77b3c25db7ee25fdfcc1a3b557a
parentb0297feb1f487d466ad1186898b4e36209fcd59e (diff)
Pull the shape tree out of the vm object
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/7393
-rw-r--r--shape.c48
-rw-r--r--shape.h15
-rw-r--r--vm.c17
-rw-r--r--vm_core.h5
-rw-r--r--yjit.c2
5 files changed, 52 insertions, 35 deletions
diff --git a/shape.c b/shape.c
index 7bedf99937..6c158b2c8e 100644
--- a/shape.c
+++ b/shape.c
@@ -24,26 +24,28 @@ static ID id_frozen;
static ID id_t_object;
static ID size_pool_edge_names[SIZE_POOL_COUNT];
+rb_shape_tree_t *rb_shape_tree_ptr = NULL;
+
/*
* Shape getters
*/
rb_shape_t *
rb_shape_get_root_shape(void)
{
- return GET_VM()->root_shape;
+ return GET_SHAPE_TREE()->root_shape;
}
shape_id_t
rb_shape_id(rb_shape_t * shape)
{
- return (shape_id_t)(shape - GET_VM()->shape_list);
+ return (shape_id_t)(shape - GET_SHAPE_TREE()->shape_list);
}
void
rb_shape_each_shape(each_shape_callback callback, void *data)
{
rb_shape_t *cursor = rb_shape_get_root_shape();
- rb_shape_t *end = rb_shape_get_shape_by_id(GET_VM()->next_shape_id);
+ rb_shape_t *end = rb_shape_get_shape_by_id(GET_SHAPE_TREE()->next_shape_id);
while (cursor < end) {
callback(cursor, data);
cursor += 1;
@@ -55,8 +57,7 @@ rb_shape_get_shape_by_id(shape_id_t shape_id)
{
RUBY_ASSERT(shape_id != INVALID_SHAPE_ID);
- rb_vm_t *vm = GET_VM();
- rb_shape_t *shape = &vm->shape_list[shape_id];
+ rb_shape_t *shape = &GET_SHAPE_TREE()->shape_list[shape_id];
return shape;
}
@@ -122,16 +123,15 @@ rb_shape_get_shape(VALUE obj)
static rb_shape_t *
shape_alloc(void)
{
- rb_vm_t *vm = GET_VM();
- shape_id_t shape_id = vm->next_shape_id;
- vm->next_shape_id++;
+ shape_id_t shape_id = GET_SHAPE_TREE()->next_shape_id;
+ GET_SHAPE_TREE()->next_shape_id++;
if (shape_id == MAX_SHAPE_ID) {
// TODO: Make an OutOfShapesError ??
rb_bug("Out of shapes\n");
}
- return &GET_VM()->shape_list[shape_id];
+ return &GET_SHAPE_TREE()->shape_list[shape_id];
}
static rb_shape_t *
@@ -770,16 +770,36 @@ static VALUE
rb_shape_find_by_id(VALUE mod, VALUE id)
{
shape_id_t shape_id = NUM2UINT(id);
- if (shape_id >= GET_VM()->next_shape_id) {
+ if (shape_id >= GET_SHAPE_TREE()->next_shape_id) {
rb_raise(rb_eArgError, "Shape ID %d is out of bounds\n", shape_id);
}
return rb_shape_t_to_rb_cShape(rb_shape_get_shape_by_id(shape_id));
}
#endif
+#include <sys/mman.h>
+
void
Init_default_shapes(void)
{
+ rb_shape_tree_t *st = ruby_mimmalloc(sizeof(rb_shape_tree_t));
+ memset(st, 0, sizeof(rb_shape_tree_t));
+ rb_shape_tree_ptr = st;
+
+#ifdef HAVE_MMAP
+ rb_shape_tree_ptr->shape_list = (rb_shape_t *)mmap(NULL, rb_size_mul_or_raise(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t), rb_eRuntimeError),
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (GET_SHAPE_TREE()->shape_list == MAP_FAILED) {
+ GET_SHAPE_TREE()->shape_list = 0;
+ }
+#else
+ GET_SHAPE_TREE()->shape_list = xcalloc(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t));
+#endif
+
+ if (!GET_SHAPE_TREE()->shape_list) {
+ rb_memerror();
+ }
+
id_frozen = rb_make_internal_id();
id_t_object = rb_make_internal_id();
@@ -793,8 +813,8 @@ Init_default_shapes(void)
root->capacity = (uint32_t)((rb_size_pool_slot_size(0) - offsetof(struct RObject, as.ary)) / sizeof(VALUE));
root->type = SHAPE_ROOT;
root->size_pool_index = 0;
- GET_VM()->root_shape = root;
- RUBY_ASSERT(rb_shape_id(GET_VM()->root_shape) == ROOT_SHAPE_ID);
+ GET_SHAPE_TREE()->root_shape = root;
+ RUBY_ASSERT(rb_shape_id(GET_SHAPE_TREE()->root_shape) == ROOT_SHAPE_ID);
// Shapes by size pool
for (int i = 1; i < SIZE_POOL_COUNT; i++) {
@@ -822,13 +842,13 @@ Init_default_shapes(void)
#endif
get_next_shape_internal(root, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true, false);
RUBY_ASSERT(rb_shape_id(special_const_shape) == SPECIAL_CONST_SHAPE_ID);
- RUBY_ASSERT(SPECIAL_CONST_SHAPE_ID == (GET_VM()->next_shape_id - 1));
+ RUBY_ASSERT(SPECIAL_CONST_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1));
RUBY_ASSERT(rb_shape_frozen_shape_p(special_const_shape));
rb_shape_t * hash_fallback_shape = rb_shape_alloc_with_parent_id(0, ROOT_SHAPE_ID);
hash_fallback_shape->type = SHAPE_OBJ_TOO_COMPLEX;
hash_fallback_shape->size_pool_index = 0;
- RUBY_ASSERT(OBJ_TOO_COMPLEX_SHAPE_ID == (GET_VM()->next_shape_id - 1));
+ RUBY_ASSERT(OBJ_TOO_COMPLEX_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1));
RUBY_ASSERT(rb_shape_id(hash_fallback_shape) == OBJ_TOO_COMPLEX_SHAPE_ID);
}
diff --git a/shape.h b/shape.h
index ab5f707383..dc4a3d5ce1 100644
--- a/shape.h
+++ b/shape.h
@@ -62,6 +62,21 @@ enum shape_type {
SHAPE_OBJ_TOO_COMPLEX,
};
+typedef struct {
+ /* object shapes */
+ rb_shape_t *shape_list;
+ rb_shape_t *root_shape;
+ shape_id_t next_shape_id;
+} rb_shape_tree_t;
+RUBY_EXTERN rb_shape_tree_t *rb_shape_tree_ptr;
+
+static inline rb_shape_tree_t *
+rb_current_shape_tree(void)
+{
+ return rb_shape_tree_ptr;
+}
+#define GET_SHAPE_TREE() rb_current_shape_tree()
+
#if SHAPE_IN_BASIC_FLAGS
static inline shape_id_t
RBASIC_SHAPE_ID(VALUE obj)
diff --git a/vm.c b/vm.c
index eb60d3792d..27d57a3b24 100644
--- a/vm.c
+++ b/vm.c
@@ -40,6 +40,7 @@
#include "vm_insnhelper.h"
#include "ractor_core.h"
#include "vm_sync.h"
+#include "shape.h"
#include "builtin.h"
@@ -592,7 +593,7 @@ vm_stat(int argc, VALUE *argv, VALUE self)
SET(constant_cache_invalidations, ruby_vm_constant_cache_invalidations);
SET(constant_cache_misses, ruby_vm_constant_cache_misses);
SET(global_cvar_state, ruby_vm_global_cvar_state);
- SET(next_shape_id, (rb_serial_t)GET_VM()->next_shape_id);
+ SET(next_shape_id, (rb_serial_t)GET_SHAPE_TREE()->next_shape_id);
#undef SET
#if USE_DEBUG_COUNTER
@@ -4023,20 +4024,6 @@ Init_vm_objects(void)
#if EXTSTATIC
vm->static_ext_inits = st_init_strtable();
#endif
-
-#ifdef HAVE_MMAP
- vm->shape_list = (rb_shape_t *)mmap(NULL, rb_size_mul_or_raise(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t), rb_eRuntimeError),
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (vm->shape_list == MAP_FAILED) {
- vm->shape_list = 0;
- }
-#else
- vm->shape_list = xcalloc(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t));
-#endif
-
- if (!vm->shape_list) {
- rb_memerror();
- }
}
/* Stub for builtin function when not building YJIT units*/
diff --git a/vm_core.h b/vm_core.h
index 4d4ed2387d..76385446f1 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -667,11 +667,6 @@ typedef struct rb_vm_struct {
VALUE mark_object_ary;
const VALUE special_exceptions[ruby_special_error_count];
- /* object shapes */
- rb_shape_t *shape_list;
- rb_shape_t *root_shape;
- shape_id_t next_shape_id;
-
/* load */
VALUE top_self;
VALUE load_path;
diff --git a/yjit.c b/yjit.c
index 431a774880..2d3b7c9e9d 100644
--- a/yjit.c
+++ b/yjit.c
@@ -1105,7 +1105,7 @@ static VALUE
object_shape_count(rb_execution_context_t *ec, VALUE self)
{
// next_shape_id starts from 0, so it's the same as the count
- return ULONG2NUM((unsigned long)GET_VM()->next_shape_id);
+ return ULONG2NUM((unsigned long)GET_SHAPE_TREE()->next_shape_id);
}
// Assert that we have the VM lock. Relevant mostly for multi ractor situations.