@@ -11,14 +11,17 @@ function _infer(f, args_type)
11
11
return ir0
12
12
end
13
13
14
+ # const Bindings = Dict{Symbol, Any}
15
+ const Bindings = Vector{Any}
16
+
14
17
mutable struct TapedFunction{F, TapeType}
15
18
func:: F # maybe a function, a constructor, or a callable object
16
19
arity:: Int
17
20
ir:: Core.CodeInfo
18
21
tape:: TapeType
19
22
counter:: Int
20
- bindings:: Dict{Symbol, Any}
21
- retval:: Symbol
23
+ bindings:: Bindings
24
+ retval:: Int
22
25
23
26
function TapedFunction {F, T} (f:: F , args... ; cache= false ) where {F, T}
24
27
args_type = _accurate_typeof .(args)
@@ -33,7 +36,7 @@ mutable struct TapedFunction{F, TapeType}
33
36
ir = _infer (f, args_type)
34
37
bindings, tape = translate! (RawTape (), ir)
35
38
36
- tf = new {F, T} (f, length (args), ir, tape, 1 , bindings, :none )
39
+ tf = new {F, T} (f, length (args), ir, tape, 1 , bindings, 0 )
37
40
TRCache[cache_key] = tf # set cache
38
41
return tf
39
42
end
@@ -43,7 +46,7 @@ mutable struct TapedFunction{F, TapeType}
43
46
44
47
function TapedFunction {F, T0} (tf:: TapedFunction{F, T1} ) where {F, T0, T1}
45
48
new {F, T0} (tf. func, tf. arity, tf. ir, tf. tape,
46
- tf. counter, tf. bindings, :none )
49
+ tf. counter, tf. bindings, 0 )
47
50
end
48
51
49
52
TapedFunction (tf:: TapedFunction{F, T} ) where {F, T} = TapedFunction {F, T} (tf)
76
79
end
77
80
78
81
struct Box{T}
79
- id:: Symbol
80
- get:: TypedFunction{T, Tuple{TapedFunction, Symbol }}
82
+ id:: Int
83
+ # get::TypedFunction{T, Tuple{TapedFunction, Int }}
81
84
82
- function Box {T} (id:: Symbol ) where T
83
- return new (id, TypedFunction {T, Tuple{TapedFunction, Symbol}} (_inner_getter))
85
+ function Box {T} (id:: Int ) where T
86
+ return new (id)
87
+ # return new(id, TypedFunction{T, Tuple{TapedFunction, Int}}(_inner_getter))
84
88
end
85
89
end
86
90
Base. show (io:: IO , box:: Box{T} ) where {T} = print (io, " Box{$T }($(box. id) )" )
87
91
88
- @inline _inner_getter (tf:: TapedFunction , v:: Symbol ) = tf. bindings[v]
89
- @inline _lookup (tf:: TapedFunction , v:: Box{T} ) where T = v . get (tf, v. id)
90
- @inline _update_var! (tf:: TapedFunction , v:: Symbol , c) = (tf. bindings[v] = c; nothing )
91
- @inline _update_var! (tf:: TapedFunction , v:: Box{T} , c:: T ) where T = (tf. bindings[v. id] = c; nothing )
92
+ @inline _inner_getter (tf:: TapedFunction , v:: Int ) = @inbounds tf. bindings[v]
93
+ @inline _lookup (tf:: TapedFunction , v:: Box{T} ) where T = @inbounds tf . bindings[ v. id]
94
+ # @inline _lookup (tf::TapedFunction, v::Box{T}) where T = v.get (tf, v.id )
95
+ @inline _update_var! (tf:: TapedFunction , v:: Box{T} , c:: T ) where T = (@inbounds tf. bindings[v. id] = c; nothing )
92
96
93
97
"""
94
98
Instruction
@@ -114,20 +118,19 @@ end
114
118
115
119
@inline result (t:: TapedFunction ) = t. bindings[t. retval]
116
120
117
- const SLOTS = [Symbol (" _" , i) for i in 1 : 100 ]
118
-
119
121
function (tf:: TapedFunction )(args... ; callback= nothing , continuation= false )
120
122
if ! continuation # reset counter and retval to run from the start
121
- tf. counter = 1 ;
122
- tf. retval = :none ;
123
+ tf. counter = 1
124
+ tf. retval = 0
123
125
end
124
126
125
127
# set args
126
128
if tf. counter <= 1
127
- haskey (tf . bindings, :_1 ) && _update_var! (tf, :_1 , tf. func)
129
+ _update_var! (tf, Box {typeof(tf.func)} ( 1 ) , tf. func)
128
130
for i in 1 : length (args)
129
- slot = i < length (SLOTS) ? SLOTS[i + 1 ] : Symbol (" _" , i + 1 )
130
- haskey (tf. bindings, slot) && _update_var! (tf, slot, args[i])
131
+ slot = i + 1
132
+ b = Box {typeof(args[i])} (slot)
133
+ _update_var! (tf, b, args[i])
131
134
end
132
135
end
133
136
@@ -136,7 +139,7 @@ function (tf::TapedFunction)(args...; callback=nothing, continuation=false)
136
139
ins = tf. tape[tf. counter]
137
140
ins (tf)
138
141
callback != = nothing && callback ()
139
- tf. retval != = :none && break
142
+ tf. retval != 0 && break
140
143
end
141
144
return result (tf)
142
145
end
205
208
end
206
209
207
210
function (instr:: GotoInstruction )(tf:: TapedFunction )
208
- cond = instr. condition. id === :_true ? true :
209
- instr. condition. id === :_false ? false :
211
+ cond = instr. condition. id === - 1 ? true :
212
+ instr. condition. id === 0 ? false :
210
213
_lookup (tf, instr. condition)
211
214
212
215
if cond
@@ -220,9 +223,7 @@ function (instr::ReturnInstruction)(tf::TapedFunction)
220
223
tf. retval = instr. arg. id
221
224
end
222
225
223
-
224
226
# # internal functions
225
-
226
227
_accurate_typeof (v) = typeof (v)
227
228
_accurate_typeof (:: Type{V} ) where V = Type{V}
228
229
_loose_type (t) = t
@@ -240,33 +241,40 @@ end
240
241
241
242
242
243
# # Translation: CodeInfo -> Tape
243
-
244
- function bind_var! (var, bindings:: Dict{Symbol, Any} , ir:: Core.CodeInfo ) # for literal constants
245
- id = gensym ()
246
- bindings[id] = var
247
- Box {typeof(var)} (id)
248
- end
249
- bind_var! (var:: GlobalRef , bindings:: Dict{Symbol, Any} , ir:: Core.CodeInfo ) =
244
+ const CNT_SLOT = 20
245
+ const CNT_LITE = 100
246
+ const OFFSET_VAR = CNT_SLOT + CNT_LITE
247
+
248
+ function bind_var! (var, bindings:: Bindings , ir:: Core.CodeInfo ) # for literal constants
249
+ last_idx = bindings[CNT_SLOT]
250
+ idx = last_idx + 1
251
+ bindings[CNT_SLOT] = idx
252
+ bindings[idx] = var
253
+ Box {typeof(var)} (idx)
254
+ end
255
+ bind_var! (var:: GlobalRef , bindings:: Bindings , ir:: Core.CodeInfo ) =
250
256
bind_var! (getproperty (var. mod, var. name), bindings, ir)
251
- bind_var! (var:: QuoteNode , bindings:: Dict{Symbol, Any} , ir:: Core.CodeInfo ) =
257
+ bind_var! (var:: QuoteNode , bindings:: Bindings , ir:: Core.CodeInfo ) =
252
258
bind_var! (eval (var), bindings, ir)
253
- bind_var! (var:: Core.SSAValue , bindings:: Dict{Symbol, Any} , ir:: Core.CodeInfo ) =
254
- bind_var! (Symbol ( var. id) , bindings, ir. ssavaluetypes[var. id])
255
- bind_var! (var:: Core.TypedSlot , bindings:: Dict{Symbol, Any} , ir:: Core.CodeInfo ) =
256
- bind_var! (Symbol ( :_ , var. id) , bindings, ir. slottypes[var. id])
257
- bind_var! (var:: Core.SlotNumber , bindings:: Dict{Symbol, Any} , ir:: Core.CodeInfo ) =
258
- bind_var! (Symbol ( :_ , var. id) , bindings, ir. slottypes[var. id])
259
- bind_var! (var:: Symbol , boxes:: Dict{Symbol, Any} , c:: Core.Const ) =
259
+ bind_var! (var:: Core.SSAValue , bindings:: Bindings , ir:: Core.CodeInfo ) =
260
+ bind_var! (var. id + OFFSET_VAR , bindings, ir. ssavaluetypes[var. id])
261
+ bind_var! (var:: Core.TypedSlot , bindings:: Bindings , ir:: Core.CodeInfo ) =
262
+ bind_var! (var. id, bindings, ir. slottypes[var. id])
263
+ bind_var! (var:: Core.SlotNumber , bindings:: Bindings , ir:: Core.CodeInfo ) =
264
+ bind_var! (var. id, bindings, ir. slottypes[var. id])
265
+ bind_var! (var:: Int , boxes:: Bindings , c:: Core.Const ) =
260
266
bind_var! (var, boxes, _loose_type (Type{c. val}))
261
- bind_var! (var:: Symbol , boxes:: Dict{Symbol, Any} , c:: Core.PartialStruct ) =
267
+ bind_var! (var:: Int , boxes:: Bindings , c:: Core.PartialStruct ) =
262
268
bind_var! (var, boxes, _loose_type (c. typ))
263
- function bind_var! (var:: Symbol , bindings:: Dict{Symbol, Any} , :: Type{T} ) where T
264
- get ! (bindings, var, nothing )
269
+ function bind_var! (var:: Int , bindings:: Bindings , :: Type{T} ) where T
270
+ var > length (bindings) && resize ! (bindings, var + 10 )
265
271
Box {T} (var)
266
272
end
267
273
268
274
function translate! (tape:: RawTape , ir:: Core.CodeInfo )
269
- bindings = Dict {Symbol, Any} ()
275
+ bindings = Bindings ()
276
+ resize! (bindings, OFFSET_VAR + 10 )
277
+ bindings[CNT_SLOT] = CNT_SLOT
270
278
271
279
for (idx, line) in enumerate (ir. code)
272
280
isa (line, Core. Const) && (line = line. val) # unbox Core.Const
@@ -279,24 +287,24 @@ end
279
287
280
288
const IRVar = Union{Core. SSAValue, Core. SlotNumber}
281
289
282
- function _const_instruction (var:: IRVar , v, bindings:: Dict{Symbol, Any} , ir)
290
+ function _const_instruction (var:: IRVar , v, bindings:: Bindings , ir)
283
291
if isa (var, Core. SSAValue)
284
292
box = bind_var! (var, bindings, ir)
285
293
bindings[box. id] = v
286
- return GotoInstruction (Box {Bool} (:_true ), 0 ) # NOOP
294
+ return GotoInstruction (Box {Bool} (- 1 ), 0 ) # NOOP
287
295
end
288
296
return Instruction (identity, (bind_var! (v, bindings, ir),), bind_var! (var, bindings, ir))
289
297
end
290
298
291
299
function translate!! (var:: IRVar , line:: Core.NewvarNode ,
292
- bindings:: Dict{Symbol, Any} , isconst:: Bool , @nospecialize (ir))
300
+ bindings:: Bindings , isconst:: Bool , @nospecialize (ir))
293
301
# use a noop to ensure the 1-to-1 mapping from ir.code to instructions
294
302
# on tape. see GotoInstruction.dest.
295
- return GotoInstruction (Box {Bool} (:_true ), 0 )
303
+ return GotoInstruction (Box {Bool} (- 1 ), 0 )
296
304
end
297
305
298
306
function translate!! (var:: IRVar , line:: GlobalRef ,
299
- bindings:: Dict{Symbol, Any} , isconst:: Bool , ir)
307
+ bindings:: Bindings , isconst:: Bool , ir)
300
308
if isconst
301
309
v = ir. ssavaluetypes[var. id]. val
302
310
return _const_instruction (var, v, bindings, ir)
@@ -305,7 +313,7 @@ function translate!!(var::IRVar, line::GlobalRef,
305
313
end
306
314
307
315
function translate!! (var:: IRVar , line:: Core.SlotNumber ,
308
- bindings:: Dict{Symbol, Any} , isconst:: Bool , ir)
316
+ bindings:: Bindings , isconst:: Bool , ir)
309
317
if isconst
310
318
v = ir. ssavaluetypes[var. id]. val
311
319
return _const_instruction (var, v, bindings, ir)
@@ -314,35 +322,35 @@ function translate!!(var::IRVar, line::Core.SlotNumber,
314
322
end
315
323
316
324
function translate!! (var:: IRVar , line:: Core.TypedSlot ,
317
- bindings:: Dict{Symbol, Any} , isconst:: Bool , ir)
325
+ bindings:: Bindings , isconst:: Bool , ir)
318
326
input_box = bind_var! (Core. SlotNumber (line. id), bindings, ir)
319
327
return Instruction (identity, (input_box,), bind_var! (var, bindings, ir))
320
328
end
321
329
322
330
function translate!! (var:: IRVar , line:: Core.GotoIfNot ,
323
- bindings:: Dict{Symbol, Any} , isconst:: Bool , ir)
331
+ bindings:: Bindings , isconst:: Bool , ir)
324
332
_cond = bind_var! (line. cond, bindings, ir)
325
333
cond = if isa (_cond, Bool)
326
- Box {Bool} (_cond ? :_true : :_false )
334
+ Box {Bool} (_cond ? - 1 : 0 )
327
335
else
328
336
_cond
329
337
end
330
338
return GotoInstruction (cond, line. dest)
331
339
end
332
340
333
341
function translate!! (var:: IRVar , line:: Core.GotoNode ,
334
- bindings:: Dict{Symbol, Any} , isconst:: Bool , @nospecialize (ir))
335
- return GotoInstruction (Box {Bool} (:_false ), line. label)
342
+ bindings:: Bindings , isconst:: Bool , @nospecialize (ir))
343
+ return GotoInstruction (Box {Bool} (0 ), line. label)
336
344
end
337
345
338
346
function translate!! (var:: IRVar , line:: Core.ReturnNode ,
339
- bindings:: Dict{Symbol, Any} , isconst:: Bool , ir)
347
+ bindings:: Bindings , isconst:: Bool , ir)
340
348
return ReturnInstruction (bind_var! (line. val, bindings, ir))
341
349
end
342
350
343
351
_canbeoptimized (v) = isa (v, DataType) || isprimitivetype (typeof (v))
344
352
function translate!! (var:: IRVar , line:: Expr ,
345
- bindings:: Dict{Symbol, Any} , isconst:: Bool , ir:: Core.CodeInfo )
353
+ bindings:: Bindings , isconst:: Bool , ir:: Core.CodeInfo )
346
354
head = line. head
347
355
_bind_fn = (x) -> bind_var! (x, bindings, ir)
348
356
if head === :new
@@ -410,10 +418,10 @@ tape_copy(x::Core.Box) = Core.Box(tape_copy(x.contents))
410
418
# tape_copy(x::Array) = deepcopy(x)
411
419
# tape_copy(x::Dict) = deepcopy(x)
412
420
413
- function copy_bindings (old:: Dict{Symbol, Any} )
421
+ function copy_bindings (old:: Bindings )
414
422
newb = copy (old)
415
- for (k, v) in old
416
- newb[k] = tape_copy (v )
423
+ for k in 1 : length ( old)
424
+ isassigned (old, k) && ( newb[k] = tape_copy (old[k]) )
417
425
end
418
426
return newb
419
427
end
0 commit comments