Skip to content

Commit f5083c4

Browse files
authored
Merge branch 'master' into better_inference_for_oftype_via_common_subexpression_elimination
2 parents 4ebbaa1 + 2f34760 commit f5083c4

File tree

15 files changed

+131
-61
lines changed

15 files changed

+131
-61
lines changed

base/precompilation.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,8 @@ function _precompilepkgs(pkgs::Vector{String},
835835
# window between print cycles
836836
termwidth = displaysize(io)[2] - 4
837837
if !final_loop
838-
str = sprint(io -> show_progress(io, bar; termwidth, carriagereturn=false); context=io)
839-
print(iostr, Base._truncate_at_width_or_chars(true, str, termwidth), "\n")
838+
s = sprint(io -> show_progress(io, bar; termwidth, carriagereturn=false); context=io)
839+
print(iostr, Base._truncate_at_width_or_chars(true, s, termwidth), "\n")
840840
end
841841
for pkg_config in pkg_queue_show
842842
dep, config = pkg_config

base/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ get(io::IO, key, default) = default
442442
keys(io::IOContext) = keys(io.dict)
443443
keys(io::IO) = keys(ImmutableDict{Symbol,Any}())
444444

445-
displaysize(io::IOContext) = haskey(io, :displaysize) ? io[:displaysize]::Tuple{Int,Int} : displaysize(io.io)
445+
displaysize(io::IOContext) = haskey(io, :displaysize) ? io[:displaysize]::Tuple{Int,Int} : displaysize(io.io)::Tuple{Int,Int}
446446

447447
show_circular(io::IO, @nospecialize(x)) = false
448448
function show_circular(io::IOContext, @nospecialize(x))

base/task.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ end
11521152
end
11531153

11541154
const get_sched_task = OncePerThread{Task}() do
1155-
@task wait_forever()
1155+
Task(wait_forever)
11561156
end
11571157

11581158
function ensure_rescheduled(othertask::Task)

contrib/juliac-buildscript.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ let mod = Base.include(Base.__toplevel__, inputfile)
197197
#entrypoint(join, (Base.GenericIOBuffer{Memory{UInt8}}, Array{String, 1}, Char))
198198
entrypoint(Base.task_done_hook, (Task,))
199199
entrypoint(Base.wait, ())
200+
entrypoint(Base.wait_forever, ())
200201
entrypoint(Base.trypoptask, (Base.StickyWorkqueue,))
201202
entrypoint(Base.checktaskempty, ())
202203
if add_ccallables
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cdbbe19efa29dcaa89fe167e15de449d
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7ddce211c686a4c91ac7806dd134e4d0a3abcfe8d0a5c6568697a26e4dd0164c60fb2611421e5e7821819145cdbda85ecd1eec0724409346affcb457a41f5aee

deps/checksums/Pkg-93fb66db1834ddf432141a4809b2b6395b5d3260.tar.gz/md5

Lines changed: 0 additions & 1 deletion
This file was deleted.

deps/checksums/Pkg-93fb66db1834ddf432141a4809b2b6395b5d3260.tar.gz/sha512

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/julia-syntax.scm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,6 +4109,7 @@ f(x) = yt(x)
41094109
(capt-var-access v fname opaq)
41104110
v)))
41114111
cvs)))
4112+
(set-car! (cdddr (lam:vinfo lam2)) '()) ;; must capture static_parameters as values inside opaque_closure
41124113
`(new_opaque_closure
41134114
,(cadr e) ,(or (caddr e) '(call (core apply_type) (core Union))) ,(or (cadddr e) '(core Any)) ,allow-partial
41144115
(opaque_closure_method (null) ,nargs ,isva ,functionloc ,(convert-lambda lam2 (car (lam:args lam2)) #f '() (symbol-to-idx-map cvs) parsed-method-stack))

src/staticdata.c

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,22 @@ static const size_t WORLD_AGE_REVALIDATION_SENTINEL = 0x1;
9090
JL_DLLEXPORT size_t jl_require_world = ~(size_t)0;
9191
JL_DLLEXPORT _Atomic(size_t) jl_first_image_replacement_world = ~(size_t)0;
9292

93+
// This structure is used to store hash tables for the memoization
94+
// of queries in staticdata.c (currently only `type_in_worklist`).
95+
typedef struct {
96+
htable_t type_in_worklist;
97+
} jl_query_cache;
98+
99+
static void init_query_cache(jl_query_cache *cache)
100+
{
101+
htable_new(&cache->type_in_worklist, 0);
102+
}
103+
104+
static void destroy_query_cache(jl_query_cache *cache)
105+
{
106+
htable_free(&cache->type_in_worklist);
107+
}
108+
93109
#include "staticdata_utils.c"
94110
#include "precompile_utils.c"
95111

@@ -552,6 +568,7 @@ typedef struct {
552568
jl_array_t *method_roots_list;
553569
htable_t method_roots_index;
554570
uint64_t worklist_key;
571+
jl_query_cache *query_cache;
555572
jl_ptls_t ptls;
556573
jl_image_t *image;
557574
int8_t incremental;
@@ -675,14 +692,13 @@ static int jl_needs_serialization(jl_serializer_state *s, jl_value_t *v) JL_NOTS
675692
return 1;
676693
}
677694

678-
679-
static int caching_tag(jl_value_t *v) JL_NOTSAFEPOINT
695+
static int caching_tag(jl_value_t *v, jl_query_cache *query_cache) JL_NOTSAFEPOINT
680696
{
681697
if (jl_is_method_instance(v)) {
682698
jl_method_instance_t *mi = (jl_method_instance_t*)v;
683699
jl_value_t *m = mi->def.value;
684700
if (jl_is_method(m) && jl_object_in_image(m))
685-
return 1 + type_in_worklist(mi->specTypes);
701+
return 1 + type_in_worklist(mi->specTypes, query_cache);
686702
}
687703
if (jl_is_binding(v)) {
688704
jl_globalref_t *gr = ((jl_binding_t*)v)->globalref;
@@ -697,24 +713,24 @@ static int caching_tag(jl_value_t *v) JL_NOTSAFEPOINT
697713
if (jl_is_tuple_type(dt) ? !dt->isconcretetype : dt->hasfreetypevars)
698714
return 0; // aka !is_cacheable from jltypes.c
699715
if (jl_object_in_image((jl_value_t*)dt->name))
700-
return 1 + type_in_worklist(v);
716+
return 1 + type_in_worklist(v, query_cache);
701717
}
702718
jl_value_t *dtv = jl_typeof(v);
703719
if (jl_is_datatype_singleton((jl_datatype_t*)dtv)) {
704-
return 1 - type_in_worklist(dtv); // these are already recached in the datatype in the image
720+
return 1 - type_in_worklist(dtv, query_cache); // these are already recached in the datatype in the image
705721
}
706722
return 0;
707723
}
708724

709-
static int needs_recaching(jl_value_t *v) JL_NOTSAFEPOINT
725+
static int needs_recaching(jl_value_t *v, jl_query_cache *query_cache) JL_NOTSAFEPOINT
710726
{
711-
return caching_tag(v) == 2;
727+
return caching_tag(v, query_cache) == 2;
712728
}
713729

714-
static int needs_uniquing(jl_value_t *v) JL_NOTSAFEPOINT
730+
static int needs_uniquing(jl_value_t *v, jl_query_cache *query_cache) JL_NOTSAFEPOINT
715731
{
716732
assert(!jl_object_in_image(v));
717-
return caching_tag(v) == 1;
733+
return caching_tag(v, query_cache) == 1;
718734
}
719735

720736
static void record_field_change(jl_value_t **addr, jl_value_t *newval) JL_NOTSAFEPOINT
@@ -798,7 +814,6 @@ static void jl_queue_module_for_serialization(jl_serializer_state *s, jl_module_
798814
// ... or point to Base functions accessed by the runtime
799815
(m == jl_base_module && (!strcmp(jl_symbol_name(b->globalref->name), "wait") ||
800816
!strcmp(jl_symbol_name(b->globalref->name), "task_done_hook"))))) {
801-
record_field_change((jl_value_t**)&b->backedges, NULL);
802817
jl_queue_for_serialization(s, b);
803818
}
804819
}
@@ -840,7 +855,7 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_
840855
jl_datatype_t *dt = (jl_datatype_t*)v;
841856
// ensure all type parameters are recached
842857
jl_queue_for_serialization_(s, (jl_value_t*)dt->parameters, 1, 1);
843-
if (jl_is_datatype_singleton(dt) && needs_uniquing(dt->instance)) {
858+
if (jl_is_datatype_singleton(dt) && needs_uniquing(dt->instance, s->query_cache)) {
844859
assert(jl_needs_serialization(s, dt->instance)); // should be true, since we visited dt
845860
// do not visit dt->instance for our template object as it leads to unwanted cycles here
846861
// (it may get serialized from elsewhere though)
@@ -851,7 +866,7 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_
851866
if (s->incremental && jl_is_method_instance(v)) {
852867
jl_method_instance_t *mi = (jl_method_instance_t*)v;
853868
jl_value_t *def = mi->def.value;
854-
if (needs_uniquing(v)) {
869+
if (needs_uniquing(v, s->query_cache)) {
855870
// we only need 3 specific fields of this (the rest are not used)
856871
jl_queue_for_serialization(s, mi->def.value);
857872
jl_queue_for_serialization(s, mi->specTypes);
@@ -866,7 +881,7 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_
866881
record_field_change((jl_value_t**)&mi->cache, NULL);
867882
}
868883
else {
869-
assert(!needs_recaching(v));
884+
assert(!needs_recaching(v, s->query_cache));
870885
}
871886
// n.b. opaque closures cannot be inspected and relied upon like a
872887
// normal method since they can get improperly introduced by generated
@@ -876,7 +891,7 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_
876891
// error now.
877892
}
878893
if (s->incremental && jl_is_binding(v)) {
879-
if (needs_uniquing(v)) {
894+
if (needs_uniquing(v, s->query_cache)) {
880895
jl_binding_t *b = (jl_binding_t*)v;
881896
jl_queue_for_serialization(s, b->globalref->mod);
882897
jl_queue_for_serialization(s, b->globalref->name);
@@ -1044,6 +1059,9 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_
10441059
record_field_change((jl_value_t **)&tn->mt, NULL);
10451060
}
10461061
}
1062+
else if (jl_is_binding(v)) {
1063+
record_field_change((jl_value_t**)&((jl_binding_t*)v)->backedges, NULL);
1064+
}
10471065
}
10481066
char *data = (char*)jl_data_ptr(v);
10491067
size_t i, np = layout->npointers;
@@ -1100,9 +1118,9 @@ static void jl_queue_for_serialization_(jl_serializer_state *s, jl_value_t *v, i
11001118
// Items that require postorder traversal must visit their children prior to insertion into
11011119
// the worklist/serialization_order (and also before their first use)
11021120
if (s->incremental && !immediate) {
1103-
if (jl_is_datatype(t) && needs_uniquing(v))
1121+
if (jl_is_datatype(t) && needs_uniquing(v, s->query_cache))
11041122
immediate = 1;
1105-
if (jl_is_datatype_singleton((jl_datatype_t*)t) && needs_uniquing(v))
1123+
if (jl_is_datatype_singleton((jl_datatype_t*)t) && needs_uniquing(v, s->query_cache))
11061124
immediate = 1;
11071125
}
11081126

@@ -1265,7 +1283,7 @@ static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v, jl_array_t *
12651283

12661284
static void record_uniquing(jl_serializer_state *s, jl_value_t *fld, uintptr_t offset) JL_NOTSAFEPOINT
12671285
{
1268-
if (s->incremental && jl_needs_serialization(s, fld) && needs_uniquing(fld)) {
1286+
if (s->incremental && jl_needs_serialization(s, fld) && needs_uniquing(fld, s->query_cache)) {
12691287
if (jl_is_datatype(fld) || jl_is_datatype_singleton((jl_datatype_t*)jl_typeof(fld)))
12701288
arraylist_push(&s->uniquing_types, (void*)(uintptr_t)offset);
12711289
else if (jl_is_method_instance(fld) || jl_is_binding(fld))
@@ -1489,7 +1507,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
14891507
// write header
14901508
if (object_id_expected)
14911509
write_uint(f, jl_object_id(v));
1492-
if (s->incremental && jl_needs_serialization(s, (jl_value_t*)t) && needs_uniquing((jl_value_t*)t))
1510+
if (s->incremental && jl_needs_serialization(s, (jl_value_t*)t) && needs_uniquing((jl_value_t*)t, s->query_cache))
14931511
arraylist_push(&s->uniquing_types, (void*)(uintptr_t)(ios_pos(f)|1));
14941512
if (f == s->const_data)
14951513
write_uint(s->const_data, ((uintptr_t)t->smalltag << 4) | GC_OLD_MARKED | GC_IN_IMAGE);
@@ -1500,7 +1518,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
15001518
layout_table.items[item] = (void*)(reloc_offset | (f == s->const_data)); // store the inverse mapping of `serialization_order` (`id` => object-as-streampos)
15011519

15021520
if (s->incremental) {
1503-
if (needs_uniquing(v)) {
1521+
if (needs_uniquing(v, s->query_cache)) {
15041522
if (jl_typetagis(v, jl_binding_type)) {
15051523
jl_binding_t *b = (jl_binding_t*)v;
15061524
if (b->globalref == NULL)
@@ -1529,7 +1547,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
15291547
assert(jl_is_datatype_singleton(t) && "unreachable");
15301548
}
15311549
}
1532-
else if (needs_recaching(v)) {
1550+
else if (needs_recaching(v, s->query_cache)) {
15331551
arraylist_push(jl_is_datatype(v) ? &s->fixup_types : &s->fixup_objs, (void*)reloc_offset);
15341552
}
15351553
}
@@ -1962,7 +1980,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
19621980
}
19631981
}
19641982
void *superidx = ptrhash_get(&serialization_order, dt->super);
1965-
if (s->incremental && superidx != HT_NOTFOUND && from_seroder_entry(superidx) > item && needs_uniquing((jl_value_t*)dt->super))
1983+
if (s->incremental && superidx != HT_NOTFOUND && from_seroder_entry(superidx) > item && needs_uniquing((jl_value_t*)dt->super, s->query_cache))
19661984
arraylist_push(&s->uniquing_super, dt->super);
19671985
}
19681986
else if (jl_is_typename(v)) {
@@ -2873,13 +2891,14 @@ JL_DLLEXPORT jl_value_t *jl_as_global_root(jl_value_t *val, int insert)
28732891
static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *newly_inferred,
28742892
/* outputs */ jl_array_t **extext_methods JL_REQUIRE_ROOTED_SLOT,
28752893
jl_array_t **new_ext_cis JL_REQUIRE_ROOTED_SLOT,
2876-
jl_array_t **edges JL_REQUIRE_ROOTED_SLOT)
2894+
jl_array_t **edges JL_REQUIRE_ROOTED_SLOT,
2895+
jl_query_cache *query_cache)
28772896
{
28782897
// extext_methods: [method1, ...], worklist-owned "extending external" methods added to functions owned by modules outside the worklist
28792898
// edges: [caller1, ext_targets, ...] for worklist-owned methods calling external methods
28802899

28812900
// Save the inferred code from newly inferred, external methods
2882-
*new_ext_cis = queue_external_cis(newly_inferred);
2901+
*new_ext_cis = queue_external_cis(newly_inferred, query_cache);
28832902

28842903
// Collect method extensions and edges data
28852904
*extext_methods = jl_alloc_vec_any(0);
@@ -2909,7 +2928,8 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new
29092928
// In addition to the system image (where `worklist = NULL`), this can also save incremental images with external linkage
29102929
static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
29112930
jl_array_t *worklist, jl_array_t *extext_methods,
2912-
jl_array_t *new_ext_cis, jl_array_t *edges)
2931+
jl_array_t *new_ext_cis, jl_array_t *edges,
2932+
jl_query_cache *query_cache)
29132933
{
29142934
htable_new(&field_replace, 0);
29152935
htable_new(&bits_replace, 0);
@@ -3016,6 +3036,7 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
30163036
ios_mem(&gvar_record, 0);
30173037
ios_mem(&fptr_record, 0);
30183038
jl_serializer_state s = {0};
3039+
s.query_cache = query_cache;
30193040
s.incremental = !(worklist == NULL);
30203041
s.s = &sysimg;
30213042
s.const_data = &const_data;
@@ -3373,11 +3394,14 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
33733394
int64_t datastartpos = 0;
33743395
JL_GC_PUSH4(&mod_array, &extext_methods, &new_ext_cis, &edges);
33753396

3397+
jl_query_cache query_cache;
3398+
init_query_cache(&query_cache);
3399+
33763400
if (worklist) {
33773401
mod_array = jl_get_loaded_modules(); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
33783402
// Generate _native_data`
33793403
if (_native_data != NULL) {
3380-
jl_prepare_serialization_data(mod_array, newly_inferred, &extext_methods, &new_ext_cis, NULL);
3404+
jl_prepare_serialization_data(mod_array, newly_inferred, &extext_methods, &new_ext_cis, NULL, &query_cache);
33813405
jl_precompile_toplevel_module = (jl_module_t*)jl_array_ptr_ref(worklist, jl_array_len(worklist)-1);
33823406
*_native_data = jl_precompile_worklist(worklist, extext_methods, new_ext_cis);
33833407
jl_precompile_toplevel_module = NULL;
@@ -3408,7 +3432,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
34083432
assert((ct->reentrant_timing & 0b1110) == 0);
34093433
ct->reentrant_timing |= 0b1000;
34103434
if (worklist) {
3411-
jl_prepare_serialization_data(mod_array, newly_inferred, &extext_methods, &new_ext_cis, &edges);
3435+
jl_prepare_serialization_data(mod_array, newly_inferred, &extext_methods, &new_ext_cis, &edges, &query_cache);
34123436
if (!emit_split) {
34133437
write_int32(f, 0); // No clone_targets
34143438
write_padding(f, LLT_ALIGN(ios_pos(f), JL_CACHE_BYTE_ALIGNMENT) - ios_pos(f));
@@ -3420,7 +3444,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
34203444
}
34213445
if (_native_data != NULL)
34223446
native_functions = *_native_data;
3423-
jl_save_system_image_to_stream(ff, mod_array, worklist, extext_methods, new_ext_cis, edges);
3447+
jl_save_system_image_to_stream(ff, mod_array, worklist, extext_methods, new_ext_cis, edges, &query_cache);
34243448
if (_native_data != NULL)
34253449
native_functions = NULL;
34263450
// make sure we don't run any Julia code concurrently before this point
@@ -3449,6 +3473,8 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
34493473
}
34503474
}
34513475

3476+
destroy_query_cache(&query_cache);
3477+
34523478
JL_GC_POP();
34533479
*s = f;
34543480
if (emit_split)

0 commit comments

Comments
 (0)