Skip to content

Commit 2c64810

Browse files
committed
Describe invokelatest in docs re world age
1 parent c497fee commit 2c64810

File tree

1 file changed

+15
-17
lines changed

1 file changed

+15
-17
lines changed

docs/src/internals.md

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,18 @@ Test Passed
180180
181181
## Toplevel code and world age
182182
183-
Some code is more complicated and requires special handling: code that defines new `struct`s,
184-
new methods, or new modules. In such cases, calling `finish_and_return!` on a frame that
183+
Code that defines new `struct`s, new methods, or new modules is a bit more complicated
184+
and requires special handling. In such cases, calling `finish_and_return!` on a frame that
185185
defines these new objects and then calls them can trigger a
186186
[world age error](https://docs.julialang.org/en/latest/manual/methods/#Redefining-Methods-1),
187187
in which the method is considered to be too new to be run by the currently compiled code.
188+
While one can resolve this by using `Base.invokelatest`, we'd have to use that strategy
189+
throughout the entire package. This would cause a major reduction in performance.
190+
To resolve this issue without leading to performance problems, care is required to
191+
return to "top level" after defining such objects. This leads to altered syntax for executing
192+
such expressions.
188193
189-
In such cases care is required to return to "top level" before continuing. Here's a demonstration:
194+
Here's a demonstration of the problem:
190195
191196
```julia
192197
ex = :(map(x->x^2, [1, 2, 3]))
@@ -195,7 +200,7 @@ julia> JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame)
195200
ERROR: this frame needs to be run a top level
196201
```
197202
198-
The reason becomes clearer if we examine `frame` or look directly at the lowered code:
203+
The reason for this error becomes clearer if we examine `frame` or look directly at the lowered code:
199204
200205
```julia
201206
julia> Meta.lower(Main, ex)
@@ -223,10 +228,11 @@ end)))
223228
))))
224229
```
225230
226-
All of the code before `%7` is devoted to defining the anonymous function `x->x^2`: it creates a new "anonymous type"
227-
(here written as `##17#18`), and then defines a call function for this type, equivalent to `(##17#18)(x) = x^2`.
231+
All of the code before the `%7` line is devoted to defining the anonymous function `x->x^2`:
232+
it creates a new "anonymous type" (here written as `##17#18`), and then defines a "call
233+
function" for this type, equivalent to `(##17#18)(x) = x^2`.
228234
229-
The easy way to fix this is to simply add a flag:
235+
In some cases one can fix this simply by indicating that we want to run this frame at top level:
230236
231237
```julia
232238
julia> JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true)
@@ -236,7 +242,8 @@ julia> JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true)
236242
9
237243
```
238244
239-
Here's a more fine-grained look at what's happening under the hood:
245+
Here's a more fine-grained look at what's happening under the hood (and a robust strategy
246+
for more complex situations where there may be nested calls of new methods):
240247
241248
```julia
242249
modexs, _ = JuliaInterpreter.prepare_toplevel(Main, ex)
@@ -255,15 +262,6 @@ Then, each frame is executed until it finishes defining a new method, then retur
255262
The return to top level causes an update in the world age.
256263
If the frame hasn't been finished yet (if the return value wasn't `nothing`),
257264
this continues executing where it left off.
258-
You can extract the return value with
259-
260-
```julia
261-
julia> JuliaInterpreter.get_return(frames[end])
262-
3-element Array{Int64,1}:
263-
1
264-
4
265-
9
266-
```
267265
268266
(Incidentally, `JuliaInterpreter.enter_call(map, x->x^2, [1, 2, 3])` works fine on its own,
269267
because the anonymous function is defined by the caller---you'll see that the created frame

0 commit comments

Comments
 (0)