mirror of
https://github.com/ParkerTenBroeck/coroutines.git
synced 2026-06-07 05:08:51 -04:00
Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a733ac3d44 | ||
|
|
3c59263a55 | ||
|
|
1c0430cfac | ||
|
|
c8f3b6c01f | ||
|
|
6ca8ac2d25 | ||
|
|
32880edc3d |
39 changed files with 212 additions and 177 deletions
101
README.md
101
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
# Generators/Futures for Java 24+
|
# Coroutines for Java 24+
|
||||||
|
|
||||||
Futures/Generators implemented as state machines integrated into standard java.
|
Coroutines implemented as state machines integrated into standard java.
|
||||||
|
|
||||||
- Futures/Generators are lazy and only make progress when called upon
|
- Futures/Generators are lazy and only make progress when called upon
|
||||||
- Integrated as much as possible into java to work with the type system as much as possible
|
- Integrated as much as possible into java to work with the type system as much as possible
|
||||||
|
|
@ -36,6 +36,31 @@ public static Gen<Long, Void> primes() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Use this library
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// settings.gradle.kts
|
||||||
|
sourceControl {
|
||||||
|
gitRepository(URI.create("https://github.com/ParkerTenBroeck/coroutines.git")) {
|
||||||
|
producesModule("com.parkertenbroeck.coroutines:lib")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build.gradle.kts
|
||||||
|
implementation("com.parkertenbroeck.coroutines:lib:0.1.1")
|
||||||
|
```
|
||||||
|
|
||||||
|
This library requires the application be ran with a custom class loader, there is a utility provided to make this easier.
|
||||||
|
```java
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// loads the current class with a custom class loader and calls *this* method with the provided arguments.
|
||||||
|
// *this* method - the one used to call `runWithCoroutine`
|
||||||
|
RT.runWithCoroutine(CoroutineClassLoader.Config.builtin(), (Object) args);
|
||||||
|
|
||||||
|
// past this point Coroutines will be created on methods which match the criteria
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## How does it know what functions to transform?
|
## How does it know what functions to transform?
|
||||||
|
|
||||||
Detection is done by
|
Detection is done by
|
||||||
|
|
@ -61,6 +86,10 @@ public static Future<Void, RuntimeException> regular_function() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Why not annotations?
|
||||||
|
Unfortunately annotations cannot be put on lambdas.
|
||||||
|
|
||||||
|
|
||||||
## Oddities
|
## Oddities
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
@ -81,7 +110,38 @@ public static Future<Void, IOException> echo(🔷@Cancellation("close") Socket s
|
||||||
|
|
||||||
## Things to watch out for
|
## Things to watch out for
|
||||||
|
|
||||||
### Future errors are not type checked
|
### Await function works specifically for the Future type
|
||||||
|
|
||||||
|
```java
|
||||||
|
class MyFuture implements Future<String, RuntimeException>{
|
||||||
|
public Object poll(Waker waker){ /* code */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Future<Void, RuntimeException> wrong() {
|
||||||
|
new MyFuture().await();//⚡
|
||||||
|
return Future.ret();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Internally the await call will become a `invokevirtual` call to `await` on `MyFuture`. Which will not currently be recognized as a "special" method to transform.
|
||||||
|
|
||||||
|
To avoid this use static methods to return a future and make manually implemented futures have private/protected constructors
|
||||||
|
```java
|
||||||
|
class MyFuture implements Future<String, RuntimeException>{
|
||||||
|
private MyFuture(){}
|
||||||
|
public static Future<String, RuntimeException> make(){
|
||||||
|
return new MyFuture();
|
||||||
|
}
|
||||||
|
public Object poll(Waker waker){ /* code */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Future<Void, RuntimeException> wrong() {
|
||||||
|
MyFuture.make().await();
|
||||||
|
return Future.ret();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Future exceptions are not type checked
|
||||||
```java
|
```java
|
||||||
public static Future<Void, RuntimeException> wrong() throws Exception {
|
public static Future<Void, RuntimeException> wrong() throws Exception {
|
||||||
Waker.waker().wake();
|
Waker.waker().wake();
|
||||||
|
|
@ -130,7 +190,7 @@ public static Future<Void, RuntimeException> add_reorder() {
|
||||||
|
|
||||||
### synchronized
|
### synchronized
|
||||||
|
|
||||||
when a generator/future method is declared as `synchronized` the `next`/`poll`/`cancel` functions will all be synchronized over the instance or class which the method was declared in.
|
when a coroutine method is declared as `synchronized` the `next`/`poll`/`cancel` functions will all be synchronized over the instance or class the method was declared in.
|
||||||
|
|
||||||
it is important to note that the monitor is **NOT** held across suspend points where the function returns.
|
it is important to note that the monitor is **NOT** held across suspend points where the function returns.
|
||||||
|
|
||||||
|
|
@ -146,22 +206,7 @@ static Future<Void, RuntimeException> unsync(Object value) {
|
||||||
|
|
||||||
## How this works
|
## How this works
|
||||||
|
|
||||||
This library requires the application be ran with a custom class loader as follows (this can be done manually if needed)
|
Say we have some async function like this.
|
||||||
```java
|
|
||||||
public static void main(String[] args) {
|
|
||||||
// loads the current class with a custom class loader and calls *this* method with the provided arguments.
|
|
||||||
// *this* method - the one used to call `runWithStateMachines`
|
|
||||||
RT.runWithStateMachines(StateMachineClassLoader.Config.builtin(), (Object) args);
|
|
||||||
|
|
||||||
// past this point generators will be created on methods which match the criteria
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Once finished any class loaded will be scanned for methods which match a particular signature.
|
|
||||||
|
|
||||||
When matched a shim is introduced into the source method and a class is constructed which stores all state for the future/generator
|
|
||||||
|
|
||||||
A basic example here where we have some parameters
|
|
||||||
```java
|
```java
|
||||||
public static Future<Void, IOException> example(@Cancellation("close") Socket socket, String message) throws IOException {
|
public static Future<Void, IOException> example(@Cancellation("close") Socket socket, String message) throws IOException {
|
||||||
try(socket){
|
try(socket){
|
||||||
|
|
@ -170,6 +215,8 @@ public static Future<Void, IOException> example(@Cancellation("close") Socket so
|
||||||
return Future.ret();
|
return Future.ret();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
The loader will see the methods which it needs to transform, then modify the bytecode, transforming the function into a class where state across suspend points is saved/restored (local variables & the current state of the stack).
|
||||||
|
|
||||||
This is a (modified) decompiled version of the generated method.
|
This is a (modified) decompiled version of the generated method.
|
||||||
```java
|
```java
|
||||||
public static Future<Void, IOException> example(Socket socket, String message) {
|
public static Future<Void, IOException> example(Socket socket, String message) {
|
||||||
|
|
@ -273,10 +320,10 @@ public static Future<Void, IOException> example(Socket socket, String message) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
### Steps
|
|
||||||
- A functions signature and code is determined to be "of interest"
|
## Potential additions
|
||||||
- When a function is found we wish to modify it first builds a frame(locals, stack, annotations) for every area of interest in the function
|
|
||||||
- The number of unique locations which can be suspended from are kept track of
|
- Type checking during transformations
|
||||||
- A switch is built which handles each state the function can resume from setting up any locals/stack that needs to be resumed as well as setting up the code for saving locals/stack state
|
- Better debugger support (Currently line stepping is generally supported but most breakpoint sets are not working)
|
||||||
- the locations which special methods are found are modified to perform their particular function and potentially save state and return
|
- Annotations (possibly integration during build time)
|
||||||
- (Futures) generate cancellation code for locals which have specified so, and cancellation for a pending future.
|
- More library features (async)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
package basic;
|
package basic;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
|
||||||
import com.parkertenbroeck.future.Waker;
|
|
||||||
|
|
||||||
public class Futures {
|
public class Futures {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package basic;
|
package basic;
|
||||||
|
|
||||||
import com.parkertenbroeck.generator.Gen;
|
import com.parkertenbroeck.coroutines.generator.Gen;
|
||||||
|
|
||||||
public class Gens {
|
public class Gens {
|
||||||
public static Gen<Long, Void> primes(){
|
public static Gen<Long, Void> primes(){
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package basic;
|
package basic;
|
||||||
|
|
||||||
import com.parkertenbroeck.bcsm.RT;
|
import com.parkertenbroeck.coroutines.bcsm.RT;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.StateMachineClassLoader;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.CoroutineClassLoader;
|
||||||
import com.parkertenbroeck.generator.Gen;
|
import com.parkertenbroeck.coroutines.generator.Gen;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
RT.runWithStateMachines(StateMachineClassLoader.Config.builtin().write_classes("build/modified/generators/"), (Object) args);
|
RT.runWithCoroutine(CoroutineClassLoader.Config.builtin().write_classes("build/modified/generators/"), (Object) args);
|
||||||
|
|
||||||
primes();
|
primes();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package lexer;
|
package lexer;
|
||||||
|
|
||||||
import com.parkertenbroeck.generator.Gen;
|
import com.parkertenbroeck.coroutines.generator.Gen;
|
||||||
|
|
||||||
public class Lexer {
|
public class Lexer {
|
||||||
public sealed interface Token{}
|
public sealed interface Token{}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package lexer;
|
package lexer;
|
||||||
|
|
||||||
import com.parkertenbroeck.generator.Gen;
|
import com.parkertenbroeck.coroutines.generator.Gen;
|
||||||
import com.parkertenbroeck.bcsm.RT;
|
import com.parkertenbroeck.coroutines.bcsm.RT;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.StateMachineClassLoader;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.CoroutineClassLoader;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
RT.runWithStateMachines(StateMachineClassLoader.Config.builtin().write_classes("build/modified/generators/"), (Object) args);
|
RT.runWithCoroutine(CoroutineClassLoader.Config.builtin().write_classes("build/modified/generators/"), (Object) args);
|
||||||
|
|
||||||
lexer();
|
lexer();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package sockets;
|
package sockets;
|
||||||
|
|
||||||
import com.parkertenbroeck.async_runtime.Jokio;
|
import com.parkertenbroeck.coroutines.async_runtime.Jokio;
|
||||||
import com.parkertenbroeck.bcsm.RT;
|
import com.parkertenbroeck.coroutines.bcsm.RT;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.StateMachineClassLoader;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.CoroutineClassLoader;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
RT.runWithStateMachines(StateMachineClassLoader.Config.builtin().write_classes("build/modified/generators/"), (Object) args);
|
RT.runWithCoroutine(CoroutineClassLoader.Config.builtin().write_classes("build/modified/generators/"), (Object) args);
|
||||||
|
|
||||||
await();
|
await();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
package sockets;
|
package sockets;
|
||||||
|
|
||||||
import com.parkertenbroeck.async_runtime.Delay;
|
import com.parkertenbroeck.coroutines.async_runtime.Delay;
|
||||||
import com.parkertenbroeck.async_runtime.Jokio;
|
import com.parkertenbroeck.coroutines.async_runtime.Jokio;
|
||||||
import com.parkertenbroeck.async_runtime.io.net.ServerSocket;
|
import com.parkertenbroeck.coroutines.async_runtime.io.net.ServerSocket;
|
||||||
import com.parkertenbroeck.async_runtime.io.net.Socket;
|
import com.parkertenbroeck.coroutines.async_runtime.io.net.Socket;
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.future.Cancellation;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.future.Cancellation;
|
||||||
import com.parkertenbroeck.future.Waker;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
group = "com.parkertenbroeck.generators"
|
group = "com.parkertenbroeck.coroutines"
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.parkertenbroeck.coroutines.async_runtime;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class AsyncExecutor {
|
||||||
|
void test(){
|
||||||
|
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,16 @@
|
||||||
package com.parkertenbroeck.async_runtime;
|
package com.parkertenbroeck.coroutines.async_runtime;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.future.Waker;
|
import com.parkertenbroeck.coroutines.future.Waker;
|
||||||
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class Delay implements Future<Void, RuntimeException> {
|
public class Delay implements Future<Void, RuntimeException> {
|
||||||
private final static Timer timer;
|
private final static Timer timer = new Timer(true);
|
||||||
|
|
||||||
private TimerTask task;
|
private TimerTask task;
|
||||||
|
|
||||||
static {
|
|
||||||
timer = new Timer(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int delay;
|
private int delay;
|
||||||
private boolean ready;
|
|
||||||
|
|
||||||
protected Delay(int ms) {
|
protected Delay(int ms) {
|
||||||
if (ms < 0) throw new IllegalArgumentException("async_example.Delay cannot be negative");
|
if (ms < 0) throw new IllegalArgumentException("async_example.Delay cannot be negative");
|
||||||
|
|
@ -33,16 +28,12 @@ public class Delay implements Future<Void, RuntimeException> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Object poll(Waker waker) {
|
public synchronized Object poll(Waker waker) {
|
||||||
if (delay == 0) {
|
if (delay == 0) return null;
|
||||||
ready = true;
|
if (delay > 0) {
|
||||||
delay = -1;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (delay != -1) {
|
|
||||||
task = new TimerTask() {
|
task = new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ready = true;
|
delay = 0;
|
||||||
waker.wake();
|
waker.wake();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -50,7 +41,6 @@ public class Delay implements Future<Void, RuntimeException> {
|
||||||
delay = -1;
|
delay = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ready) return null;
|
|
||||||
return Pending.INSTANCE;
|
return Pending.INSTANCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.parkertenbroeck.async_runtime;
|
package com.parkertenbroeck.coroutines.async_runtime;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.future.Waker;
|
import com.parkertenbroeck.coroutines.future.Waker;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
package com.parkertenbroeck.async_runtime;
|
package com.parkertenbroeck.coroutines.async_runtime;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.parkertenbroeck.async_runtime.io;
|
package com.parkertenbroeck.coroutines.async_runtime.io;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.async_runtime.io;
|
package com.parkertenbroeck.coroutines.async_runtime.io;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.parkertenbroeck.async_runtime.io;
|
package com.parkertenbroeck.coroutines.async_runtime.io;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.parkertenbroeck.async_runtime.io.fs;
|
package com.parkertenbroeck.coroutines.async_runtime.io.fs;
|
||||||
|
|
||||||
import com.parkertenbroeck.async_runtime.io.Readable;
|
import com.parkertenbroeck.coroutines.async_runtime.io.Readable;
|
||||||
import com.parkertenbroeck.async_runtime.io.Writable;
|
import com.parkertenbroeck.coroutines.async_runtime.io.Writable;
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.future.Waker;
|
import com.parkertenbroeck.coroutines.future.Waker;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package com.parkertenbroeck.async_runtime.io.net;
|
package com.parkertenbroeck.coroutines.async_runtime.io.net;
|
||||||
|
|
||||||
import com.parkertenbroeck.async_runtime.io.Readable;
|
import com.parkertenbroeck.coroutines.async_runtime.io.Readable;
|
||||||
import com.parkertenbroeck.async_runtime.io.SelectorThread;
|
import com.parkertenbroeck.coroutines.async_runtime.io.SelectorThread;
|
||||||
import com.parkertenbroeck.async_runtime.io.Writable;
|
import com.parkertenbroeck.coroutines.async_runtime.io.Writable;
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.future.Waker;
|
import com.parkertenbroeck.coroutines.future.Waker;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.parkertenbroeck.async_runtime.io.net;
|
package com.parkertenbroeck.coroutines.async_runtime.io.net;
|
||||||
|
|
||||||
import com.parkertenbroeck.async_runtime.io.SelectorThread;
|
import com.parkertenbroeck.coroutines.async_runtime.io.SelectorThread;
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.future.Waker;
|
import com.parkertenbroeck.coroutines.future.Waker;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package com.parkertenbroeck.async_runtime.io.net;
|
package com.parkertenbroeck.coroutines.async_runtime.io.net;
|
||||||
|
|
||||||
import com.parkertenbroeck.async_runtime.io.Readable;
|
import com.parkertenbroeck.coroutines.async_runtime.io.Readable;
|
||||||
import com.parkertenbroeck.async_runtime.io.SelectorThread;
|
import com.parkertenbroeck.coroutines.async_runtime.io.SelectorThread;
|
||||||
import com.parkertenbroeck.async_runtime.io.Writable;
|
import com.parkertenbroeck.coroutines.async_runtime.io.Writable;
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.future.Waker;
|
import com.parkertenbroeck.coroutines.future.Waker;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.parkertenbroeck.bcsm;
|
package com.parkertenbroeck.coroutines.bcsm;
|
||||||
|
|
||||||
|
|
||||||
import com.parkertenbroeck.bcsm.loadtime.StateMachineClassLoader;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.CoroutineClassLoader;
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -9,10 +9,10 @@ import java.util.Set;
|
||||||
import static java.lang.StackWalker.Option.*;
|
import static java.lang.StackWalker.Option.*;
|
||||||
|
|
||||||
public class RT {
|
public class RT {
|
||||||
public static void runWithStateMachines(StateMachineClassLoader.Config config, Object... params){
|
public static void runWithCoroutine(CoroutineClassLoader.Config config, Object... params){
|
||||||
if(RT.class.getClassLoader() instanceof StateMachineClassLoader)return;
|
if(RT.class.getClassLoader() instanceof CoroutineClassLoader)return;
|
||||||
|
|
||||||
var loader = new StateMachineClassLoader(RT.class.getClassLoader(), config);
|
var loader = new CoroutineClassLoader(RT.class.getClassLoader(), config);
|
||||||
try{
|
try{
|
||||||
StackWalker walker = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE, SHOW_REFLECT_FRAMES, SHOW_HIDDEN_FRAMES));
|
StackWalker walker = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE, SHOW_REFLECT_FRAMES, SHOW_HIDDEN_FRAMES));
|
||||||
var frame = walker.walk(s -> s.skip(1).findFirst()).get();
|
var frame = walker.walk(s -> s.skip(1).findFirst()).get();
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
import java.lang.classfile.attribute.InnerClassInfo;
|
import java.lang.classfile.attribute.InnerClassInfo;
|
||||||
|
|
@ -12,9 +12,7 @@ import java.lang.reflect.AccessFlag;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.lang.constant.ConstantDescs.*;
|
public abstract class CoroutineBuilder<T extends CoroutineBuilder<T>> {
|
||||||
|
|
||||||
public abstract class StateMachineBuilder<T extends StateMachineBuilder<T>> {
|
|
||||||
public final static String PARAM_PREFIX = "param_";
|
public final static String PARAM_PREFIX = "param_";
|
||||||
public final static String LOCAL_PREFIX = "local_";
|
public final static String LOCAL_PREFIX = "local_";
|
||||||
public final static String STATE_NAME = "state";
|
public final static String STATE_NAME = "state";
|
||||||
|
|
@ -50,7 +48,7 @@ public abstract class StateMachineBuilder<T extends StateMachineBuilder<T>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StateMachineBuilder(ClassModel src_clm, MethodModel src_mem, CodeModel src_com, String namePostfix){
|
public CoroutineBuilder(ClassModel src_clm, MethodModel src_mem, CodeModel src_com, String namePostfix){
|
||||||
this.src_clm = src_clm;
|
this.src_clm = src_clm;
|
||||||
this.src_mem = src_mem;
|
this.src_mem = src_mem;
|
||||||
this.src_com = src_com;
|
this.src_com = src_com;
|
||||||
|
|
@ -93,7 +91,7 @@ public abstract class StateMachineBuilder<T extends StateMachineBuilder<T>> {
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
var param = params[i];
|
var param = params[i];
|
||||||
for(var attr : param_attrs.get(i))
|
for(var attr : param_attrs.get(i))
|
||||||
parameterVariableAnnotations.add(new ParameterVariableAnnotation(attr, StateMachineBuilder.PARAM_PREFIX + offset, param));
|
parameterVariableAnnotations.add(new ParameterVariableAnnotation(attr, CoroutineBuilder.PARAM_PREFIX + offset, param));
|
||||||
offset += TypeKind.from(param).slotSize();
|
offset += TypeKind.from(param).slotSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.generator.Gen;
|
import com.parkertenbroeck.coroutines.generator.Gen;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.future.FutureSMBuilder;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.future.FutureSMBuilder;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.gen.GenSMBuilder;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.gen.GenSMBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
|
|
@ -14,14 +14,14 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class StateMachineClassLoader extends ClassLoader {
|
public class CoroutineClassLoader extends ClassLoader {
|
||||||
private final HashMap<String, Class<?>> customClazzMap = new HashMap<>();
|
private final HashMap<String, Class<?>> customClazzMap = new HashMap<>();
|
||||||
private final List<String> skip;
|
private final List<String> skip;
|
||||||
private final HashMap<ClassDesc, SMBB> builders;
|
private final HashMap<ClassDesc, SMBB> builders;
|
||||||
private final String write_classes_path;
|
private final String write_classes_path;
|
||||||
|
|
||||||
public interface SMBB{
|
public interface SMBB{
|
||||||
StateMachineBuilder<?> build(ClassModel src_clm, MethodModel src_mem, CodeModel src_com);
|
CoroutineBuilder<?> build(ClassModel src_clm, MethodModel src_mem, CodeModel src_com);
|
||||||
}
|
}
|
||||||
public static class Config{
|
public static class Config{
|
||||||
HashSet<String> skip = new HashSet<>();
|
HashSet<String> skip = new HashSet<>();
|
||||||
|
|
@ -33,7 +33,7 @@ public class StateMachineClassLoader extends ClassLoader {
|
||||||
}
|
}
|
||||||
public static Config builtin(){
|
public static Config builtin(){
|
||||||
return empty()
|
return empty()
|
||||||
.skip("java", "jdk", "jre", "com.parkertenbroeck.bcsm.loadtime")
|
.skip("java", "jdk", "jre", "com.parkertenbroeck.coroutines.bcsm.loadtime")
|
||||||
.with(Future.class, FutureSMBuilder::new)
|
.with(Future.class, FutureSMBuilder::new)
|
||||||
.with(Gen.class, GenSMBuilder::new);
|
.with(Gen.class, GenSMBuilder::new);
|
||||||
}
|
}
|
||||||
|
|
@ -59,11 +59,11 @@ public class StateMachineClassLoader extends ClassLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StateMachineClassLoader(ClassLoader parent) {
|
public CoroutineClassLoader(ClassLoader parent) {
|
||||||
this(parent, Config.builtin());
|
this(parent, Config.builtin());
|
||||||
}
|
}
|
||||||
|
|
||||||
public StateMachineClassLoader(ClassLoader parent, Config config) {
|
public CoroutineClassLoader(ClassLoader parent, Config config) {
|
||||||
super(parent);
|
super(parent);
|
||||||
skip = config.skip.stream().toList();
|
skip = config.skip.stream().toList();
|
||||||
builders = new HashMap<>(config.builders);
|
builders = new HashMap<>(config.builders);
|
||||||
|
|
@ -93,7 +93,7 @@ public class StateMachineClassLoader extends ClassLoader {
|
||||||
|
|
||||||
|
|
||||||
var p = "/" + name.replace('.', '/') + ".class";
|
var p = "/" + name.replace('.', '/') + ".class";
|
||||||
try (var stream = StateMachineClassLoader.class.getResourceAsStream(p)) {
|
try (var stream = CoroutineClassLoader.class.getResourceAsStream(p)) {
|
||||||
var bytes = Objects.requireNonNull(stream).readAllBytes();
|
var bytes = Objects.requireNonNull(stream).readAllBytes();
|
||||||
add(name, searchReplaceableMethods(bytes));
|
add(name, searchReplaceableMethods(bytes));
|
||||||
return customClazzMap.get(name);
|
return customClazzMap.get(name);
|
||||||
|
|
@ -114,7 +114,7 @@ public class StateMachineClassLoader extends ClassLoader {
|
||||||
return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES, ClassFile.StackMapsOption.STACK_MAPS_WHEN_REQUIRED).build(clm.thisClass().asSymbol(), cb -> {
|
return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES, ClassFile.StackMapsOption.STACK_MAPS_WHEN_REQUIRED).build(clm.thisClass().asSymbol(), cb -> {
|
||||||
for (var ce : clm) {
|
for (var ce : clm) {
|
||||||
if (ce instanceof MethodModel mem && mem.code().isPresent()) {
|
if (ce instanceof MethodModel mem && mem.code().isPresent()) {
|
||||||
StateMachineBuilder<?> builder = builders
|
CoroutineBuilder<?> builder = builders
|
||||||
.getOrDefault(
|
.getOrDefault(
|
||||||
mem.methodTypeSymbol().returnType(),
|
mem.methodTypeSymbol().returnType(),
|
||||||
(_, _, _) -> null
|
(_, _, _) -> null
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.classfile.CodeBuilder;
|
import java.lang.classfile.CodeBuilder;
|
||||||
import java.lang.classfile.instruction.LineNumber;
|
import java.lang.classfile.instruction.LineNumber;
|
||||||
|
|
@ -16,7 +16,7 @@ public record Frame(FrameTracker.Type[] locals, FrameTracker.Type[] stack, int b
|
||||||
+ "]";
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save_locals(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off){
|
public void save_locals(CoroutineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off){
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
for (var entry : locals) {
|
for (var entry : locals) {
|
||||||
slot++;// <-----
|
slot++;// <-----
|
||||||
|
|
@ -28,20 +28,20 @@ public record Frame(FrameTracker.Type[] locals, FrameTracker.Type[] stack, int b
|
||||||
sst.save_local(smb, cob, entry.toCD(), slot - smb.paramSlotOff + loc_off - 1); //minus one cause increment before here
|
sst.save_local(smb, cob, entry.toCD(), slot - smb.paramSlotOff + loc_off - 1); //minus one cause increment before here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void save_stack(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int stack_off) {
|
public void save_stack(CoroutineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int stack_off) {
|
||||||
for(int i = stack.length-1-stack_off; i >= 0; i --){
|
for(int i = stack.length-1-stack_off; i >= 0; i --){
|
||||||
if(stack[i].isCategory2_2nd())continue;
|
if(stack[i].isCategory2_2nd())continue;
|
||||||
sst.save_stack(smb, cob, stack[i].toCD());
|
sst.save_stack(smb, cob, stack[i].toCD());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavedStateTracker save(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off, int stack_off) {
|
public SavedStateTracker save(CoroutineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off, int stack_off) {
|
||||||
save_locals(smb, cob, sst, loc_off);
|
save_locals(smb, cob, sst, loc_off);
|
||||||
save_stack(smb, cob, sst, stack_off);
|
save_stack(smb, cob, sst, stack_off);
|
||||||
return sst;
|
return sst;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavedStateTracker save(StateMachineBuilder smb, CodeBuilder cob, int loc_off, int stack_off) {
|
public SavedStateTracker save(CoroutineBuilder smb, CodeBuilder cob, int loc_off, int stack_off) {
|
||||||
var sst = new SavedStateTracker();
|
var sst = new SavedStateTracker();
|
||||||
return save(smb, cob, sst, loc_off, stack_off);
|
return save(smb, cob, sst, loc_off, stack_off);
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
|
import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
|
||||||
|
|
@ -7,7 +7,6 @@ import java.lang.classfile.attribute.StackMapFrameInfo;
|
||||||
import java.lang.classfile.attribute.StackMapTableAttribute;
|
import java.lang.classfile.attribute.StackMapTableAttribute;
|
||||||
import java.lang.classfile.instruction.*;
|
import java.lang.classfile.instruction.*;
|
||||||
import java.lang.constant.*;
|
import java.lang.constant.*;
|
||||||
import java.lang.reflect.AccessFlag;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static java.lang.constant.ConstantDescs.*;
|
import static java.lang.constant.ConstantDescs.*;
|
||||||
|
|
@ -30,7 +29,7 @@ public class FrameTracker {
|
||||||
ITEM_LONG_2ND = 13,
|
ITEM_LONG_2ND = 13,
|
||||||
ITEM_DOUBLE_2ND = 14;
|
ITEM_DOUBLE_2ND = 14;
|
||||||
|
|
||||||
public static ArrayList<Frame> frames(StateMachineBuilder<?> smb, CodeModel src_com) {
|
public static ArrayList<Frame> frames(CoroutineBuilder<?> smb, CodeModel src_com) {
|
||||||
var ft = new FrameTracker(smb, src_com);
|
var ft = new FrameTracker(smb, src_com);
|
||||||
var frames = new ArrayList<Frame>();
|
var frames = new ArrayList<Frame>();
|
||||||
for(var coe : src_com){
|
for(var coe : src_com){
|
||||||
|
|
@ -163,7 +162,7 @@ public class FrameTracker {
|
||||||
|
|
||||||
final ArrayList<Type> stack = new ArrayList<>();
|
final ArrayList<Type> stack = new ArrayList<>();
|
||||||
final ArrayList<Type> locals = new ArrayList<>();
|
final ArrayList<Type> locals = new ArrayList<>();
|
||||||
final StateMachineBuilder smb;
|
final CoroutineBuilder smb;
|
||||||
|
|
||||||
LineNumber current_line_number = null;
|
LineNumber current_line_number = null;
|
||||||
int bci = 0;
|
int bci = 0;
|
||||||
|
|
@ -176,7 +175,7 @@ public class FrameTracker {
|
||||||
final HashMap<Label, List<LocalVariableAnnotation>> annotationEndMap = new HashMap<>();
|
final HashMap<Label, List<LocalVariableAnnotation>> annotationEndMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
FrameTracker(StateMachineBuilder smb, CodeModel com) {
|
FrameTracker(CoroutineBuilder smb, CodeModel com) {
|
||||||
this.smb = smb;
|
this.smb = smb;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
public enum ReplacementKind {
|
public enum ReplacementKind {
|
||||||
ImmediateReplacingPop,
|
ImmediateReplacingPop,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.classfile.CodeBuilder;
|
import java.lang.classfile.CodeBuilder;
|
||||||
import java.lang.classfile.TypeKind;
|
import java.lang.classfile.TypeKind;
|
||||||
|
|
@ -18,18 +18,18 @@ public class SavedStateTracker {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String get_name(StateMachineBuilder<?> smb, ClassDesc desc){
|
private String get_name(CoroutineBuilder<?> smb, ClassDesc desc){
|
||||||
var value = smb.lstate.stream() // find unused state
|
var value = smb.lstate.stream() // find unused state
|
||||||
.filter(v -> saved.stream().noneMatch(s -> s.name().equals(v.name())))
|
.filter(v -> saved.stream().noneMatch(s -> s.name().equals(v.name())))
|
||||||
.filter(v -> v.cd().equals(desc)).findFirst();
|
.filter(v -> v.cd().equals(desc)).findFirst();
|
||||||
if(value.isPresent())
|
if(value.isPresent())
|
||||||
return value.get().name();
|
return value.get().name();
|
||||||
var name = StateMachineBuilder.LOCAL_PREFIX+smb.lstate.size();
|
var name = CoroutineBuilder.LOCAL_PREFIX+smb.lstate.size();
|
||||||
smb.lstate.add(new StateMachineBuilder.LState(name, desc));
|
smb.lstate.add(new CoroutineBuilder.LState(name, desc));
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavedState save_stack(StateMachineBuilder<?> smb, CodeBuilder cob, ClassDesc desc){
|
public SavedState save_stack(CoroutineBuilder<?> smb, CodeBuilder cob, ClassDesc desc){
|
||||||
var name = get_name(smb, desc);
|
var name = get_name(smb, desc);
|
||||||
|
|
||||||
if(TypeKind.from(desc).slotSize()==2){
|
if(TypeKind.from(desc).slotSize()==2){
|
||||||
|
|
@ -43,7 +43,7 @@ public class SavedStateTracker {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavedState save_local(StateMachineBuilder<?> smb, CodeBuilder cob, ClassDesc desc, int slot){
|
public SavedState save_local(CoroutineBuilder<?> smb, CodeBuilder cob, ClassDesc desc, int slot){
|
||||||
var name = get_name(smb, desc);
|
var name = get_name(smb, desc);
|
||||||
|
|
||||||
cob.aload(0).loadLocal(TypeKind.from(desc), slot).putfield(smb.CD_this, name, desc);
|
cob.aload(0).loadLocal(TypeKind.from(desc), slot).putfield(smb.CD_this, name, desc);
|
||||||
|
|
@ -63,7 +63,7 @@ public class SavedStateTracker {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavedStateTracker restore(StateMachineBuilder<?> smb, CodeBuilder cob, SavedState s){
|
public SavedStateTracker restore(CoroutineBuilder<?> smb, CodeBuilder cob, SavedState s){
|
||||||
if(!saved.remove(s))throw new IllegalStateException();
|
if(!saved.remove(s))throw new IllegalStateException();
|
||||||
switch(s){
|
switch(s){
|
||||||
case LocalState(var name, var desc, int slot) ->
|
case LocalState(var name, var desc, int slot) ->
|
||||||
|
|
@ -74,21 +74,21 @@ public class SavedStateTracker {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restore_stack(StateMachineBuilder<?> smb, CodeBuilder cob){
|
public void restore_stack(CoroutineBuilder<?> smb, CodeBuilder cob){
|
||||||
for(int i = saved.size()-1; i >= 0; i --){
|
for(int i = saved.size()-1; i >= 0; i --){
|
||||||
if(saved.get(i) instanceof StackState)
|
if(saved.get(i) instanceof StackState)
|
||||||
restore(smb, cob, saved.get(i));
|
restore(smb, cob, saved.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restore_locals(StateMachineBuilder<?> smb, CodeBuilder cob){
|
public void restore_locals(CoroutineBuilder<?> smb, CodeBuilder cob){
|
||||||
for(int i = saved.size()-1; i >= 0; i --){
|
for(int i = saved.size()-1; i >= 0; i --){
|
||||||
if(saved.get(i) instanceof StackState)
|
if(saved.get(i) instanceof StackState)
|
||||||
restore(smb, cob, saved.get(i));
|
restore(smb, cob, saved.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restore_all(StateMachineBuilder<?> smb, CodeBuilder cob) {
|
public void restore_all(CoroutineBuilder<?> smb, CodeBuilder cob) {
|
||||||
while(!saved.isEmpty())
|
while(!saved.isEmpty())
|
||||||
restore(smb, cob, saved.getLast());
|
restore(smb, cob, saved.getLast());
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
import java.lang.constant.MethodTypeDesc;
|
import java.lang.constant.MethodTypeDesc;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.classfile.CodeBuilder;
|
import java.lang.classfile.CodeBuilder;
|
||||||
|
|
||||||
public interface SpecialMethodBuilder<T extends StateMachineBuilder<T>> {
|
public interface SpecialMethodBuilder<T extends CoroutineBuilder<T>> {
|
||||||
SpecialMethodHandler<T> build(T smb, CodeBuilder cob, Frame frame, StateBuilder sb);
|
SpecialMethodHandler<T> build(T smb, CodeBuilder cob, Frame frame, StateBuilder sb);
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.classfile.CodeBuilder;
|
import java.lang.classfile.CodeBuilder;
|
||||||
|
|
||||||
public interface SpecialMethodHandler<T extends StateMachineBuilder> {
|
public interface SpecialMethodHandler<T extends CoroutineBuilder> {
|
||||||
|
|
||||||
void build_prelude(T smb, CodeBuilder cob, Frame frame);
|
void build_prelude(T smb, CodeBuilder cob, Frame frame);
|
||||||
default boolean removeCall() {
|
default boolean removeCall() {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime;
|
||||||
|
|
||||||
import java.lang.classfile.CodeBuilder;
|
import java.lang.classfile.CodeBuilder;
|
||||||
import java.lang.classfile.Label;
|
import java.lang.classfile.Label;
|
||||||
|
|
@ -12,8 +12,8 @@ public class StateBuilder {
|
||||||
cob.labelBinding(label);
|
cob.labelBinding(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setState(StateMachineBuilder smb, CodeBuilder cob){
|
public void setState(CoroutineBuilder smb, CodeBuilder cob){
|
||||||
cob.aload(0).loadConstant(id).putfield(smb.CD_this, StateMachineBuilder.STATE_NAME, ConstantDescs.CD_int);
|
cob.aload(0).loadConstant(id).putfield(smb.CD_this, CoroutineBuilder.STATE_NAME, ConstantDescs.CD_int);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime.future;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime.future;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime.future;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime.future;
|
||||||
|
|
||||||
import com.parkertenbroeck.future.Future;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.*;
|
||||||
import com.parkertenbroeck.future.Waker;
|
import com.parkertenbroeck.coroutines.future.Future;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.*;
|
import com.parkertenbroeck.coroutines.future.Waker;
|
||||||
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.*;
|
||||||
|
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
import java.lang.classfile.instruction.SwitchCase;
|
import java.lang.classfile.instruction.SwitchCase;
|
||||||
|
|
@ -11,7 +12,7 @@ import java.lang.reflect.Method;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
public class FutureSMBuilder extends CoroutineBuilder<FutureSMBuilder> {
|
||||||
|
|
||||||
public final static ClassDesc CD_Future = ClassDesc.ofDescriptor(Future.class.descriptorString());
|
public final static ClassDesc CD_Future = ClassDesc.ofDescriptor(Future.class.descriptorString());
|
||||||
public final static ClassDesc CD_Waker = ClassDesc.ofDescriptor(Waker.class.descriptorString());
|
public final static ClassDesc CD_Waker = ClassDesc.ofDescriptor(Waker.class.descriptorString());
|
||||||
|
|
@ -26,7 +27,7 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
|
||||||
|
|
||||||
private final HashMap<Integer, Consumer<CodeBuilder>> cancellation_behavior = new HashMap<>();
|
private final HashMap<Integer, Consumer<CodeBuilder>> cancellation_behavior = new HashMap<>();
|
||||||
|
|
||||||
static class AwaitHandler implements SpecialMethodHandler<FutureSMBuilder>{
|
static class AwaitHandler implements SpecialMethodHandler<FutureSMBuilder> {
|
||||||
final StateBuilder.State awaiting;
|
final StateBuilder.State awaiting;
|
||||||
final Label save_label;
|
final Label save_label;
|
||||||
final Label resume_inline;
|
final Label resume_inline;
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
package com.parkertenbroeck.bcsm.loadtime.gen;
|
package com.parkertenbroeck.coroutines.bcsm.loadtime.gen;
|
||||||
|
|
||||||
import com.parkertenbroeck.generator.Gen;
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.*;
|
||||||
import com.parkertenbroeck.bcsm.loadtime.*;
|
import com.parkertenbroeck.coroutines.generator.Gen;
|
||||||
|
import com.parkertenbroeck.coroutines.bcsm.loadtime.*;
|
||||||
|
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
|
|
@ -9,7 +10,7 @@ import java.lang.constant.ConstantDescs;
|
||||||
import java.lang.constant.MethodTypeDesc;
|
import java.lang.constant.MethodTypeDesc;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class GenSMBuilder extends StateMachineBuilder<GenSMBuilder> {
|
public class GenSMBuilder extends CoroutineBuilder<GenSMBuilder> {
|
||||||
|
|
||||||
public final static ClassDesc CD_Gen = ClassDesc.ofDescriptor(Gen.class.descriptorString());
|
public final static ClassDesc CD_Gen = ClassDesc.ofDescriptor(Gen.class.descriptorString());
|
||||||
public final static ClassDesc CD_Res = ClassDesc.ofDescriptor(Gen.Res.class.descriptorString());
|
public final static ClassDesc CD_Res = ClassDesc.ofDescriptor(Gen.Res.class.descriptorString());
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.future;
|
package com.parkertenbroeck.coroutines.future;
|
||||||
|
|
||||||
public interface Future<R, E extends Throwable> {
|
public interface Future<R, E extends Throwable> {
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.future;
|
package com.parkertenbroeck.coroutines.future;
|
||||||
|
|
||||||
public interface Waker {
|
public interface Waker {
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.parkertenbroeck.generator;
|
package com.parkertenbroeck.coroutines.generator;
|
||||||
|
|
||||||
public interface Gen<Y, R> {
|
public interface Gen<Y, R> {
|
||||||
Res<Y, R> next();
|
Res<Y, R> next();
|
||||||
|
|
@ -1,7 +1,2 @@
|
||||||
plugins {
|
rootProject.name = "coroutines"
|
||||||
// Apply the foojay-resolver plugin to allow automatic download of JDKs
|
|
||||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0"
|
|
||||||
}
|
|
||||||
|
|
||||||
rootProject.name = "generators"
|
|
||||||
include("lib", "app")
|
include("lib", "app")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue