2020#include "darray.h"
2121#include "zjit.h"
2222
23+ #include "builtin.h"
24+
2325#include <stdio.h>
2426
2527#ifdef HAVE_FCNTL_H
@@ -36,8 +38,12 @@ VALUE rb_cBox = 0;
3638VALUE rb_cBoxEntry = 0 ;
3739VALUE rb_mBoxLoader = 0 ;
3840
39- static rb_box_t root_box [1 ]; /* Initialize in initialize_root_box() */
41+ static rb_box_t master_box [1 ]; /* Initialize in initialize_master_box() */
42+ static rb_box_t * root_box ;
4043static rb_box_t * main_box ;
44+
45+ static rb_box_gem_flags_t box_gem_flags [1 ];
46+
4147static char * tmp_dir ;
4248static bool tmp_dir_has_dirsep ;
4349
@@ -61,15 +67,33 @@ VALUE rb_resolve_feature_path(VALUE klass, VALUE fname);
6167static VALUE rb_box_inspect (VALUE obj );
6268static void cleanup_all_local_extensions (VALUE libmap );
6369
70+ void
71+ rb_box_set_gem_flags (rb_box_gem_flags_t * flags )
72+ {
73+
74+ box_gem_flags -> gem = flags -> gem ;
75+ box_gem_flags -> error_highlight = flags -> error_highlight ;
76+ box_gem_flags -> did_you_mean = flags -> did_you_mean ;
77+ box_gem_flags -> syntax_suggest = flags -> syntax_suggest ;
78+ }
79+
6480void
6581rb_box_init_done (void )
6682{
6783 ruby_box_init_done = true;
6884}
6985
86+ const rb_box_t *
87+ rb_master_box (void )
88+ {
89+ return master_box ;
90+ }
91+
7092const rb_box_t *
7193rb_root_box (void )
7294{
95+ if (!root_box ) // The root box isn't initialized yet - The Ruby runtime is in setup.
96+ return master_box ;
7397 return root_box ;
7498}
7599
@@ -83,12 +107,14 @@ const rb_box_t *
83107rb_current_box (void )
84108{
85109 /*
86- * If RUBY_BOX is not set, the root box is the only available one.
110+ * If RUBY_BOX is not set, the master box is the only available one.
87111 *
88- * Until the main_box is not initialized, the root box is
112+ * While the root/main boxes are not initialized, the master box is
89113 * the only valid box.
90114 * This early return is to avoid accessing EC before its setup.
91115 */
116+ if (!root_box )
117+ return master_box ;
92118 if (!main_box )
93119 return root_box ;
94120
@@ -98,6 +124,8 @@ rb_current_box(void)
98124const rb_box_t *
99125rb_loading_box (void )
100126{
127+ if (!root_box )
128+ return master_box ;
101129 if (!main_box )
102130 return root_box ;
103131
@@ -133,7 +161,7 @@ box_main_to_s(VALUE obj)
133161static void
134162box_entry_initialize (rb_box_t * box )
135163{
136- const rb_box_t * root = rb_root_box ();
164+ const rb_box_t * master = rb_master_box ();
137165
138166 // These will be updated immediately
139167 box -> box_object = 0 ;
@@ -142,15 +170,15 @@ box_entry_initialize(rb_box_t *box)
142170 box -> top_self = rb_obj_alloc (rb_cObject );
143171 rb_define_singleton_method (box -> top_self , "to_s" , box_main_to_s , 0 );
144172 rb_define_alias (rb_singleton_class (box -> top_self ), "inspect" , "to_s" );
145- box -> load_path = rb_ary_dup (root -> load_path );
146- box -> expanded_load_path = rb_ary_dup (root -> expanded_load_path );
173+ box -> load_path = rb_ary_dup (master -> load_path );
174+ box -> expanded_load_path = rb_ary_dup (master -> expanded_load_path );
147175 box -> load_path_snapshot = rb_ary_new ();
148176 box -> load_path_check_cache = 0 ;
149- box -> loaded_features = rb_ary_dup (root -> loaded_features );
177+ box -> loaded_features = rb_ary_dup (master -> loaded_features );
150178 box -> loaded_features_snapshot = rb_ary_new ();
151179 box -> loaded_features_index = st_init_numtable ();
152- box -> loaded_features_realpaths = rb_hash_dup (root -> loaded_features_realpaths );
153- box -> loaded_features_realpath_map = rb_hash_dup (root -> loaded_features_realpath_map );
180+ box -> loaded_features_realpaths = rb_hash_dup (master -> loaded_features_realpaths );
181+ box -> loaded_features_realpath_map = rb_hash_dup (master -> loaded_features_realpath_map );
154182 box -> loading_table = st_init_strtable ();
155183 box -> ruby_dln_libmap = rb_hash_new_with_size (0 );
156184 box -> gvar_tbl = rb_hash_new_with_size (0 );
@@ -227,7 +255,7 @@ free_loaded_feature_index_i(st_data_t key, st_data_t value, st_data_t arg)
227255}
228256
229257static void
230- box_root_free (void * ptr )
258+ free_box_st_tables (void * ptr )
231259{
232260 rb_box_t * box = (rb_box_t * )ptr ;
233261 if (box -> loading_table ) {
@@ -274,7 +302,7 @@ box_entry_free(void *ptr)
274302
275303 cleanup_all_local_extensions (box -> ruby_dln_libmap );
276304
277- box_root_free (ptr );
305+ free_box_st_tables (ptr );
278306 SIZED_FREE (box );
279307}
280308
@@ -303,11 +331,11 @@ static const rb_data_type_t rb_box_data_type = {
303331 0 , 0 , RUBY_TYPED_FREE_IMMEDIATELY // TODO: enable RUBY_TYPED_WB_PROTECTED when inserting write barriers
304332};
305333
306- static const rb_data_type_t rb_root_box_data_type = {
307- "Ruby::Box::Root " ,
334+ static const rb_data_type_t rb_master_box_data_type = {
335+ "Ruby::Box::Master " ,
308336 {
309337 rb_box_entry_mark ,
310- box_root_free ,
338+ free_box_st_tables ,
311339 box_entry_memsize ,
312340 rb_box_gc_update_references ,
313341 },
@@ -340,7 +368,7 @@ rb_get_box_t(VALUE box)
340368 VM_ASSERT (box );
341369
342370 if (NIL_P (box ))
343- return root_box ;
371+ return ( rb_box_t * ) rb_root_box () ;
344372
345373 VM_ASSERT (BOX_OBJ_P (box ));
346374
@@ -394,6 +422,14 @@ box_initialize(VALUE box_value)
394422
395423 rb_ivar_set (box_value , id_box_entry , entry );
396424
425+ if (ruby_box_init_done ) {
426+ if (box_gem_flags -> gem ) {
427+ rb_vm_call_cfunc_in_box (Qnil , rb_define_gem_modules , (VALUE )box_gem_flags , Qnil ,
428+ rb_str_new_cstr ("before_prelude.user.dummy" ), (const rb_box_t * )box );
429+ rb_load_gem_prelude ((VALUE )box );
430+ }
431+ }
432+
397433 // Invalidate ZJIT code that assumes only the root box is active
398434 rb_zjit_invalidate_root_box ();
399435
@@ -845,49 +881,52 @@ rb_box_require_relative(VALUE box, VALUE fname)
845881}
846882
847883static void
848- initialize_root_box (void )
884+ initialize_master_box (void )
849885{
850886 rb_vm_t * vm = GET_VM ();
851- rb_box_t * root = (rb_box_t * )rb_root_box ();
887+ rb_box_t * master = (rb_box_t * )rb_master_box ();
852888
853- root -> load_path = rb_ary_new ();
854- root -> expanded_load_path = rb_ary_hidden_new (0 );
855- root -> load_path_snapshot = rb_ary_hidden_new (0 );
856- root -> load_path_check_cache = 0 ;
857- rb_define_singleton_method (root -> load_path , "resolve_feature_path" , rb_resolve_feature_path , 1 );
889+ master -> load_path = rb_ary_new ();
890+ master -> expanded_load_path = rb_ary_hidden_new (0 );
891+ master -> load_path_snapshot = rb_ary_hidden_new (0 );
892+ master -> load_path_check_cache = 0 ;
893+ rb_define_singleton_method (master -> load_path , "resolve_feature_path" , rb_resolve_feature_path , 1 );
858894
859- root -> loaded_features = rb_ary_new ();
860- root -> loaded_features_snapshot = rb_ary_hidden_new (0 );
861- root -> loaded_features_index = st_init_numtable ();
862- root -> loaded_features_realpaths = rb_hash_new ();
863- rb_obj_hide (root -> loaded_features_realpaths );
864- root -> loaded_features_realpath_map = rb_hash_new ();
865- rb_obj_hide (root -> loaded_features_realpath_map );
895+ master -> loaded_features = rb_ary_new ();
896+ master -> loaded_features_snapshot = rb_ary_hidden_new (0 );
897+ master -> loaded_features_index = st_init_numtable ();
898+ master -> loaded_features_realpaths = rb_hash_new ();
899+ rb_obj_hide (master -> loaded_features_realpaths );
900+ master -> loaded_features_realpath_map = rb_hash_new ();
901+ rb_obj_hide (master -> loaded_features_realpath_map );
866902
867- root -> ruby_dln_libmap = rb_hash_new_with_size (0 );
868- root -> gvar_tbl = rb_hash_new_with_size (0 );
869- root -> classext_cow_classes = NULL ; // classext CoW never happen on the root box
903+ master -> ruby_dln_libmap = rb_hash_new_with_size (0 );
904+ master -> gvar_tbl = rb_hash_new_with_size (0 );
905+ master -> classext_cow_classes = NULL ; // classext CoW never happen on the master box
870906
871- vm -> root_box = root ;
907+ vm -> master_box = master ;
872908
873909 if (rb_box_available ()) {
874- VALUE root_box , entry ;
910+ VALUE master_box , entry ;
875911 ID id_box_entry ;
876912 CONST_ID (id_box_entry , "__box_entry__" );
877913
878- root_box = rb_obj_alloc (rb_cBox );
879- RCLASS_SET_PRIME_CLASSEXT_WRITABLE (root_box , true);
880- RCLASS_SET_CONST_TBL (root_box , RCLASSEXT_CONST_TBL (RCLASS_EXT_PRIME (rb_cObject )), true);
914+ master_box = rb_obj_alloc (rb_cBox );
915+ RCLASS_SET_PRIME_CLASSEXT_WRITABLE (master_box , true);
916+ RCLASS_SET_CONST_TBL (master_box , RCLASSEXT_CONST_TBL (RCLASS_EXT_PRIME (rb_cObject )), true);
917+
918+ master -> box_id = box_generate_id ();
919+ master -> box_object = master_box ;
881920
882- root -> box_id = box_generate_id ( );
883- root -> box_object = root_box ;
921+ entry = TypedData_Wrap_Struct ( rb_cBoxEntry , & rb_master_box_data_type , master );
922+ rb_ivar_set ( master_box , id_box_entry , entry ) ;
884923
885- entry = TypedData_Wrap_Struct ( rb_cBoxEntry , & rb_root_box_data_type , root );
886- rb_ivar_set ( root_box , id_box_entry , entry );
924+ rb_gc_register_mark_object ( master_box );
925+ rb_gc_register_mark_object ( entry );
887926 }
888927 else {
889- root -> box_id = 1 ;
890- root -> box_object = Qnil ;
928+ master -> box_id = 1 ;
929+ master -> box_object = Qnil ;
891930 }
892931}
893932
@@ -911,11 +950,26 @@ static int box_experimental_warned = 0;
911950
912951RUBY_EXTERN const char ruby_api_version_name [];
913952
914- void
915- rb_initialize_main_box ( void )
953+ static VALUE
954+ box_value_initialize ( bool root , bool user , bool optional )
916955{
917956 rb_box_t * box ;
918- VALUE main_box_value ;
957+ VALUE box_value = rb_class_new_instance (0 , NULL , rb_cBox );
958+
959+ VM_ASSERT (BOX_OBJ_P (box_value ));
960+
961+ box = rb_get_box_t (box_value );
962+ box -> box_object = box_value ;
963+ box -> is_root = root ;
964+ box -> is_user = user ;
965+ box -> is_optional = optional ;
966+ return box_value ;
967+ }
968+
969+ void
970+ rb_initialize_mandatory_boxes (void )
971+ {
972+ VALUE root_box_value , main_box_value ;
919973 rb_vm_t * vm = GET_VM ();
920974
921975 VM_ASSERT (rb_box_available ());
@@ -928,19 +982,18 @@ rb_initialize_main_box(void)
928982 box_experimental_warned = 1 ;
929983 }
930984
931- main_box_value = rb_class_new_instance (0 , NULL , rb_cBox );
932- VM_ASSERT (BOX_OBJ_P (main_box_value ));
933- box = rb_get_box_t (main_box_value );
934- box -> box_object = main_box_value ;
935- box -> is_user = true;
936- box -> is_optional = false;
985+ root_box_value = box_value_initialize (true, false, false);
986+ main_box_value = box_value_initialize (false, true, false);
937987
988+ rb_const_set (rb_cBox , rb_intern ("ROOT" ), root_box_value );
938989 rb_const_set (rb_cBox , rb_intern ("MAIN" ), main_box_value );
939990
940- vm -> main_box = main_box = box ;
991+ vm -> root_box = root_box = rb_get_box_t (root_box_value );
992+ vm -> main_box = main_box = rb_get_box_t (main_box_value );
941993
942994 // create the writable classext of ::Object explicitly to finalize the set of visible top-level constants
943- RCLASS_EXT_WRITABLE_IN_BOX (rb_cObject , box );
995+ RCLASS_EXT_WRITABLE_IN_BOX (rb_cObject , root_box );
996+ RCLASS_EXT_WRITABLE_IN_BOX (rb_cObject , main_box );
944997}
945998
946999static VALUE
@@ -949,12 +1002,15 @@ rb_box_inspect(VALUE obj)
9491002 rb_box_t * box ;
9501003 VALUE r ;
9511004 if (obj == Qfalse ) {
952- r = rb_str_new_cstr ("#<Ruby::Box:root >" );
1005+ r = rb_str_new_cstr ("#<Ruby::Box:master >" );
9531006 return r ;
9541007 }
9551008 box = rb_get_box_t (obj );
9561009 r = rb_str_new_cstr ("#<Ruby::Box:" );
9571010 rb_str_concat (r , rb_funcall (LONG2NUM (box -> box_id ), rb_intern ("to_s" ), 0 ));
1011+ if (BOX_MASTER_P (box )) {
1012+ rb_str_cat_cstr (r , ",master" );
1013+ }
9581014 if (BOX_ROOT_P (box )) {
9591015 rb_str_cat_cstr (r , ",root" );
9601016 }
@@ -986,9 +1042,9 @@ box_define_loader_method(const char *name)
9861042}
9871043
9881044void
989- Init_root_box (void )
1045+ Init_master_box (void )
9901046{
991- root_box -> loading_table = st_init_strtable ();
1047+ master_box -> loading_table = st_init_strtable ();
9921048}
9931049
9941050void
@@ -1003,6 +1059,13 @@ Init_enable_box(void)
10031059 }
10041060}
10051061
1062+ /* :nodoc: */
1063+ static VALUE
1064+ rb_box_s_master (VALUE recv )
1065+ {
1066+ return master_box -> box_object ;
1067+ }
1068+
10061069/* :nodoc: */
10071070static VALUE
10081071rb_box_s_root (VALUE recv )
@@ -1017,6 +1080,14 @@ rb_box_s_main(VALUE recv)
10171080 return main_box -> box_object ;
10181081}
10191082
1083+ /* :nodoc: */
1084+ static VALUE
1085+ rb_box_master_p (VALUE box_value )
1086+ {
1087+ const rb_box_t * box = (const rb_box_t * )rb_get_box_t (box_value );
1088+ return RBOOL (BOX_MASTER_P (box ));
1089+ }
1090+
10201091/* :nodoc: */
10211092static VALUE
10221093rb_box_root_p (VALUE box_value )
@@ -1151,7 +1222,7 @@ rb_f_dump_classext(VALUE recv, VALUE klass)
11511222 box = RCLASSEXT_BOX (ext );
11521223 snprintf (buf , 2048 , "Prime classext box(%ld,%s), readable(%s), writable(%s)\n" ,
11531224 box -> box_id ,
1154- BOX_ROOT_P (box ) ? "root" : (BOX_MAIN_P (box ) ? "main" : "optional" ),
1225+ BOX_MASTER_P ( box ) ? "master" : ( BOX_ROOT_P (box ) ? "root" : (BOX_MAIN_P (box ) ? "main" : "optional" ) ),
11551226 RCLASS_PRIME_CLASSEXT_READABLE_P (klass ) ? "t" : "f" ,
11561227 RCLASS_PRIME_CLASSEXT_WRITABLE_P (klass ) ? "t" : "f" );
11571228 rb_str_cat_cstr (res , buf );
@@ -1193,7 +1264,7 @@ Init_Box(void)
11931264 rb_cBoxEntry = rb_define_class_under (rb_cBox , "Entry" , rb_cObject );
11941265 rb_define_alloc_func (rb_cBoxEntry , rb_box_entry_alloc );
11951266
1196- initialize_root_box ();
1267+ initialize_master_box ();
11971268
11981269 /* :nodoc: */
11991270 rb_mBoxLoader = rb_define_module_under (rb_cBox , "Loader" );
@@ -1204,8 +1275,10 @@ Init_Box(void)
12041275 if (rb_box_available ()) {
12051276 rb_include_module (rb_cObject , rb_mBoxLoader );
12061277
1278+ rb_define_singleton_method (rb_cBox , "master" , rb_box_s_master , 0 );
12071279 rb_define_singleton_method (rb_cBox , "root" , rb_box_s_root , 0 );
12081280 rb_define_singleton_method (rb_cBox , "main" , rb_box_s_main , 0 );
1281+ rb_define_method (rb_cBox , "master?" , rb_box_master_p , 0 );
12091282 rb_define_method (rb_cBox , "root?" , rb_box_root_p , 0 );
12101283 rb_define_method (rb_cBox , "main?" , rb_box_main_p , 0 );
12111284
0 commit comments