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 generators.RT;
import future.Future; import future.Future;
import gen.Gen; import gen.Gen;
import generators.loadtime.future.Cancellation;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -12,10 +13,38 @@ public class Main implements Runnable {
RT.runWithGeneratorSupport(Main.class); 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 @Override
public void run() { public void run() {
new Jokio().blocking(AsyncExamples.meow()); // new Jokio().blocking();
new Jokio().blocking(new AsyncExamples().meow2()); var future = nya();
future.poll(null);
future.poll(null);
future.cancel();
// new Jokio().blocking(AsyncExamples.meow());
// new Jokio().blocking(new AsyncExamples().meow2());
// async_lambda(() -> { // async_lambda(() -> {
// System.out.println("START"); // System.out.println("START");
// Delay.delay(100).await(); // Delay.delay(100).await();
@ -31,8 +60,8 @@ public class Main implements Runnable {
// start = end; // start = end;
// } // }
// }); // });
lexer(); // lexer();
await(); // await();
} }
void async_lambda(Supplier<Future<?, ?>> lambda){ 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){ public void save_locals(StateMachineBuilder smb, CodeBuilder cob, SavedStateTracker sst, int loc_off){
int slot = 0; int slot = 0;
for (var entry : locals) { for (var entry : locals) {
slot++; slot++;// <-----
if (slot <= smb.paramSlotOff) continue; if (slot <= smb.paramSlotOff) continue;
if(entry.tag() == FrameTracker.Type.TOP_TYPE.tag())continue; if(entry.tag() == FrameTracker.Type.TOP_TYPE.tag())continue;
if (entry.isCategory2_2nd()) 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) { 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.classfile.TypeKind;
import java.lang.constant.ClassDesc; import java.lang.constant.ClassDesc;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
public class SavedStateTracker { public class SavedStateTracker {
private final ArrayList<SavedState> saved = new ArrayList<>(); private final ArrayList<SavedState> saved = new ArrayList<>();
public sealed interface SavedState{ public sealed interface SavedState{
String name(); String name();
} }
@ -52,6 +54,16 @@ public class SavedStateTracker {
return s; 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){ public SavedStateTracker restore(StateMachineBuilder<?> smb, CodeBuilder cob, SavedState s){
if(!saved.remove(s))throw new IllegalStateException(); if(!saved.remove(s))throw new IllegalStateException();
switch(s){ switch(s){

View file

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