@@ -10,7 +10,8 @@ can be serialized to resume execution in a different JVM running the same code (
10
10
See the JavaDoc of the ` org.graalvm.continuations ` package, and make sure to add the ` continuations.jar ` in the Espresso
11
11
distribution to your classpath when compiling (but not at runtime).
12
12
13
- Currently, only the Espresso VM supports the continuations feature.
13
+ Currently, only the Espresso VM supports the continuations feature. Since it is still experimental, the option needs to
14
+ be enabled by using the flags ` --experimental-options --java.Continuum=true ` .
14
15
15
16
### High level
16
17
@@ -21,36 +22,36 @@ implement `generate` and call `emit` from inside it.
21
22
### Low level
22
23
23
24
You create a new ` Continuation ` by passing the constructor an object that implements the functional
24
- interface ` Continuation.EntryPoint ` (which can be a lambda). That object's ` start ` method receives
25
- a ` Continuation. SuspendCapability` that lets you trigger a suspend . You can do that from _ any_ depth in the stack as
26
- long as the code was invoked via the entry point, and all the frames between the call to ` suspend ` and ` start ` will be
25
+ interface ` ContinuationEntryPoint ` (which can be a lambda). That object's ` start ` method receives
26
+ a ` SuspendCapability ` that lets you trigger suspension . You can do that from _ any_ depth in the stack as
27
+ long as the code was invoked via the entry point, and all the frames between the call to ` suspend ` and ` resume ` will be
27
28
unwound and stored inside the ` Continuation ` object. You can then call ` resume() ` on it to kick it off for the first
28
29
time or to restart from the last suspend point.
29
30
30
31
Continuations are single-threaded constructs. There are no second threads involved, and the ` resume() ` method blocks
31
- until the continuation either finishes successfully, throws an exception or calls suspend. The difference can be seen in
32
- the result of the ` getState() ` method.
32
+ until the continuation either finishes successfully, throws an exception or calls suspend. ` isResumable() ` can be called
33
+ to determine if the continuation can be resumed (if the continuation has been freshly created or it has been previously
34
+ suspended), and ` isCompleted() ` can be called to determine if the continuation has completed (either by returning
35
+ normally, or if an exception escaped).
33
36
34
- ` Continuation ` implements ` Externalizable ` and can serialize to a backwards compatible format (not guaranteed until
35
- final release). Because frames can point to anything in their parameters and local variables, it must be persisted by a
36
- serialization engine that can handle arbitrary objects like [ Kryo ] ( https://github.com/EsotericSoftware/kryo/ )
37
- or ` ObjectOutputStream ` .
37
+ ` Continuation ` implements ` Serializable ` and can serialize to a backwards compatible format. Because frames can point to
38
+ anything in their parameters and local variables, the class ` ContinuationSerializable ` provides static
39
+ methods ` readObjectExternal ` and ` writeObjectExternal ` which may be used to coordinate serialization of
40
+ continuation-related objects with a non-jdk serialization engine .
38
41
39
42
## Security
40
43
41
44
Continuations that have ** not** been _ materialized_ are safe, as the frame record is kept internal to the VM.
42
45
43
46
Materializing a continuation refers to making the record visible to Java code, through the
44
- private ` Continuation.stackFrameHead ` field.
45
-
46
- Currently, the only path for materialization is through serialization.
47
+ private ` ContinuationImpl.stackFrameHead ` field. Currently, the only path for materialization is through serialization.
47
48
48
49
When restoring from a materialized frame (_ dematerialization_ ), only minimal checks are performed by the VM, and only to
49
50
prevent a VM crash. Examples of these checks are:
50
51
51
52
- Ensures that resume only happens on ` invoke ` bytecodes.
52
53
- Ensures that the recorded frame data is consistent with what was computed by the bytecode verifier.
53
- - Ensures that the last frame in the record is ` Continuation .suspend` .
54
+ - Ensures that the last frame in the record is ` ContinuationImpl .suspend` .
54
55
55
56
Deserializing a continuation supplied by an attacker will allow complete takeover of the JVM. Only resume continuations
56
57
you persisted yourself!
@@ -129,15 +130,15 @@ Furthermore, there is currently no support for continuation-in-continuation.
129
130
130
131
* This section is only relevant for people working on Espresso itself.*
131
132
132
- Continuations interact with the VM via private intrinsics registered on the ` Continuation ` class.
133
+ Continuations interact with the VM via private intrinsics registered on the ` Continuation ` and ` ContinuationImpl ` class.
133
134
134
135
A continuation starts by calling into the VM. Execution resurfaces in the guest world at the private ` run ` method of
135
- ` Continuation ` , which then invokes the user's given entry point.
136
+ ` ContinuationImpl ` , which then invokes the user's given entry point.
136
137
137
138
Suspending throws a host-side exception that is caught by the ` BytecodeNode ` interpreter loop. The stack frame is copied
138
139
into a new host-side object called a ` HostFrameRecord ` (HFR). The exception is then rethrown. The HFRs are chained
139
- together in a linked list. Once execution reaches the private ` run ` method of ` Continuation ` the HFR list is attached
140
- into a hidden field of ` Continuation ` . Control is then returned to the guest.
140
+ together in a linked list. Once execution reaches the private ` run ` method of ` ContinuationImpl ` the HFR list is
141
+ attached into a hidden field of ` ContinuationImpl ` . Control is then returned to the guest.
141
142
142
143
On resuming a ` Continuation ` , the entire call stack needs to be re-winded. This happens through a different ` CallTarget `
143
144
than for regular calls, and there is one such call target per encountered resume ` bci ` .
@@ -149,7 +150,7 @@ we pass the rest of the records to the next method. This is all done in a specia
149
150
The separation of the call targets has two advantages:
150
151
151
152
- It does not interfere with regular calls.
152
- - Resuming and suspending can be PE'd , leading to fast suspend/resume cycles.
153
+ - Resuming and suspending can be partial-evaluated , leading to fast suspend/resume cycles.
153
154
154
- Serialization is done entirely in guest-side code, by having the ` Continuation ` class implement ` Externalizable ` . The
155
+ Serialization is done entirely in guest-side code, by having the ` Continuation ` class implement ` Serializable ` . The
155
156
format is designed to enable backwards-compatible evolution of the format.
0 commit comments