now each handler has an inline and prelude section so exception handlers run properly

This commit is contained in:
Parker TenBroeck 2025-05-01 11:03:26 -04:00
parent 8593eada03
commit 1e1b1beadf
7 changed files with 199 additions and 146 deletions

View file

@ -18,7 +18,7 @@ public class Examples {
Jokio.runtime().await().spawn(server()); Jokio.runtime().await().spawn(server());
for(int i = 0; i < 100; i ++){ for(int i = 0; i < 200; i ++){
var builder = new StringBuilder(); var builder = new StringBuilder();
for(int c = 0; c < 4096*16*3; c ++) for(int c = 0; c < 4096*16*3; c ++)
builder.append((char)((Math.random()*('z'-'a')+'a'))); builder.append((char)((Math.random()*('z'-'a')+'a')));

View file

@ -9,7 +9,7 @@ public record Frame(FrameTracker.Type[] locals, FrameTracker.Type[] stack) {
@Override @Override
public String toString() { public String toString() {
return "Frame[l =" + Arrays.toString(locals) + ", s = " + Arrays.toString(stack) + "]"; return "Frame[label =" + Arrays.toString(locals) + ", s = " + Arrays.toString(stack) + "]";
} }
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){

View file

@ -1,26 +1,13 @@
package generator.runtime; package generator.runtime;
import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeBuilder;
import java.lang.classfile.Label;
public abstract class SpecialMethodHandler { public interface SpecialMethodHandler {
public final Label handler_start;
public final Label handler_resume;
protected SpecialMethodHandler(StateMachineBuilder smb, CodeBuilder cob) { void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame);
handler_start = cob.newLabel(); default boolean removeCall() {
handler_resume = cob.newLabel();
}
public abstract void buildHandler(StateMachineBuilder smb, CodeBuilder cob, Frame frame);
public boolean removeCall() {
return true; return true;
} }
void build_inline(StateMachineBuilder smb, CodeBuilder cob, Frame frame);
public void insertShim(StateMachineBuilder smb, CodeBuilder cob){ ReplacementKind replacementKind();
cob.goto_(handler_start).labelBinding(handler_resume);
}
public abstract ReplacementKind replacementKind();
} }

View file

@ -0,0 +1,31 @@
package generator.runtime;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.Label;
import java.lang.classfile.instruction.SwitchCase;
import java.lang.constant.ConstantDescs;
import java.util.ArrayList;
public class StateBuilder {
public record State(Label label, int id){
public void bind(CodeBuilder cob){
cob.labelBinding(label);
}
public void setState(StateMachineBuilder smb, CodeBuilder cob){
cob.aload(0).loadConstant(id).putfield(smb.CD_this, StateMachineBuilder.STATE_NAME, ConstantDescs.CD_int);
}
}
private final ArrayList<State> states = new ArrayList<>();
public State create(CodeBuilder cob){
var state = new State(cob.newLabel(), states.size());
states.add(state);
return state;
}
public void buildSwitch(CodeBuilder cob, Label default_label){
cob.lookupswitch(default_label, states.stream().map(l -> SwitchCase.of(l.id, l.label)).toList());
}
}

View file

@ -10,7 +10,6 @@ import java.lang.constant.ConstantDescs;
import java.lang.constant.MethodTypeDesc; import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag; import java.lang.reflect.AccessFlag;
import java.util.*; import java.util.*;
import java.util.function.BiFunction;
public abstract class StateMachineBuilder { public abstract class StateMachineBuilder {
public final static String PARAM_PREFIX = "param_"; public final static String PARAM_PREFIX = "param_";
@ -36,9 +35,13 @@ public abstract class StateMachineBuilder {
record LState(String name, ClassDesc cd) { record LState(String name, ClassDesc cd) {
} }
protected HashMap<SpecialMethod, BiFunction<StateMachineBuilder, CodeBuilder, SpecialMethodHandler>> smmap = new HashMap<>(); public interface SpecialMethodBuilder{
SpecialMethodHandler build(StateMachineBuilder smb, CodeBuilder cob, StateBuilder sb);
}
private final ArrayList<SwitchCase> stateSwitchCases = new ArrayList<>(); protected HashMap<SpecialMethod, SpecialMethodBuilder> smmap = new HashMap<>();
// private final ArrayList<SwitchCase> stateSwitchCases = new ArrayList<>();
protected String uniqueName(){ protected String uniqueName(){
return sequence+++""; return sequence+++"";
@ -108,10 +111,10 @@ public abstract class StateMachineBuilder {
}; };
} }
public int add_state(Label label) { // public int add_state(Label label) {
stateSwitchCases.add(SwitchCase.of(stateSwitchCases.size(), label)); // stateSwitchCases.add(SwitchCase.of(stateSwitchCases.size(), label));
return stateSwitchCases.size() - 1; // return stateSwitchCases.size() - 1;
} // }
public void buildSourceMethodShim(CodeBuilder cob){ public void buildSourceMethodShim(CodeBuilder cob){
cob.new_(CD_this).dup(); cob.new_(CD_this).dup();
@ -179,43 +182,38 @@ public abstract class StateMachineBuilder {
} }
public void buildStateMachineCode(ClassBuilder clb, CodeBuilder cob, int loc_param_off) { public void buildStateMachineCode(ClassBuilder clb, CodeBuilder cob, int loc_param_off) {
var stateBuilder = new StateBuilder();
boolean ignore_next_pop = false; boolean ignore_next_pop = false;
var invalid_state = cob.newLabel(); var invalid_state = cob.newLabel();
var start_label = cob.newLabel(); var start_state = stateBuilder.create(cob);
add_state(start_label);
for(var wf : with_frames()){ for(var wf : with_frames()){
if (wf.coe() instanceof InvokeInstruction is){ if (wf.coe() instanceof InvokeInstruction is){
var handler = smmap.get(new SpecialMethod(is.owner().asSymbol(), is.name().stringValue(), is.typeSymbol())); var handler = smmap.get(new SpecialMethod(is.owner().asSymbol(), is.name().stringValue(), is.typeSymbol()));
if(handler != null) if(handler != null)
handlers.add(handler.apply(this, cob)); handlers.add(handler.build(this, cob, stateBuilder));
} }
} }
cob.aload(0).getfield(CD_this, STATE_NAME, TypeKind.INT.upperBound()).lookupswitch(invalid_state, stateSwitchCases); cob.aload(0).getfield(CD_this, STATE_NAME, TypeKind.INT.upperBound());
var start = cob.startLabel(); stateBuilder.buildSwitch(cob, invalid_state);
var end = cob.newLabel();
cob.localVariable(0, "this", CD_this, start, end); cob.localVariable(0, "this", CD_this, cob.startLabel(), cob.endLabel());
{ {
int i = 0; int i = 0;
for (var wf : with_frames()) { for (var wf : with_frames()) {
if (wf.coe() instanceof InvokeInstruction is) { if (wf.coe() instanceof InvokeInstruction is) {
var h = smmap.get(new SpecialMethod(is.owner().asSymbol(), is.name().stringValue(), is.typeSymbol())); var h = smmap.get(new SpecialMethod(is.owner().asSymbol(), is.name().stringValue(), is.typeSymbol()));
if(h!=null){ if(h!=null) handlers.get(i++).build_prelude(this, cob, wf.frame());
var handler = handlers.get(i++);
cob.labelBinding(handler.handler_start);
handler.buildHandler(this, cob, wf.frame());
cob.goto_(handler.handler_resume);
}
} }
} }
} }
SpecialMethodHandler currentHandler = null; SpecialMethodHandler currentHandler = null;
cob.labelBinding(start_label); start_state.bind(cob);
for (var wf : with_frames()) { for (var wf : with_frames()) {
var coe = wf.coe(); var coe = wf.coe();
var frame = wf.frame(); var frame = wf.frame();
@ -227,7 +225,7 @@ public abstract class StateMachineBuilder {
}else throw new RuntimeException("Expected Pop Instruction"); }else throw new RuntimeException("Expected Pop Instruction");
if (i.opcode() == Opcode.ARETURN){ if (i.opcode() == Opcode.ARETURN){
if (currentHandler !=null && currentHandler.replacementKind() == ReplacementKind.ReplacingNextReturn){ if (currentHandler !=null && currentHandler.replacementKind() == ReplacementKind.ReplacingNextReturn){
currentHandler.insertShim(this, cob); currentHandler.build_inline(this, cob, frame);
currentHandler = null; currentHandler = null;
continue; continue;
} }
@ -238,9 +236,9 @@ public abstract class StateMachineBuilder {
if(currentHandler!=null)throw new RuntimeException("Multiple method handlers at once not supported"); if(currentHandler!=null)throw new RuntimeException("Multiple method handlers at once not supported");
var handler = handlers.removeFirst(); var handler = handlers.removeFirst();
if(!handler.removeCall()) cob.with(coe); if(!handler.removeCall()) cob.with(coe);
if(handler.replacementKind() == ReplacementKind.Immediate) handler.insertShim(this, cob); if(handler.replacementKind() == ReplacementKind.Immediate) handler.build_inline(this, cob, frame);
else if(handler.replacementKind() == ReplacementKind.ImmediateReplacingPop) { else if(handler.replacementKind() == ReplacementKind.ImmediateReplacingPop) {
handler.insertShim(this, cob); handler.build_inline(this, cob, frame);
ignore_next_pop = true; ignore_next_pop = true;
}else }else
currentHandler = handler; currentHandler = handler;
@ -285,7 +283,6 @@ public abstract class StateMachineBuilder {
cob.new_(ClassDesc.ofDescriptor(IllegalStateException.class.descriptorString())).dup() cob.new_(ClassDesc.ofDescriptor(IllegalStateException.class.descriptorString())).dup()
.invokespecial(ClassDesc.ofDescriptor(IllegalStateException.class.descriptorString()), ConstantDescs.INIT_NAME, ConstantDescs.MTD_void) .invokespecial(ClassDesc.ofDescriptor(IllegalStateException.class.descriptorString()), ConstantDescs.INIT_NAME, ConstantDescs.MTD_void)
.athrow(); .athrow();
cob.labelBinding(end);
for (var lstate : lstate) { for (var lstate : lstate) {
clb.withField(lstate.name(), lstate.cd(), ClassFile.ACC_PRIVATE); clb.withField(lstate.name(), lstate.cd(), ClassFile.ACC_PRIVATE);

View file

@ -17,42 +17,51 @@ public class FutureSMBuilder extends StateMachineBuilder {
public final static ClassDesc CD_Pending = ClassDesc.ofDescriptor(Future.Pending.class.descriptorString()); public final static ClassDesc CD_Pending = ClassDesc.ofDescriptor(Future.Pending.class.descriptorString());
public final static MethodTypeDesc MTD_Future_Obj = MethodTypeDesc.of(CD_Future, ConstantDescs.CD_Object); public final static MethodTypeDesc MTD_Future_Obj = MethodTypeDesc.of(CD_Future, ConstantDescs.CD_Object);
public final static MethodTypeDesc MTD_Future = MethodTypeDesc.of(CD_Future);
public final static MethodTypeDesc MTD_Object_Waker = MethodTypeDesc.of(ConstantDescs.CD_Object, CD_Waker); public final static MethodTypeDesc MTD_Object_Waker = MethodTypeDesc.of(ConstantDescs.CD_Object, CD_Waker);
public final static MethodTypeDesc MTD_Obj = MethodTypeDesc.of(ConstantDescs.CD_Object); public final static MethodTypeDesc MTD_Obj = MethodTypeDesc.of(ConstantDescs.CD_Object);
public final static String AWAITING_FIELD_NAME = "awaiting"; public final static String AWAITING_FIELD_NAME = "awaiting";
static class AwaitHandler extends SpecialMethodHandler{ static class AwaitHandler implements SpecialMethodHandler{
final int awaiting_state; final StateBuilder.State awaiting;
final Label restore_label;
final Label save_label; final Label save_label;
final Label resume_inline;
public AwaitHandler(StateMachineBuilder smb, CodeBuilder cob) { public AwaitHandler(StateMachineBuilder smb, CodeBuilder cob, StateBuilder sb) {
super(smb, cob); awaiting = sb.create(cob);
awaiting_state = smb.add_state(restore_label = cob.newLabel());
save_label = cob.newLabel(); save_label = cob.newLabel();
resume_inline = cob.newLabel();
} }
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;} public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
@Override @Override
public void buildHandler(StateMachineBuilder smb, CodeBuilder cob, Frame frame) { public void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
cob.aload(0).loadConstant(awaiting_state).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()); cob.labelBinding(save_label);
var start = cob.newBoundLabel();
cob.dup()
.aload(1).invokeinterface(CD_Future, "poll", MTD_Object_Waker).dup()
.instanceOf(CD_Pending);
cob.ifThenElse(bcb -> {
bcb.swap().aload(0).swap().putfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future);
var sst = new SavedStateTracker(); var sst = new SavedStateTracker();
frame.save_locals(smb, cob, sst,2); frame.save_locals(smb, cob, sst,2);
bcb.storeLocal(TypeKind.REFERENCE, frame.locals().length+2); cob.storeLocal(TypeKind.REFERENCE, frame.locals().length+2);
frame.save_stack(smb, cob, sst,1); frame.save_stack(smb, cob, sst,1);
bcb.loadLocal(TypeKind.REFERENCE, frame.locals().length+2); cob.loadLocal(TypeKind.REFERENCE, frame.locals().length+2);
bcb.areturn().labelBinding(restore_label); cob.areturn();
awaiting.bind(cob);
sst.restore_all(smb, cob); sst.restore_all(smb, cob);
cob.goto_(resume_inline);
}
@Override
public void build_inline(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
// [... Future]
var start = cob.newBoundLabel();
cob.dup().aload(1).invokeinterface(CD_Future, "poll", MTD_Object_Waker).dup().instanceOf(CD_Pending);
// [... Future Polled is_pending]
cob.ifThenElse(bcb -> {
awaiting.setState(smb, cob);
// [... Future Polled]
bcb.swap().aload(0).swap().putfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future);
// [... Polled]
cob.goto_(save_label).labelBinding(resume_inline);
bcb.aload(0).getfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future); bcb.aload(0).getfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future);
bcb.aload(0).aconst_null().putfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future); bcb.aload(0).aconst_null().putfield(smb.CD_this, AWAITING_FIELD_NAME, CD_Future);
@ -60,39 +69,52 @@ public class FutureSMBuilder extends StateMachineBuilder {
}, bcb -> { }, bcb -> {
bcb.swap().pop(); bcb.swap().pop();
}); });
// [... Polled]
} }
} }
static class YieldHandler extends SpecialMethodHandler { static class YieldHandler implements SpecialMethodHandler {
final int resume_state; final StateBuilder.State resume;
final Label resume_label; final Label save_ret;
final Label end;
public YieldHandler(StateMachineBuilder smb, CodeBuilder cob) { public YieldHandler(StateMachineBuilder smb, CodeBuilder cob, StateBuilder sb) {
super(smb, cob); resume = sb.create(cob);
resume_state = smb.add_state(resume_label = cob.newLabel()); save_ret = cob.newLabel();
end = cob.newLabel();
} }
public ReplacementKind replacementKind(){return ReplacementKind.Immediate;} public ReplacementKind replacementKind(){return ReplacementKind.Immediate;}
@Override @Override
public void buildHandler(StateMachineBuilder smb, CodeBuilder cob, Frame frame) { public void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
cob.labelBinding(save_ret);
var saved = frame.save(smb, cob, 2, 0); var saved = frame.save(smb, cob, 2, 0);
cob.aload(0).loadConstant(resume_state).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound())
.getstatic(CD_Pending, "INSTANCE", CD_Pending) resume.setState(smb, cob);
.areturn().labelBinding(resume_label); cob.getstatic(CD_Pending, "INSTANCE", CD_Pending).areturn();
resume.bind(cob);
saved.restore_all(smb, cob); saved.restore_all(smb, cob);
} cob.goto_(end);
}
static class WakerHandler extends SpecialMethodHandler{
protected WakerHandler(StateMachineBuilder smb, CodeBuilder cob) {
super(smb, cob);
} }
@Override @Override
public void buildHandler(StateMachineBuilder smb, CodeBuilder cob, Frame frame) { public void build_inline(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
cob.goto_(save_ret);
cob.labelBinding(end);
}
}
static class WakerHandler implements SpecialMethodHandler{
protected WakerHandler(StateMachineBuilder smb, CodeBuilder cob, StateBuilder sb) {}
@Override
public void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {}
@Override
public void build_inline(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
cob.aload(1); cob.aload(1);
} }
@ -102,21 +124,36 @@ public class FutureSMBuilder extends StateMachineBuilder {
} }
} }
static class RetHandler extends SpecialMethodHandler{ static class RetHandler implements SpecialMethodHandler{
protected RetHandler(StateMachineBuilder smb, CodeBuilder cob, StateBuilder sb) {}
protected RetHandler(StateMachineBuilder smb, CodeBuilder cob) {
super(smb, cob);
}
public ReplacementKind replacementKind(){return ReplacementKind.ReplacingNextReturn;} public ReplacementKind replacementKind(){return ReplacementKind.ReplacingNextReturn;}
@Override @Override
public void buildHandler(StateMachineBuilder smb, CodeBuilder cob, Frame frame) { public void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {}
@Override
public void build_inline(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
cob.aload(0).loadConstant(-1).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()).areturn(); cob.aload(0).loadConstant(-1).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()).areturn();
} }
} }
static class RetVoidHandler implements SpecialMethodHandler{
protected RetVoidHandler(StateMachineBuilder smb, CodeBuilder cob, StateBuilder sb) {}
public ReplacementKind replacementKind(){return ReplacementKind.ReplacingNextReturn;}
@Override
public void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
cob.aload(0).loadConstant(-1).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()).aconst_null().areturn();
}
@Override
public void build_inline(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
}
}
@Override @Override
protected String uniqueName() { protected String uniqueName() {
return "Fut"; return "Fut";
@ -143,6 +180,7 @@ public class FutureSMBuilder extends StateMachineBuilder {
super(src_clm, src_mem, src_com); super(src_clm, src_mem, src_com);
smmap.put(new SpecialMethod(CD_Future, "await", MTD_Obj), AwaitHandler::new); smmap.put(new SpecialMethod(CD_Future, "await", MTD_Obj), AwaitHandler::new);
smmap.put(new SpecialMethod(CD_Future, "ret", MTD_Future_Obj), RetHandler::new); smmap.put(new SpecialMethod(CD_Future, "ret", MTD_Future_Obj), RetHandler::new);
smmap.put(new SpecialMethod(CD_Future, "ret", MTD_Future), RetVoidHandler::new);
smmap.put(new SpecialMethod(CD_Future, "yield", ConstantDescs.MTD_void), YieldHandler::new); smmap.put(new SpecialMethod(CD_Future, "yield", ConstantDescs.MTD_void), YieldHandler::new);
smmap.put(new SpecialMethod(CD_Waker, "waker", MethodTypeDesc.of(CD_Waker)), WakerHandler::new); smmap.put(new SpecialMethod(CD_Waker, "waker", MethodTypeDesc.of(CD_Waker)), WakerHandler::new);
} }

View file

@ -20,64 +20,64 @@ public class GenSMBuilder extends StateMachineBuilder {
public final static MethodTypeDesc MTD_Gen = MethodTypeDesc.of(CD_Gen); public final static MethodTypeDesc MTD_Gen = MethodTypeDesc.of(CD_Gen);
public final static MethodTypeDesc MTD_Obj = MethodTypeDesc.of(ConstantDescs.CD_Object); public final static MethodTypeDesc MTD_Obj = MethodTypeDesc.of(ConstantDescs.CD_Object);
static class YieldHandler extends SpecialMethodHandler { // static class YieldHandler extends SpecialMethodHandler {
final int resume_state; // final int resume_state;
final Label resume_label; // final Label resume_label;
final boolean is_void; // final boolean is_void;
//
public YieldHandler(StateMachineBuilder smb, CodeBuilder cob, boolean is_void) { // public YieldHandler(StateMachineBuilder smb, CodeBuilder cob, boolean is_void) {
super(smb, cob); // super(smb, cob);
resume_state = smb.add_state(resume_label = cob.newLabel()); // resume_state = smb.add_state(resume_label = cob.newLabel());
this.is_void = is_void; // this.is_void = is_void;
} // }
//
public ReplacementKind replacementKind(){return ReplacementKind.ImmediateReplacingPop;} // public ReplacementKind replacementKind(){return ReplacementKind.ImmediateReplacingPop;}
//
@Override // @Override
public void buildHandler(StateMachineBuilder smb, CodeBuilder cob, Frame frame) { // public void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
if(is_void)cob.aconst_null(); // if(is_void)cob.aconst_null();
//
// smb.lt.savingLocals(smb.CD_this, cob, () -> { //// smb.lt.savingLocals(smb.CD_this, cob, () -> {
// cob.aload(0).loadConstant(resume_state).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound()) //// cob.aload(0).loadConstant(resume_state).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound())
// .new_(CD_Yield) //// .new_(CD_Yield)
//// .dup_x1()
//// .swap()
//// .invokespecial(CD_Yield, ConstantDescs.INIT_NAME, MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_Object))
//// .areturn();
//// cob.labelBinding(resume_label);
//// });
// }
// }
//
// static class RetHandler extends SpecialMethodHandler {
// final boolean is_void;
//
// public RetHandler(StateMachineBuilder smb, CodeBuilder cob, boolean is_void) {
// super(smb, cob);
// this.is_void = is_void;
// }
//
// public ReplacementKind replacementKind(){return ReplacementKind.ReplacingNextReturn;}
//
// @Override
// public void build_prelude(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
// if(is_void)cob.aconst_null();
//
// cob.aload(0).loadConstant(-1).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound())
// .new_(CD_Ret)
// .dup_x1() // .dup_x1()
// .swap() // .swap()
// .invokespecial(CD_Yield, ConstantDescs.INIT_NAME, MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_Object)) // .invokespecial(CD_Ret, ConstantDescs.INIT_NAME, MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_Object))
// .areturn(); // .areturn();
// cob.labelBinding(resume_label); // }
// }); // }
}
}
static class RetHandler extends SpecialMethodHandler {
final boolean is_void;
public RetHandler(StateMachineBuilder smb, CodeBuilder cob, boolean is_void) {
super(smb, cob);
this.is_void = is_void;
}
public ReplacementKind replacementKind(){return ReplacementKind.ReplacingNextReturn;}
@Override
public void buildHandler(StateMachineBuilder smb, CodeBuilder cob, Frame frame) {
if(is_void)cob.aconst_null();
cob.aload(0).loadConstant(-1).putfield(smb.CD_this, STATE_NAME, TypeKind.INT.upperBound())
.new_(CD_Ret)
.dup_x1()
.swap()
.invokespecial(CD_Ret, ConstantDescs.INIT_NAME, MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_Object))
.areturn();
}
}
public GenSMBuilder(ClassModel src_clm, MethodModel src_mem, CodeModel src_com) { public GenSMBuilder(ClassModel src_clm, MethodModel src_mem, CodeModel src_com) {
super(src_clm, src_mem, src_com); super(src_clm, src_mem, src_com);
smmap.put(new SpecialMethod(CD_Gen, "yield", MTD_Gen_Obj),(smb, cob) -> new YieldHandler(smb, cob, false)); // smmap.put(new SpecialMethod(CD_Gen, "yield", MTD_Gen_Obj),(smb, cob) -> new YieldHandler(smb, cob, false));
smmap.put(new SpecialMethod(CD_Gen, "yield", MTD_Gen),(smb, cob) -> new YieldHandler(smb, cob, true)); // smmap.put(new SpecialMethod(CD_Gen, "yield", MTD_Gen),(smb, cob) -> new YieldHandler(smb, cob, true));
smmap.put(new SpecialMethod(CD_Gen, "ret", MTD_Gen_Obj),(smb, cob) -> new RetHandler(smb, cob, false)); // smmap.put(new SpecialMethod(CD_Gen, "ret", MTD_Gen_Obj),(smb, cob) -> new RetHandler(smb, cob, false));
smmap.put(new SpecialMethod(CD_Gen, "ret", MTD_Gen),(smb, cob) -> new RetHandler(smb, cob, true)); // smmap.put(new SpecialMethod(CD_Gen, "ret", MTD_Gen),(smb, cob) -> new RetHandler(smb, cob, true));
} }
@Override @Override