Skip to content

Commit 31f5a63

Browse files
committed
Merge pull request #16745 from JuliaLang/jn/precompile-kwfunc
serialize kwftypes via their real type
2 parents 06f1857 + df90d8e commit 31f5a63

File tree

2 files changed

+63
-40
lines changed

2 files changed

+63
-40
lines changed

src/dump.c

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,20 @@ static void jl_serialize_datatype(ios_t *s, jl_datatype_t *dt)
529529
tag = 4;
530530
else if (dt == jl_uint8_type)
531531
tag = 8;
532+
533+
if (strncmp(jl_symbol_name(dt->name->name), "#kw#", 4) == 0) {
534+
/* XXX: yuck, but the auto-generated kw types from the serializer isn't a real type, so we *must* be very careful */
535+
assert(tag == 0 || tag == 5 || tag == 6);
536+
if (tag == 6) {
537+
jl_methtable_t *mt = dt->name->mt;
538+
jl_datatype_t *primarydt = (jl_datatype_t*)jl_get_global(mt->module, mt->name);
539+
assert(jl_is_datatype(primarydt));
540+
assert(jl_typeof(primarydt->name->mt->kwsorter) == (jl_value_t*)dt);
541+
dt = primarydt;
542+
tag = 9;
543+
}
544+
}
545+
532546
writetag(s, (jl_value_t*)SmallDataType_tag);
533547
write_uint8(s, 0); // virtual size
534548
jl_serialize_value(s, (jl_value_t*)jl_datatype_type);
@@ -542,6 +556,11 @@ static void jl_serialize_datatype(ios_t *s, jl_datatype_t *dt)
542556
jl_serialize_value(s, dt->parameters);
543557
return;
544558
}
559+
if (tag == 9) {
560+
jl_serialize_value(s, dt);
561+
return;
562+
}
563+
545564
size_t nf = jl_datatype_nfields(dt);
546565
write_uint16(s, nf);
547566
write_int32(s, dt->size);
@@ -993,37 +1012,25 @@ struct jl_serialize_methcache_from_mod_env {
9931012
ios_t *s;
9941013
jl_sym_t *name;
9951014
jl_module_t *mod;
996-
int8_t iskw;
9971015
};
9981016

9991017
static int jl_serialize_methcache_from_mod(jl_typemap_entry_t *ml, void *closure)
10001018
{
10011019
struct jl_serialize_methcache_from_mod_env *env = (struct jl_serialize_methcache_from_mod_env*)closure;
10021020
if (module_in_worklist(ml->func.method->module)) {
1003-
jl_serialize_value(env->s, env->mod);
1004-
jl_serialize_value(env->s, env->name);
1005-
write_int8(env->s, env->iskw);
1006-
jl_serialize_value(env->s, ml->simplesig);
10071021
jl_serialize_value(env->s, ml->func.method);
1022+
jl_serialize_value(env->s, ml->simplesig);
10081023
}
10091024
return 1;
10101025
}
10111026

1012-
static void jl_serialize_methtable_from_mod(ios_t *s, jl_typename_t *tn, int8_t iskw)
1027+
static void jl_serialize_methtable_from_mod(ios_t *s, jl_typename_t *tn)
10131028
{
10141029
struct jl_serialize_methcache_from_mod_env env;
10151030
env.s = s;
10161031
env.mod = tn->module;
10171032
env.name = tn->name;
1018-
env.iskw = iskw;
10191033
assert(tn->module);
1020-
if (iskw) {
1021-
if (!tn->mt->kwsorter)
1022-
return;
1023-
assert(tn->mt->module == jl_gf_mtable(tn->mt->kwsorter)->module);
1024-
tn = ((jl_datatype_t*)jl_typeof(tn->mt->kwsorter))->name;
1025-
assert(tn->mt->kwsorter == NULL);
1026-
}
10271034
jl_typemap_visitor(tn->mt->defs, jl_serialize_methcache_from_mod, &env);
10281035
}
10291036

@@ -1036,14 +1043,12 @@ static void jl_serialize_lambdas_from_mod(ios_t *s, jl_module_t *m)
10361043
if (table[i] != HT_NOTFOUND) {
10371044
jl_binding_t *b = (jl_binding_t*)table[i];
10381045
if (b->owner == m && b->value && b->constp) {
1039-
if (jl_is_datatype(b->value) &&
1040-
(strlen(jl_symbol_name(b->name)) <= 4 || strncmp(jl_symbol_name(b->name), "#kw#", 4))) { /* XXX: yuck, but the auto-generated kw types from the serializer isn't a real type, so we *must* reject it */
1046+
if (jl_is_datatype(b->value)) {
10411047
jl_typename_t *tn = ((jl_datatype_t*)b->value)->name;
10421048
if (tn->module == m && tn->name == b->name) {
10431049
jl_methtable_t *mt = tn->mt;
10441050
if (mt != NULL && (jl_value_t*)mt != jl_nothing && (mt != jl_type_type_mt || tn == jl_type_type->name)) {
1045-
jl_serialize_methtable_from_mod(s, tn, 0);
1046-
jl_serialize_methtable_from_mod(s, tn, 1);
1051+
jl_serialize_methtable_from_mod(s, tn);
10471052
}
10481053
}
10491054
}
@@ -1175,12 +1180,18 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos, jl_value_t **loc)
11751180
backref_list.items[pos] = dtv;
11761181
return dtv;
11771182
}
1183+
if (tag == 9) {
1184+
jl_datatype_t *primarydt = (jl_datatype_t*)jl_deserialize_value(s, NULL);
1185+
jl_value_t *dtv = jl_typeof(jl_get_kwsorter(primarydt->name));
1186+
backref_list.items[pos] = dtv;
1187+
return dtv;
1188+
}
11781189
uint16_t nf = read_uint16(s);
11791190
size_t size = read_int32(s);
11801191
uint8_t flags = read_uint8(s);
11811192
uint8_t depth = read_int32(s);
11821193
uint8_t fielddesc_type = read_int8(s);
1183-
jl_datatype_t *dt;
1194+
jl_datatype_t *dt = NULL;
11841195
if (tag == 2)
11851196
dt = jl_int32_type;
11861197
else if (tag == 3)
@@ -1189,8 +1200,10 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos, jl_value_t **loc)
11891200
dt = jl_int64_type;
11901201
else if (tag == 8)
11911202
dt = jl_uint8_type;
1192-
else
1203+
else if (tag == 0 || tag == 5)
11931204
dt = jl_new_uninitialized_datatype(nf, fielddesc_type);
1205+
else
1206+
assert(0);
11941207
assert(tree_literal_values==NULL && mode != MODE_AST);
11951208
backref_list.items[pos] = dt;
11961209
dt->size = size;
@@ -1684,19 +1697,12 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t
16841697
static void jl_deserialize_lambdas_from_mod(ios_t *s)
16851698
{
16861699
while (1) {
1687-
jl_module_t *mod = (jl_module_t*)jl_deserialize_value(s, NULL);
1688-
if (mod == NULL)
1700+
jl_method_t *meth = (jl_method_t*)jl_deserialize_value(s, NULL);
1701+
if (meth == NULL)
16891702
return;
1690-
jl_sym_t *name = (jl_sym_t*)jl_deserialize_value(s, NULL);
1691-
jl_datatype_t *gf = (jl_datatype_t*)jl_get_global(mod, name);
1692-
assert(jl_is_datatype(gf));
1693-
int8_t iskw = read_int8(s);
1694-
if (iskw) {
1695-
gf = (jl_datatype_t*)jl_typeof(jl_get_kwsorter(gf->name));
1696-
assert(jl_is_datatype(gf));
1697-
}
16981703
jl_tupletype_t *simpletype = (jl_tupletype_t*)jl_deserialize_value(s, NULL);
1699-
jl_method_t *meth = (jl_method_t*)jl_deserialize_value(s, NULL);
1704+
jl_datatype_t *gf = (jl_datatype_t*)jl_tparam0(meth->sig);
1705+
assert(jl_is_datatype(gf));
17001706
jl_method_table_insert(gf->name->mt, meth, simpletype);
17011707
}
17021708
}

test/compile.jl

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using Base.Test
44

55
function redirected_stderr()
66
rd, wr = redirect_stderr()
7-
@async readall(rd) # make sure the kernel isn't being forced to buffer the output
7+
@async readstring(rd) # make sure the kernel isn't being forced to buffer the output
88
nothing
99
end
1010

@@ -20,16 +20,28 @@ try
2020
write(Foo_file,
2121
"""
2222
__precompile__(true)
23+
24+
# test that docs get reconnected
2325
module $Foo_module
24-
@doc "foo function" foo(x) = x + 1
25-
include_dependency("foo.jl")
26-
include_dependency("foo.jl")
27-
module Bar
28-
@doc "bar function" bar(x) = x + 2
29-
include_dependency("bar.jl")
30-
end
26+
@doc "foo function" foo(x) = x + 1
27+
include_dependency("foo.jl")
28+
include_dependency("foo.jl")
29+
module Bar
30+
@doc "bar function" bar(x) = x + 2
31+
include_dependency("bar.jl")
32+
end
33+
34+
# test that types and methods get reconnected correctly
35+
# issue 16529 (adding a method to a type with no instances)
36+
(::Task)(::UInt8, ::UInt16, ::UInt32) = 2
37+
38+
# issue 16471 (capturing references to an kwfunc)
39+
Base.Test.@test_throws ErrorException Core.kwfunc(Base.nothing)
40+
Base.nothing(::UInt8, ::UInt16, ::UInt32; x = 52) = x
41+
const nothingkw = Core.kwfunc(Base.nothing)
3142
end
3243
""")
44+
@test_throws ErrorException Core.kwfunc(Base.nothing) # make sure `nothing` didn't have a kwfunc (which would invalidate the attempted test)
3345

3446
# Issue #12623
3547
@test __precompile__(true) === nothing
@@ -38,7 +50,7 @@ try
3850
cachefile = joinpath(dir, "$Foo_module.ji")
3951

4052
# use _require_from_serialized to ensure that the test fails if
41-
# the module doesn't load from the image:
53+
# the module doesn't reload from the image:
4254
try
4355
redirected_stderr()
4456
@test nothing !== Base._require_from_serialized(myid(), Foo_module, #=broadcast-load=#false)
@@ -58,6 +70,11 @@ try
5870
@test sort(deps[1]) == map(s -> (s, Base.module_uuid(eval(s))),
5971
[:Base,:Core,:Main])
6072
@test map(x -> x[1], sort(deps[2])) == [Foo_file,joinpath(dir,"bar.jl"),joinpath(dir,"foo.jl")]
73+
74+
@test current_task()(0x01, 0x4000, 0x30031234) == 2
75+
@test nothing(0x01, 0x4000, 0x30031234) == 52
76+
@test nothing(0x01, 0x4000, 0x30031234; x = 9142) == 9142
77+
@test Foo.nothingkw === Core.kwfunc(Base.nothing)
6178
end
6279

6380
Baz_file = joinpath(dir, "Baz.jl")

0 commit comments

Comments
 (0)