Skip to content

Commit 9ba6ef7

Browse files
committed
InternalCodeCache update
1 parent 5d856dc commit 9ba6ef7

File tree

6 files changed

+47
-12
lines changed

6 files changed

+47
-12
lines changed

base/boot.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,9 +501,8 @@ struct LineInfoNode # legacy support for aiding Serializer.deserialize of old IR
501501
LineInfoNode(mod::Module, @nospecialize(method), file::Symbol, line::Int32, inlined_at::Int32) = new(mod, method, file, line, inlined_at)
502502
end
503503

504-
505504
function CodeInstance(
506-
mi::MethodInstance, @nospecialize(rettype), @nospecialize(exctype), @nospecialize(inferred_const),
505+
mi::MethodSpecialization, @nospecialize(rettype), @nospecialize(exctype), @nospecialize(inferred_const),
507506
@nospecialize(inferred), const_flags::Int32, min_world::UInt, max_world::UInt,
508507
ipo_effects::UInt32, effects::UInt32, @nospecialize(analysis_results),
509508
relocatability::UInt8, edges::DebugInfo)
@@ -649,12 +648,12 @@ Symbol(s::Symbol) = s
649648
# module providing the IR object model
650649
module IR
651650

652-
export CodeInfo, MethodInstance, CodeInstance, GotoNode, GotoIfNot, ReturnNode,
651+
export CodeInfo, MethodSpecialization, MethodInstance, CodeInstance, GotoNode, GotoIfNot, ReturnNode,
653652
NewvarNode, SSAValue, SlotNumber, Argument,
654653
PiNode, PhiNode, PhiCNode, UpsilonNode, DebugInfo,
655654
Const, PartialStruct, InterConditional, EnterNode
656655

657-
using Core: CodeInfo, MethodInstance, CodeInstance, GotoNode, GotoIfNot, ReturnNode,
656+
using Core: CodeInfo, MethodSpecialization, MethodInstance, CodeInstance, GotoNode, GotoIfNot, ReturnNode,
658657
NewvarNode, SSAValue, SlotNumber, Argument,
659658
PiNode, PhiNode, PhiCNode, UpsilonNode, DebugInfo,
660659
Const, PartialStruct, InterConditional, EnterNode
@@ -1006,6 +1005,9 @@ const check_top_bit = check_sign_bit
10061005
EnterNode(old::EnterNode, new_dest::Int) = isdefined(old, :scope) ?
10071006
EnterNode(new_dest, old.scope) : EnterNode(new_dest)
10081007

1008+
eval(Core, :((MS::Type{<:MethodSpecialization})(def::Union{Method, Module, MethodSpecialization}, abi::Type{<:Tuple}) =
1009+
$(Expr(:new, :MS, :def, :abi))))
1010+
10091011
include(Core, "optimized_generics.jl")
10101012

10111013
ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Core, true)

base/compiler/cicache.jl

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,35 @@
33
"""
44
struct InternalCodeCache
55
6-
Internally, each `MethodInstance` keep a unique global cache of code instances
7-
that have been created for the given method instance, stratified by world age
8-
ranges. This struct abstracts over access to this cache.
6+
The internal code cache is keyed on type specializations, represented by
7+
MethodSpecialization{DefaultSpec} aka MethodInstance. External abstract
8+
interpreters may use this same structure by using a different `Spec` for their
9+
`MethodSpecialization{Spec}`. `InternalCodeCache` will match such specializations
10+
by type. Additionally, it is possible to specialize methods on properties other
11+
than types, but this requires custom caching logic. `InternalCodeCache` currently
12+
only supports type-based specialization.
913
"""
1014
struct InternalCodeCache
15+
mitype::DataType # <: MethodSpecialization, but stored as DataType for efficient ===
16+
InternalCodeCache(T::Type{<:MethodSpecialization}) =
17+
new(T)
1118
end
19+
InternalCodeCache() = InternalCodeCache(MethodInstance)
1220

1321
function setindex!(cache::InternalCodeCache, ci::CodeInstance, mi::MethodInstance)
14-
ccall(:jl_mi_cache_insert, Cvoid, (Any, Any), mi, ci)
22+
ms::MethodSpecialization = mi
23+
while typeof(ms) !== cache.mitype
24+
if !isdefined(ms, :next)
25+
# No specialization for this spec. Try to allocate it now.
26+
newms = cache.mitype(mi.def, mi.specTypes)
27+
if @atomiconce :sequentially_consistent (ms.next = newms)
28+
ms = newms
29+
break
30+
end
31+
end
32+
ms = @atomic :acquire ms.next
33+
end
34+
ccall(:jl_mi_cache_insert, Cvoid, (Any, Any), ms, ci)
1535
return cache
1636
end
1737

@@ -48,11 +68,21 @@ WorldView(wvc::WorldView, wr::WorldRange) = WorldView(wvc.cache, wr)
4868
WorldView(wvc::WorldView, args...) = WorldView(wvc.cache, args...)
4969

5070
function haskey(wvc::WorldView{InternalCodeCache}, mi::MethodInstance)
51-
return ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), mi, first(wvc.worlds), last(wvc.worlds)) !== nothing
71+
ms::MethodSpecialization = mi
72+
while typeof(ms) !== wvc.cache.mitype
73+
isdefined(ms, :next) || return false
74+
ms = ms.next
75+
end
76+
return ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), ms, first(wvc.worlds), last(wvc.worlds)) !== nothing
5277
end
5378

5479
function get(wvc::WorldView{InternalCodeCache}, mi::MethodInstance, default)
55-
r = ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), mi, first(wvc.worlds), last(wvc.worlds))
80+
ms::MethodSpecialization = mi
81+
while typeof(ms) !== wvc.cache.mitype
82+
isdefined(ms, :next) || return default
83+
ms = ms.next
84+
end
85+
r = ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), ms, first(wvc.worlds), last(wvc.worlds))
5686
if r === nothing
5787
return default
5888
end

base/compiler/compiler.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ using Core.Intrinsics, Core.IR
66

77
import Core: print, println, show, write, unsafe_write, stdout, stderr,
88
_apply_iterate, svec, apply_type, Builtin, IntrinsicFunction,
9+
MethodSpecialization,
910
MethodInstance, CodeInstance, MethodTable, MethodMatch, PartialOpaque,
1011
TypeofVararg
1112

1213
const getproperty = Core.getfield
1314
const setproperty! = Core.setfield!
15+
const setpropertyonce! = Core.setfieldonce!
1416
const swapproperty! = Core.swapfield!
1517
const modifyproperty! = Core.modifyfield!
1618
const replaceproperty! = Core.replacefield!

src/codegen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5162,7 +5162,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, ArrayR
51625162
jl_cgval_t result;
51635163
if (lival.constant) {
51645164
jl_method_instance_t *mi = (jl_method_instance_t*)lival.constant;
5165-
assert(jl_is_method_instance(mi));
5165+
assert(jl_is_method_specialization(mi));
51665166
if (mi == ctx.linfo) {
51675167
// handle self-recursion specially
51685168
jl_returninfo_t::CallingConv cc = jl_returninfo_t::CallingConv::Boxed;

src/jltypes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3332,7 +3332,7 @@ void jl_init_types(void) JL_GC_DISABLED
33323332
(jl_unionall_t*)jl_meth_spec_type->name->wrapper;
33333333
// These fields should be constant, but Serialization wants to mutate them in initialization
33343334
//const static uint32_t method_instance_constfields[1] = { 0x00000007 }; // (1<<0)|(1<<1);
3335-
const static uint32_t method_instance_atomicfields[1] = { 0x0000008 }; // (1<<3)
3335+
const static uint32_t method_instance_atomicfields[1] = { 0x0000018 }; // (1<<3)|(1<<4)
33363336
//Fields 3 and 4 must be protected by method->write_lock, and thus all operations on jl_method_instance_t are threadsafe. TODO: except inInference
33373337
//jl_method_instance_type->name->constfields = method_instance_constfields;
33383338
jl_meth_spec_type->name->atomicfields = method_instance_atomicfields;

src/julia.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,7 @@ static inline int jl_field_isconst(jl_datatype_t *st, int i) JL_NOTSAFEPOINT
15281528
#define jl_is_newvarnode(v) jl_typetagis(v,jl_newvarnode_type)
15291529
#define jl_is_linenode(v) jl_typetagis(v,jl_linenumbernode_type)
15301530
#define jl_is_method_instance(v) jl_typetagis(v,jl_method_instance_type)
1531+
#define jl_is_method_specialization(v) jl_isa((jl_value_t*)v,(jl_value_t*)jl_method_specialization_type)
15311532
#define jl_is_code_instance(v) jl_typetagis(v,jl_code_instance_type)
15321533
#define jl_is_code_info(v) jl_typetagis(v,jl_code_info_type)
15331534
#define jl_is_method(v) jl_typetagis(v,jl_method_type)

0 commit comments

Comments
 (0)