Skip to content

Commit e8b52e6

Browse files
committed
bindings: backdate initial module statements
For model simplicity (and eventually for better unspecialized compilation), try to backdate initial module operations back to world 0 if nobody could have observed them before, rather than putting each incremental operation in a separate, but unobserved world.
1 parent 13311f3 commit e8b52e6

File tree

11 files changed

+97
-99
lines changed

11 files changed

+97
-99
lines changed

base/Base_compiler.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
baremodule Base
3+
module Base
44

5-
using Core
6-
using Core.Intrinsics, Core.IR
5+
using .Core.Intrinsics, .Core.IR
76

87
# to start, we're going to use a very simple definition of `include`
98
# that doesn't require any function (except what we can get from the `Core` top-module)
@@ -375,5 +374,5 @@ Core._setparser!(fl_parse)
375374

376375
# Further definition of Base will happen in Base.jl if loaded.
377376

378-
end # baremodule Base
377+
end # module Base
379378
using .Base

base/sysimg.jl

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
# Can be loaded on top of either an existing system image built from
4-
# `Base_compiler.jl` or standalone, in which case we will build it now.
5-
let had_compiler = isdefined(Main, :Base)
6-
if had_compiler; else
7-
include("Base_compiler.jl")
8-
end
9-
10-
Core.include(Base, "Base.jl")
3+
Base.Core.include(Base, "Base.jl") # finish populating Base (currently just has the Compiler)
114

12-
had_compiler && ccall(:jl_init_restored_module, Cvoid, (Any,), Base)
13-
end
5+
# Set up Main module by importing from Base
6+
using .Base
7+
using .Base.MainInclude # ans, err, and sometimes Out
148

15-
# Set up Main module
16-
using Base.MainInclude # ans, err, and sometimes Out
9+
ccall(:jl_init_restored_module, Cvoid, (Any,), Base)
1710

1811
# These definitions calls Base._include rather than Base.include to get
1912
# one-frame stacktraces for the common case of using include(fname) in Main.
@@ -59,7 +52,7 @@ definition of `eval`, which evaluates expressions in that module.
5952
const eval = Core.EvalInto(Main)
6053

6154
# Ensure this file is also tracked
62-
pushfirst!(Base._included_files, (@__MODULE__, abspath(@__FILE__)))
55+
pushfirst!(Base._included_files, (Main, abspath(@__FILE__)))
6356

6457
# set up depot & load paths to be able to find stdlib packages
6558
Base.init_depot_path()

doc/src/devdocs/init.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ the [LLVM library](https://llvm.org).
6363
If there is no sysimg file (`!jl_options.image_file`) then the `Core` and `Main` modules are
6464
created and `boot.jl` is evaluated:
6565

66-
`jl_core_module = jl_new_module(jl_symbol("Core"))` creates the Julia `Core` module.
66+
`jl_core_module = jl_new_module(jl_symbol("Core"), NULL)` creates the Julia `Core` module.
6767

6868
[`jl_init_intrinsic_functions()`](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp)
6969
creates a new Julia module `Intrinsics` containing constant `jl_intrinsic_type` symbols. These define

src/builtins.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,8 +2396,7 @@ static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f)
23962396
{
23972397
jl_value_t *i = jl_permbox32(jl_intrinsic_type, 0, (int32_t)f);
23982398
jl_sym_t *sym = jl_symbol(name);
2399-
jl_set_const(inm, sym, i);
2400-
jl_module_public(inm, sym, 1);
2399+
jl_set_initial_const(inm, sym, i, 1);
24012400
}
24022401

24032402
void jl_init_intrinsic_properties(void) JL_GC_DISABLED
@@ -2413,9 +2412,8 @@ void jl_init_intrinsic_properties(void) JL_GC_DISABLED
24132412

24142413
void jl_init_intrinsic_functions(void) JL_GC_DISABLED
24152414
{
2416-
jl_module_t *inm = jl_new_module(jl_symbol("Intrinsics"), NULL);
2417-
inm->parent = jl_core_module;
2418-
jl_set_const(jl_core_module, jl_symbol("Intrinsics"), (jl_value_t*)inm);
2415+
jl_module_t *inm = jl_new_module_(jl_symbol("Intrinsics"), jl_core_module, 0, 1);
2416+
jl_set_initial_const(jl_core_module, jl_symbol("Intrinsics"), (jl_value_t*)inm, 0);
24192417
jl_mk_builtin_func(jl_intrinsic_type, "IntrinsicFunction", jl_f_intrinsic_call);
24202418
jl_mk_builtin_func(
24212419
(jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_opaque_closure_type),
@@ -2437,7 +2435,7 @@ void jl_init_intrinsic_functions(void) JL_GC_DISABLED
24372435

24382436
static void add_builtin(const char *name, jl_value_t *v)
24392437
{
2440-
jl_set_const(jl_core_module, jl_symbol(name), v);
2438+
jl_set_initial_const(jl_core_module, jl_symbol(name), v, 0);
24412439
}
24422440

24432441
jl_fptr_args_t jl_get_builtin_fptr(jl_datatype_t *dt)

src/gf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_a
294294
if (dt == NULL) {
295295
// Builtins are specially considered available from world 0
296296
jl_value_t *f = jl_new_generic_function_with_supertype(sname, jl_core_module, jl_builtin_type, 0);
297-
jl_set_const(jl_core_module, sname, f);
297+
jl_set_initial_const(jl_core_module, sname, f, 0);
298298
dt = (jl_datatype_t*)jl_typeof(f);
299299
}
300300

src/jl_exported_funcs.inc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#define JL_RUNTIME_EXPORTED_FUNCS(XX) \
44
XX(jl_active_task_stack) \
5-
XX(jl_add_standard_imports) \
65
XX(jl_adopt_thread) \
76
XX(jl_alignment) \
87
XX(jl_alloc_array_1d) \
@@ -98,7 +97,6 @@
9897
XX(jl_cstr_to_string) \
9998
XX(jl_current_exception) \
10099
XX(jl_debug_method_invalidation) \
101-
XX(jl_defines_or_exports_p) \
102100
XX(jl_deprecate_binding) \
103101
XX(jl_dlclose) \
104102
XX(jl_dlopen) \

src/jltypes.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3287,10 +3287,9 @@ void jl_init_types(void) JL_GC_DISABLED
32873287
jl_emptysvec, 0, 0, 3);
32883288

32893289
core = jl_new_module(jl_symbol("Core"), NULL);
3290-
core->parent = core;
32913290
jl_type_typename->mt->module = core;
32923291
jl_core_module = core;
3293-
core = NULL; // not ready yet to use
3292+
core = NULL; // not actually ready yet to use
32943293

32953294
tv = jl_svec1(tvar("Backend"));
32963295
jl_addrspace_typename =
@@ -3381,9 +3380,8 @@ void jl_init_types(void) JL_GC_DISABLED
33813380
core = jl_core_module;
33823381
jl_atomic_store_relaxed(&core->bindingkeyset, (jl_genericmemory_t*)jl_an_empty_memory_any);
33833382
// export own name, so "using Foo" makes "Foo" itself visible
3384-
jl_set_const(core, core->name, (jl_value_t*)core);
3385-
jl_module_public(core, core->name, 1);
3386-
jl_set_const(core, jl_symbol("CPU"), (jl_value_t*)cpumem);
3383+
jl_set_initial_const(core, core->name, (jl_value_t*)core, 1);
3384+
jl_set_initial_const(core, jl_symbol("CPU"), (jl_value_t*)cpumem, 0);
33873385
core = NULL;
33883386

33893387
jl_expr_type =

src/julia.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,13 +2093,13 @@ JL_DLLEXPORT void jl_check_binding_currently_writable(jl_binding_t *b, jl_module
20932093
JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var);
20942094
JL_DLLEXPORT jl_value_t *jl_get_existing_strong_gf(jl_binding_t *b JL_PROPAGATES_ROOT, size_t new_world);
20952095
JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var, int allow_import);
2096-
JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var);
20972096
JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var);
20982097
JL_DLLEXPORT int jl_globalref_is_const(jl_globalref_t *gr);
20992098
JL_DLLEXPORT jl_value_t *jl_get_globalref_value(jl_globalref_t *gr);
21002099
JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var);
21012100
JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT);
21022101
JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT);
2102+
void jl_set_initial_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT, int exported);
21032103
JL_DLLEXPORT void jl_checked_assignment(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *rhs JL_MAYBE_UNROOTED);
21042104
JL_DLLEXPORT jl_value_t *jl_checked_swap(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *rhs JL_MAYBE_UNROOTED);
21052105
JL_DLLEXPORT jl_value_t *jl_checked_replace(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *expected, jl_value_t *rhs);
@@ -2115,7 +2115,6 @@ JL_DLLEXPORT void jl_module_import_as(jl_task_t *ct, jl_module_t *to, jl_module_
21152115
JL_DLLEXPORT void jl_module_public(jl_module_t *from, jl_sym_t *s, int exported);
21162116
JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *s);
21172117
JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var);
2118-
JL_DLLEXPORT void jl_add_standard_imports(jl_module_t *m);
21192118

21202119
// eq hash tables
21212120
JL_DLLEXPORT jl_genericmemory_t *jl_eqtable_put(jl_genericmemory_t *h JL_ROOTING_ARGUMENT, jl_value_t *key, jl_value_t *val JL_ROOTED_ARGUMENT, int *inserted);

src/julia_internal.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@ JL_DLLEXPORT void jl_declare_global(jl_module_t *m, jl_value_t *arg, jl_value_t
849849
JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3(jl_binding_t *b JL_ROOTING_ARGUMENT, jl_module_t *mod, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED, enum jl_partition_kind, size_t new_world) JL_GLOBALLY_ROOTED;
850850
JL_DLLEXPORT jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded, const char **toplevel_filename, int *toplevel_lineno);
851851

852+
void jl_module_initial_using(jl_module_t *to, jl_module_t *from);
852853
STATIC_INLINE struct _jl_module_using *module_usings_getidx(jl_module_t *m JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT;
853854
STATIC_INLINE jl_module_t *module_usings_getmod(jl_module_t *m JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT;
854855
void jl_add_usings_backedge(jl_module_t *from, jl_module_t *to);
@@ -921,7 +922,7 @@ JL_DLLEXPORT jl_binding_partition_t *jl_replace_binding_locked2(jl_binding_t *b
921922
JL_DLLEXPORT void jl_update_loaded_bpart(jl_binding_t *b, jl_binding_partition_t *bpart);
922923
extern jl_array_t *jl_module_init_order JL_GLOBALLY_ROOTED;
923924
extern htable_t jl_current_modules JL_GLOBALLY_ROOTED;
924-
extern JL_DLLEXPORT jl_module_t *jl_precompile_toplevel_module JL_GLOBALLY_ROOTED;
925+
extern jl_module_t *jl_precompile_toplevel_module JL_GLOBALLY_ROOTED;
925926
extern jl_genericmemory_t *jl_global_roots_list JL_GLOBALLY_ROOTED;
926927
extern jl_genericmemory_t *jl_global_roots_keyset JL_GLOBALLY_ROOTED;
927928
extern arraylist_t *jl_entrypoint_mis;
@@ -1255,9 +1256,8 @@ _Atomic(jl_value_t*) *jl_table_peek_bp(jl_genericmemory_t *a, jl_value_t *key) J
12551256

12561257
JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t*);
12571258

1258-
JL_DLLEXPORT jl_module_t *jl_new_module__(jl_sym_t *name, jl_module_t *parent);
1259-
JL_DLLEXPORT jl_module_t *jl_new_module_(jl_sym_t *name, jl_module_t *parent, uint8_t default_using_core, uint8_t self_name);
1260-
JL_DLLEXPORT void jl_add_default_names(jl_module_t *m, uint8_t default_using_core, uint8_t self_name);
1259+
jl_module_t *jl_new_module_(jl_sym_t *name, jl_module_t *parent, uint8_t default_using_core, uint8_t self_name);
1260+
jl_module_t *jl_add_standard_imports(jl_module_t *m);
12611261
JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module);
12621262
JL_DLLEXPORT jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, int mt_cache);
12631263
jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp) JL_PROPAGATES_ROOT;

src/module.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_leaf_partitions_value_if_const(jl_bindin
401401
return NULL;
402402
}
403403

404-
JL_DLLEXPORT jl_module_t *jl_new_module__(jl_sym_t *name, jl_module_t *parent)
404+
static jl_module_t *jl_new_module__(jl_sym_t *name, jl_module_t *parent)
405405
{
406406
jl_task_t *ct = jl_current_task;
407407
const jl_uuid_t uuid_zero = {0, 0};
@@ -410,7 +410,7 @@ JL_DLLEXPORT jl_module_t *jl_new_module__(jl_sym_t *name, jl_module_t *parent)
410410
jl_set_typetagof(m, jl_module_tag, 0);
411411
assert(jl_is_symbol(name));
412412
m->name = name;
413-
m->parent = parent;
413+
m->parent = parent ? parent : m;
414414
m->istopmod = 0;
415415
m->uuid = uuid_zero;
416416
static unsigned int mcounter; // simple counter backup, in case hrtime is not incrementing
@@ -437,23 +437,22 @@ JL_DLLEXPORT jl_module_t *jl_new_module__(jl_sym_t *name, jl_module_t *parent)
437437
return m;
438438
}
439439

440-
JL_DLLEXPORT void jl_add_default_names(jl_module_t *m, uint8_t default_using_core, uint8_t self_name)
440+
static void jl_add_default_names(jl_module_t *m, uint8_t default_using_core, uint8_t self_name)
441441
{
442442
if (jl_core_module) {
443443
// Bootstrap: Before jl_core_module is defined, we don't have enough infrastructure
444444
// for bindings, so Core itself gets special handling in jltypes.c
445445
if (default_using_core) {
446-
jl_module_using(m, jl_core_module);
446+
jl_module_initial_using(m, jl_core_module);
447447
}
448448
if (self_name) {
449449
// export own name, so "using Foo" makes "Foo" itself visible
450-
jl_set_const(m, m->name, (jl_value_t*)m);
451-
jl_module_public(m, m->name, 1);
450+
jl_set_initial_const(m, m->name, (jl_value_t*)m, 1);
452451
}
453452
}
454453
}
455454

456-
JL_DLLEXPORT jl_module_t *jl_new_module_(jl_sym_t *name, jl_module_t *parent, uint8_t default_using_core, uint8_t self_name)
455+
jl_module_t *jl_new_module_(jl_sym_t *name, jl_module_t *parent, uint8_t default_using_core, uint8_t self_name)
457456
{
458457
jl_module_t *m = jl_new_module__(name, parent);
459458
JL_GC_PUSH1(&m);
@@ -1231,6 +1230,19 @@ void jl_add_usings_backedge(jl_module_t *from, jl_module_t *to)
12311230
JL_UNLOCK(&from->lock);
12321231
}
12331232

1233+
void jl_module_initial_using(jl_module_t *to, jl_module_t *from)
1234+
{
1235+
struct _jl_module_using new_item = {
1236+
.mod = from,
1237+
.min_world = 0,
1238+
.max_world = ~(size_t)0
1239+
};
1240+
arraylist_grow(&to->usings, sizeof(struct _jl_module_using)/sizeof(void*));
1241+
memcpy(&to->usings.items[to->usings.len-3], &new_item, sizeof(struct _jl_module_using));
1242+
jl_gc_wb(to, from);
1243+
jl_add_usings_backedge(from, to);
1244+
}
1245+
12341246
JL_DLLEXPORT void jl_module_using(jl_module_t *to, jl_module_t *from)
12351247
{
12361248
if (to == from)
@@ -1325,6 +1337,7 @@ JL_DLLEXPORT jl_value_t *jl_get_module_binding_or_nothing(jl_module_t *m, jl_sym
13251337

13261338
JL_DLLEXPORT void jl_module_public(jl_module_t *from, jl_sym_t *s, int exported)
13271339
{
1340+
// caller must hold world_counter_lock
13281341
jl_binding_t *b = jl_get_module_binding(from, s, 1);
13291342
JL_LOCK(&world_counter_lock);
13301343
size_t new_world = jl_atomic_load_acquire(&jl_world_counter)+1;
@@ -1370,13 +1383,6 @@ JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var, int allow_import) // u
13701383
return jl_atomic_load(&b->value) != NULL;
13711384
}
13721385

1373-
JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var)
1374-
{
1375-
jl_binding_t *b = jl_get_module_binding(m, var, 0);
1376-
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
1377-
return b && ((bpart->kind & PARTITION_FLAG_EXPORTED) || jl_binding_kind(bpart) == PARTITION_KIND_GLOBAL);
1378-
}
1379-
13801386
JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var)
13811387
{
13821388
jl_binding_t *b = jl_get_module_binding(m, var, 0);
@@ -1475,9 +1481,25 @@ JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *va
14751481
jl_checked_assignment(bp, m, var, val);
14761482
}
14771483

1484+
JL_DLLEXPORT void jl_set_initial_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT, int exported)
1485+
{
1486+
// this function is only valid during initialization, so there is no risk of data races her are not too important to use
1487+
int kind = PARTITION_KIND_CONST | (exported ? PARTITION_FLAG_EXPORTED : 0);
1488+
// jl_declare_constant_val3(NULL, m, var, (jl_value_t*)jl_any_type, kind, 0);
1489+
jl_binding_t *bp = jl_get_module_binding(m, var, 1);
1490+
jl_binding_partition_t *bpart = jl_get_binding_partition(bp, 0);
1491+
assert(bpart->min_world == 0);
1492+
jl_atomic_store_relaxed(&bpart->max_world, ~(size_t)0); // jl_check_new_binding_implicit likely incorrectly truncated it
1493+
if (exported)
1494+
jl_atomic_fetch_or_relaxed(&bp->flags, BINDING_FLAG_PUBLICP);
1495+
bpart->kind = kind | (bpart->kind & PARTITION_MASK_FLAG);
1496+
bpart->restriction = val;
1497+
jl_gc_wb(bpart, val);
1498+
}
1499+
14781500
JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT)
14791501
{
1480-
// this function is mostly only used during initialization, so the data races here are not too important to us
1502+
// this function is dangerous and unsound. do not use.
14811503
jl_binding_t *bp = jl_get_module_binding(m, var, 1);
14821504
jl_binding_partition_t *bpart = jl_get_binding_partition(bp, jl_current_task->world_age);
14831505
bpart->min_world = 0;

0 commit comments

Comments
 (0)