feat: reflect scope optimizations in runtime
This commit is contained in:
parent
7c74df4d36
commit
6f548ce5ff
@ -3,12 +3,13 @@ package me.topchetoeu.jscript.common;
|
|||||||
public class FunctionBody {
|
public class FunctionBody {
|
||||||
public final FunctionBody[] children;
|
public final FunctionBody[] children;
|
||||||
public final Instruction[] instructions;
|
public final Instruction[] instructions;
|
||||||
public final int localsN, capturesN, length;
|
public final int localsN, capturablesN, capturesN, length;
|
||||||
|
|
||||||
public FunctionBody(int localsN, int capturesN, int length, Instruction[] instructions, FunctionBody[] children) {
|
public FunctionBody(int localsN, int capturablesN, int capturesN, int length, Instruction[] instructions, FunctionBody[] children) {
|
||||||
this.children = children;
|
this.children = children;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.localsN = localsN;
|
this.localsN = localsN;
|
||||||
|
this.capturablesN = capturablesN;
|
||||||
this.capturesN = capturesN;
|
this.capturesN = capturesN;
|
||||||
this.instructions = instructions;
|
this.instructions = instructions;
|
||||||
}
|
}
|
||||||
|
@ -35,20 +35,21 @@ public class Instruction {
|
|||||||
LOAD_FUNC(0x30),
|
LOAD_FUNC(0x30),
|
||||||
LOAD_ARR(0x31),
|
LOAD_ARR(0x31),
|
||||||
LOAD_OBJ(0x32),
|
LOAD_OBJ(0x32),
|
||||||
LOAD_GLOB(0x33),
|
LOAD_REGEX(0x33),
|
||||||
LOAD_INTRINSICS(0x34),
|
|
||||||
LOAD_REGEX(0x35),
|
LOAD_GLOB(0x38),
|
||||||
|
LOAD_INTRINSICS(0x39),
|
||||||
|
LOAD_ARGS(0x3A),
|
||||||
|
LOAD_REST_ARGS(0x3B),
|
||||||
|
LOAD_CALLEE(0x3C),
|
||||||
|
LOAD_THIS(0x3D),
|
||||||
|
LOAD_ERROR(0x3E),
|
||||||
|
|
||||||
LOAD_VAR(0x40),
|
LOAD_VAR(0x40),
|
||||||
LOAD_MEMBER(0x41),
|
LOAD_MEMBER(0x41),
|
||||||
LOAD_MEMBER_INT(0x42),
|
LOAD_MEMBER_INT(0x42),
|
||||||
LOAD_MEMBER_STR(0x43),
|
LOAD_MEMBER_STR(0x43),
|
||||||
|
|
||||||
LOAD_ARGS(0x44),
|
|
||||||
LOAD_REST_ARGS(0x45),
|
|
||||||
LOAD_CALLEE(0x46),
|
|
||||||
LOAD_THIS(0x47),
|
|
||||||
|
|
||||||
STORE_VAR(0x48),
|
STORE_VAR(0x48),
|
||||||
STORE_MEMBER(0x49),
|
STORE_MEMBER(0x49),
|
||||||
STORE_MEMBER_INT(0x4A),
|
STORE_MEMBER_INT(0x4A),
|
||||||
@ -368,6 +369,9 @@ public class Instruction {
|
|||||||
public static Instruction loadIntrinsics(String key) {
|
public static Instruction loadIntrinsics(String key) {
|
||||||
return new Instruction(Type.LOAD_INTRINSICS, key);
|
return new Instruction(Type.LOAD_INTRINSICS, key);
|
||||||
}
|
}
|
||||||
|
public static Instruction loadError() {
|
||||||
|
return new Instruction(Type.LOAD_ERROR);
|
||||||
|
}
|
||||||
public static Instruction loadMember() {
|
public static Instruction loadMember() {
|
||||||
return new Instruction(Type.LOAD_MEMBER);
|
return new Instruction(Type.LOAD_MEMBER);
|
||||||
}
|
}
|
||||||
@ -457,12 +461,15 @@ public class Instruction {
|
|||||||
return new Instruction(Type.OPERATION, op);
|
return new Instruction(Type.OPERATION, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Instruction stackAlloc(int n) {
|
public static Instruction stackAlloc(int start, int n) {
|
||||||
return new Instruction(Type.STACK_ALLOC, n);
|
return new Instruction(Type.STACK_ALLOC, start, start + n);
|
||||||
}
|
}
|
||||||
public static Instruction stackRealloc(int n) {
|
public static Instruction stackRealloc(int start, int n) {
|
||||||
return new Instruction(Type.STACK_REALLOC, n);
|
return new Instruction(Type.STACK_REALLOC, start, start + n);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
public static Instruction stackFree(int n) {
|
public static Instruction stackFree(int n) {
|
||||||
return new Instruction(Type.STACK_FREE, n);
|
return new Instruction(Type.STACK_FREE, n);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ public final class CompileResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new FunctionBody(
|
return new FunctionBody(
|
||||||
scope.localsCount() + scope.allocCount(), scope.capturesCount(),
|
scope.localsCount(), scope.capturablesCount(), scope.capturesCount(),
|
||||||
length, instrRes, builtChildren
|
length, instrRes, builtChildren
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ public class CompoundNode extends Node {
|
|||||||
|
|
||||||
var subtarget = hasScope ? target.subtarget() : target;
|
var subtarget = hasScope ? target.subtarget() : target;
|
||||||
if (hasScope) {
|
if (hasScope) {
|
||||||
subtarget.add(i -> Instruction.stackAlloc(subtarget.scope.allocCount()));
|
subtarget.add(i -> Instruction.stackAlloc(subtarget.scope.capturablesOffset(), subtarget.scope.allocCount()));
|
||||||
subtarget.scope.singleEntry = singleEntry;
|
subtarget.scope.singleEntry = singleEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,10 +45,7 @@ public class CompoundNode extends Node {
|
|||||||
else stm.compile(subtarget, polluted = pollute, BreakpointType.STEP_OVER);
|
else stm.compile(subtarget, polluted = pollute, BreakpointType.STEP_OVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasScope) {
|
if (hasScope) subtarget.scope.end();
|
||||||
subtarget.scope.end();
|
|
||||||
subtarget.add(_i -> Instruction.stackFree(subtarget.scope.allocCount()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!polluted && pollute) {
|
if (!polluted && pollute) {
|
||||||
target.add(Instruction.pushUndefined());
|
target.add(Instruction.pushUndefined());
|
||||||
|
@ -26,7 +26,7 @@ public class ForNode extends Node {
|
|||||||
@Override public void compile(CompileResult target, boolean pollute) {
|
@Override public void compile(CompileResult target, boolean pollute) {
|
||||||
var subtarget = target.subtarget();
|
var subtarget = target.subtarget();
|
||||||
subtarget.scope.singleEntry = false;
|
subtarget.scope.singleEntry = false;
|
||||||
subtarget.add(i -> Instruction.stackAlloc(subtarget.scope.allocCount()));
|
subtarget.add(i -> Instruction.stackAlloc(subtarget.scope.capturablesOffset(), subtarget.scope.allocCount()));
|
||||||
|
|
||||||
declaration.compile(subtarget, false, BreakpointType.STEP_OVER);
|
declaration.compile(subtarget, false, BreakpointType.STEP_OVER);
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ public class ForNode extends Node {
|
|||||||
CompoundNode.compileMultiEntry(body, subtarget, false, BreakpointType.STEP_OVER);
|
CompoundNode.compileMultiEntry(body, subtarget, false, BreakpointType.STEP_OVER);
|
||||||
LabelContext.popLoop(subtarget.env, label);
|
LabelContext.popLoop(subtarget.env, label);
|
||||||
|
|
||||||
subtarget.add(_i -> Instruction.stackRealloc(subtarget.scope.allocCount()));
|
subtarget.add(_i -> Instruction.stackRealloc(subtarget.scope.capturablesOffset(), subtarget.scope.allocCount()));
|
||||||
|
|
||||||
CompoundNode.compileMultiEntry(assignment, subtarget, false, BreakpointType.STEP_OVER);
|
CompoundNode.compileMultiEntry(assignment, subtarget, false, BreakpointType.STEP_OVER);
|
||||||
int endI = subtarget.size();
|
int endI = subtarget.size();
|
||||||
@ -52,7 +52,6 @@ public class ForNode extends Node {
|
|||||||
if (pollute) subtarget.add(Instruction.pushUndefined());
|
if (pollute) subtarget.add(Instruction.pushUndefined());
|
||||||
|
|
||||||
subtarget.scope.end();
|
subtarget.scope.end();
|
||||||
subtarget.add(_i -> Instruction.stackFree(subtarget.scope.allocCount()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ForNode(Location loc, String label, Node declaration, Node condition, Node assignment, Node body) {
|
public ForNode(Location loc, String label, Node declaration, Node condition, Node assignment, Node body) {
|
||||||
|
@ -44,7 +44,7 @@ public class SwitchNode extends Node {
|
|||||||
value.compile(target, true, BreakpointType.STEP_OVER);
|
value.compile(target, true, BreakpointType.STEP_OVER);
|
||||||
|
|
||||||
var subtarget = target.subtarget();
|
var subtarget = target.subtarget();
|
||||||
subtarget.add(_i -> Instruction.stackAlloc(subtarget.scope.allocCount()));
|
subtarget.add(_i -> Instruction.stackAlloc(subtarget.scope.capturablesOffset(), subtarget.scope.allocCount()));
|
||||||
|
|
||||||
// TODO: create a jump map
|
// TODO: create a jump map
|
||||||
for (var ccase : cases) {
|
for (var ccase : cases) {
|
||||||
@ -65,7 +65,6 @@ public class SwitchNode extends Node {
|
|||||||
LabelContext.getBreak(target.env).pop(label);
|
LabelContext.getBreak(target.env).pop(label);
|
||||||
|
|
||||||
subtarget.scope.end();
|
subtarget.scope.end();
|
||||||
subtarget.add(_i -> Instruction.stackFree(subtarget.scope.allocCount()));
|
|
||||||
|
|
||||||
int endI = subtarget.size();
|
int endI = subtarget.size();
|
||||||
end.set(endI);
|
end.set(endI);
|
||||||
|
@ -23,8 +23,8 @@ public class TryNode extends Node {
|
|||||||
|
|
||||||
@Override public void resolve(CompileResult target) {
|
@Override public void resolve(CompileResult target) {
|
||||||
tryBody.resolve(target);
|
tryBody.resolve(target);
|
||||||
catchBody.resolve(target);
|
if (catchBody != null) catchBody.resolve(target);
|
||||||
finallyBody.resolve(target);
|
if (finallyBody != null) finallyBody.resolve(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void compile(CompileResult target, boolean pollute, BreakpointType bpt) {
|
@Override public void compile(CompileResult target, boolean pollute, BreakpointType bpt) {
|
||||||
@ -43,8 +43,14 @@ public class TryNode extends Node {
|
|||||||
|
|
||||||
if (captureName != null) {
|
if (captureName != null) {
|
||||||
var subtarget = target.subtarget();
|
var subtarget = target.subtarget();
|
||||||
subtarget.scope.defineStrict(new Variable(captureName, false), catchBody.loc());
|
subtarget.add(i -> Instruction.stackAlloc(subtarget.scope.capturablesOffset(), subtarget.scope.allocCount()));
|
||||||
|
subtarget.scope.singleEntry = true;
|
||||||
|
|
||||||
|
var catchVar = subtarget.scope.defineStrict(new Variable(captureName, false), catchBody.loc());
|
||||||
|
subtarget.add(Instruction.loadError());
|
||||||
|
subtarget.add(_i -> catchVar.index().toSet(false));
|
||||||
catchBody.compile(subtarget, false);
|
catchBody.compile(subtarget, false);
|
||||||
|
|
||||||
subtarget.scope.end();
|
subtarget.scope.end();
|
||||||
}
|
}
|
||||||
else catchBody.compile(target, false);
|
else catchBody.compile(target, false);
|
||||||
|
@ -9,8 +9,8 @@ import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
|
|||||||
public class Scope {
|
public class Scope {
|
||||||
protected final HashMap<String, Variable> strictVarMap = new HashMap<>();
|
protected final HashMap<String, Variable> strictVarMap = new HashMap<>();
|
||||||
|
|
||||||
protected final VariableList variables = new VariableList(VariableIndex.IndexType.LOCALS, this::parentVarOffset);
|
protected final VariableList variables = new VariableList(VariableIndex.IndexType.LOCALS, this::variableOffset);
|
||||||
protected final VariableList captured = new VariableList(VariableIndex.IndexType.CAPTURABLES, this::parentCapOffset);
|
protected final VariableList captured = new VariableList(VariableIndex.IndexType.CAPTURABLES, this::capturablesOffset);
|
||||||
|
|
||||||
private boolean ended = false;
|
private boolean ended = false;
|
||||||
private boolean finished = false;
|
private boolean finished = false;
|
||||||
@ -41,14 +41,14 @@ public class Scope {
|
|||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int parentVarOffset() {
|
// private final int parentVarOffset() {
|
||||||
if (parent != null) return parent.variableOffset();
|
// if (parent != null) return parent.variableOffset();
|
||||||
else return 0;
|
// else return 0;
|
||||||
}
|
// }
|
||||||
private final int parentCapOffset() {
|
// private final int parentCapOffset() {
|
||||||
if (parent != null) return parent.capturedOffset();
|
// if (parent != null) return parent.capturedOffset();
|
||||||
else return localsCount();
|
// else return localsCount();
|
||||||
}
|
// }
|
||||||
|
|
||||||
protected final SyntaxException alreadyDefinedErr(Location loc, String name) {
|
protected final SyntaxException alreadyDefinedErr(Location loc, String name) {
|
||||||
return new SyntaxException(loc, String.format("Identifier '%s' has already been declared", name));
|
return new SyntaxException(loc, String.format("Identifier '%s' has already been declared", name));
|
||||||
@ -118,12 +118,28 @@ public class Scope {
|
|||||||
* Gets the index offset from this scope to its children
|
* Gets the index offset from this scope to its children
|
||||||
*/
|
*/
|
||||||
public final int variableOffset() {
|
public final int variableOffset() {
|
||||||
if (parent != null) return parent.variableOffset() + variables.size();
|
var res = 0;
|
||||||
else return variables.size();
|
|
||||||
|
for (var curr = parent; curr != null; curr = curr.parent) {
|
||||||
|
res += parent.variables.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
|
||||||
|
// if (parent != null) return parent.variableOffset() + variables.size();
|
||||||
|
// else return variables.size();
|
||||||
}
|
}
|
||||||
public final int capturedOffset() {
|
public final int capturablesOffset() {
|
||||||
if (parent != null) return parent.capturedOffset() + captured.size();
|
var res = 0;
|
||||||
else return localsCount() + captured.size();
|
|
||||||
|
for (var curr = this; curr != null; curr = curr.parent) {
|
||||||
|
if (curr != this) res += parent.captured.size();
|
||||||
|
if (curr.parent == null) res += curr.localsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
// if (parent != null) return parent.capturedOffset() + captured.size();
|
||||||
|
// else return localsCount() + captured.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int localsCount() {
|
public int localsCount() {
|
||||||
@ -142,7 +158,7 @@ public class Scope {
|
|||||||
}
|
}
|
||||||
public int capturablesCount() {
|
public int capturablesCount() {
|
||||||
var res = captured.size();
|
var res = captured.size();
|
||||||
for (var child : children) res += child.allocCount();
|
for (var child : children) res += child.capturablesCount();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package me.topchetoeu.jscript.runtime;
|
package me.topchetoeu.jscript.runtime;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@ -99,7 +98,8 @@ public final class Frame {
|
|||||||
* A list of one-element arrays of values. This is so that we can pass captures to other functions
|
* A list of one-element arrays of values. This is so that we can pass captures to other functions
|
||||||
*/
|
*/
|
||||||
public final Value[][] captures;
|
public final Value[][] captures;
|
||||||
public final List<Value[]> locals = new ArrayList<>();
|
public final Value[] locals;
|
||||||
|
public final Value[][] capturables;
|
||||||
public final Value argsVal;
|
public final Value argsVal;
|
||||||
public Value self;
|
public Value self;
|
||||||
public Value fakeArgs;
|
public Value fakeArgs;
|
||||||
@ -110,9 +110,20 @@ public final class Frame {
|
|||||||
public final Environment env;
|
public final Environment env;
|
||||||
private final DebugContext dbg;
|
private final DebugContext dbg;
|
||||||
|
|
||||||
public Value[] getVar(int i) {
|
public Value getVar(int i) {
|
||||||
|
if (i < 0) return captures[~i][0];
|
||||||
|
else if (i < locals.length) return locals[i];
|
||||||
|
else return capturables[i - locals.length][0];
|
||||||
|
}
|
||||||
|
public Value setVar(int i, Value val) {
|
||||||
|
if (i < 0) return captures[~i][0] = val;
|
||||||
|
else if (i < locals.length) return locals[i] = val;
|
||||||
|
else return capturables[i - locals.length][0] = val;
|
||||||
|
}
|
||||||
|
public Value[] captureVar(int i) {
|
||||||
if (i < 0) return captures[~i];
|
if (i < 0) return captures[~i];
|
||||||
else return locals.get(i);
|
if (i >= locals.length) return capturables[i - locals.length];
|
||||||
|
else throw new RuntimeException("Illegal capture");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value[] stack = new Value[32];
|
public Value[] stack = new Value[32];
|
||||||
@ -215,12 +226,13 @@ public final class Frame {
|
|||||||
if (newCtx != tryCtx) {
|
if (newCtx != tryCtx) {
|
||||||
switch (newCtx.state) {
|
switch (newCtx.state) {
|
||||||
case CATCH:
|
case CATCH:
|
||||||
if (tryCtx.state != TryState.CATCH) locals.add(new Value[] { error.value });
|
// TODO: may cause problems
|
||||||
|
// if (tryCtx.state != TryState.CATCH) locals.add(new Value[] { error.value });
|
||||||
codePtr = tryCtx.catchStart;
|
codePtr = tryCtx.catchStart;
|
||||||
stackPtr = tryCtx.restoreStackPtr;
|
stackPtr = tryCtx.restoreStackPtr;
|
||||||
break;
|
break;
|
||||||
case FINALLY:
|
case FINALLY:
|
||||||
if (tryCtx.state == TryState.CATCH) locals.remove(locals.size() - 1);
|
// if (tryCtx.state == TryState.CATCH) locals.remove(locals.size() - 1);
|
||||||
codePtr = tryCtx.finallyStart;
|
codePtr = tryCtx.finallyStart;
|
||||||
stackPtr = tryCtx.restoreStackPtr;
|
stackPtr = tryCtx.restoreStackPtr;
|
||||||
default:
|
default:
|
||||||
@ -236,7 +248,7 @@ public final class Frame {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
popTryFlag = false;
|
popTryFlag = false;
|
||||||
if (tryCtx.state == TryState.CATCH) locals.remove(locals.size() - 1);
|
// if (tryCtx.state == TryState.CATCH) locals.remove(locals.size() - 1);
|
||||||
|
|
||||||
if (tryCtx.state != TryState.FINALLY && tryCtx.hasFinally()) {
|
if (tryCtx.state != TryState.FINALLY && tryCtx.hasFinally()) {
|
||||||
codePtr = tryCtx.finallyStart;
|
codePtr = tryCtx.finallyStart;
|
||||||
@ -422,8 +434,13 @@ public final class Frame {
|
|||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
|
||||||
for (i = 0; i < func.body.localsN; i++) {
|
this.locals = new Value[func.body.localsN];
|
||||||
this.locals.add(new Value[] { Value.UNDEFINED });
|
Arrays.fill(locals, Value.UNDEFINED);
|
||||||
|
|
||||||
|
this.capturables = new Value[func.body.capturablesN][1];
|
||||||
|
|
||||||
|
for (i = 0; i < func.body.capturablesN; i++) {
|
||||||
|
this.capturables[i][0] = Value.UNDEFINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ public class InstructionRunner {
|
|||||||
private static Value execLoadVar(Environment env, Instruction instr, Frame frame) {
|
private static Value execLoadVar(Environment env, Instruction instr, Frame frame) {
|
||||||
int i = instr.get(0);
|
int i = instr.get(0);
|
||||||
|
|
||||||
frame.push(frame.getVar(i)[0]);
|
frame.push(frame.getVar(i));
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -179,7 +179,7 @@ public class InstructionRunner {
|
|||||||
var captures = new Value[instr.params.length - 5][];
|
var captures = new Value[instr.params.length - 5][];
|
||||||
|
|
||||||
for (var i = 5; i < instr.params.length; i++) {
|
for (var i = 5; i < instr.params.length; i++) {
|
||||||
captures[i - 5] = frame.getVar(instr.get(i));
|
captures[i - 5] = frame.captureVar(instr.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
var func = new CodeFunction(env, name, frame.function.body.children[id], captures);
|
var func = new CodeFunction(env, name, frame.function.body.children[id], captures);
|
||||||
@ -278,7 +278,7 @@ public class InstructionRunner {
|
|||||||
var val = (boolean)instr.get(1) ? frame.peek() : frame.pop();
|
var val = (boolean)instr.get(1) ? frame.peek() : frame.pop();
|
||||||
int i = instr.get(0);
|
int i = instr.get(0);
|
||||||
|
|
||||||
frame.getVar(i)[0] = val;
|
frame.setVar(i, val);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -498,29 +498,34 @@ public class InstructionRunner {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
private static Value execLoadError(Environment env, Instruction instr, Frame frame) {
|
||||||
|
frame.push(frame.tryStack.peek().error.value);
|
||||||
|
frame.codePtr++;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static Value execStackAlloc(Environment env, Instruction instr, Frame frame) {
|
private static Value execStackAlloc(Environment env, Instruction instr, Frame frame) {
|
||||||
int n = instr.get(0);
|
int offset = instr.get(0);
|
||||||
|
int n = instr.get(1);
|
||||||
|
|
||||||
for (var i = 0; i < n; i++) frame.locals.add(new Value[] { Value.UNDEFINED });
|
for (var i = offset; i < n; i++) frame.capturables[i] = new Value[] { Value.UNDEFINED };
|
||||||
|
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static Value execStackRealloc(Environment env, Instruction instr, Frame frame) {
|
private static Value execStackRealloc(Environment env, Instruction instr, Frame frame) {
|
||||||
int n = instr.get(0);
|
int offset = instr.get(0);
|
||||||
|
int n = instr.get(1);
|
||||||
|
|
||||||
for (var i = frame.locals.size() - n; i < frame.locals.size(); i++) frame.locals.set(i, new Value[] { frame.locals.get(i)[0] });
|
for (var i = offset; i < n; i++) frame.capturables[i] = new Value[] { frame.capturables[i][0] };
|
||||||
|
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static Value execStackFree(Environment env, Instruction instr, Frame frame) {
|
private static Value execStackFree(Environment env, Instruction instr, Frame frame) {
|
||||||
int n = instr.get(0);
|
// int n = instr.get(0);
|
||||||
|
|
||||||
for (var i = 0; i < n; i++) {
|
// TODO: Remove if safe to do so
|
||||||
frame.locals.remove(frame.locals.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return null;
|
return null;
|
||||||
@ -559,6 +564,7 @@ public class InstructionRunner {
|
|||||||
case LOAD_REST_ARGS: return execLoadRestArgs(env, instr, frame);
|
case LOAD_REST_ARGS: return execLoadRestArgs(env, instr, frame);
|
||||||
case LOAD_CALLEE: return execLoadCallee(env, instr, frame);
|
case LOAD_CALLEE: return execLoadCallee(env, instr, frame);
|
||||||
case LOAD_THIS: return execLoadThis(env, instr, frame);
|
case LOAD_THIS: return execLoadThis(env, instr, frame);
|
||||||
|
case LOAD_ERROR: return execLoadError(env, instr, frame);
|
||||||
|
|
||||||
case DISCARD: return execDiscard(env, instr, frame);
|
case DISCARD: return execDiscard(env, instr, frame);
|
||||||
case STORE_MEMBER: return execStoreMember(env, instr, frame);
|
case STORE_MEMBER: return execStoreMember(env, instr, frame);
|
||||||
|
Loading…
Reference in New Issue
Block a user