From baf0e86f397fe17569f081e4e14ec3b0b8109313 Mon Sep 17 00:00:00 2001 From: ParkerTenBroeck <51721964+ParkerTenBroeck@users.noreply.github.com> Date: Sat, 3 May 2025 23:20:11 -0400 Subject: [PATCH] added first iteration of cancellations in futures --- src/Main.java | 37 +++++++- src/generators/loadtime/Frame.java | 4 +- .../loadtime/SavedStateTracker.java | 12 +++ .../loadtime/future/FutureSMBuilder.java | 86 +++++++++++-------- 4 files changed, 99 insertions(+), 40 deletions(-) diff --git a/src/Main.java b/src/Main.java index 61ee5ab..bb8da11 100644 --- a/src/Main.java +++ b/src/Main.java @@ -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 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> lambda){ diff --git a/src/generators/loadtime/Frame.java b/src/generators/loadtime/Frame.java index 0035123..c3fe156 100644 --- a/src/generators/loadtime/Frame.java +++ b/src/generators/loadtime/Frame.java @@ -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) { diff --git a/src/generators/loadtime/SavedStateTracker.java b/src/generators/loadtime/SavedStateTracker.java index 682526f..b5cb279 100644 --- a/src/generators/loadtime/SavedStateTracker.java +++ b/src/generators/loadtime/SavedStateTracker.java @@ -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 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){ diff --git a/src/generators/loadtime/future/FutureSMBuilder.java b/src/generators/loadtime/future/FutureSMBuilder.java index b27996f..55b2e29 100644 --- a/src/generators/loadtime/future/FutureSMBuilder.java +++ b/src/generators/loadtime/future/FutureSMBuilder.java @@ -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 { 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 { 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 { 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 { @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 { 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> 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 { .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 -> {