374
374
function serialize (s:: AbstractSerializer , g:: GlobalRef )
375
375
writetag (s. io, GLOBALREF_TAG)
376
376
if g. mod === Main && isdefined (g. mod, g. name) && isconst (g. mod, g. name)
377
- v = eval (g )
377
+ v = getfield (g . mod, g . name )
378
378
if isa (v, DataType) && v === v. name. primary && should_send_whole_type (s, v)
379
379
# handle references to types in Main by sending the whole type.
380
380
# needed to be able to send nested functions (#15451).
@@ -393,17 +393,16 @@ function serialize(s::AbstractSerializer, t::TypeName)
393
393
serialize_cycle (s, t) && return
394
394
writetag (s. io, TYPENAME_TAG)
395
395
write (s. io, object_number (t))
396
- serialize (s, t. name)
397
- serialize (s, t. module)
398
- serialize_typename_body (s, t)
396
+ serialize_typename (s, t)
399
397
end
400
398
401
- function serialize_typename_body (s:: AbstractSerializer , t:: TypeName )
399
+ function serialize_typename (s:: AbstractSerializer , t:: TypeName )
400
+ serialize (s, t. name)
402
401
serialize (s, t. names)
403
402
serialize (s, t. primary. super)
404
403
serialize (s, t. primary. parameters)
405
404
serialize (s, t. primary. types)
406
- serialize (s, t. primary. size )
405
+ serialize (s, isdefined ( t. primary, :instance ) )
407
406
serialize (s, t. primary. abstract)
408
407
serialize (s, t. primary. mutable)
409
408
serialize (s, t. primary. ninitialized)
@@ -419,27 +418,32 @@ function serialize_typename_body(s::AbstractSerializer, t::TypeName)
419
418
else
420
419
writetag (s. io, UNDEFREF_TAG)
421
420
end
421
+ nothing
422
422
end
423
423
424
424
# decide whether to send all data for a type (instead of just its name)
425
- function should_send_whole_type (s, t:: ANY )
425
+ function should_send_whole_type (s, t:: DataType )
426
426
tn = t. name
427
427
if isdefined (tn, :mt )
428
428
# TODO improve somehow
429
429
# send whole type for anonymous functions in Main
430
- fname = tn. mt. name
430
+ name = tn. mt. name
431
431
mod = tn. module
432
- toplevel = isdefined (mod, fname) && isdefined (t, :instance ) &&
433
- getfield (mod, fname) === t. instance
434
- ishidden = unsafe_load (unsafe_convert (Ptr{UInt8}, fname))== UInt8 (' #' )
435
- return mod === __deserialized_types__ || (mod === Main && (ishidden || ! toplevel))
432
+ isanonfunction = mod === Main && # only Main
433
+ t. super === Function && # only Functions
434
+ unsafe_load (unsafe_convert (Ptr{UInt8}, tn. name)) == UInt8 (' #' ) && # hidden type
435
+ (! isdefined (mod, name) || t != typeof (getfield (mod, name))) # XXX : 95% accurate test for this being an inner function
436
+ # TODO : more accurate test? (tn.name !== "#" name)
437
+ # TODO : iskw = startswith(tn.name, "#kw#") && ???
438
+ # TODO : iskw && return send-as-kwftype
439
+ return mod === __deserialized_types__ || isanonfunction
436
440
end
437
441
return false
438
442
end
439
443
440
444
# `type_itself` means we are serializing a type object. when it's false, we are
441
445
# sending the type tag part of some other object's representation.
442
- function serialize_type_data (s, t:: ANY , type_itself:: Bool )
446
+ function serialize_type_data (s, t:: DataType , type_itself:: Bool )
443
447
whole = should_send_whole_type (s, t)
444
448
form = type_itself ? UInt8 (0 ) : UInt8 (1 )
445
449
if whole
@@ -724,68 +728,66 @@ function deserialize(s::AbstractSerializer, ::Type{Union})
724
728
Union{types... }
725
729
end
726
730
727
- module __deserialized_types__
728
- end
729
-
731
+ module __deserialized_types__ end
730
732
731
733
function deserialize (s:: AbstractSerializer , :: Type{TypeName} )
734
+ # the deserialize_cycle call can be delayed, since neither
735
+ # Symbol nor Module will use the backref table
732
736
number = read (s. io, UInt64)
733
- name = deserialize (s)
734
- mod = deserialize (s)
735
- if haskey (known_object_data, number)
736
- tn = known_object_data[number]:: TypeName
737
- name = tn. name
738
- mod = tn. module
739
- makenew = false
740
- elseif isdefined (mod, name)
741
- tn = getfield (mod, name). name
742
- # TODO : confirm somehow that the types match
743
- name = tn. name
744
- mod = tn. module
737
+ return deserialize_typename (s, number)
738
+ end
739
+
740
+ function deserialize_typename (s:: AbstractSerializer , number)
741
+ name = deserialize (s):: Symbol
742
+ tn = get (known_object_data, number, nothing )
743
+ if tn != = nothing
745
744
makenew = false
746
745
else
747
- name = gensym ()
748
- mod = __deserialized_types__
749
- tn = ccall (:jl_new_typename_in , Ref{TypeName}, (Any, Any), name, mod)
746
+ # reuse the same name for the type, if possible, for nicer debugging
747
+ tn_name = isdefined (__deserialized_types__, name) ? gensym () : name
748
+ tn = ccall (:jl_new_typename_in , Ref{TypeName}, (Any, Any),
749
+ tn_name, __deserialized_types__)
750
750
makenew = true
751
+ known_object_data[number] = tn
752
+ end
753
+ if ! haskey (object_numbers, tn)
754
+ # setup up reverse mapping for serialize
755
+ object_numbers[tn] = number
751
756
end
752
757
deserialize_cycle (s, tn)
753
- deserialize_typename_body (s, tn, number, name, mod, makenew)
754
- makenew && (known_object_data[number] = tn)
755
- return tn
756
- end
757
758
758
- function deserialize_typename_body (s:: AbstractSerializer , tn, number, name, mod, makenew)
759
- names = deserialize (s)
760
- super = deserialize (s)
761
- parameters = deserialize (s)
762
- types = deserialize (s)
763
- size = deserialize (s)
764
- abstr = deserialize (s)
765
- mutable = deserialize (s)
766
- ninitialized = deserialize (s)
759
+ names = deserialize (s):: SimpleVector
760
+ super = deserialize (s):: Type
761
+ parameters = deserialize (s):: SimpleVector
762
+ types = deserialize (s):: SimpleVector
763
+ has_instance = deserialize (s):: Bool
764
+ abstr = deserialize (s):: Bool
765
+ mutable = deserialize (s):: Bool
766
+ ninitialized = deserialize (s):: Int32
767
767
768
768
if makenew
769
769
tn. names = names
770
+ # TODO : there's an unhanded cycle in the dependency graph at this point:
771
+ # while deserializing super and/or types, we may have encountered
772
+ # tn.primary and throw UndefRefException before we get to this point
770
773
tn. primary = ccall (:jl_new_datatype , Any, (Any, Any, Any, Any, Any, Cint, Cint, Cint),
771
774
tn, super, parameters, names, types,
772
775
abstr, mutable, ninitialized)
773
776
ty = tn. primary
774
- ccall (:jl_set_const , Void, (Any, Any, Any), mod, name, ty)
775
- if ! isdefined (ty,:instance )
776
- if isempty (parameters) && ! abstr && size == 0 && (! mutable || isempty (names))
777
- setfield! (ty, :instance , ccall (:jl_new_struct , Any, (Any,Any... ), ty))
778
- end
777
+ ccall (:jl_set_const , Void, (Any, Any, Any), tn. module, tn. name, ty)
778
+ if has_instance && ! isdefined (ty, :instance )
779
+ # use setfield! directly to avoid `fieldtype` lowering expecting to see a Singleton object already on ty
780
+ Core. setfield! (ty, :instance , ccall (:jl_new_struct , Any, (Any, Any... ), ty))
779
781
end
780
782
end
781
783
782
784
tag = Int32 (read (s. io, UInt8):: UInt8 )
783
785
if tag != UNDEFREF_TAG
784
786
mtname = handle_deserialize (s, tag)
785
787
defs = deserialize (s)
786
- maxa = deserialize (s)
788
+ maxa = deserialize (s):: Int
787
789
if makenew
788
- tn. mt = ccall (:jl_new_method_table , Any, (Any, Any), name, mod )
790
+ tn. mt = ccall (:jl_new_method_table , Any, (Any, Any), name, tn . module )
789
791
tn. mt. name = mtname
790
792
tn. mt. defs = defs
791
793
tn. mt. max_args = maxa
@@ -798,6 +800,7 @@ function deserialize_typename_body(s::AbstractSerializer, tn, number, name, mod,
798
800
end
799
801
end
800
802
end
803
+ return tn:: TypeName
801
804
end
802
805
803
806
function deserialize_datatype (s:: AbstractSerializer )
@@ -845,7 +848,8 @@ function deserialize(s::AbstractSerializer, t::DataType)
845
848
return ccall (:jl_new_struct , Any, (Any,Any... ), t)
846
849
elseif isbits (t)
847
850
if nf == 1
848
- return ccall (:jl_new_struct , Any, (Any,Any... ), t, deserialize (s))
851
+ f1 = deserialize (s)
852
+ return ccall (:jl_new_struct , Any, (Any,Any... ), t, f1)
849
853
elseif nf == 2
850
854
f1 = deserialize (s)
851
855
f2 = deserialize (s)
0 commit comments