@@ -9,35 +9,25 @@ let's build a frame:
9
9
10
10
``` julia
11
11
julia> frame = JuliaInterpreter. enter_call (summer, A)
12
- Frame (JuliaInterpreter. FrameCode (summer (A:: AbstractArray{T,N} where N) where T in Main at REPL[1 ]: 2 , CodeInfo (
13
- 1 ─ s = ($ (QuoteNode (zero)))($ (Expr (:static_parameter , 1 )))
14
- │ % 2 = A
15
- │ # temp# = ($(QuoteNode(iterate)))(%2)
16
- │ % 4 = ($ (QuoteNode (=== )))(# temp#, nothing)
17
- │ % 5 = ($ (QuoteNode (not_int)))(% 4 )
18
- └── goto # 4 if not %5
19
- 2 ┄ % 7 = # temp#
20
- │ a = ($ (QuoteNode (getfield)))(% 7 , 1 )
21
- │ % 9 = ($ (QuoteNode (getfield)))(% 7 , 2 )
22
- │ s = ($ (QuoteNode (+ )))(s, a)
23
- │ # temp# = ($(QuoteNode(iterate)))(%2, %9)
24
- │ % 12 = ($ (QuoteNode (=== )))(# temp#, nothing)
25
- │ % 13 = ($ (QuoteNode (not_int)))(% 12 )
26
- └── goto # 4 if not %13
27
- 3 ─ goto # 2
28
- 4 ┄ return s
29
- ), Core. TypeMapEntry[# undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef], BitSet([2, 4, 5, 7, 9, 12, 13]), false, false, true), Union{Nothing, Some{Any}}[Some(summer), Some([1, 2, 5]), nothing, nothing, nothing], Any[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef], Any[Int64], Int64[], Base.RefValue{Any}(nothing), Base.RefValue{JuliaInterpreter.JuliaProgramCounter}(JuliaProgramCounter(1)), Dict{Symbol,Int64}(), Any[])
12
+ Frame for summer (A:: AbstractArray{T,N} where N) where T in Main at REPL[2 ]: 2
13
+ 1 * 2 1 ─ s = (zero)($ (Expr (:static_parameter , 1 )))
14
+ 2 3 │ % 2 = A
15
+ 3 3 │ # temp# = (iterate)(%2)
16
+ ⋮
17
+ A = [1 , 2 , 5 ]
18
+ T = Int64
30
19
```
31
20
32
- This is a [`JuliaInterpreter.Frame`](@ref). The `CodeInfo` is the most prominent part of this display,
33
- and extractable as `code = frame.framecode.code`. (It's a slightly modified form of one returned by `@code_lowered`,
21
+ This is a [ ` Frame ` ] ( @ref ) . Only a portion of the ` CodeInfo ` is shown, a small region surrounding
22
+ the current statement (marked with ` * ` or in yellow text). The full ` CodeInfo ` can be extracted
23
+ as ` code = frame.framecode.src ` . (It's a slightly modified form of one returned by ` @code_lowered ` ,
34
24
in that it has been processed by [ ` JuliaInterpreter.optimize! ` ] ( @ref ) to speed up run-time execution.)
35
25
36
- Much of the rest of the `frame` holds values needed for or generated by execution.
26
+ ` frame ` has another field, ` framedata ` , that holds values needed for or generated by execution.
37
27
The input arguments are in ` locals ` :
38
28
39
29
``` julia
40
- julia> frame. locals
30
+ julia> frame. framedata . locals
41
31
5 - element Array{Union{Nothing, Some{Any}},1 }:
42
32
Some (summer)
43
33
Some ([1 , 2 , 5 ])
@@ -62,7 +52,7 @@ The `Expr(:static_parameter, 1)` statement refers to this value.
62
52
The other main storage is for the generated SSA values:
63
53
64
54
``` julia
65
- julia> frame. ssavalues
55
+ julia> frame. framedata . ssavalues
66
56
16 - element Array{Any,1 }:
67
57
# undef
68
58
# undef
@@ -89,31 +79,25 @@ which just indicates the next statement to be executed:
89
79
90
80
``` julia
91
81
julia> frame. pc
92
- JuliaProgramCounter ( 1 )
82
+ 1
93
83
```
94
84
95
- This is stored as a `Ref` so that it can be updated as execution progresses.
96
-
97
- Let's try executing the first statement. So that we can recurse into calls (e.g., `iterate`, `+`, etc.,),
98
- we'll create a [stack](https://en.wikipedia.org/wiki/Call_stack) of frames and then run the first statement:
85
+ Let's try executing the first statement:
99
86
100
87
``` julia
101
- julia> stack = JuliaInterpreter. Frame[]
102
- 0 - element Array{Frame,1 }
103
-
104
- julia> JuliaInterpreter. step_expr! (stack, frame)
105
- JuliaProgramCounter (2 )
88
+ julia> JuliaInterpreter. step_expr! (frame)
89
+ 2
106
90
```
107
91
108
92
This indicates that it ran statement 1 and is prepared to run statement 2.
109
93
(It's worth noting that the first line included a ` call ` to ` zero ` , so behind the scenes
110
- JuliaInterpreter pushed this frame onto `stack`, created a new frame for `zero`,
111
- executed all the statements, and then popped the stack .)
94
+ JuliaInterpreter created a new frame for ` zero ` , executed all the statements, and then popped
95
+ back to ` frame ` .)
112
96
Since the first statement is an assignment of a local variable, let's check the
113
97
locals again:
114
98
115
99
``` julia
116
- julia> frame. locals
100
+ julia> frame. framedata . locals
117
101
5 - element Array{Union{Nothing, Some{Any}},1 }:
118
102
Some (summer)
119
103
Some ([1 , 2 , 5 ])
@@ -128,10 +112,10 @@ The next statement just retrieves one of the slots (the input argument `A`) and
128
112
it in an SSA value:
129
113
130
114
``` julia
131
- julia> JuliaInterpreter. step_expr! (stack, frame)
132
- JuliaProgramCounter ( 3 )
115
+ julia> JuliaInterpreter. step_expr! (frame)
116
+ 3
133
117
134
- julia> frame. ssavalues
118
+ julia> frame. framedata . ssavalues
135
119
16 - element Array{Any,1 }:
136
120
# undef
137
121
[1 , 2 , 5 ]
@@ -152,9 +136,9 @@ julia> frame.ssavalues
152
136
```
153
137
154
138
One can easily continue this until execution completes, which is indicated when ` step_expr! `
155
- returns `nothing`. Alternatively, use the higher-level `JuliaInterpreter.finish!(stack, frame)`
139
+ returns ` nothing ` . Alternatively, use the higher-level ` JuliaInterpreter.finish!(frame) `
156
140
to step through the entire frame,
157
- or `JuliaInterpreter.finish_and_return!(stack, frame)` to also obtain the return value.
141
+ or ` JuliaInterpreter.finish_and_return!(frame) ` to also obtain the return value.
158
142
159
143
## More complex expressions
160
144
@@ -171,7 +155,7 @@ ex = quote
171
155
end
172
156
173
157
frame = JuliaInterpreter.prepare_thunk(Main, ex)
174
- JuliaInterpreter. finish_and_return! (Frame[], frame)
158
+ JuliaInterpreter.finish_and_return!(frame)
175
159
176
160
# output
177
161
@@ -196,7 +180,7 @@ Here's a demonstration of the problem:
196
180
``` julia
197
181
ex = :(map (x-> x^ 2 , [1 , 2 , 3 ]))
198
182
frame = JuliaInterpreter. prepare_thunk (Main, ex)
199
- julia> JuliaInterpreter. finish_and_return! (Frame[], frame)
183
+ julia> JuliaInterpreter. finish_and_return! (frame)
200
184
ERROR: this frame needs to be run a top level
201
185
```
202
186
@@ -235,7 +219,7 @@ function" for this type, equivalent to `(##17#18)(x) = x^2`.
235
219
In some cases one can fix this simply by indicating that we want to run this frame at top level:
236
220
237
221
``` julia
238
- julia> JuliaInterpreter. finish_and_return! (Frame[], frame, true )
222
+ julia> JuliaInterpreter. finish_and_return! (frame, true )
239
223
3 - element Array{Int64,1 }:
240
224
1
241
225
4
@@ -247,11 +231,10 @@ for more complex situations where there may be nested calls of new methods):
247
231
248
232
``` julia
249
233
modexs, _ = JuliaInterpreter. split_expressions (Main, ex)
250
- stack = Frame[]
251
234
for (mod, e) in modexs
252
235
frame = JuliaInterpreter. prepare_thunk (mod, e)
253
236
while true
254
- JuliaInterpreter. through_methoddef_or_done! (stack, frame) === nothing && break
237
+ JuliaInterpreter. through_methoddef_or_done! (frame) === nothing && break
255
238
end
256
239
JuliaInterpreter. get_return (frame)
257
240
end
0 commit comments