package org.dynjs.compiler.bytecode.partial; import static me.qmx.jitescript.util.CodegenUtils.*; import me.qmx.jitescript.CodeBlock; import org.dynjs.codegen.CodeGeneratingVisitor.Arities; import org.dynjs.runtime.Completion; import org.dynjs.runtime.Completion.Type; import org.dynjs.runtime.ExecutionContext; import me.qmx.jitescript.internal.org.objectweb.asm.tree.LabelNode; public class SingleClassCaller extends CodeBlock { public SingleClassCaller(final String className, final int numBodies) { LabelNode abrupt = new LabelNode(); LabelNode end = new LabelNode(); invokestatic(p(Completion.class), "createNormal", sig(Completion.class)); // completion astore(Arities.COMPLETION); // <empty> for (int i = 0; i < numBodies; ++i) { LabelNode nonAbrupt = new LabelNode(); LabelNode bringForwardValue = new LabelNode(); LabelNode nextStatement = new LabelNode(); // <empty> aload( Arities.THIS ); // this aload( Arities.EXECUTION_CONTEXT ); // this context invokevirtual(className.replace(".", "/"), "callChunk" + i, sig(Completion.class, ExecutionContext.class)); // completion dup(); // completion completion getfield(p(Completion.class), "type", ci(Completion.Type.class)); // completion type invokevirtual(p(Completion.Type.class), "ordinal", sig(int.class)); // completion type-num lookupswitch(nonAbrupt, new int[] { Type.NORMAL.ordinal(), Type.BREAK.ordinal(), Type.CONTINUE.ordinal(), Type.RETURN.ordinal() }, new LabelNode[] { nonAbrupt, abrupt, abrupt, abrupt }); // ---------------------------------------- // Non-abrupt label(nonAbrupt); // completion(cur); dup(); // completion(cur) completion(cur) getfield(p(Completion.class), "value", ci(Object.class)); // completion(cur) value ifnull(bringForwardValue); // completion(cur) astore(Arities.COMPLETION); // <empty> go_to(nextStatement); // ---------------------------------------- label(bringForwardValue); // completion(cur) dup(); // completion(cur) completion(cur) aload(Arities.COMPLETION); // completion(cur) completion(cur) completion(prev) getfield(p(Completion.class), "value", ci(Object.class)); // completion(cur) completion(cur) val(prev) putfield(p(Completion.class), "value", ci(Object.class)); // completion(cur) astore(Arities.COMPLETION); // <empty> label(nextStatement); } go_to(end); // ---------------------------------------- // ABRUPT label(abrupt); // completion(cur) astore(Arities.COMPLETION); // <empty> // ---------------------------------------- // END label(end); // <empty> aload(Arities.COMPLETION); // completion areturn(); } }