Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,9 @@ JL_DLLEXPORT void jl_method_set_source(jl_method_t *m, jl_code_info_t *src)
}
src = jl_copy_code_info(src);
src->isva = m->isva; // TODO: It would be nice to reverse this
// If nargs hasn't been set yet, do it now. This can happen if an old CodeInfo is deserialized.
if (src->nargs == 0)
src->nargs = m->nargs;
assert(m->nargs == src->nargs);
src->code = copy;
jl_gc_wb(src, copy);
Expand Down
36 changes: 33 additions & 3 deletions stdlib/Serialization/src/Serialization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Provide serialization of Julia objects via the functions
module Serialization

import Base: Bottom, unsafe_convert
import Base.ScopedValues: ScopedValue, with
import Core: svec, SimpleVector
using Base: unaliascopy, unwrap_unionall, require_one_based_indexing, ntupleany
using Core.IR
Expand All @@ -28,6 +29,8 @@ end

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

const current_module = ScopedValue{Union{Nothing,Module}}(nothing)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this just a struct field of the Serializer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it can be, I just wanted to avoid mutation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, now I know why: there are other subtypes that won't have the field, so rather than need to add it to all of them I think the ScopedValue is better.


## serializing values ##

const n_int_literals = 33
Expand Down Expand Up @@ -1064,7 +1067,10 @@ function deserialize(s::AbstractSerializer, ::Type{Method})
nospecializeinfer = false
constprop = 0x00
purity = 0x0000
template_or_is_opaque = deserialize(s)
local template_or_is_opaque, template
with(current_module => mod) do
template_or_is_opaque = deserialize(s)
end
if isa(template_or_is_opaque, Bool)
is_for_opaque_closure = template_or_is_opaque
if format_version(s) >= 24
Expand All @@ -1078,7 +1084,9 @@ function deserialize(s::AbstractSerializer, ::Type{Method})
elseif format_version(s) >= 17
purity = UInt16(deserialize(s)::UInt8)
end
template = deserialize(s)
with(current_module => mod) do
template = deserialize(s)
end
else
template = template_or_is_opaque
end
Expand Down Expand Up @@ -1182,6 +1190,22 @@ function deserialize(s::AbstractSerializer, ::Type{PhiNode})
return PhiNode(edges, values)
end

# v1.12 disallows bare symbols in IR, but older CodeInfos might still have them
function symbol_to_globalref(@nospecialize(x), m::Module)
mapper(@nospecialize(x)) = symbol_to_globalref(x, m)
if x isa Symbol
return GlobalRef(m, x)
elseif x isa Expr
return Expr(x.head, map(mapper, x.args)...)
elseif x isa ReturnNode
return ReturnNode(mapper(x.val))
elseif x isa GotoIfNot
return GotoIfNot(mapper(x.cond), x.dest)
else
return x
end
end

function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
ci = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ())
deserialize_cycle(s, ci)
Expand All @@ -1200,6 +1224,9 @@ function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
end
end
end
if current_module[] !== nothing
map!(x->symbol_to_globalref(x, current_module[]), code)
end
_x = deserialize(s)
have_debuginfo = _x isa Core.DebugInfo
if have_debuginfo
Expand Down Expand Up @@ -1248,6 +1275,9 @@ function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
ci.slottypes = deserialize(s)
ci.rettype = deserialize(s)
ci.parent = deserialize(s)
if format_version(s) < 29 && ci.parent isa MethodInstance && ci.parent.def isa Method
ci.nargs = ci.parent.def.nargs
end
world_or_edges = deserialize(s)
pre_13 = isa(world_or_edges, Union{UInt, Int})
if pre_13
Expand All @@ -1258,7 +1288,7 @@ function deserialize(s::AbstractSerializer, ::Type{CodeInfo})
ci.min_world = deserialize(s)::UInt
ci.max_world = deserialize(s)::UInt
end
if format_version(s) >= 26
if format_version(s) >= 29
ci.method_for_inference_limit_heuristics = deserialize(s)
end
end
Expand Down
12 changes: 12 additions & 0 deletions stdlib/Serialization/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Test, Random, Serialization, Base64
using Base.ScopedValues: with

# Check that serializer hasn't gone out-of-frame
@test Serialization.sertag(Symbol) == 1
Expand Down Expand Up @@ -661,3 +662,14 @@ end
@test_broken isempty(undoc)
@test undoc == [:AbstractSerializer, :Serializer]
end

# test method definitions from v1.11
if Int === Int64
let f_data = "N0pMGgQAAAAWAQEFdGh1bmsbFUbnFgEBBXRodW5rGxVG4DoWAQEGbWV0aG9kAQtmMTExX3RvXzExMhUABuABAAAA4BUAB+AAAAAAThVG4DQQAQxMaW5lSW5mb05vZGUfTptEH04BBE1haW5EAQ90b3AtbGV2ZWwgc2NvcGUBBG5vbmW+vhUAAd8V305GTk4JAQAAAAAAAAAJ//////////9MTExMAwADAAUAAAX//xYBAQZtZXRob2QsBwAWAlYkH06bRAEGVHlwZW9mLAcAFgNWJB9Om0QBBHN2ZWMo4iQfTptETxYBViQfTptEAQRzdmVjFgRWJB9Om0QBBHN2ZWMo4yjkGhfgAQRub25lFgMBBm1ldGhvZCwHACjlGxVG5AEBXhYDViQfTptElyQfTp5EAQNWYWzhFgFWKOEWBFYkH06eRAELbGl0ZXJhbF9wb3co4CXhKOI6KOMVAAbkAQAAAAEAAAABAAAAAQAAAAAAAADkFQAH5AAAAAAAAAAAAAAAAAAAAAAAAAAAThVG4DQsCwAfTgEETWFpbkQBBG5vbmUBBG5vbmW/vhUAAeGifRXhAAhORk5OCQEAAAAAAAAACf//////////TExMTAMAAwAFAAAF//86ThUABucBAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAOcVAAfnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOFUbgNCwLAB9OAQRNYWluRCwNAAEEbm9uZb6+FQAB3xXfTkZOTgkBAAAAAAAAAAn//////////0xMTEwDAAMABQAABf//"
@eval Main function f111_to_112 end
Core.eval(Main, with(Serialization.current_module => Main) do
deserialize(IOBuffer(base64decode(f_data)))
end)
@test @invokelatest(Main.f111_to_112(16)) == 256
end
end