Skip to content

Commit 9f69961

Browse files
authored
fix serializer compat with CodeInfos from v1.11 (#58650)
1 parent ce600a0 commit 9f69961

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

src/method.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,9 @@ JL_DLLEXPORT void jl_method_set_source(jl_method_t *m, jl_code_info_t *src)
958958
}
959959
src = jl_copy_code_info(src);
960960
src->isva = m->isva; // TODO: It would be nice to reverse this
961+
// If nargs hasn't been set yet, do it now. This can happen if an old CodeInfo is deserialized.
962+
if (src->nargs == 0)
963+
src->nargs = m->nargs;
961964
assert(m->nargs == src->nargs);
962965
src->code = copy;
963966
jl_gc_wb(src, copy);

stdlib/Serialization/src/Serialization.jl

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Provide serialization of Julia objects via the functions
88
module Serialization
99

1010
import Base: Bottom, unsafe_convert
11+
import Base.ScopedValues: ScopedValue, with
1112
import Core: svec, SimpleVector
1213
using Base: unaliascopy, unwrap_unionall, require_one_based_indexing, ntupleany
1314
using Core.IR
@@ -28,6 +29,8 @@ end
2829

2930
Serializer(io::IO) = Serializer{typeof(io)}(io)
3031

32+
const current_module = ScopedValue{Union{Nothing,Module}}(nothing)
33+
3134
## serializing values ##
3235

3336
const n_int_literals = 33
@@ -1064,7 +1067,10 @@ function deserialize(s::AbstractSerializer, ::Type{Method})
10641067
nospecializeinfer = false
10651068
constprop = 0x00
10661069
purity = 0x0000
1067-
template_or_is_opaque = deserialize(s)
1070+
local template_or_is_opaque, template
1071+
with(current_module => mod) do
1072+
template_or_is_opaque = deserialize(s)
1073+
end
10681074
if isa(template_or_is_opaque, Bool)
10691075
is_for_opaque_closure = template_or_is_opaque
10701076
if format_version(s) >= 24
@@ -1078,7 +1084,9 @@ function deserialize(s::AbstractSerializer, ::Type{Method})
10781084
elseif format_version(s) >= 17
10791085
purity = UInt16(deserialize(s)::UInt8)
10801086
end
1081-
template = deserialize(s)
1087+
with(current_module => mod) do
1088+
template = deserialize(s)
1089+
end
10821090
else
10831091
template = template_or_is_opaque
10841092
end
@@ -1182,6 +1190,22 @@ function deserialize(s::AbstractSerializer, ::Type{PhiNode})
11821190
return PhiNode(edges, values)
11831191
end
11841192

1193+
# v1.12 disallows bare symbols in IR, but older CodeInfos might still have them
1194+
function symbol_to_globalref(@nospecialize(x), m::Module)
1195+
mapper(@nospecialize(x)) = symbol_to_globalref(x, m)
1196+
if x isa Symbol
1197+
return GlobalRef(m, x)
1198+
elseif x isa Expr
1199+
return Expr(x.head, map(mapper, x.args)...)
1200+
elseif x isa ReturnNode
1201+
return ReturnNode(mapper(x.val))
1202+
elseif x isa GotoIfNot
1203+
return GotoIfNot(mapper(x.cond), x.dest)
1204+
else
1205+
return x
1206+
end
1207+
end
1208+
11851209
function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
11861210
ci = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ())
11871211
deserialize_cycle(s, ci)
@@ -1200,6 +1224,9 @@ function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
12001224
end
12011225
end
12021226
end
1227+
if current_module[] !== nothing
1228+
map!(x->symbol_to_globalref(x, current_module[]), code)
1229+
end
12031230
_x = deserialize(s)
12041231
have_debuginfo = _x isa Core.DebugInfo
12051232
if have_debuginfo
@@ -1248,6 +1275,9 @@ function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
12481275
ci.slottypes = deserialize(s)
12491276
ci.rettype = deserialize(s)
12501277
ci.parent = deserialize(s)
1278+
if format_version(s) < 29 && ci.parent isa MethodInstance && ci.parent.def isa Method
1279+
ci.nargs = ci.parent.def.nargs
1280+
end
12511281
world_or_edges = deserialize(s)
12521282
pre_13 = isa(world_or_edges, Union{UInt, Int})
12531283
if pre_13
@@ -1258,7 +1288,7 @@ function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
12581288
ci.min_world = deserialize(s)::UInt
12591289
ci.max_world = deserialize(s)::UInt
12601290
end
1261-
if format_version(s) >= 26
1291+
if format_version(s) >= 29
12621292
ci.method_for_inference_limit_heuristics = deserialize(s)
12631293
end
12641294
end

stdlib/Serialization/test/runtests.jl

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

33
using Test, Random, Serialization, Base64
4+
using Base.ScopedValues: with
45

56
# Check that serializer hasn't gone out-of-frame
67
@test Serialization.sertag(Symbol) == 1
@@ -661,3 +662,14 @@ end
661662
@test_broken isempty(undoc)
662663
@test undoc == [:AbstractSerializer, :Serializer]
663664
end
665+
666+
# test method definitions from v1.11
667+
if Int === Int64
668+
let f_data = "N0pMGgQAAAAWAQEFdGh1bmsbFUbnFgEBBXRodW5rGxVG4DoWAQEGbWV0aG9kAQtmMTExX3RvXzExMhUABuABAAAA4BUAB+AAAAAAThVG4DQQAQxMaW5lSW5mb05vZGUfTptEH04BBE1haW5EAQ90b3AtbGV2ZWwgc2NvcGUBBG5vbmW+vhUAAd8V305GTk4JAQAAAAAAAAAJ//////////9MTExMAwADAAUAAAX//xYBAQZtZXRob2QsBwAWAlYkH06bRAEGVHlwZW9mLAcAFgNWJB9Om0QBBHN2ZWMo4iQfTptETxYBViQfTptEAQRzdmVjFgRWJB9Om0QBBHN2ZWMo4yjkGhfgAQRub25lFgMBBm1ldGhvZCwHACjlGxVG5AEBXhYDViQfTptElyQfTp5EAQNWYWzhFgFWKOEWBFYkH06eRAELbGl0ZXJhbF9wb3co4CXhKOI6KOMVAAbkAQAAAAEAAAABAAAAAQAAAAAAAADkFQAH5AAAAAAAAAAAAAAAAAAAAAAAAAAAThVG4DQsCwAfTgEETWFpbkQBBG5vbmUBBG5vbmW/vhUAAeGifRXhAAhORk5OCQEAAAAAAAAACf//////////TExMTAMAAwAFAAAF//86ThUABucBAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAOcVAAfnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOFUbgNCwLAB9OAQRNYWluRCwNAAEEbm9uZb6+FQAB3xXfTkZOTgkBAAAAAAAAAAn//////////0xMTEwDAAMABQAABf//"
669+
@eval Main function f111_to_112 end
670+
Core.eval(Main, with(Serialization.current_module => Main) do
671+
deserialize(IOBuffer(base64decode(f_data)))
672+
end)
673+
@test @invokelatest(Main.f111_to_112(16)) == 256
674+
end
675+
end

0 commit comments

Comments
 (0)