From 21412f4670e842ec744de24eeef83901a03fd494 Mon Sep 17 00:00:00 2001 From: Parker TenBroeck <51721964+ParkerTenBroeck@users.noreply.github.com> Date: Mon, 28 Apr 2025 14:58:59 -0400 Subject: [PATCH] added stack tracking --- src/Examples.java | 50 +- src/generator/future/Future.java | 2 + .../runtime/GeneratorClassLoader.java | 4 +- src/generator/runtime/LocalTracker.java | 484 +++++++++++++++--- .../runtime/StateMachineBuilder.java | 19 +- 5 files changed, 473 insertions(+), 86 deletions(-) diff --git a/src/Examples.java b/src/Examples.java index ce3daa2..1e17944 100644 --- a/src/Examples.java +++ b/src/Examples.java @@ -70,21 +70,34 @@ public class Examples { // } public static class Delay implements Future{ - - private final int delay; + private final static Timer timer; + static{ + timer = new Timer(true); + } + private int delay; private boolean ready; public Delay(int ms){ + if(ms<0)throw new IllegalArgumentException("Delay cannot be negative"); delay = ms; } @Override - public Object poll(Waker waker) { - new Timer().schedule(new TimerTask() { - @Override - public void run() { - ready = true; - waker.wake(); - } - }, delay); + public synchronized Object poll(Waker waker) { + if(delay==0){ + ready=true; + delay=-1; + return null; + } + if(delay != -1){ + timer.schedule(new TimerTask() { + @Override + public void run() { + ready = true; + waker.wake(); + } + }, delay); + delay = -1; + } + if(ready)return null; return Pending.INSTANCE; } @@ -96,8 +109,21 @@ public class Examples { } public Future awaitTest(int number){ - var result = awaitTest2(number).await(); - return Future.ret("Result: " + result); + try(var m = new Meow()){ + var result = awaitTest2(number).await(); + return Future.ret("Result: " + result); + } + } + + public static class Meow implements AutoCloseable{ + { + System.out.println("OPen"); + } + + @Override + public void close() { + System.out.println("Close"); + } } // public static Gen test(double[] nyas){ diff --git a/src/generator/future/Future.java b/src/generator/future/Future.java index ac322e2..030f13b 100644 --- a/src/generator/future/Future.java +++ b/src/generator/future/Future.java @@ -10,6 +10,8 @@ public interface Future { throw new RuntimeException("NO!"); } + default void cancel(){} + static Future ret(R r){ throw new RuntimeException("NO!"); } diff --git a/src/generator/runtime/GeneratorClassLoader.java b/src/generator/runtime/GeneratorClassLoader.java index 3c20613..d8e288c 100644 --- a/src/generator/runtime/GeneratorClassLoader.java +++ b/src/generator/runtime/GeneratorClassLoader.java @@ -104,10 +104,12 @@ public class GeneratorClassLoader extends ClassLoader { var smb = new FutureSMBuilder(src_clm, src_mem, com); try{ add(smb.CD_this.displayName(), smb.buildStateMachine()); - }catch (Exception ignore){ + }catch (Exception e){ + e.printStackTrace(); cb.withMethod(src_mem.methodName(), src_mem.methodType(), src_mem.flags().flagsMask(), mb -> { mb.with(com); }); + return smb; } cb.withMethod(src_mem.methodName(), src_mem.methodType(), src_mem.flags().flagsMask(), mb -> { mb.withCode(smb::buildSourceMethodShim); diff --git a/src/generator/runtime/LocalTracker.java b/src/generator/runtime/LocalTracker.java index 843d48a..cc1ec0f 100644 --- a/src/generator/runtime/LocalTracker.java +++ b/src/generator/runtime/LocalTracker.java @@ -1,33 +1,235 @@ package generator.runtime; import java.lang.classfile.*; +import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute; +import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute; import java.lang.classfile.attribute.StackMapFrameInfo; +import java.lang.classfile.attribute.StackMapTableAttribute; +import java.lang.classfile.instruction.*; import java.lang.constant.ClassDesc; import java.util.ArrayList; import java.util.HashMap; +import java.util.Objects; -import static java.lang.classfile.attribute.StackMapFrameInfo.SimpleVerificationTypeInfo.TOP; +import static generator.runtime.StateMachineBuilder.LOCAL_PREFIX; +import static java.lang.constant.ConstantDescs.*; public class LocalTracker { record LocalStore(String name, ClassDesc cd) { } - HashMap parameter_map = new HashMap<>(); + private static final int ITEM_TOP = 0, + ITEM_INTEGER = 1, + ITEM_FLOAT = 2, + ITEM_DOUBLE = 3, + ITEM_LONG = 4, + ITEM_NULL = 5, + ITEM_UNINITIALIZED_THIS = 6, + ITEM_OBJECT = 7, + ITEM_UNINITIALIZED = 8, + ITEM_BOOLEAN = 9, + ITEM_BYTE = 10, + ITEM_SHORT = 11, + ITEM_CHAR = 12, + ITEM_LONG_2ND = 13, + ITEM_DOUBLE_2ND = 14; - HashMap localVarTypes = new HashMap<>(); + private static record Type(int tag, ClassDesc sym, int bci) { + + //singleton types + static final Type TOP_TYPE = simpleType(ITEM_TOP), + NULL_TYPE = simpleType(ITEM_NULL), + INTEGER_TYPE = simpleType(ITEM_INTEGER), + FLOAT_TYPE = simpleType(ITEM_FLOAT), + LONG_TYPE = simpleType(ITEM_LONG), + LONG2_TYPE = simpleType(ITEM_LONG_2ND), + DOUBLE_TYPE = simpleType(ITEM_DOUBLE), + BOOLEAN_TYPE = simpleType(ITEM_BOOLEAN), + BYTE_TYPE = simpleType(ITEM_BYTE), + CHAR_TYPE = simpleType(ITEM_CHAR), + SHORT_TYPE = simpleType(ITEM_SHORT), + DOUBLE2_TYPE = simpleType(ITEM_DOUBLE_2ND), + UNITIALIZED_THIS_TYPE = simpleType(ITEM_UNINITIALIZED_THIS); + + //frequently used types to reduce footprint + static final Type OBJECT_TYPE = referenceType(CD_Object), + THROWABLE_TYPE = referenceType(CD_Throwable), + INT_ARRAY_TYPE = referenceType(CD_int.arrayType()), + BOOLEAN_ARRAY_TYPE = referenceType(CD_boolean.arrayType()), + BYTE_ARRAY_TYPE = referenceType(CD_byte.arrayType()), + CHAR_ARRAY_TYPE = referenceType(CD_char.arrayType()), + SHORT_ARRAY_TYPE = referenceType(CD_short.arrayType()), + LONG_ARRAY_TYPE = referenceType(CD_long.arrayType()), + DOUBLE_ARRAY_TYPE = referenceType(CD_double.arrayType()), + FLOAT_ARRAY_TYPE = referenceType(CD_float.arrayType()), + STRING_TYPE = referenceType(CD_String), + CLASS_TYPE = referenceType(CD_Class), + METHOD_HANDLE_TYPE = referenceType(CD_MethodHandle), + METHOD_TYPE = referenceType(CD_MethodType); + + @Override + public String toString(){ + return switch(tag){ + case ITEM_TOP -> "TOP"; + case ITEM_INTEGER -> "int"; + case ITEM_FLOAT -> "float"; + case ITEM_DOUBLE -> "double"; + case ITEM_LONG -> "long"; + case ITEM_NULL -> sym==null?"null":"null("+sym.displayName()+")"; + case ITEM_UNINITIALIZED_THIS -> sym==null?"uninitialized(this)":"uninitialized(this "+sym.displayName()+")"; + case ITEM_OBJECT -> "Object("+sym.displayName()+")"; + case ITEM_UNINITIALIZED -> sym==null?"uninitialized()":"uninitialized("+sym.displayName()+")"; + case ITEM_BOOLEAN -> "boolean"; + case ITEM_BYTE -> "byte"; + case ITEM_SHORT -> "short"; + case ITEM_CHAR -> "char"; + case ITEM_LONG_2ND -> "float2"; + case ITEM_DOUBLE_2ND -> "double2"; + default -> throw new IllegalStateException("Unexpected value: " + tag); + }; + } + + private static Type simpleType(int tag) { + return new Type(tag, null, 0); + } + + static Type referenceType(ClassDesc desc) { + return new Type(ITEM_OBJECT, desc, 0); + } + + static Type uninitializedType(ClassDesc sym) { + return new Type(ITEM_UNINITIALIZED, sym, 0); + } + + @Override //mandatory override to avoid use of method reference during JDK bootstrap + public boolean equals(Object o) { + return (o instanceof Type t) && t.tag == tag && t.bci == bci && Objects.equals(sym, t.sym); + } + + boolean isCategory2_2nd() { + return this == DOUBLE2_TYPE || this == LONG2_TYPE; + } + + boolean isReference() { + return tag == ITEM_OBJECT || this == NULL_TYPE; + } + + boolean isObject() { + return tag == ITEM_OBJECT && sym.isClassOrInterface(); + } + + boolean isArray() { + return tag == ITEM_OBJECT && sym.isArray(); + } + + + static Type verificationType(StackMapFrameInfo.VerificationTypeInfo v){ + return switch (v){ + case StackMapFrameInfo.ObjectVerificationTypeInfo o -> Type.referenceType(o.classSymbol()); + case StackMapFrameInfo.SimpleVerificationTypeInfo s -> Type.simpleType(s.tag()); + case StackMapFrameInfo.UninitializedVerificationTypeInfo u -> { + //Type.simpleType(u.tag()); + throw new RuntimeException(); + } + }; + } + + ClassDesc toCD(){ + return switch (tag) { + case ITEM_BOOLEAN -> CD_boolean; + case ITEM_BYTE -> CD_byte; + case ITEM_CHAR -> CD_char; + case ITEM_SHORT -> CD_short; + case ITEM_INTEGER -> CD_int; + case ITEM_LONG -> CD_long; + case ITEM_FLOAT -> CD_float; + case ITEM_DOUBLE -> CD_double; + case ITEM_OBJECT -> sym; + default -> throw new RuntimeException(); + }; + } + + Type toArray() { + return switch (tag) { + case ITEM_BOOLEAN -> BOOLEAN_ARRAY_TYPE; + case ITEM_BYTE -> BYTE_ARRAY_TYPE; + case ITEM_CHAR -> CHAR_ARRAY_TYPE; + case ITEM_SHORT -> SHORT_ARRAY_TYPE; + case ITEM_INTEGER -> INT_ARRAY_TYPE; + case ITEM_LONG -> LONG_ARRAY_TYPE; + case ITEM_FLOAT -> FLOAT_ARRAY_TYPE; + case ITEM_DOUBLE -> DOUBLE_ARRAY_TYPE; + case ITEM_OBJECT -> Type.referenceType(sym.arrayType()); + default -> OBJECT_TYPE; + }; + } + + Type getComponent() { + if (isArray()) { + var comp = sym.componentType(); + if (comp.isPrimitive()) { + return switch (comp.descriptorString().charAt(0)) { + case 'Z' -> Type.BOOLEAN_TYPE; + case 'B' -> Type.BYTE_TYPE; + case 'C' -> Type.CHAR_TYPE; + case 'S' -> Type.SHORT_TYPE; + case 'I' -> Type.INTEGER_TYPE; + case 'J' -> Type.LONG_TYPE; + case 'F' -> Type.FLOAT_TYPE; + case 'D' -> Type.DOUBLE_TYPE; + default -> Type.TOP_TYPE; + }; + } + return Type.referenceType(comp); + } + return Type.TOP_TYPE; + } + } + + + final ArrayList stack = new ArrayList<>(); + final ArrayList locals = new ArrayList<>(); +// HashMap localVarTypes = new HashMap<>(); +// StackMapFrameInfo currentFrame; + + HashMap parameter_map = new HashMap<>(); HashMap stackMapFrames = new HashMap<>(); - StackMapFrameInfo currentFrame; ArrayList localStore = new ArrayList<>(); + final int local_param_off; + final StateMachineBuilder smb; LocalTracker(StateMachineBuilder smb, CodeModel com, int local_param_off) { this.local_param_off = local_param_off; + this.smb = smb; int offset = 0; + + for (var param : smb.params) { parameter_map.put(offset, param); + + if(param == CD_long){ + setLocal2(offset, Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE); + }else if(param == CD_double){ + setLocal2(offset, Type.LONG_TYPE, Type.LONG2_TYPE); + }else if(!param.isPrimitive()){ + setLocal(offset, Type.referenceType(param)); + }else if(param == CD_float){ + setLocal(offset, Type.FLOAT_TYPE); + }else if(param == CD_char){ + setLocal(offset, Type.CHAR_TYPE); + }else if(param == CD_boolean){ + setLocal(offset, Type.BOOLEAN_TYPE); + }else if(param == CD_byte){ + setLocal(offset, Type.BYTE_TYPE); + }else if(param == CD_short){ + setLocal(offset, Type.SHORT_TYPE); + }else{ + setLocal(offset, Type.INTEGER_TYPE); + } offset += TypeKind.from(param).slotSize(); } @@ -37,13 +239,215 @@ public class LocalTracker { var locals = new ArrayList<>(smfi.locals()); for (int i = 0; i < smb.params.length; i++) locals.removeFirst(); -// locals.addFirst(StackMapFrameInfo.ObjectVerificationTypeInfo.of(smb.CD_this)); entries.add(StackMapFrameInfo.of(smfi.target(), locals, smfi.stack())); stackMapFrames.put(smfi.target(), entries.getLast()); } } } + LocalTracker pushStack(ClassDesc desc) { + if (desc == CD_long) return pushStack(Type.LONG_TYPE, Type.LONG2_TYPE); + if (desc == CD_double) return pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE); + return desc == CD_void ? this + : pushStack( + desc.isPrimitive() + ? (desc == CD_float ? Type.FLOAT_TYPE : Type.INTEGER_TYPE) + : Type.referenceType(desc)); + } + + LocalTracker pushStack(Type type) { + stack.add(type); + return this; + } + + LocalTracker pushStack(Type type1, Type type2) { + stack.add(type1); + stack.add(type2); + return this; + } + + Type popStack() { + return stack.removeLast(); + } + + LocalTracker decStack(int size) { + for(int i = 0; i < size; i ++)stack.removeLast(); + return this; + } + + void setLocal(int slot, Type type){ + while(locals.size()<=slot)locals.add(null); + + var old = locals.get(slot); + if(old == Type.DOUBLE_TYPE || old == Type.LONG_TYPE) + locals.set(slot+1, Type.TOP_TYPE); + if(old == Type.DOUBLE2_TYPE || old == Type.LONG2_TYPE) + locals.set(slot-1, Type.TOP_TYPE); + locals.set(slot, type); + } + + void setLocal2(int slot, Type type1, Type type2){ + while(locals.size()<=slot+1)locals.add(null); + + var old = locals.get(slot+1); + if(old == Type.DOUBLE_TYPE || old == Type.LONG_TYPE) + locals.set(slot+2, Type.TOP_TYPE); + old = locals.get(slot); + if(old == Type.DOUBLE2_TYPE || old == Type.LONG2_TYPE) + locals.set(slot-1, Type.TOP_TYPE); + + locals.set(slot, type1); + locals.set(slot+1, type2); + } + + public void encounter(CodeElement ce){ + switch(ce){ + case Label l -> encounterLabel(l); + case Instruction ins -> { + switch (ins) { + case ArrayLoadInstruction al -> { + popStack(); + var arr = popStack(); + pushStack(arr.toCD().componentType()); + } + case ArrayStoreInstruction as -> decStack(1 + as.typeKind().slotSize()); + case BranchInstruction b when b.opcode() == Opcode.GOTO || b.opcode() == Opcode.GOTO_W -> {} + case BranchInstruction b -> popStack(); + case ConstantInstruction c when ins.opcode() == Opcode.ACONST_NULL -> pushStack(Type.NULL_TYPE); + case ConstantInstruction c -> pushStack(c.typeKind().upperBound()); + case ConvertInstruction c -> decStack(c.fromType().slotSize()).pushStack(c.toType().upperBound()); + case FieldInstruction f -> { + + } + case IncrementInstruction i -> {} + case InvokeDynamicInstruction i -> { + for(var param : i.typeSymbol().parameterArray()) + decStack(TypeKind.from(param).slotSize()); + pushStack(i.typeSymbol().returnType()); + } + case InvokeInstruction i when i.opcode() == Opcode.INVOKESTATIC -> { + for(var param : i.typeSymbol().parameterArray()) + decStack(TypeKind.from(param).slotSize()); + pushStack(i.typeSymbol().returnType()); + } + case InvokeInstruction i when i.opcode() == Opcode.INVOKESPECIAL && i.name().equalsString(INIT_NAME) -> { + for(var param : i.typeSymbol().parameterArray()) + decStack(TypeKind.from(param).slotSize()); + var ty = popStack(); + } + case InvokeInstruction i -> { + for(var param : i.typeSymbol().parameterArray()) + decStack(TypeKind.from(param).slotSize()); + popStack(); + pushStack(i.typeSymbol().returnType()); + } + case LoadInstruction l when locals.size()<=l.slot()||locals.get(l.slot())==null -> + pushStack(l.typeKind().upperBound()); + case LoadInstruction l -> + pushStack(locals.get(l.slot()).toCD()); + case LookupSwitchInstruction ls -> popStack(); + case MonitorInstruction m -> popStack(); + case NewMultiArrayInstruction nma -> decStack(nma.dimensions()).pushStack(nma.arrayType().asSymbol()); + case NewObjectInstruction no -> pushStack(no.className().asSymbol()); + case NewPrimitiveArrayInstruction npa -> decStack(1).pushStack(npa.typeKind().upperBound().arrayType()); + case NewReferenceArrayInstruction nra -> decStack(1).pushStack(nra.componentType().asSymbol()); + case NopInstruction n -> {} + + case OperatorInstruction o -> { + switch(o.opcode()){ + case IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IOR, IXOR, IAND -> + decStack(2).pushStack(Type.INTEGER_TYPE); + case INEG, ARRAYLENGTH, INSTANCEOF -> + decStack(1).pushStack(Type.INTEGER_TYPE); + case LADD, LSUB, LMUL, LDIV, LREM, LAND, LOR, LXOR -> + decStack(4).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE); + case LNEG -> + decStack(2).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE); + case LSHL, LSHR, LUSHR -> + decStack(3).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE); + case FADD, FSUB, FMUL, FDIV, FREM -> + decStack(2).pushStack(Type.FLOAT_TYPE); + case FNEG -> + decStack(1).pushStack(Type.FLOAT_TYPE); + case DADD, DSUB, DMUL, DDIV, DREM -> + decStack(4).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE); + case DNEG -> + decStack(2).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE); + default -> throw new RuntimeException(); + } + } + case StackInstruction s -> { + Type type1, type2, type3, type4; + switch(s.opcode()){ + case POP -> + decStack(1); + case POP2 -> + decStack(2); + case DUP -> + pushStack(type1 = popStack()).pushStack(type1); + case DUP_X1 -> { + type1 = popStack(); + type2 = popStack(); + pushStack(type1).pushStack(type2).pushStack(type1); + } + case DUP_X2 -> { + type1 = popStack(); + type2 = popStack(); + type3 = popStack(); + pushStack(type1).pushStack(type3).pushStack(type2).pushStack(type1); + } + case DUP2 -> { + type1 = popStack(); + type2 = popStack(); + pushStack(type2).pushStack(type1).pushStack(type2).pushStack(type1); + } + case DUP2_X1 -> { + type1 = popStack(); + type2 = popStack(); + type3 = popStack(); + pushStack(type2).pushStack(type1).pushStack(type3).pushStack(type2).pushStack(type1); + } + case DUP2_X2 -> { + type1 = popStack(); + type2 = popStack(); + type3 = popStack(); + type4 = popStack(); + pushStack(type2).pushStack(type1).pushStack(type4).pushStack(type3).pushStack(type2).pushStack(type1); + } + case SWAP -> { + type1 = popStack(); + type2 = popStack(); + pushStack(type1); + pushStack(type2); + } + default -> throw new RuntimeException(); + } + } + + case ReturnInstruction r when r.typeKind()==TypeKind.VOID -> {} + case ReturnInstruction r -> decStack(r.typeKind().slotSize()); + + case StoreInstruction s when s.typeKind() == TypeKind.DOUBLE -> decStack(2).setLocal2(s.slot(), Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE); + case StoreInstruction s when s.typeKind() == TypeKind.LONG -> decStack(2).setLocal2(s.slot(), Type.LONG_TYPE, Type.LONG2_TYPE); + case StoreInstruction s -> setLocal(s.slot(), popStack()); + + case TableSwitchInstruction ts -> popStack(); + case ThrowInstruction t -> popStack(); + case TypeCheckInstruction tc -> {} + case DiscontinuedInstruction d -> throw new IllegalStateException(d.toString()); + default -> throw new IllegalStateException(); + } + } + case PseudoInstruction _ -> {} + case RuntimeInvisibleTypeAnnotationsAttribute _ -> {} + case RuntimeVisibleTypeAnnotationsAttribute _ -> {} + case CustomAttribute _ -> {} + case StackMapTableAttribute _ -> {} + } + if(ce instanceof Instruction) + System.out.println("loc: " + locals + " stack: " + stack); + } + //Tries its best to reuse old saved locals field slots, only reuses if types exactly match public void savingLocals(ClassDesc cd, CodeBuilder cob, Runnable run) { @@ -51,19 +455,9 @@ public class LocalTracker { } var saved = new ArrayList(); - var lls = new ArrayList<>(localStore); currentLocals((slot, tk, desc) -> { - String name = null; - for (int i = 0; i < lls.size(); i++) - if (lls.get(i).cd.equals(desc)) { - name = lls.get(i).name; - lls.remove(i); - break; - } - if (name == null) { - name = StateMachineBuilder.LOCAL_PREFIX + localStore.size(); - localStore.add(new LocalStore(name, desc)); - } + String name = LOCAL_PREFIX + localStore.size(); + localStore.add(new LocalStore(name, desc)); saved.add(new Saved(slot, name, desc)); cob.aload(0).loadLocal(tk, slot).putfield(cd, name, desc); }); @@ -83,8 +477,12 @@ public class LocalTracker { public void encounterLabel(Label l) { var tmp = stackMapFrames.get(l); if (tmp != null) { - localVarTypes.clear(); - currentFrame = tmp; + stack.clear(); + locals.clear(); + for( var sl : tmp.stack()) + pushStack(Type.verificationType(sl)); + for( var local : tmp.locals()) + locals.add(Type.verificationType(local)); } } @@ -92,53 +490,17 @@ public class LocalTracker { return parameter_map.get(slot); } - public void trackLocal(int slot, TypeKind typeKind) { - localVarTypes.put(slot, typeKind); - } - public interface LocalConsumer { void consume(int slot, TypeKind tk, ClassDesc desc); } public void currentLocals(LocalConsumer consumer) { - var slot = local_param_off; - if (currentFrame != null) { - for (var kind : currentFrame.locals()) { - switch (kind) { - case StackMapFrameInfo.ObjectVerificationTypeInfo o -> { - if (slot != 0) - consumer.consume(slot, o.className().typeKind(), o.classSymbol()); - slot += 1; - } - case StackMapFrameInfo.SimpleVerificationTypeInfo ti -> { - if (kind == TOP) { - slot += 1; - if (localVarTypes.get(slot - 1) instanceof TypeKind tk) { - ClassDesc cd = tk.upperBound(); - consumer.consume(slot - 1, tk, cd); - } - continue; - } - var type = switch (ti) { - case INTEGER -> TypeKind.INT; - case FLOAT -> TypeKind.FLOAT; - case DOUBLE -> TypeKind.DOUBLE; - case LONG -> TypeKind.LONG; - case NULL -> TypeKind.REFERENCE; - default -> throw new IllegalStateException(); - }; - consumer.consume(slot, type, type.upperBound()); - slot += 1; - } - case StackMapFrameInfo.UninitializedVerificationTypeInfo _ -> throw new IllegalStateException(); - } - } - }else{ - for (var entry : localVarTypes.entrySet()) { - if (entry.getKey() < slot) continue; - ClassDesc cd = entry.getValue().upperBound(); - consumer.consume(entry.getKey(), TypeKind.from(cd), cd); - } + int slot = 0; + for (var entry : locals) { + slot++; + if (slot <= local_param_off) continue; + if(entry.isCategory2_2nd())continue; + consumer.consume(slot - smb.paramSlotOff + local_param_off - 1, TypeKind.from(entry.toCD()), entry.toCD()); } } diff --git a/src/generator/runtime/StateMachineBuilder.java b/src/generator/runtime/StateMachineBuilder.java index e951173..2f05fa7 100644 --- a/src/generator/runtime/StateMachineBuilder.java +++ b/src/generator/runtime/StateMachineBuilder.java @@ -121,10 +121,6 @@ public abstract class StateMachineBuilder { ctb -> ctb.catchingAll( blc -> blc.aload(0).loadConstant(-1).putfield(CD_this, STATE_NAME, ConstantDescs.CD_int) - .new_(ClassDesc.ofDescriptor(RuntimeException.class.descriptorString())) - .dup_x1() - .swap() - .invokespecial(ClassDesc.ofDescriptor(RuntimeException.class.descriptorString()), ConstantDescs.INIT_NAME, MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_Throwable)) .athrow() ) ).aconst_null().areturn(); @@ -133,6 +129,8 @@ public abstract class StateMachineBuilder { public void buildStateMachineCode(ClassBuilder clb, CodeBuilder cob, int loc_param_off) { boolean ignore_next_pop = false; + System.out.println(); + System.out.println("Begin"); this.lt = new LocalTracker(this, src_com, loc_param_off); var invalidState = cob.newLabel(); @@ -172,9 +170,6 @@ public abstract class StateMachineBuilder { } } } - if (coe instanceof Label l) { - lt.encounterLabel(l); - } if (coe instanceof InvokeInstruction is){ if(smmap.get(new SpecialMethod(is.owner().asSymbol(), is.name().stringValue(), is.typeSymbol())) != null){ if(currentHandler!=null)throw new RuntimeException("Multiple method handlers at once not supported"); @@ -189,7 +184,9 @@ public abstract class StateMachineBuilder { continue; } } - if(coe instanceof LocalVariable lv) System.out.println(lv); + + lt.encounter(coe); + switch (coe) { // locals which were once function parameters can be ignored @@ -216,10 +213,8 @@ public abstract class StateMachineBuilder { cob.aload(0).dup_x2().pop().putfield(CD_this, PARAM_PREFIX + ls.slot(), lt.paramType(ls.slot())); case StoreInstruction ls when ls.slot() < paramSlotOff -> cob.aload(0).swap().putfield(CD_this, PARAM_PREFIX + ls.slot(), lt.paramType(ls.slot())); - case StoreInstruction ls -> { - lt.trackLocal(ls.slot() - paramSlotOff + loc_param_off, ls.typeKind()); - cob.storeLocal(ls.typeKind(), ls.slot() - paramSlotOff + loc_param_off); - } + case StoreInstruction ls -> + cob.storeLocal(ls.typeKind(), ls.slot() - paramSlotOff + loc_param_off); default -> cob.with(coe); }