From decb802b9d44a09fb981f380774fbc1234883eca Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 9 May 2019 16:05:19 -0400 Subject: [PATCH] sysimg: reduce the number of special cases (#31948) Put the entire image(*) into our pre-constructed data image, instead of attempting to leave out a couple of items. This saves us a couple lines of code, and should makes it simpler to keep the list of builtin objects (gc.c "tags") up-to-date. (*) The remaining special objects are ptls->root_task, since I was unsure the best way to handle it as no other Task object is allowed to be referenced, and the small integer caches. --- src/builtins.c | 61 +++-- src/codegen.cpp | 8 +- src/datatype.c | 9 +- src/dump.c | 4 - src/gc.c | 1 - src/gf.c | 5 +- src/init.c | 121 ++++----- src/jltypes.c | 107 ++++---- src/julia.h | 5 +- src/julia_internal.h | 2 +- src/rtutils.c | 4 +- src/staticdata.c | 585 ++++++++++++++++++------------------------- src/symbol.c | 3 +- src/task.c | 44 +--- src/toplevel.c | 6 +- 15 files changed, 412 insertions(+), 553 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 9a9e7fbf0645f..4369663ffe063 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -279,7 +279,7 @@ static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) JL_NOTSAFEPOIN JL_DLLEXPORT uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) JL_NOTSAFEPOINT { - if (tv == (jl_value_t*)jl_sym_type) + if (tv == (jl_value_t*)jl_symbol_type) return ((jl_sym_t*)v)->hash; if (tv == (jl_value_t*)jl_simplevector_type) return hash_svec((jl_svec_t*)v); @@ -899,7 +899,7 @@ static int valid_type_param(jl_value_t *v) size_t i, l = jl_nparams(tt); for(i=0; i < l; i++) { jl_value_t *pi = jl_tparam(tt,i); - if (!(pi == (jl_value_t*)jl_sym_type || jl_isbits(pi))) + if (!(pi == (jl_value_t*)jl_symbol_type || jl_isbits(pi))) return 0; } return 1; @@ -1253,54 +1253,53 @@ jl_fptr_args_t jl_get_builtin_fptr(jl_value_t *b) return ((jl_typemap_entry_t*)jl_gf_mtable(b)->cache)->func.linfo->cache->specptr.fptr1; } -static void add_builtin_func(const char *name, jl_fptr_args_t fptr) +static jl_value_t *add_builtin_func(const char *name, jl_fptr_args_t fptr) { - jl_mk_builtin_func(NULL, name, fptr); + return jl_mk_builtin_func(NULL, name, fptr)->instance; } void jl_init_primitives(void) JL_GC_DISABLED { - add_builtin_func("===", jl_f_is); - add_builtin_func("typeof", jl_f_typeof); - add_builtin_func("sizeof", jl_f_sizeof); - add_builtin_func("<:", jl_f_issubtype); - add_builtin_func("isa", jl_f_isa); - add_builtin_func("typeassert", jl_f_typeassert); - add_builtin_func("throw", jl_f_throw); - add_builtin_func("tuple", jl_f_tuple); - add_builtin_func("ifelse", jl_f_ifelse); + jl_builtin_is = add_builtin_func("===", jl_f_is); + jl_builtin_typeof = add_builtin_func("typeof", jl_f_typeof); + jl_builtin_sizeof = add_builtin_func("sizeof", jl_f_sizeof); + jl_builtin_issubtype = add_builtin_func("<:", jl_f_issubtype); + jl_builtin_isa = add_builtin_func("isa", jl_f_isa); + jl_builtin_typeassert = add_builtin_func("typeassert", jl_f_typeassert); + jl_builtin_throw = add_builtin_func("throw", jl_f_throw); + jl_builtin_tuple = add_builtin_func("tuple", jl_f_tuple); + jl_builtin_ifelse = add_builtin_func("ifelse", jl_f_ifelse); // field access - add_builtin_func("getfield", jl_f_getfield); - add_builtin_func("setfield!", jl_f_setfield); - add_builtin_func("fieldtype", jl_f_fieldtype); - add_builtin_func("nfields", jl_f_nfields); - add_builtin_func("isdefined", jl_f_isdefined); + jl_builtin_getfield = add_builtin_func("getfield", jl_f_getfield); + jl_builtin_setfield = add_builtin_func("setfield!", jl_f_setfield); + jl_builtin_fieldtype = add_builtin_func("fieldtype", jl_f_fieldtype); + jl_builtin_nfields = add_builtin_func("nfields", jl_f_nfields); + jl_builtin_isdefined = add_builtin_func("isdefined", jl_f_isdefined); // array primitives - add_builtin_func("arrayref", jl_f_arrayref); - add_builtin_func("const_arrayref", jl_f_arrayref); - add_builtin_func("arrayset", jl_f_arrayset); - add_builtin_func("arraysize", jl_f_arraysize); + jl_builtin_arrayref = add_builtin_func("arrayref", jl_f_arrayref); + jl_builtin_const_arrayref = add_builtin_func("const_arrayref", jl_f_arrayref); + jl_builtin_arrayset = add_builtin_func("arrayset", jl_f_arrayset); + jl_builtin_arraysize = add_builtin_func("arraysize", jl_f_arraysize); // method table utils - add_builtin_func("applicable", jl_f_applicable); - add_builtin_func("invoke", jl_f_invoke); - jl_value_t *invokef = jl_get_global(jl_core_module, jl_symbol("invoke")); - jl_typename_t *itn = ((jl_datatype_t*)jl_typeof(invokef))->name; + jl_builtin_applicable = add_builtin_func("applicable", jl_f_applicable); + jl_builtin_invoke = add_builtin_func("invoke", jl_f_invoke); + jl_typename_t *itn = ((jl_datatype_t*)jl_typeof(jl_builtin_invoke))->name; jl_value_t *ikws = jl_new_generic_function_with_supertype(itn->name, jl_core_module, jl_builtin_type, 1); itn->mt->kwsorter = ikws; jl_gc_wb(itn->mt, ikws); jl_mk_builtin_func((jl_datatype_t*)jl_typeof(ikws), jl_symbol_name(jl_gf_name(ikws)), jl_f_invoke_kwsorter); // internal functions - add_builtin_func("apply_type", jl_f_apply_type); - add_builtin_func("_apply", jl_f__apply); + jl_builtin_apply_type = add_builtin_func("apply_type", jl_f_apply_type); + jl_builtin__apply = add_builtin_func("_apply", jl_f__apply); + jl_builtin__expr = add_builtin_func("_expr", jl_f__expr); + jl_builtin_svec = add_builtin_func("svec", jl_f_svec); add_builtin_func("_apply_pure", jl_f__apply_pure); add_builtin_func("_apply_latest", jl_f__apply_latest); - add_builtin_func("_expr", jl_f__expr); add_builtin_func("_typevar", jl_f__typevar); - add_builtin_func("svec", jl_f_svec); // builtin types add_builtin("Any", (jl_value_t*)jl_any_type); @@ -1323,7 +1322,7 @@ void jl_init_primitives(void) JL_GC_DISABLED add_builtin("CodeInstance", (jl_value_t*)jl_code_instance_type); add_builtin("TypeMapEntry", (jl_value_t*)jl_typemap_entry_type); add_builtin("TypeMapLevel", (jl_value_t*)jl_typemap_level_type); - add_builtin("Symbol", (jl_value_t*)jl_sym_type); + add_builtin("Symbol", (jl_value_t*)jl_symbol_type); add_builtin("SSAValue", (jl_value_t*)jl_ssavalue_type); add_builtin("Slot", (jl_value_t*)jl_abstractslot_type); add_builtin("SlotNumber", (jl_value_t*)jl_slotnumber_type); diff --git a/src/codegen.cpp b/src/codegen.cpp index b927dda80d565..03d7bf07a8b67 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -345,6 +345,7 @@ static std::map builtin_func_map; // --- code generation --- extern "C" { int globalUnique = 0; + jl_cgparams_t jl_default_cgparams = {1, 1, 1, 1, 0, NULL, NULL, NULL, NULL, NULL}; } template @@ -2383,7 +2384,7 @@ static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgva // TODO: handle with emit_bitsunion_compare int ptr_comparable = 0; // whether this type is unique'd by pointer - if (rt1 == (jl_value_t*)jl_sym_type || rt2 == (jl_value_t*)jl_sym_type) + if (rt1 == (jl_value_t*)jl_symbol_type || rt2 == (jl_value_t*)jl_symbol_type) ptr_comparable = 1; if (jl_is_mutable_datatype(rt1) && // excludes abstract types rt1 != (jl_value_t*)jl_string_type && // technically mutable, but compared by contents @@ -7637,6 +7638,11 @@ extern "C" void *jl_init_llvm(void) jl_page_size = jl_getpagesize(); imaging_mode = jl_generating_output() && !jl_options.incremental; + jl_default_cgparams.module_setup = jl_nothing; + jl_default_cgparams.module_activation = jl_nothing; + jl_default_cgparams.raise_exception = jl_nothing; + jl_default_cgparams.emit_function = jl_nothing; + jl_default_cgparams.emitted_function = jl_nothing; jl_init_debuginfo(); #ifdef USE_POLLY diff --git a/src/datatype.c b/src/datatype.c index dd2f60769a6de..b420974022d8e 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -223,7 +223,7 @@ unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t) STATIC_INLINE int jl_is_datatype_make_singleton(jl_datatype_t *d) { - return (!d->abstract && jl_datatype_size(d) == 0 && d != jl_sym_type && d->name != jl_array_typename && + return (!d->abstract && jl_datatype_size(d) == 0 && d != jl_symbol_type && d->name != jl_array_typename && d->uid != 0 && !d->mutabl); } @@ -337,7 +337,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) return; uint32_t nfields = jl_svec_len(st->types); if (nfields == 0) { - if (st == jl_sym_type || st == jl_string_type) { + if (st == jl_symbol_type || st == jl_string_type) { // opaque layout - heap-allocated blob static const jl_datatype_layout_t opaque_byte_layout = {0, 1, 0, 1, 0}; st->layout = &opaque_byte_layout; @@ -371,7 +371,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) desc = (jl_fielddesc32_t*)alloca(descsz); int haspadding = 0; assert(st->name == jl_tuple_typename || - st == jl_sym_type || + st == jl_symbol_type || st == jl_simplevector_type || nfields != 0); @@ -623,8 +623,7 @@ void jl_assign_bits(void *dest, jl_value_t *bits) #define PERMBOXN_FUNC(nb,nw) \ jl_value_t *jl_permbox##nb(jl_datatype_t *t, int##nb##_t x) \ - { \ - assert(jl_isbits(t)); \ + { /* NOTE: t must be a concrete isbits datatype */ \ assert(jl_datatype_size(t) == sizeof(x)); \ jl_value_t *v = jl_gc_permobj(nw * sizeof(void*), t); \ *(int##nb##_t*)jl_data_ptr(v) = x; \ diff --git a/src/dump.c b/src/dump.c index 3702f29c16613..b0165607ab491 100644 --- a/src/dump.c +++ b/src/dump.c @@ -68,10 +68,6 @@ static jl_array_t *serializer_worklist JL_GLOBALLY_ROOTED; // (only used by the incremental serializer in MODE_MODULE) htable_t edges_map; -// list of modules being deserialized with __init__ methods -// (not used in MODE_IR) -extern jl_array_t *jl_module_init_order; - #define TAG_SYMBOL 2 #define TAG_SSAVALUE 3 #define TAG_DATATYPE 4 diff --git a/src/gc.c b/src/gc.c index 3706acffc5e3f..08a8771143536 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2477,7 +2477,6 @@ mark: { } } -extern jl_array_t *jl_module_init_order; extern jl_typemap_entry_t *call_cache[N_CALL_CACHE]; extern jl_array_t *jl_all_methods; diff --git a/src/gf.c b/src/gf.c index 1620b5c7a455e..79d2b99a61da6 100644 --- a/src/gf.c +++ b/src/gf.c @@ -133,7 +133,7 @@ JL_DLLEXPORT jl_code_instance_t* jl_set_method_inferred( jl_value_t *inferred_const, jl_value_t *inferred, int32_t const_flags, size_t min_world, size_t max_world); -void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED +jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED { jl_sym_t *sname = jl_symbol(name); if (dt == NULL) { @@ -164,6 +164,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr jl_typemap_insert(&mt->cache, (jl_value_t*)mt, jl_anytuple_type, NULL, jl_emptysvec, (jl_value_t*)mi, 0, &lambda_cache, 1, ~(size_t)0, NULL); JL_GC_POP(); + return dt; } // run type inference on lambda "mi" for given argument types. @@ -1695,7 +1696,7 @@ JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int return jl_false; // indeterminate - ml_matches can't deal with this case jl_methtable_t *mt = dt->name->mt; if (mt == NULL) - return (jl_value_t*)jl_alloc_vec_any(0); + return (jl_value_t*)jl_an_empty_vec_any; return ml_matches(mt->defs, 0, types, lim, include_ambiguous, world, min_valid, max_valid); } diff --git a/src/init.c b/src/init.c index 5f97d46a0b8e3..0c5a52ef32768 100644 --- a/src/init.c +++ b/src/init.c @@ -50,6 +50,9 @@ extern BOOL (WINAPI *hSymRefreshModuleList)(HANDLE); #include #endif +// list of modules being deserialized with __init__ methods +jl_array_t *jl_module_init_order; + #ifdef JL_ASAN_ENABLED JL_DLLEXPORT const char* __asan_default_options() { return "allow_user_segv_handler=1:detect_leaks=0"; @@ -305,8 +308,7 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) #endif } -void jl_get_builtin_hooks(void); -void jl_get_builtins(void); +static void post_boot_hooks(void); JL_DLLEXPORT void *jl_dl_handle; void *jl_RTLD_DEFAULT_handle; @@ -666,6 +668,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.), // best to call this first, since it also initializes libuv jl_init_uv(); + init_stdio(); restore_signals(); jl_page_size = jl_getpagesize(); @@ -738,7 +741,16 @@ void _julia_init(JL_IMAGE_SEARCH rel) } #endif + if ((jl_options.outputo || jl_options.outputbc) && + (jl_options.code_coverage || jl_options.malloc_log)) { + jl_error("cannot generate code-coverage or track allocation information while generating a .o or .bc output file"); + } + jl_init_threading(); + jl_init_intrinsic_properties(); + + jl_gc_init(); + jl_gc_enable(0); jl_resolve_sysimg_location(rel); // loads sysimg if available, and conditionally sets jl_options.cpu_target @@ -747,30 +759,24 @@ void _julia_init(JL_IMAGE_SEARCH rel) if (jl_options.cpu_target == NULL) jl_options.cpu_target = "native"; - jl_gc_init(); - jl_gc_enable(0); - jl_init_types(); - jl_init_frontend(); + arraylist_new(&partial_inst, 0); + if (jl_options.image_file) { + jl_restore_system_image(jl_options.image_file); + } + else { + jl_init_types(); + jl_init_codegen(); + } + jl_init_tasks(); jl_init_root_task(stack_lo, stack_hi); - #ifdef ENABLE_TIMINGS jl_root_task->timing_stack = jl_root_timing; #endif + jl_init_frontend(); - init_stdio(); - // libuv stdio cleanup depends on jl_init_tasks() because JL_TRY is used in jl_atexit_hook() - - if ((jl_options.outputo || jl_options.outputbc) && - (jl_options.code_coverage || jl_options.malloc_log)) { - jl_error("cannot generate code-coverage or track allocation information while generating a .o or .bc output file"); - } - - jl_init_codegen(); - - jl_an_empty_vec_any = (jl_value_t*)jl_alloc_vec_any(0); + jl_an_empty_vec_any = (jl_value_t*)jl_alloc_vec_any(0); // used by ml_matches jl_init_serializer(); - jl_init_intrinsic_properties(); if (!jl_options.image_file) { jl_core_module = jl_new_module(jl_symbol("Core")); @@ -778,44 +784,9 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_top_module = jl_core_module; jl_init_intrinsic_functions(); jl_init_primitives(); - jl_get_builtins(); jl_init_main_module(); - jl_load(jl_core_module, "boot.jl"); - jl_get_builtin_hooks(); - jl_init_box_caches(); - } - - if (jl_options.image_file) { - JL_TRY { - jl_restore_system_image(jl_options.image_file); - } - JL_CATCH { - jl_printf(JL_STDERR, "error during init:\n"); - jl_static_show(JL_STDERR, jl_current_exception()); - jl_printf(JL_STDERR, "\n"); - jl_exit(1); - } - } - - // set module field of primitive types - int i; - void **table = jl_core_module->bindings.table; - for(i=1; i < jl_core_module->bindings.size; i+=2) { - if (table[i] != HT_NOTFOUND) { - jl_binding_t *b = (jl_binding_t*)table[i]; - jl_value_t *v = b->value; - if (v) { - if (jl_is_unionall(v)) - v = jl_unwrap_unionall(v); - if (jl_is_datatype(v)) { - jl_datatype_t *tt = (jl_datatype_t*)v; - tt->name->module = jl_core_module; - if (tt->name->mt) - tt->name->mt->module = jl_core_module; - } - } - } + post_boot_hooks(); } // the Main module is the one which is always open, and set as the @@ -866,7 +837,7 @@ static jl_value_t *core(const char *name) } // fetch references to things defined in boot.jl -void jl_get_builtin_hooks(void) +static void post_boot_hooks(void) { jl_char_type = (jl_datatype_t*)core("Char"); jl_int8_type = (jl_datatype_t*)core("Int8"); @@ -880,6 +851,7 @@ void jl_get_builtin_hooks(void) jl_signed_type = (jl_datatype_t*)core("Signed"); jl_datatype_t *jl_unsigned_type = (jl_datatype_t*)core("Unsigned"); jl_datatype_t *jl_integer_type = (jl_datatype_t*)core("Integer"); + jl_bool_type->super = jl_integer_type; jl_uint8_type->super = jl_unsigned_type; jl_int32_type->super = jl_signed_type; @@ -907,23 +879,28 @@ void jl_get_builtin_hooks(void) jl_weakref_type = (jl_datatype_t*)core("WeakRef"); jl_vecelement_typename = ((jl_datatype_t*)jl_unwrap_unionall(core("VecElement")))->name; -} -void jl_get_builtins(void) -{ - jl_builtin_throw = core("throw"); jl_builtin_is = core("==="); - jl_builtin_typeof = core("typeof"); jl_builtin_sizeof = core("sizeof"); - jl_builtin_issubtype = core("<:"); jl_builtin_isa = core("isa"); - jl_builtin_typeassert = core("typeassert"); jl_builtin__apply = core("_apply"); - jl_builtin_isdefined = core("isdefined"); jl_builtin_nfields = core("nfields"); - jl_builtin_tuple = core("tuple"); jl_builtin_svec = core("svec"); - jl_builtin_getfield = core("getfield"); jl_builtin_setfield = core("setfield!"); - jl_builtin_fieldtype = core("fieldtype"); jl_builtin_arrayref = core("arrayref"); - jl_builtin_const_arrayref = core("const_arrayref"); - jl_builtin_arrayset = core("arrayset"); jl_builtin_arraysize = core("arraysize"); - jl_builtin_apply_type = core("apply_type"); jl_builtin_applicable = core("applicable"); - jl_builtin_invoke = core("invoke"); jl_builtin__expr = core("_expr"); - jl_builtin_ifelse = core("ifelse"); + jl_init_box_caches(); + + // set module field of primitive types + int i; + void **table = jl_core_module->bindings.table; + for (i = 1; i < jl_core_module->bindings.size; i += 2) { + if (table[i] != HT_NOTFOUND) { + jl_binding_t *b = (jl_binding_t*)table[i]; + jl_value_t *v = b->value; + if (v) { + if (jl_is_unionall(v)) + v = jl_unwrap_unionall(v); + if (jl_is_datatype(v)) { + jl_datatype_t *tt = (jl_datatype_t*)v; + tt->name->module = jl_core_module; + if (tt->name->mt) + tt->name->mt->module = jl_core_module; + } + } + } + } } #ifdef __cplusplus diff --git a/src/jltypes.c b/src/jltypes.c index 2e6e193480626..89b3291bc7f15 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -24,7 +24,6 @@ jl_unionall_t *jl_type_type; jl_typename_t *jl_type_typename; jl_methtable_t *jl_type_type_mt; jl_datatype_t *jl_typename_type; -jl_datatype_t *jl_sym_type; jl_datatype_t *jl_symbol_type; jl_datatype_t *jl_ssavalue_type; jl_datatype_t *jl_abstractslot_type; @@ -119,6 +118,7 @@ jl_datatype_t *jl_void_type; jl_datatype_t *jl_voidpointer_type; jl_typename_t *jl_namedtuple_typename; jl_unionall_t *jl_namedtuple_type; +jl_datatype_t *jl_task_type; jl_value_t *jl_an_empty_vec_any; jl_value_t *jl_an_empty_string; jl_value_t *jl_stackovf_exception; @@ -126,16 +126,12 @@ jl_value_t *jl_stackovf_exception; jl_value_t *jl_segv_exception; #endif JL_DLLEXPORT jl_value_t *jl_diverror_exception; -JL_DLLEXPORT jl_value_t *jl_domain_exception; -JL_DLLEXPORT jl_value_t *jl_overflow_exception; JL_DLLEXPORT jl_value_t *jl_undefref_exception; jl_value_t *jl_interrupt_exception; jl_datatype_t *jl_boundserror_type; jl_value_t *jl_memory_exception; jl_value_t *jl_readonlymemory_exception; -jl_cgparams_t jl_default_cgparams = {1, 1, 1, 1, 0, NULL, NULL, NULL, NULL, NULL}; - // --- type properties and predicates --- static int typeenv_has(jl_typeenv_t *env, jl_tvar_t *v) @@ -1656,35 +1652,27 @@ void jl_reset_instantiate_inner_types(jl_datatype_t *t) // initialization ------------------------------------------------------------- +extern void jl_init_int32_int64_cache(void); + static jl_tvar_t *tvar(const char *name) { return jl_new_typevar(jl_symbol(name), (jl_value_t*)jl_bottom_type, (jl_value_t*)jl_any_type); } -extern void jl_init_int32_int64_cache(void); - void jl_init_types(void) JL_GC_DISABLED { jl_module_t *core = NULL; // will need to be assigned later - arraylist_new(&partial_inst, 0); // create base objects jl_datatype_type = jl_new_uninitialized_datatype(); jl_set_typeof(jl_datatype_type, jl_datatype_type); jl_typename_type = jl_new_uninitialized_datatype(); - jl_sym_type = jl_new_uninitialized_datatype(); - jl_symbol_type = jl_sym_type; + jl_symbol_type = jl_new_uninitialized_datatype(); jl_simplevector_type = jl_new_uninitialized_datatype(); jl_methtable_type = jl_new_uninitialized_datatype(); jl_nothing = jl_gc_permobj(0, NULL); - jl_default_cgparams.module_setup = jl_nothing; - jl_default_cgparams.module_activation = jl_nothing; - jl_default_cgparams.raise_exception = jl_nothing; - jl_default_cgparams.emit_function = jl_nothing; - jl_default_cgparams.emitted_function = jl_nothing; - jl_emptysvec = (jl_svec_t*)jl_gc_permobj(sizeof(void*), jl_simplevector_type); jl_svec_set_len_unsafe(jl_emptysvec, 0); @@ -1751,7 +1739,7 @@ void jl_init_types(void) JL_GC_DISABLED "names", "wrapper", "cache", "linearcache", "hash", "mt"); - jl_typename_type->types = jl_svec(8, jl_sym_type, jl_any_type, jl_simplevector_type, + jl_typename_type->types = jl_svec(8, jl_symbol_type, jl_any_type, jl_simplevector_type, jl_type_type, jl_simplevector_type, jl_simplevector_type, jl_any_type, jl_any_type); jl_typename_type->uid = jl_assign_type_uid(); @@ -1772,7 +1760,7 @@ void jl_init_types(void) JL_GC_DISABLED "cache", "max_args", "kwsorter", "module", "backedges", "", "", "offs"); - jl_methtable_type->types = jl_svec(10, jl_sym_type, jl_any_type, jl_any_type, jl_any_type/*jl_long*/, + jl_methtable_type->types = jl_svec(10, jl_symbol_type, jl_any_type, jl_any_type, jl_any_type/*jl_long*/, jl_any_type, jl_any_type/*module*/, jl_any_type/*any vector*/, jl_any_type/*long*/, jl_any_type/*int32*/, jl_any_type/*uint8*/); @@ -1785,22 +1773,22 @@ void jl_init_types(void) JL_GC_DISABLED jl_methtable_type->ninitialized = 4; jl_precompute_memoized_dt(jl_methtable_type); - jl_sym_type->name = jl_new_typename_in(jl_symbol("Symbol"), core); - jl_sym_type->name->wrapper = (jl_value_t*)jl_sym_type; - jl_sym_type->name->mt = jl_new_method_table(jl_sym_type->name->name, core); - jl_sym_type->super = jl_any_type; - jl_sym_type->parameters = jl_emptysvec; - jl_sym_type->name->names = jl_emptysvec; - jl_sym_type->types = jl_emptysvec; - jl_sym_type->instance = NULL; - jl_sym_type->uid = jl_assign_type_uid(); - jl_sym_type->struct_decl = NULL; - jl_sym_type->ditype = NULL; - jl_sym_type->size = 0; - jl_sym_type->abstract = 0; - jl_sym_type->mutabl = 1; - jl_sym_type->ninitialized = 0; - jl_precompute_memoized_dt(jl_sym_type); + jl_symbol_type->name = jl_new_typename_in(jl_symbol("Symbol"), core); + jl_symbol_type->name->wrapper = (jl_value_t*)jl_symbol_type; + jl_symbol_type->name->mt = jl_new_method_table(jl_symbol_type->name->name, core); + jl_symbol_type->super = jl_any_type; + jl_symbol_type->parameters = jl_emptysvec; + jl_symbol_type->name->names = jl_emptysvec; + jl_symbol_type->types = jl_emptysvec; + jl_symbol_type->instance = NULL; + jl_symbol_type->uid = jl_assign_type_uid(); + jl_symbol_type->struct_decl = NULL; + jl_symbol_type->ditype = NULL; + jl_symbol_type->size = 0; + jl_symbol_type->abstract = 0; + jl_symbol_type->mutabl = 1; + jl_symbol_type->ninitialized = 0; + jl_precompute_memoized_dt(jl_symbol_type); jl_simplevector_type->name = jl_new_typename_in(jl_symbol("SimpleVector"), core); jl_simplevector_type->name->wrapper = (jl_value_t*)jl_simplevector_type; @@ -1837,7 +1825,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(3, "name", "lb", "ub"), - jl_svec(3, jl_sym_type, jl_any_type, jl_any_type), + jl_svec(3, jl_symbol_type, jl_any_type, jl_any_type), 0, 1, 3); jl_unionall_type = jl_new_datatype(jl_symbol("UnionAll"), core, type_type, jl_emptysvec, @@ -1991,7 +1979,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_compute_field_offsets((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_array_type)); jl_array_any_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_any_type, jl_box_long(1)); - jl_array_symbol_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_sym_type, jl_box_long(1)); + jl_array_symbol_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_symbol_type, jl_box_long(1)); jl_array_uint8_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_uint8_type, jl_box_long(1)); jl_array_int32_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_int32_type, jl_box_long(1)); @@ -1999,13 +1987,13 @@ void jl_init_types(void) JL_GC_DISABLED jl_new_datatype(jl_symbol("Expr"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "head", "args"), - jl_svec(2, jl_sym_type, jl_array_any_type), + jl_svec(2, jl_symbol_type, jl_array_any_type), 0, 1, 2); jl_module_type = jl_new_datatype(jl_symbol("Module"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "name", "parent"), - jl_svec(2, jl_sym_type, jl_any_type), 0, 1, 2); + jl_svec(2, jl_symbol_type, jl_any_type), 0, 1, 2); jl_linenumbernode_type = jl_new_datatype(jl_symbol("LineNumberNode"), core, jl_any_type, jl_emptysvec, @@ -2015,7 +2003,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_lineinfonode_type = jl_new_datatype(jl_symbol("LineInfoNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(4, "method", "file", "line", "inlined_at"), - jl_svec(4, jl_any_type, jl_sym_type, jl_long_type, jl_long_type), 0, 0, 4); + jl_svec(4, jl_any_type, jl_symbol_type, jl_long_type, jl_long_type), 0, 0, 4); jl_gotonode_type = jl_new_datatype(jl_symbol("GotoNode"), core, jl_any_type, jl_emptysvec, @@ -2055,7 +2043,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_globalref_type = jl_new_datatype(jl_symbol("GlobalRef"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "mod", "name"), - jl_svec(2, jl_module_type, jl_sym_type), 0, 0, 2); + jl_svec(2, jl_module_type, jl_symbol_type), 0, 0, 2); jl_code_info_type = jl_new_datatype(jl_symbol("CodeInfo"), core, @@ -2123,9 +2111,9 @@ void jl_init_types(void) JL_GC_DISABLED "isva", "pure"), jl_svec(20, - jl_sym_type, + jl_symbol_type, jl_module_type, - jl_sym_type, + jl_symbol_type, jl_int32_type, jl_long_type, jl_long_type, @@ -2236,6 +2224,39 @@ void jl_init_types(void) JL_GC_DISABLED ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_namedtuple_type))->layout = NULL; jl_namedtuple_typename = ntt->name; + jl_task_type = (jl_datatype_t*) + jl_new_datatype(jl_symbol("Task"), + NULL, + jl_any_type, + jl_emptysvec, + jl_perm_symsvec(11, + "next", + "queue", + "storage", + "state", + "donenotify", + "result", + "exception", + "backtrace", + "logstate", + "code", + "sticky"), + jl_svec(11, + jl_any_type, + jl_any_type, + jl_any_type, + jl_symbol_type, + jl_any_type, + jl_any_type, + jl_any_type, + jl_any_type, + jl_any_type, + jl_any_type, + jl_bool_type), + 0, 1, 9); + jl_value_t *listt = jl_new_struct(jl_uniontype_type, jl_task_type, jl_void_type); + jl_svecset(jl_task_type->types, 0, listt); + // complete builtin type metadata jl_value_t *pointer_void = jl_apply_type1((jl_value_t*)jl_pointer_type, (jl_value_t*)jl_void_type); jl_voidpointer_type = (jl_datatype_t*)pointer_void; @@ -2291,7 +2312,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_compute_field_offsets(jl_code_instance_type); jl_compute_field_offsets(jl_unionall_type); jl_compute_field_offsets(jl_simplevector_type); - jl_compute_field_offsets(jl_sym_type); + jl_compute_field_offsets(jl_symbol_type); } #ifdef __cplusplus diff --git a/src/julia.h b/src/julia.h index c8115f8b1252b..82d8aed5c60f5 100644 --- a/src/julia.h +++ b/src/julia.h @@ -552,7 +552,6 @@ extern JL_DLLEXPORT jl_unionall_t *jl_type_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_unionall_t *jl_typetype_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_typename_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_typename_t *jl_type_typename JL_GLOBALLY_ROOTED; -extern JL_DLLEXPORT jl_datatype_t *jl_sym_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_symbol_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_ssavalue_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_abstractslot_type JL_GLOBALLY_ROOTED; @@ -567,7 +566,6 @@ extern JL_DLLEXPORT jl_datatype_t *jl_emptytuple_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_unionall_t *jl_anytuple_type_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_unionall_t *jl_vararg_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_typename_t *jl_vararg_typename JL_GLOBALLY_ROOTED; -extern JL_DLLEXPORT jl_datatype_t *jl_task_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_function_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_builtin_type JL_GLOBALLY_ROOTED; @@ -625,6 +623,7 @@ extern JL_DLLEXPORT jl_unionall_t *jl_ref_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_typename_t *jl_pointer_typename JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_typename_t *jl_namedtuple_typename JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_unionall_t *jl_namedtuple_type JL_GLOBALLY_ROOTED; +extern JL_DLLEXPORT jl_datatype_t *jl_task_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_value_t *jl_array_uint8_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_value_t *jl_array_any_type JL_GLOBALLY_ROOTED; @@ -997,7 +996,7 @@ static inline int jl_is_layout_opaque(const jl_datatype_layout_t *l) JL_NOTSAFEP #define jl_is_uint32(v) jl_typeis(v,jl_uint32_type) #define jl_is_uint64(v) jl_typeis(v,jl_uint64_type) #define jl_is_bool(v) jl_typeis(v,jl_bool_type) -#define jl_is_symbol(v) jl_typeis(v,jl_sym_type) +#define jl_is_symbol(v) jl_typeis(v,jl_symbol_type) #define jl_is_ssavalue(v) jl_typeis(v,jl_ssavalue_type) #define jl_is_slot(v) (jl_typeis(v,jl_slotnumber_type) || jl_typeis(v,jl_typedslot_type)) #define jl_is_expr(v) jl_typeis(v,jl_expr_type) diff --git a/src/julia_internal.h b/src/julia_internal.h index 7c690254316d7..47dfc8ceed711 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -422,7 +422,7 @@ int jl_has_concrete_subtype(jl_value_t *typ) JL_NOTSAFEPOINT; jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np) JL_ALWAYS_LEAFTYPE; jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p) JL_ALWAYS_LEAFTYPE; JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype); -void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED; +jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED; jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, int *issubty); jl_value_t *jl_type_intersection_env(jl_value_t *a, jl_value_t *b, jl_svec_t **penv); int jl_subtype_matching(jl_value_t *a, jl_value_t *b, jl_svec_t **penv); diff --git a/src/rtutils.c b/src/rtutils.c index 2275dbb7bf71b..17389bfa91714 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -600,7 +600,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt else if (v == (jl_value_t*)jl_typename_type) { n += jl_printf(out, "Core.TypeName"); } - else if (v == (jl_value_t*)jl_sym_type) { + else if (v == (jl_value_t*)jl_symbol_type) { n += jl_printf(out, "Symbol"); } else if (v == (jl_value_t*)jl_methtable_type) { @@ -820,7 +820,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt } n += jl_printf(out, "%s", jl_symbol_name(m->name)); } - else if (vt == jl_sym_type) { + else if (vt == jl_symbol_type) { char *sn = jl_symbol_name((jl_sym_t*)v); int quoted = !jl_is_identifier(sn) && jl_operator_precedence(sn) == 0; if (quoted) diff --git a/src/staticdata.c b/src/staticdata.c index e41d377cdc231..bf5f9aae20654 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -30,53 +30,93 @@ extern "C" { // TODO: put WeakRefs on the weak_refs list during deserialization // TODO: handle finalizers +// An array of references that need to be restored from the sysimg +// This is a manually constructed dual of the gvars array, which would be produced by codegen for Julia code, for C. +static void *const _tags[] = { + // builtin types + &jl_any_type, &jl_symbol_type, &jl_ssavalue_type, &jl_datatype_type, &jl_slotnumber_type, + &jl_simplevector_type, &jl_array_type, &jl_typedslot_type, + &jl_expr_type, &jl_globalref_type, &jl_string_type, + &jl_module_type, &jl_tvar_type, &jl_method_instance_type, &jl_method_type, &jl_code_instance_type, + &jl_linenumbernode_type, &jl_lineinfonode_type, + &jl_gotonode_type, &jl_quotenode_type, + &jl_pinode_type, &jl_phinode_type, &jl_phicnode_type, &jl_upsilonnode_type, + &jl_type_type, &jl_bottom_type, &jl_ref_type, &jl_pointer_type, + &jl_vararg_type, &jl_abstractarray_type, + &jl_densearray_type, &jl_void_type, &jl_function_type, &jl_typeofbottom_type, + &jl_unionall_type, &jl_typename_type, &jl_builtin_type, &jl_code_info_type, + &jl_task_type, &jl_uniontype_type, &jl_typetype_type, &jl_abstractstring_type, + &jl_array_any_type, &jl_intrinsic_type, &jl_abstractslot_type, + &jl_methtable_type, &jl_typemap_level_type, &jl_typemap_entry_type, + &jl_voidpointer_type, &jl_newvarnode_type, + &jl_anytuple_type_type, &jl_anytuple_type, &jl_namedtuple_type, &jl_emptytuple_type, + &jl_array_symbol_type, &jl_array_uint8_type, &jl_array_int32_type, + &jl_int32_type, &jl_int64_type, &jl_bool_type, &jl_uint8_type, + &jl_uint32_type, &jl_uint64_type, &jl_char_type, &jl_weakref_type, + &jl_int8_type, &jl_int16_type, &jl_uint16_type, + &jl_float16_type, &jl_float32_type, &jl_float64_type, &jl_floatingpoint_type, + &jl_number_type, &jl_signed_type, + // special typenames + &jl_tuple_typename, &jl_pointer_typename, &jl_array_typename, &jl_type_typename, + &jl_vararg_typename, &jl_namedtuple_typename, + &jl_vecelement_typename, + // special exceptions + &jl_errorexception_type, &jl_argumenterror_type, &jl_typeerror_type, + &jl_methoderror_type, &jl_loaderror_type, &jl_initerror_type, + &jl_undefvarerror_type, &jl_stackovf_exception, &jl_diverror_exception, + &jl_interrupt_exception, &jl_boundserror_type, &jl_memory_exception, + &jl_undefref_exception, &jl_readonlymemory_exception, +#ifdef SEGV_EXCEPTION + &jl_segv_exception, +#endif + // other special values + &jl_emptysvec, &jl_emptytuple, &jl_false, &jl_true, &jl_nothing, &jl_an_empty_string, + &jl_module_init_order, &jl_core_module, &jl_base_module, &jl_main_module, &jl_top_module, + &jl_typeinf_func, &jl_type_type_mt, + // some Core.Builtin Functions that we want to be able to reference: + &jl_builtin_throw, &jl_builtin_is, &jl_builtin_typeof, &jl_builtin_sizeof, + &jl_builtin_issubtype, &jl_builtin_isa, &jl_builtin_typeassert, &jl_builtin__apply, + &jl_builtin_isdefined, &jl_builtin_nfields, &jl_builtin_tuple, &jl_builtin_svec, + &jl_builtin_getfield, &jl_builtin_setfield, &jl_builtin_fieldtype, &jl_builtin_arrayref, + &jl_builtin_const_arrayref, &jl_builtin_arrayset, &jl_builtin_arraysize, + &jl_builtin_apply_type, &jl_builtin_applicable, &jl_builtin_invoke, + &jl_builtin__expr, &jl_builtin_ifelse, + NULL }; +static jl_value_t **const*const tags = (jl_value_t**const*const)_tags; + // hash of definitions for predefined tagged object -static htable_t sertag_table; static htable_t symbol_table; static uintptr_t nsym_tag; // array of definitions for the predefined tagged object types -// (reverse of sertag_table and symbol_table) -static arraylist_t deser_tag; +// (reverse of symbol_table) static arraylist_t deser_sym; // table of all objects that are serialized static htable_t backref_table; static int backref_table_numel; static arraylist_t layout_table; +static arraylist_t builtin_typenames; // list of (size_t pos, (void *f)(jl_value_t*)) entries // for the serializer to mark values in need of rework by function f // during deserialization later static arraylist_t reinit_list; -// list of modules being deserialized with __init__ methods -// (not used in MODE_AST) -jl_array_t *jl_module_init_order; - // hash of definitions for predefined function pointers static htable_t fptr_to_id; // array of definitions for the predefined function pointers // (reverse of fptr_to_id) +// This is a manually constructed dual of the fvars array, which would be produced by codegen for Julia code, for C. static const jl_fptr_args_t id_to_fptrs[] = { - jl_f_throw, jl_f_is, jl_f_typeof, jl_f_issubtype, jl_f_isa, - jl_f_typeassert, jl_f__apply, jl_f__apply_pure, jl_f__apply_latest, jl_f_isdefined, - jl_f_tuple, jl_f_svec, jl_f_intrinsic_call, jl_f_invoke_kwsorter, - jl_f_getfield, jl_f_setfield, jl_f_fieldtype, jl_f_nfields, - jl_f_arrayref, jl_f_const_arrayref, jl_f_arrayset, jl_f_arraysize, jl_f_apply_type, - jl_f_applicable, jl_f_invoke, jl_f_sizeof, jl_f__expr, jl_f__typevar, - jl_f_ifelse, + &jl_f_throw, &jl_f_is, &jl_f_typeof, &jl_f_issubtype, &jl_f_isa, + &jl_f_typeassert, &jl_f__apply, &jl_f__apply_pure, &jl_f__apply_latest, &jl_f_isdefined, + &jl_f_tuple, &jl_f_svec, &jl_f_intrinsic_call, &jl_f_invoke_kwsorter, + &jl_f_getfield, &jl_f_setfield, &jl_f_fieldtype, &jl_f_nfields, + &jl_f_arrayref, &jl_f_const_arrayref, &jl_f_arrayset, &jl_f_arraysize, &jl_f_apply_type, + &jl_f_applicable, &jl_f_invoke, &jl_f_sizeof, &jl_f__expr, &jl_f__typevar, + &jl_f_ifelse, NULL }; -typedef enum _DUMP_MODES { - // not in the serializer at all, or - // something is seriously wrong - MODE_INVALID = 0, - - // jl_restore_system_image - // restoring an entire system image from disk - MODE_SYSTEM_IMAGE, -} DUMP_MODES; - typedef struct { ios_t *s; ios_t *const_data; @@ -86,7 +126,6 @@ typedef struct { ios_t *fptr_record; arraylist_t relocs_list; arraylist_t gctags_list; - DUMP_MODES mode; jl_ptls_t ptls; } jl_serializer_state; @@ -94,7 +133,6 @@ static jl_value_t *jl_idtable_type = NULL; static jl_typename_t *jl_idtable_typename = NULL; static jl_value_t *jl_bigint_type = NULL; static int gmp_limb_size = 0; -static arraylist_t builtin_typenames; enum RefTags { DataRef, @@ -242,14 +280,31 @@ static void jl_serialize_module(jl_serializer_state *s, jl_module_t *m) } +#define NBOX_C 1024 + static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) { + // ignore items that are given a special representation if (v == NULL || jl_is_symbol(v)) { return; } - - void *builtin = ptrhash_get(&sertag_table, v); - if (builtin != HT_NOTFOUND) { + else if (jl_typeis(v, jl_task_type)) { + if (v == (jl_value_t*)s->ptls->root_task) { + jl_serialize_value(s, ((jl_task_t*)v)->tls); + return; + } + } + else if (jl_typeis(v, jl_int64_type)) { + int64_t i64 = *(int64_t*)v + NBOX_C / 2; + if ((uint64_t)i64 < NBOX_C) + return; + } + else if (jl_typeis(v, jl_int32_type)) { + int32_t i32 = *(int32_t*)v + NBOX_C / 2; + if ((uint32_t)i32 < NBOX_C) + return; + } + else if (jl_typeis(v, jl_uint8_type)) { return; } @@ -290,9 +345,6 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) else if (jl_typeis(v, jl_module_type)) { jl_serialize_module(s, (jl_module_t*)v); } - else if (jl_typeis(v, jl_task_type)) { - jl_error("Task cannot be serialized"); - } else { char *data = (char*)jl_data_ptr(v); size_t i, nf = jl_datatype_nfields(t); @@ -364,8 +416,22 @@ static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v) JL_NOTSAFEPO *pidx = idx; } } - else { - idx = ptrhash_get(&sertag_table, v); + else if (v == (jl_value_t*)s->ptls->root_task) { + return (uintptr_t)TagRef << RELOC_TAG_OFFSET; + } + else if (jl_typeis(v, jl_int64_type)) { + int64_t i64 = *(int64_t*)v + NBOX_C / 2; + if ((uint64_t)i64 < NBOX_C) + return ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + i64 + 1; + } + else if (jl_typeis(v, jl_int32_type)) { + int32_t i32 = *(int32_t*)v + NBOX_C / 2; + if ((uint32_t)i32 < NBOX_C) + return ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + i32 + 1 + NBOX_C; + } + else if (jl_typeis(v, jl_uint8_type)) { + uint8_t u8 = *(uint8_t*)v; + return ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + u8 + 1 + NBOX_C + NBOX_C; } if (idx == HT_NOTFOUND) { idx = ptrhash_get(&backref_table, v); @@ -609,7 +675,7 @@ static void jl_write_values(jl_serializer_state *s) jl_write_module(s, item, (jl_module_t*)v); // will need to recreate the binding table for this arraylist_push(&reinit_list, (void*)item); - arraylist_push(&reinit_list, (void*)5); + arraylist_push(&reinit_list, (void*)2); } else if (jl_typeis(v, jl_task_type)) { jl_error("Task cannot be serialized"); @@ -617,7 +683,7 @@ static void jl_write_values(jl_serializer_state *s) else if (jl_is_svec(v)) { ios_write(s->s, (char*)v, sizeof(void*)); size_t i, l = jl_svec_len(v); - assert(l > 0); + assert(l > 0 || (jl_svec_t*)v == jl_emptysvec); for (i = 0; i < l; i++) { write_pointerfield(s, jl_svecref(v, i)); } @@ -797,6 +863,31 @@ static void jl_write_gv_syms(jl_serializer_state *s, jl_sym_t *v) jl_write_gv_syms(s, v->right); } +static void jl_write_gv_int(jl_serializer_state *s, jl_value_t *v) +{ + int32_t gv = jl_get_llvm_gv((jl_value_t*)v); + if (gv != 0) { + uintptr_t item = backref_id(s, v); + assert(item >> RELOC_TAG_OFFSET == TagRef); + record_gvar(s, gv, item); + } +} +static void jl_write_gv_ints(jl_serializer_state *s) +{ + // this also ensures all objects referenced in the code have + // references in the system image to their global variable + // since codegen knows that some integer boxes are static, + // they might not have had a reference anywhere in the code + // image other than here + size_t i; + for (i = 0; i < NBOX_C; i++) { + jl_write_gv_int(s, jl_box_int32((int32_t)i - NBOX_C / 2)); + jl_write_gv_int(s, jl_box_int64((int64_t)i - NBOX_C / 2)); + } + for (i = 0; i < 256; i++) { + jl_write_gv_int(s, jl_box_uint8(i)); + } +} static inline uint32_t load_uint32(uintptr_t *base) { @@ -841,12 +932,12 @@ static uintptr_t get_reloc_for_item(uintptr_t reloc_item, size_t reloc_offset) switch (tag) { case ConstDataRef: break; - case TagRef: - assert(offset >= 2 && offset < deser_tag.len && deser_tag.items[offset] && "corrupt relocation item id"); - break; case SymbolRef: assert(offset < nsym_tag && "corrupt relocation item id"); break; + case TagRef: + assert(offset < 2 * NBOX_C + 257 && "corrupt relocation item id"); + break; case BindingRef: assert(offset == 0 && "corrupt relocation offset"); break; @@ -858,7 +949,7 @@ static uintptr_t get_reloc_for_item(uintptr_t reloc_item, size_t reloc_offset) break; case DataRef: default: - assert("corrupt relocation item id"); + assert(0 && "corrupt relocation item id"); abort(); } #endif @@ -873,18 +964,29 @@ static inline uintptr_t get_item_for_reloc(jl_serializer_state *s, uintptr_t bas size_t offset = (reloc_id & (((uintptr_t)1 << RELOC_TAG_OFFSET) - 1)); switch (tag) { case DataRef: - assert(offset < size); + assert(offset <= size); return base + offset; case ConstDataRef: - return (uintptr_t)deser_tag.items[0] + (offset * sizeof(void*)); - case TagRef: - assert(offset < deser_tag.len && deser_tag.items[offset] && "corrupt relocation item id"); - return (uintptr_t)deser_tag.items[offset]; + return (uintptr_t)s->const_data->buf + (offset * sizeof(void*)); case SymbolRef: assert(offset < deser_sym.len && deser_sym.items[offset] && "corrupt relocation item id"); return (uintptr_t)deser_sym.items[offset]; case BindingRef: return jl_buff_tag | GC_OLD_MARKED; + case TagRef: + if (offset == 0) + return (uintptr_t)s->ptls->root_task; + offset -= 1; + if (offset < NBOX_C) + return (uintptr_t)jl_box_int64((int64_t)offset - NBOX_C / 2); + offset -= NBOX_C; + if (offset < NBOX_C) + return (uintptr_t)jl_box_int32((int32_t)offset - NBOX_C / 2); + offset -= NBOX_C; + if (offset < 256) + return (uintptr_t)jl_box_uint8(offset); + offset -= 256; + assert(0 && "corrupt relocation item id"); case BuiltinFunctionRef: assert(offset < sizeof(id_to_fptrs) / sizeof(*id_to_fptrs) && "unknown function pointer ID"); return (uintptr_t)id_to_fptrs[offset]; @@ -1074,15 +1176,6 @@ static void jl_update_all_gvars(jl_serializer_state *s) static void jl_finalize_serializer(jl_serializer_state *s) { size_t i, l; - // save module initialization order - if (jl_module_init_order != NULL) { - l = jl_array_len(jl_module_init_order); - for (i = 0; i < l; i++) { - // verify that all these modules were saved - assert(ptrhash_get(&backref_table, jl_array_ptr_ref(jl_module_init_order, i)) != HT_NOTFOUND); - } - } - jl_write_value(s, jl_module_init_order); // record list of reinitialization functions l = reinit_list.len; @@ -1097,91 +1190,43 @@ static void jl_finalize_serializer(jl_serializer_state *s) } -void jl_typemap_rehash(jl_typemap_t *ml, int8_t offs); -static void jl_reinit_item(jl_value_t *v, int how, arraylist_t *tracee_list) +static void jl_reinit_item(jl_value_t *v, int how) { - JL_TRY { - switch (how) { - case 1: { // rehash IdDict - jl_array_t **a = (jl_array_t**)v; - assert(jl_is_array(*a)); - // Assume *a don't need a write barrier - *a = jl_idtable_rehash(*a, jl_array_len(*a)); - jl_gc_wb(v, *a); - break; - } - case 2: { // reinsert module v into parent (const) - jl_module_t *mod = (jl_module_t*)v; - assert(jl_is_module(mod)); - jl_binding_t *b = jl_get_binding_wr(mod->parent, mod->name, 1); - jl_declare_constant(b); // this can throw - if (b->value != NULL) { - if (!jl_is_module(b->value)) { - jl_errorf("Invalid redefinition of constant %s.", - jl_symbol_name(mod->name)); // this also throws - } - if (jl_generating_output() && jl_options.incremental) { - jl_errorf("Cannot replace module %s during incremental precompile.", jl_symbol_name(mod->name)); - } - jl_printf(JL_STDERR, "WARNING: replacing module %s.\n", - jl_symbol_name(mod->name)); - } - b->value = v; - jl_gc_wb_binding(b, v); - break; - } - case 3: { // rehash MethodTable - jl_methtable_t *mt = (jl_methtable_t*)v; - assert(jl_is_mtable(mt)); - jl_typemap_rehash(mt->defs, 0); - // TODO: consider reverting this when we can split on Type{...} better - jl_typemap_rehash(mt->cache, 1); //(mt == jl_type_typename->mt) ? 0 : 1); - if (tracee_list) - arraylist_push(tracee_list, mt); - break; - } - case 4: { // rehash specializations tfunc - jl_method_t *m = (jl_method_t*)v; - assert(jl_is_method(m)); - jl_typemap_rehash(m->specializations, 0); - break; - } - case 5: { // rebuild the binding table for module v - jl_module_t *mod = (jl_module_t*)v; - assert(jl_is_module(mod)); - size_t nbindings = mod->bindings.size; - htable_new(&mod->bindings, nbindings); - struct binding { - uintptr_t tag; - jl_binding_t b; - } *b; - b = (struct binding*)&mod[1]; - while (nbindings > 0) { - ptrhash_put(&mod->bindings, (char*)b->b.name, &b->b); - b += 1; - nbindings -= 1; - } - break; + switch (how) { + case 1: { // rehash IdDict + jl_array_t **a = (jl_array_t**)v; + assert(jl_is_array(*a)); + // Assume *a don't need a write barrier + *a = jl_idtable_rehash(*a, jl_array_len(*a)); + jl_gc_wb(v, *a); + break; + } + case 2: { // rebuild the binding table for module v + jl_module_t *mod = (jl_module_t*)v; + assert(jl_is_module(mod)); + size_t nbindings = mod->bindings.size; + htable_new(&mod->bindings, nbindings); + struct binding { + uintptr_t tag; + jl_binding_t b; + } *b; + b = (struct binding*)&mod[1]; + while (nbindings > 0) { + ptrhash_put(&mod->bindings, (char*)b->b.name, &b->b); + b += 1; + nbindings -= 1; } - default: - assert(0 && "corrupt deserialization state"); - abort(); + break; } - } - JL_CATCH { - jl_printf(JL_STDERR, "WARNING: error while reinitializing value "); - jl_static_show(JL_STDERR, v); - jl_printf(JL_STDERR, ":\n"); - jl_static_show(JL_STDERR, jl_current_exception()); - jl_printf(JL_STDERR, "\n"); + default: + assert(0 && "corrupt deserialization state"); + abort(); } } -static jl_array_t *jl_finalize_deserializer(jl_serializer_state *s, arraylist_t *tracee_list) +static void jl_finalize_deserializer(jl_serializer_state *s) { - jl_array_t *init_order = (jl_array_t*)jl_read_value(s); - // run reinitialization functions uintptr_t base = (uintptr_t)&s->s->buf[0]; while (1) { @@ -1189,9 +1234,8 @@ static jl_array_t *jl_finalize_deserializer(jl_serializer_state *s, arraylist_t if (offset == 0) break; jl_value_t *v = (jl_value_t*)(base + offset); - jl_reinit_item(v, read_uint32(s->s), tracee_list); + jl_reinit_item(v, read_uint32(s->s)); } - return init_order; } @@ -1249,7 +1293,6 @@ static void jl_save_system_image_to_stream(ios_t *f) s.relocs = &relocs; s.gvar_record = &gvar_record; s.fptr_record = &fptr_record; - s.mode = MODE_SYSTEM_IMAGE; s.ptls = jl_get_ptls_states(); arraylist_new(&s.relocs_list, 0); arraylist_new(&s.gctags_list, 0); @@ -1271,27 +1314,20 @@ static void jl_save_system_image_to_stream(ios_t *f) } { // step 1: record values (recursively) that need to go in the image - jl_serialize_value(&s, jl_core_module); - jl_serialize_value(&s, jl_main_module); - jl_serialize_value(&s, jl_top_module); - jl_serialize_value(&s, jl_typeinf_func); - jl_serialize_value(&s, jl_module_init_order); - - // serialize method tables of builtin types - jl_serialize_value(&s, jl_type_typename->mt); - jl_serialize_value(&s, jl_intrinsic_type->name->mt); - jl_serialize_value(&s, jl_sym_type->name->mt); - jl_serialize_value(&s, jl_array_typename->mt); - jl_serialize_value(&s, jl_module_type->name->mt); - - jl_prune_type_cache(jl_tuple_typename->cache); - jl_prune_type_cache(jl_tuple_typename->linearcache); - jl_prune_type_cache(jl_type_typename->cache); - - uintptr_t i; + size_t i; + for (i = 0; tags[i] != NULL; i++) { + jl_value_t *tag = *tags[i]; + jl_serialize_value(&s, tag); + } for (i = 0; i < builtin_typenames.len; i++) { - jl_serialize_value(&s, ((jl_typename_t*)builtin_typenames.items[i])->cache); - jl_serialize_value(&s, ((jl_typename_t*)builtin_typenames.items[i])->linearcache); + jl_typename_t *tn = (jl_typename_t*)builtin_typenames.items[i]; + jl_prune_type_cache(tn->cache); + jl_prune_type_cache(tn->linearcache); + } + for (i = 0; i < builtin_typenames.len; i++) { + jl_typename_t *tn = (jl_typename_t*)builtin_typenames.items[i]; + jl_serialize_value(&s, tn->cache); + jl_serialize_value(&s, tn->linearcache); } } @@ -1300,12 +1336,7 @@ static void jl_save_system_image_to_stream(ios_t *f) jl_write_values(&s); jl_write_relocations(&s); jl_write_gv_syms(&s, jl_get_root_symbol()); - // ensure everything in deser_tag are reassociated with their GlobalValue - uintptr_t i; - for (i = 0; i < deser_tag.len; i++) { - jl_value_t *v = (jl_value_t*)deser_tag.items[i]; - record_gvar(&s, jl_get_llvm_gv(v), ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + i); - } + jl_write_gv_ints(&s); } // step 3: combine all of the sections into one file @@ -1343,24 +1374,17 @@ static void jl_save_system_image_to_stream(ios_t *f) { // step 4: record locations of special roots s.s = f; - jl_finalize_serializer(&s); - jl_write_value(&s, jl_main_module); - jl_write_value(&s, jl_top_module); - jl_write_value(&s, jl_typeinf_func); - write_uint32(f, jl_typeinf_world); - jl_write_value(&s, jl_type_typename->mt); - jl_write_value(&s, jl_intrinsic_type->name->mt); - jl_write_value(&s, jl_sym_type->name->mt); - jl_write_value(&s, jl_array_typename->mt); - jl_write_value(&s, jl_module_type->name->mt); - uintptr_t i; - for (i = 0; i < builtin_typenames.len; i++) { - jl_write_value(&s, ((jl_typename_t*)builtin_typenames.items[i])->cache); - jl_write_value(&s, ((jl_typename_t*)builtin_typenames.items[i])->linearcache); + size_t i; + for (i = 0; tags[i] != NULL; i++) { + jl_value_t *tag = *tags[i]; + jl_write_value(&s, tag); } + jl_write_value(&s, s.ptls->root_task->tls); write_uint32(f, jl_get_t_uid_ctr()); write_uint32(f, jl_get_gs_ctr()); write_uint32(f, jl_world_counter); + write_uint32(f, jl_typeinf_world); + jl_finalize_serializer(&s); } arraylist_free(&layout_table); @@ -1393,8 +1417,7 @@ JL_DLLEXPORT void jl_save_system_image(const char *fname) JL_SIGATOMIC_END(); } -extern void jl_get_builtins(void); -extern void jl_get_builtin_hooks(void); +extern void jl_init_int32_int64_cache(void); extern void jl_gc_set_permalloc_region(void *start, void *end); // Takes in a path of the form "usr/lib/julia/sys.so" (jl_restore_system_image should be passed the same string) @@ -1431,23 +1454,17 @@ static void jl_restore_system_image_from_stream(ios_t *f) jl_init_serializer2(0); ios_t sysimg, const_data, symbols, relocs, gvar_record, fptr_record; jl_serializer_state s; - s.s = &sysimg; + s.s = NULL; s.const_data = &const_data; s.symbols = &symbols; s.relocs = &relocs; s.gvar_record = &gvar_record; s.fptr_record = &fptr_record; - s.mode = MODE_SYSTEM_IMAGE; s.ptls = jl_get_ptls_states(); arraylist_new(&s.relocs_list, 0); arraylist_new(&s.gctags_list, 0); - jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL; - if (jl_bigint_type) { - gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")), - jl_symbol("BITS_PER_LIMB"))) / 8; - } - // step 1: read section map and apply relocations + // step 1: read section map assert(ios_pos(f) == 0 && f->bm == bm_mem); size_t sizeof_sysimg = read_uint32(f); ios_static_buffer(&sysimg, f->buf, sizeof_sysimg + sizeof(uint32_t)); @@ -1478,6 +1495,28 @@ static void jl_restore_system_image_from_stream(ios_t *f) ios_static_buffer(&fptr_record, f->buf + f->bpos, sizeof_fptr_record); ios_skip(f, sizeof_fptr_record); + // step 2: get references to special values + s.s = f; + size_t i; + for (i = 0; tags[i] != NULL; i++) { + jl_value_t **tag = tags[i]; + *tag = jl_read_value(&s); + } + s.ptls->root_task = (jl_task_t*)jl_gc_alloc(s.ptls, sizeof(jl_task_t), jl_task_type); + memset(s.ptls->root_task, 0, sizeof(jl_task_t)); + s.ptls->root_task->tls = jl_read_value(&s); + jl_init_int32_int64_cache(); + jl_init_box_caches(); + + uint32_t uid_ctr = read_uint32(f); + uint32_t gs_ctr = read_uint32(f); + jl_world_counter = read_uint32(f); + jl_typeinf_world = read_uint32(f); + jl_set_t_uid_ctr(uid_ctr); + jl_set_gs_ctr(gs_ctr); + s.s = NULL; + + // step 3: apply relocations assert(!ios_eof(f)); jl_read_symbols(&s); ios_close(&symbols); @@ -1486,14 +1525,20 @@ static void jl_restore_system_image_from_stream(ios_t *f) sysimg_relocs = &relocs.buf[0]; jl_gc_set_permalloc_region((void*)sysimg_base, (void*)(sysimg_base + sysimg.size)); - deser_tag.items[0] = (void*)const_data.buf; + s.s = &sysimg; jl_read_relocations(&s, GC_OLD_MARKED); // gctags size_t sizeof_tags = ios_pos(&relocs); (void)sizeof_tags; jl_read_relocations(&s, 0); // general relocs ios_close(&relocs); ios_close(&const_data); - ios_close(&sysimg); + jl_update_all_gvars(&s); // gvars relocs + ios_close(&gvar_record); + s.s = NULL; + + s.s = f; + jl_finalize_deserializer(&s); + s.s = NULL; if (0) { printf("sysimg size breakdown:\n" @@ -1513,52 +1558,12 @@ static void jl_restore_system_image_from_stream(ios_t *f) (unsigned)sizeof_fptr_record); } - // step 2: get special values - s.s = f; - jl_module_init_order = jl_finalize_deserializer(&s, NULL); - jl_main_module = (jl_module_t*)jl_read_value(&s); - jl_top_module = (jl_module_t*)jl_read_value(&s); - - jl_typeinf_func = (jl_function_t*)jl_read_value(&s); - jl_typeinf_world = read_uint32(f); - jl_type_type_mt = (jl_methtable_t*)jl_read_value(&s); - jl_type_typename->mt = jl_type_type_mt; - jl_unionall_type->name->mt = jl_type_type_mt; - jl_uniontype_type->name->mt = jl_type_type_mt; - jl_datatype_type->name->mt = jl_type_type_mt; - jl_intrinsic_type->name->mt = (jl_methtable_t*)jl_read_value(&s); - jl_sym_type->name->mt = (jl_methtable_t*)jl_read_value(&s); - jl_array_typename->mt = (jl_methtable_t*)jl_read_value(&s); - jl_module_type->name->mt = (jl_methtable_t*)jl_read_value(&s); - - uintptr_t i; - for (i = 0; i < builtin_typenames.len; i++) { - jl_typename_t *tn = (jl_typename_t*)builtin_typenames.items[i]; - tn->cache = (jl_svec_t*)jl_read_value(&s); - jl_gc_wb(tn, tn->cache); - tn->linearcache = (jl_svec_t*)jl_read_value(&s); - jl_gc_wb(tn, tn->linearcache); - jl_sort_types(jl_svec_data(tn->cache), jl_svec_len(tn->cache)); - } - - jl_core_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Core")); - jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Base")); - - uint32_t uid_ctr = read_uint32(f); - uint32_t gs_ctr = read_uint32(f); - jl_world_counter = read_uint32(f); - - jl_set_t_uid_ctr(uid_ctr); - jl_set_gs_ctr(gs_ctr); - - jl_get_builtins(); - jl_get_builtin_hooks(); - jl_init_box_caches(); - - jl_update_all_gvars(&s); - ios_close(&gvar_record); - jl_update_all_fptrs(&s); + s.s = &sysimg; + jl_init_codegen(); + jl_update_all_fptrs(&s); // fptr relocs and registration ios_close(&fptr_record); + ios_close(&sysimg); + s.s = NULL; jl_gc_reset_alloc_count(); jl_gc_enable(en); @@ -1612,144 +1617,32 @@ JL_DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len) static void jl_init_serializer2(int for_serialize) { - jl_ptls_t ptls = jl_get_ptls_states(); - arraylist_new(&builtin_typenames, 0); if (for_serialize) { - htable_new(&sertag_table, 0); htable_new(&symbol_table, 0); htable_new(&fptr_to_id, sizeof(id_to_fptrs) / sizeof(*id_to_fptrs)); htable_new(&backref_table, 0); + arraylist_new(&builtin_typenames, 0); } else { - arraylist_new(&deser_tag, 0); arraylist_new(&deser_sym, 0); } - uintptr_t i; - - void *tags[] = { ptls->root_task, - jl_symbol_type, jl_ssavalue_type, jl_datatype_type, jl_slotnumber_type, - jl_simplevector_type, jl_array_type, jl_typedslot_type, - jl_expr_type, jl_globalref_type, jl_string_type, - jl_module_type, jl_tvar_type, jl_method_instance_type, jl_method_type, jl_code_instance_type, - jl_emptysvec, jl_emptytuple, jl_false, jl_true, jl_nothing, jl_any_type, - call_sym, invoke_sym, goto_ifnot_sym, return_sym, jl_symbol("tuple"), - unreachable_sym, jl_an_empty_string, - jl_linenumbernode_type, jl_lineinfonode_type, - jl_gotonode_type, jl_quotenode_type, - jl_pinode_type, jl_phinode_type, jl_phicnode_type, jl_upsilonnode_type, - jl_type_type, jl_bottom_type, jl_ref_type, jl_pointer_type, - jl_vararg_type, jl_abstractarray_type, - jl_densearray_type, jl_void_type, jl_function_type, jl_typeofbottom_type, - jl_unionall_type, jl_typename_type, jl_builtin_type, jl_code_info_type, - jl_task_type, jl_uniontype_type, jl_typetype_type, jl_abstractstring_type, - jl_array_any_type, jl_intrinsic_type, jl_abstractslot_type, - jl_methtable_type, jl_typemap_level_type, jl_typemap_entry_type, - jl_voidpointer_type, jl_newvarnode_type, - jl_array_symbol_type, jl_anytuple_type, jl_tparam0(jl_anytuple_type), - jl_emptytuple_type, jl_array_uint8_type, jl_array_int32_type, - jl_symbol_type->name, jl_ssavalue_type->name, jl_tuple_typename, - ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_ref_type))->name, - jl_pointer_typename, jl_simplevector_type->name, - jl_datatype_type->name, jl_uniontype_type->name, jl_array_typename, - jl_expr_type->name, jl_typename_type->name, jl_type_typename, - jl_methtable_type->name, jl_typemap_level_type->name, jl_typemap_entry_type->name, jl_tvar_type->name, - ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_abstractarray_type))->name, - ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_densearray_type))->name, - jl_vararg_typename, jl_void_type->name, jl_method_instance_type->name, jl_method_type->name, jl_code_instance_type->name, - jl_module_type->name, jl_function_type->name, jl_typedslot_type->name, - jl_abstractslot_type->name, jl_slotnumber_type->name, - jl_unionall_type->name, jl_intrinsic_type->name, jl_task_type->name, - jl_linenumbernode_type->name, jl_builtin_type->name, - jl_gotonode_type->name, jl_quotenode_type->name, jl_lineinfonode_type->name, - jl_pinode_type->name, jl_phinode_type->name, - jl_phicnode_type->name, jl_upsilonnode_type->name, - jl_globalref_type->name, jl_typeofbottom_type->name, - jl_string_type->name, jl_abstractstring_type->name, - jl_namedtuple_type, jl_namedtuple_typename, - - jl_int32_type, jl_int64_type, jl_bool_type, jl_uint8_type, - jl_uint32_type, jl_uint64_type, - - // empirical list of very common symbols - #include "common_symbols1.inc" - - NULL }; - - arraylist_push(&deser_tag, NULL); - arraylist_push(&deser_tag, NULL); - for (i = 0; tags[i] != NULL; i++) { - void *v = tags[i]; - if (!for_serialize) { - // some builtins are only rooted through a type cache or Main.Core binding, - // but were allocated young, so we force the gc to change their tag here - jl_gc_force_mark_old(ptls, (jl_value_t*)v); - } - if (jl_is_symbol(v)) { - arraylist_push(&deser_sym, v); - if (for_serialize) - ptrhash_put(&symbol_table, v, (void*)((char*)HT_NOTFOUND + ((uintptr_t)SymbolRef << RELOC_TAG_OFFSET) + deser_sym.len)); - } - else { - arraylist_push(&deser_tag, v); - if (for_serialize) - ptrhash_put(&sertag_table, v, (void*)((char*)HT_NOTFOUND + ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + deser_tag.len)); - } - } - assert(i + 1 == sizeof(tags) / sizeof(tags[0])); - assert(!for_serialize || ptrhash_get(&sertag_table, ptls->root_task) == (char*)HT_NOTFOUND + ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + 3); - nsym_tag = deser_sym.len; - - // this also ensures all objects referenced in the code have - // references in the system image to their global variable - // since codegen knows that some integer boxes are static, - // they might not have had a reference anywhere in the code - // image other than here -#define NBOX_C 1024 - for (i = 0; i < NBOX_C; i++) { - jl_value_t *v32 = jl_box_int32(i - NBOX_C / 2); - arraylist_push(&deser_tag, v32); - if (for_serialize) - ptrhash_put(&sertag_table, v32, (void*)((char*)HT_NOTFOUND + ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + deser_tag.len)); - - jl_value_t *v64 = jl_box_int64(i - NBOX_C / 2); - arraylist_push(&deser_tag, v64); - if (for_serialize) - ptrhash_put(&sertag_table, v64, (void*)((char*)HT_NOTFOUND + ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + deser_tag.len)); - } - for (i = 0; i < 256; i++) { - jl_value_t *vu = jl_box_uint8(i); - arraylist_push(&deser_tag, vu); - if (for_serialize) - ptrhash_put(&sertag_table, vu, (void*)((char*)HT_NOTFOUND + ((uintptr_t)TagRef << RELOC_TAG_OFFSET) + deser_tag.len)); - } + nsym_tag = 0; if (for_serialize) { + uintptr_t i; for (i = 0; id_to_fptrs[i] != NULL; i++) { ptrhash_put(&fptr_to_id, (void*)(uintptr_t)id_to_fptrs[i], (void*)(i + 2)); } } - - arraylist_push(&builtin_typenames, jl_array_typename); - arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_ref_type->body)->name); - arraylist_push(&builtin_typenames, jl_pointer_typename); - arraylist_push(&builtin_typenames, jl_type_typename); - arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_abstractarray_type))->name); - arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_densearray_type))->name); - arraylist_push(&builtin_typenames, jl_tuple_typename); - arraylist_push(&builtin_typenames, jl_vararg_typename); - arraylist_push(&builtin_typenames, jl_namedtuple_typename); } static void jl_cleanup_serializer2(void) { - htable_reset(&sertag_table, 0); htable_reset(&symbol_table, 0); htable_reset(&fptr_to_id, 0); htable_reset(&backref_table, 0); - arraylist_free(&deser_tag); arraylist_free(&deser_sym); arraylist_free(&builtin_typenames); - nsym_tag = 0; } #ifdef __cplusplus diff --git a/src/symbol.c b/src/symbol.c index da17a426dbc82..240b35db8c9d9 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -31,11 +31,12 @@ static jl_sym_t *mk_symbol(const char *str, size_t len) { jl_sym_t *sym; size_t nb = symbol_nbytes(len); + assert(jl_symbol_type && "not initialized"); jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc_nolock(nb, 0, sizeof(void*), 0); sym = (jl_sym_t*)jl_valueof(tag); // set to old marked so that we won't look at it in the GC or write barrier. - tag->header = ((uintptr_t)jl_sym_type) | GC_OLD_MARKED; + tag->header = ((uintptr_t)jl_symbol_type) | GC_OLD_MARKED; sym->left = sym->right = NULL; sym->hash = hash_symbol(str, len); memcpy(jl_symbol_name(sym), str, len); diff --git a/src/task.c b/src/task.c index b5b04d38c6cbe..ba3a0617a808f 100644 --- a/src/task.c +++ b/src/task.c @@ -64,7 +64,6 @@ jl_sym_t *failed_sym; jl_sym_t *runnable_sym; extern size_t jl_page_size; -jl_datatype_t *jl_task_type; static char *jl_alloc_fiber(jl_ucontext_t *t, size_t *ssize, jl_task_t *owner); static void jl_set_fiber(jl_ucontext_t *t); static void jl_start_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t); @@ -535,38 +534,6 @@ JL_DLLEXPORT jl_value_t *jl_get_current_task(void) // Do one-time initializations for task system void jl_init_tasks(void) JL_GC_DISABLED { - jl_task_type = (jl_datatype_t*) - jl_new_datatype(jl_symbol("Task"), - NULL, - jl_any_type, - jl_emptysvec, - jl_perm_symsvec(11, - "next", - "queue", - "storage", - "state", - "donenotify", - "result", - "exception", - "backtrace", - "logstate", - "code", - "sticky"), - jl_svec(11, - jl_any_type, - jl_any_type, - jl_any_type, - jl_sym_type, - jl_any_type, - jl_any_type, - jl_any_type, - jl_any_type, - jl_any_type, - jl_any_type, - jl_bool_type), - 0, 1, 9); - jl_value_t *listt = jl_new_struct(jl_uniontype_type, jl_task_type, jl_void_type); - jl_svecset(jl_task_type->types, 0, listt); done_sym = jl_symbol("done"); failed_sym = jl_symbol("failed"); runnable_sym = jl_symbol("runnable"); @@ -933,8 +900,12 @@ static void jl_init_basefiber(size_t ssize) void jl_init_root_task(void *stack_lo, void *stack_hi) { jl_ptls_t ptls = jl_get_ptls_states(); - ptls->current_task = (jl_task_t*)jl_gc_alloc(ptls, sizeof(jl_task_t), - jl_task_type); + if (ptls->root_task == NULL) { + ptls->root_task = (jl_task_t*)jl_gc_alloc(ptls, sizeof(jl_task_t), jl_task_type); + memset(ptls->root_task, 0, sizeof(jl_task_t)); + ptls->root_task->tls = jl_nothing; + } + ptls->current_task = ptls->root_task; void *stack = stack_lo; size_t ssize = (char*)stack_hi - (char*)stack_lo; #ifndef _OS_WINDOWS_ @@ -956,7 +927,6 @@ void jl_init_root_task(void *stack_lo, void *stack_hi) ptls->current_task->started = 1; ptls->current_task->next = jl_nothing; ptls->current_task->queue = jl_nothing; - ptls->current_task->tls = jl_nothing; ptls->current_task->state = runnable_sym; ptls->current_task->start = NULL; ptls->current_task->result = jl_nothing; @@ -973,8 +943,6 @@ void jl_init_root_task(void *stack_lo, void *stack_hi) arraylist_new(&ptls->current_task->locks, 0); #endif - ptls->root_task = ptls->current_task; - if (always_copy_stacks) { ptls->stackbase = stack_hi; ptls->stacksize = ssize; diff --git a/src/toplevel.c b/src/toplevel.c index b96162b207559..756bfdcfc853e 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -119,7 +119,7 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) int std_imports = (jl_exprarg(ex, 0) == jl_true); jl_sym_t *name = (jl_sym_t*)jl_exprarg(ex, 1); if (!jl_is_symbol(name)) { - jl_type_error("module", (jl_value_t*)jl_sym_type, (jl_value_t*)name); + jl_type_error("module", (jl_value_t*)jl_symbol_type, (jl_value_t*)name); } jl_module_t *newm = jl_new_module(name); @@ -418,7 +418,7 @@ static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from JL_PR jl_module_t *m = NULL; *name = NULL; if (!jl_is_symbol(var)) - jl_type_error(keyword, (jl_value_t*)jl_sym_type, (jl_value_t*)var); + jl_type_error(keyword, (jl_value_t*)jl_symbol_type, (jl_value_t*)var); if (from != NULL) { m = from; @@ -456,7 +456,7 @@ static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from JL_PR while (1) { var = (jl_sym_t*)jl_array_ptr_ref(args, i); if (!jl_is_symbol(var)) - jl_type_error(keyword, (jl_value_t*)jl_sym_type, (jl_value_t*)var); + jl_type_error(keyword, (jl_value_t*)jl_symbol_type, (jl_value_t*)var); if (var == dot_sym) jl_errorf("invalid %s path: \".\" in identifier path", keyword); if (i == jl_array_len(args)-1)