added first iteration of cancellations in futures

This commit is contained in:
ParkerTenBroeck 2025-05-03 23:20:11 -04:00
parent 6329257702
commit baf0e86f39
4 changed files with 99 additions and 40 deletions

View file

@ -4,6 +4,7 @@ import async_runtime.Util;
import generators.RT;
import future.Future;
import gen.Gen;
import generators.loadtime.future.Cancellation;
import java.util.function.Supplier;
@ -12,10 +13,38 @@ public class Main implements Runnable {
RT.runWithGeneratorSupport(Main.class);
}
class Meow implements AutoCloseable{
{
System.out.println("CREATED");
}
@Override
public void close() {
System.out.println("CLOSED");
}
}
Future<Void, RuntimeException> nya(){
try(@Cancellation("close") var nya = new Meow()){
Future.yield();
Future.yield();
int beep = 1;
Future.yield();
Future.yield();
return Future.ret(null);
}
}
@Override
public void run() {
new Jokio().blocking(AsyncExamples.meow());
new Jokio().blocking(new AsyncExamples().meow2());
// new Jokio().blocking();
var future = nya();
future.poll(null);
future.poll(null);
future.cancel();
// new Jokio().blocking(AsyncExamples.meow());
// new Jokio().blocking(new AsyncExamples().meow2());
// async_lambda(() -> {
// System.out.println("START");
// Delay.delay(100).await();
@ -31,8 +60,8 @@ public class Main implements Runnable {
// start = end;
// }
// });
lexer();
await();
// lexer();
// await();
}
void async_lambda(Supplier<Future<?, ?>> lambda){

View file

@ -19,13 +19,13 @@ public record Frame(FrameTracker.Type[] locals, FrameTracker.Type[] stack, int b
public void save_locals(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off){
int slot = 0;
for (var entry : locals) {
slot++;
slot++;// <-----
if (slot <= smb.paramSlotOff) continue;
if(entry.tag() == FrameTracker.Type.TOP_TYPE.tag())continue;
if (entry.isCategory2_2nd()) continue;
sst.save_local(smb, cob, entry.toCD(), slot - smb.paramSlotOff + loc_off - 1);
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) {

View file

@ -4,9 +4,11 @@ import java.lang.classfile.CodeBuilder;
import java.lang.classfile.TypeKind;
import java.lang.constant.ClassDesc;
import java.util.ArrayList;
import java.util.Objects;
public class SavedStateTracker {
private final ArrayList<SavedState> saved = new ArrayList<>();
public sealed interface SavedState{
String name();
}
@ -52,6 +54,16 @@ public class SavedStateTracker {
return s;
}
public LocalState load_param(int slot) {
for(var saved : saved){
if (saved instanceof LocalState(var name, var desc, int s) && s == slot) {
return (LocalState) saved;
}
}
throw new RuntimeException();
}
public SavedStateTracker restore(StateMachineBuilder<?> smb, CodeBuilder cob, SavedState s){
if(!saved.remove(s))throw new IllegalStateException();
switch(s){

View file

@ -5,10 +5,11 @@ import future.Waker;
import generators.loadtime.*;
import java.lang.classfile.*;
import java.lang.classfile.constantpool.InterfaceMethodRefEntry;
import java.lang.classfile.constantpool.MethodRefEntry;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.MethodTypeDesc;
import java.lang.classfile.instruction.SwitchCase;
import java.lang.constant.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
@ -37,7 +38,6 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
awaiting = sb.create(cob);
save_label = cob.newLabel();
resume_inline = cob.newLabel();
smb.yielding_state(awaiting, frame);
}
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
@ -51,6 +51,8 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
frame.save_stack(smb, cob, sst,1);
cob.loadLocal(TypeKind.REFERENCE, 2);
smb.yielding_state(awaiting, frame, sst);
smb.resumable_return(cob, awaiting, TypeKind.REFERENCE);
sst.restore_all(smb, cob);
@ -89,8 +91,6 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
resume = sb.create(cob);
save_ret = cob.newLabel();
end = cob.newLabel();
smb.yielding_state(resume, frame);
}
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
@ -98,14 +98,15 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
@Override
public void build_prelude(FutureSMBuilder smb, CodeBuilder cob, Frame frame) {
cob.labelBinding(save_ret);
var saved = frame.save(smb, cob, 2, 0);
var sst = frame.save(smb, cob, 2, 0);
resume.setState(smb, cob);
cob.getstatic(CD_Pending, "INSTANCE", CD_Pending);
smb.yielding_state(resume, frame, sst);
smb.resumable_return(cob, resume, TypeKind.REFERENCE);
saved.restore_all(smb, cob);
sst.restore_all(smb, cob);
cob.goto_(end);
}
@ -202,31 +203,42 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
throw new RuntimeException();
}
private void yielding_state(StateBuilder.State state, Frame frame){
private void yielding_state(StateBuilder.State state, Frame frame, SavedStateTracker sst){
if(frame.local_annotations().length==0)return;
cancellation_behavior.put(state.id(), cob -> {
for(var ann : frame.local_annotations()){
if(ann.annotation().classSymbol().descriptorString().equals(Cancellation.class.descriptorString())){
ClassDesc owner = frame.locals()[ann.slot()].sym();
ClassDesc param = frame.locals()[ann.slot()].sym();
String name = "cancel";
for(var el : ann.annotation().elements()){
switch(el.name().stringValue()){
case "value" -> name = fromAnnValue(el.value());
case "owner" -> {}
case "param" -> {}
case "ret" -> {}
}
el.name().equalsString("value");
ArrayList<Consumer<CodeBuilder>> stuff = new ArrayList<>();
for(var ann : frame.local_annotations()){
if(ann.annotation().classSymbol().descriptorString().equals(Cancellation.class.descriptorString())){
var param = sst.load_param(ann.slot()-paramSlotOff+2);
ClassDesc owner = frame.locals()[ann.slot()].sym();
String name = "cancel";
for(var el : ann.annotation().elements()){
switch(el.name().stringValue()){
case "value" -> name = fromAnnValue(el.value());
case "owner" -> {}
case "ret" -> {}
}
var mre = cob.constantPool().methodRefEntry(owner, name, MethodTypeDesc.of(ConstantDescs.CD_void));
cob.trying(tcob -> {
tcob.aconst_null()
// .aload(ann.slot())
.invokevirtual(mre);
}, cb -> cb.catchingAll(ccob -> ccob.pop()));
el.name().equalsString("value");
}
String final_name = name;
stuff.add(cob -> {
cob.trying(tcob -> {
tcob.aload(0).getfield(CD_this, param.name(), param.desc());
try{
if(FutureSMBuilder.class.getClassLoader().loadClass(owner.displayName()).isInterface()){
tcob.invokeinterface(owner, final_name, MethodTypeDesc.of(ConstantDescs.CD_void));
}else{
tcob.invokevirtual(owner, final_name, MethodTypeDesc.of(ConstantDescs.CD_void));
}
}catch (Exception e){
throw new RuntimeException(e);
}
}, cb -> cb.catchingAll(ccob -> ccob.pop()));
});
}
}
cancellation_behavior.put(state.id(), cob -> {
for(var thing : stuff) thing.accept(cob);
});
}
@ -250,15 +262,21 @@ public class FutureSMBuilder extends StateMachineBuilder<FutureSMBuilder> {
.aload(0).aconst_null().putfield(CD_this, AWAITING_FIELD_NAME, CD_Future);
});
for(var cb : cancellation_behavior.entrySet()){
var end = tcob.newLabel();
if(!cancellation_behavior.isEmpty()){
var states = cancellation_behavior.entrySet().stream().toList();
var cases = states.stream().map(v -> SwitchCase.of(v.getKey(), tcob.newLabel())).toList();
tcob.iload(1);
tcob.loadConstant(cb.getKey());
tcob.if_icmpne(end);
cb.getValue().accept(tcob);
var end = tcob.newLabel();
tcob.tableswitch(end, cases);
for(int i = 0; i < states.size(); i ++){
tcob.labelBinding(cases.get(i).target());
states.get(i).getValue().accept(tcob);
tcob.goto_(end);
}
tcob.labelBinding(end);
}
this.synchronized_exit(tcob);
tcob.return_();
}, cb -> {