Skip to content

Commit a61b7b4

Browse files
committed
bpart: When backdating replace the entire bpart chain
Rather than rewriting the `restriction` of the bparts. With this, I believe this removes that last point where `restriction` is overwritten after construction, hopefully allowing us to go back to the original design where `restriction` is `const` after construction.
1 parent 17fff87 commit a61b7b4

File tree

2 files changed

+75
-78
lines changed

2 files changed

+75
-78
lines changed

src/module.c

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,80 @@ JL_DLLEXPORT jl_module_t *jl_new_module_(jl_sym_t *name, jl_module_t *parent, ui
248248
return m;
249249
}
250250

251+
// Precondition: world_counter_lock is held
252+
JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3(
253+
jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *val,
254+
enum jl_partition_kind constant_kind, size_t new_world)
255+
{
256+
JL_GC_PUSH1(&val);
257+
if (!b) {
258+
b = jl_get_module_binding(mod, var, 1);
259+
}
260+
jl_binding_partition_t *new_bpart = NULL;
261+
jl_binding_partition_t *bpart = jl_get_binding_partition(b, new_world);
262+
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
263+
while (!new_bpart) {
264+
enum jl_partition_kind kind = decode_restriction_kind(pku);
265+
if (jl_bkind_is_some_constant(kind)) {
266+
if (!val) {
267+
new_bpart = bpart;
268+
break;
269+
}
270+
jl_value_t *old = decode_restriction_value(pku);
271+
JL_GC_PROMISE_ROOTED(old);
272+
if (jl_egal(val, old)) {
273+
new_bpart = bpart;
274+
break;
275+
}
276+
} else if (jl_bkind_is_some_import(kind) && kind != BINDING_KIND_IMPLICIT) {
277+
jl_errorf("cannot declare %s.%s constant; it was already declared as an import",
278+
jl_symbol_name(mod->name), jl_symbol_name(var));
279+
} else if (kind == BINDING_KIND_GLOBAL) {
280+
jl_errorf("cannot declare %s.%s constant; it was already declared global",
281+
jl_symbol_name(mod->name), jl_symbol_name(var));
282+
}
283+
if (bpart->min_world == new_world) {
284+
if (!jl_atomic_cmpswap(&bpart->restriction, &pku, encode_restriction(val, constant_kind))) {
285+
continue;
286+
} else if (val) {
287+
jl_gc_wb(bpart, val);
288+
}
289+
new_bpart = bpart;
290+
} else {
291+
new_bpart = jl_replace_binding_locked(b, bpart, val, constant_kind, new_world);
292+
}
293+
int need_backdate = new_world && val;
294+
if (need_backdate) {
295+
// We will backdate as long as this partition was never explicitly
296+
// declared const, global, or imported.
297+
jl_binding_partition_t *prev_bpart = bpart;
298+
for (;;) {
299+
jl_ptr_kind_union_t prev_pku = jl_atomic_load_relaxed(&prev_bpart->restriction);
300+
enum jl_partition_kind prev_kind = decode_restriction_kind(prev_pku);
301+
if (jl_bkind_is_some_constant(prev_kind) || prev_kind == BINDING_KIND_GLOBAL ||
302+
(jl_bkind_is_some_import(prev_kind))) {
303+
need_backdate = 0;
304+
break;
305+
}
306+
if (prev_bpart->min_world == 0)
307+
break;
308+
prev_bpart = jl_get_binding_partition(b, prev_bpart->min_world - 1);
309+
}
310+
}
311+
// If backdate is required, create one new binding partition to cover
312+
// the entire backdate range.
313+
if (need_backdate) {
314+
jl_binding_partition_t *backdate_bpart = new_binding_partition();
315+
jl_atomic_store_relaxed(&backdate_bpart->restriction, encode_restriction(val, BINDING_KIND_BACKDATED_CONST));
316+
jl_atomic_store_relaxed(&backdate_bpart->max_world, new_world - 1);
317+
jl_atomic_store_release(&new_bpart->next, backdate_bpart);
318+
jl_gc_wb(new_bpart, backdate_bpart);
319+
}
320+
}
321+
JL_GC_POP();
322+
return new_bpart;
323+
}
324+
251325
JL_DLLEXPORT jl_module_t *jl_new_module(jl_sym_t *name, jl_module_t *parent)
252326
{
253327
return jl_new_module_(name, parent, 1);
@@ -1171,7 +1245,7 @@ JL_DLLEXPORT jl_binding_partition_t *jl_replace_binding_locked(jl_binding_t *b,
11711245
new_bpart->min_world = new_world;
11721246
if (kind == BINDING_KIND_IMPLICIT_RECOMPUTE) {
11731247
assert(!restriction_val);
1174-
jl_check_new_binding_implicit(new_bpart, b, NULL, new_world);
1248+
jl_check_new_binding_implicit(new_bpart /* callee rooted */, b, NULL, new_world);
11751249
}
11761250
else
11771251
jl_atomic_store_relaxed(&new_bpart->restriction, encode_restriction(restriction_val, kind));
@@ -1181,7 +1255,6 @@ JL_DLLEXPORT jl_binding_partition_t *jl_replace_binding_locked(jl_binding_t *b,
11811255
jl_atomic_store_release(&b->partitions, new_bpart);
11821256
jl_gc_wb(b, new_bpart);
11831257

1184-
11851258
if (jl_typeinf_world != 1) {
11861259
jl_task_t *ct = jl_current_task;
11871260
size_t last_world = ct->world_age;

src/toplevel.c

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -754,82 +754,6 @@ static void jl_eval_errorf(jl_module_t *m, const char *filename, int lineno, con
754754
JL_GC_POP();
755755
}
756756

757-
JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3(
758-
jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *val,
759-
enum jl_partition_kind constant_kind, size_t new_world)
760-
{
761-
JL_GC_PUSH1(&val);
762-
if (!b) {
763-
b = jl_get_module_binding(mod, var, 1);
764-
}
765-
jl_binding_partition_t *new_bpart = NULL;
766-
jl_binding_partition_t *bpart = jl_get_binding_partition(b, new_world);
767-
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
768-
while (!new_bpart) {
769-
enum jl_partition_kind kind = decode_restriction_kind(pku);
770-
if (jl_bkind_is_some_constant(kind)) {
771-
if (!val) {
772-
new_bpart = bpart;
773-
break;
774-
}
775-
jl_value_t *old = decode_restriction_value(pku);
776-
JL_GC_PROMISE_ROOTED(old);
777-
if (jl_egal(val, old)) {
778-
new_bpart = bpart;
779-
break;
780-
}
781-
} else if (jl_bkind_is_some_import(kind) && kind != BINDING_KIND_IMPLICIT) {
782-
jl_errorf("cannot declare %s.%s constant; it was already declared as an import",
783-
jl_symbol_name(mod->name), jl_symbol_name(var));
784-
} else if (kind == BINDING_KIND_GLOBAL) {
785-
jl_errorf("cannot declare %s.%s constant; it was already declared global",
786-
jl_symbol_name(mod->name), jl_symbol_name(var));
787-
}
788-
if (bpart->min_world == new_world) {
789-
if (!jl_atomic_cmpswap(&bpart->restriction, &pku, encode_restriction(val, constant_kind))) {
790-
continue;
791-
}
792-
jl_gc_wb(bpart, val);
793-
new_bpart = bpart;
794-
} else {
795-
new_bpart = jl_replace_binding_locked(b, bpart, val, constant_kind, new_world);
796-
}
797-
int need_backdate = new_world && val;
798-
if (need_backdate) {
799-
// We will backdate as long as this partition was never explicitly
800-
// declared const, global, or imported.
801-
jl_binding_partition_t *prev_bpart = bpart;
802-
for (;;) {
803-
jl_ptr_kind_union_t prev_pku = jl_atomic_load_relaxed(&prev_bpart->restriction);
804-
enum jl_partition_kind prev_kind = decode_restriction_kind(prev_pku);
805-
if (jl_bkind_is_some_constant(prev_kind) || prev_kind == BINDING_KIND_GLOBAL ||
806-
(jl_bkind_is_some_import(prev_kind))) {
807-
need_backdate = 0;
808-
break;
809-
}
810-
if (prev_bpart->min_world == 0)
811-
break;
812-
prev_bpart = jl_get_binding_partition(b, prev_bpart->min_world - 1);
813-
}
814-
}
815-
// If backdate is required, rewrite all previous binding partitions to
816-
// backdated const
817-
if (need_backdate) {
818-
// We will backdate as long as this partition was never explicitly
819-
// declared const, global, or *explicitly* imported.
820-
jl_binding_partition_t *prev_bpart = bpart;
821-
for (;;) {
822-
jl_atomic_store_relaxed(&prev_bpart->restriction, encode_restriction(val, BINDING_KIND_BACKDATED_CONST));
823-
if (prev_bpart->min_world == 0)
824-
break;
825-
prev_bpart = jl_get_binding_partition(b, prev_bpart->min_world - 1);
826-
}
827-
}
828-
}
829-
JL_GC_POP();
830-
return new_bpart;
831-
}
832-
833757
JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val2(
834758
jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *val,
835759
enum jl_partition_kind constant_kind)

0 commit comments

Comments
 (0)