diff --git a/aeneas/src/core/Eval.v3 b/aeneas/src/core/Eval.v3 index 30d06d6da..9e6a1db3d 100644 --- a/aeneas/src/core/Eval.v3 +++ b/aeneas/src/core/Eval.v3 @@ -205,8 +205,15 @@ component Eval { // Accessor to the dynamic environment for operator evaluation, including value arguments // type arguments, as well as the ability to perform tail calls and throw exceptions. class Arguments { - def numArgs() -> int; - def getArg(i: int) -> Val; + var vals_storage = Array.new(16); + var vals: Range; + + def growVals(size: int) -> Array { + var v = vals_storage; + if (v.length < size) vals_storage = v = Array.new(v.length + size + 16); + vals = v[0 ... size]; + return v; + } def getTypeArg(i: int) -> Type; def getTypeArgs() -> Array; def getProgram() -> Program; @@ -215,12 +222,12 @@ class Arguments { // Convenience accessors that perform casts on arguments def it(i: int) -> IntType { return IntType.!(getTypeArg(i)); } - def z(i: int) -> bool { return Bool.unbox(getArg(i)); } - def r(i: int) -> Record { return Record.!(getArg(i)); } - def ra(i: int) -> ArrayRangeVal { return ArrayRangeVal.!(getArg(i)); } - def ref(i: int) -> ByteArrayOffset { return ByteArrayOffset.!(getArg(i)); } + def z(i: int) -> bool { return Bool.unbox(vals[i]); } + def r(i: int) -> Record { return Record.!(vals[i]); } + def ra(i: int) -> ArrayRangeVal { return ArrayRangeVal.!(vals[i]); } + def ref(i: int) -> ByteArrayOffset { return ByteArrayOffset.!(vals[i]); } def range(i: int) -> (Record, int, int) { - match (getArg(i)) { + match (vals[i]) { null => { throw(V3Exception.NullCheck, null); return (null, 0, 0); @@ -234,22 +241,22 @@ class Arguments { } return (null, 0, 0); } - def i(i: int) -> int { return Int.unbox(getArg(i)); } - def u(i: int) -> u32 { return u32.view(Int.unbox(getArg(i))); } - def l(i: int) -> long { return Long.unboxSU(getArg(i), true); } - def q(i: int) -> u64 { return u64.view(Long.unboxSU(getArg(i), false)); } - def b(i: int) -> byte { return Byte.unbox(getArg(i)); } - def s(i: int) -> string { return Byte.unboxString(getArg(i)); } + def i(i: int) -> int { return Int.unbox(vals[i]); } + def u(i: int) -> u32 { return u32.view(Int.unbox(vals[i])); } + def l(i: int) -> long { return Long.unboxSU(vals[i], true); } + def q(i: int) -> u64 { return u64.view(Long.unboxSU(vals[i], false)); } + def b(i: int) -> byte { return Byte.unbox(vals[i]); } + def s(i: int) -> string { return Byte.unboxString(vals[i]); } def f(i: int) -> float { - var x = getArg(i); + var x = vals[i]; return if(Float32Val.?(x), float.view(Float32Val.!(x).bits)); } def d(i: int) -> double { - var x = getArg(i); + var x = vals[i]; return if(Float64Val.?(x), double.view(Float64Val.!(x).bits)); } def addr(i: int) -> Addr { - var p = getArg(i); + var p = vals[i]; if (p == null) return NULL_PTR; return Addr.!(p); } @@ -304,14 +311,14 @@ def evalOp(op: Operator, args: Arguments) -> Result { BoolOr => return Bool.box(args.z(0) || args.z(1)); BoolNot => return Bool.box(!args.z(0)); //---------------------------------------------------------------------------- - OverloadedEq, IntEq, VariantEq, RefEq => return Bool.box(Values.equal(args.getArg(0), args.getArg(1))); + OverloadedEq, IntEq, VariantEq, RefEq => return Bool.box(Values.equal(args.vals[0], args.vals[1])); //---------------------------------------------------------------------------- IntAdd => return evalIntBinop(args, int.+, long.+); IntSub => return evalIntBinop(args, int.-, long.-); IntMul => return evalIntBinop(args, int.*, long.*); IntDiv => { var it = IntType.!(args.getTypeArg(0)); - var d = args.getArg(1); + var d = args.vals[1]; match (d) { null => return args.throw(V3Exception.DivideByZero, null); x: Box => if (x.val == 0) return args.throw(V3Exception.DivideByZero, null); @@ -328,7 +335,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { } IntMod => { var it = IntType.!(args.getTypeArg(0)); - var d = args.getArg(1); + var d = args.vals[1]; match (d) { null => return args.throw(V3Exception.DivideByZero, null); x: Box => if (x.val == 0) return args.throw(V3Exception.DivideByZero, null); @@ -386,7 +393,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { FloatMul(isDouble) => return if(isDouble, args.do_dd_d(double.*), args.do_ff_f(float.*)); FloatDiv(isDouble) => return if(isDouble, args.do_dd_d(double./), args.do_ff_f(float./)); FloatBitEq(isDouble) => { - var x = args.getArg(0), y = args.getArg(1); + var x = args.vals[0], y = args.vals[1]; if (isDouble) return Bool.box(Float64Val.!(x).bits == Float64Val.!(y).bits); else return Bool.box(Float32Val.!(x).bits == Float32Val.!(y).bits); } @@ -411,11 +418,11 @@ def evalOp(op: Operator, args: Arguments) -> Result { return Bool.box(!(t.1 | t.2)); } IntViewI => { - var val = args.getArg(0), ift = args.it(0), itt = args.it(1); + var val = args.vals[0], ift = args.it(0), itt = args.it(1); return Eval.doIntView(ift, itt, val); } IntViewF(isDouble) => { - var v = args.getArg(0); + var v = args.vals[0]; if (v == null) return Values.BOTTOM; if (isDouble) return Long.box(long.view(Float64Val.!(v).bits)); else return Int.box(int.view(Float32Val.!(v).bits)); @@ -427,7 +434,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { } FloatCastI(isDouble) => { var itt = args.it(0); - var t = fround_i(isDouble, itt, args.getArg(0)); + var t = fround_i(isDouble, itt, args.vals[0]); if (t.1) return args.throw(V3Exception.TypeCheck, null); return t.0; } @@ -438,23 +445,23 @@ def evalOp(op: Operator, args: Arguments) -> Result { } FloatQueryI(isDouble) => { var itt = args.it(0); - var t = fround_i(isDouble, itt, args.getArg(0)); + var t = fround_i(isDouble, itt, args.vals[0]); return Bool.box(!t.1); } FloatQueryD => { return Bool.box(float.?(args.d(0))); } FloatPromoteI(isDouble) => { - var a = args.getArg(0); + var a = args.vals[0]; if (a == null) return Values.BOTTOM; - var l = Long.unboxSU(args.getArg(0), V3.isSigned(args.getTypeArg(0))); + var l = Long.unboxSU(args.vals[0], V3.isSigned(args.getTypeArg(0))); return if(isDouble, boxd((double.!(l))), boxf((float.!(l)))); } FloatPromoteF => { return boxd((double.!(args.f(0)))); } FloatViewI(isDouble) => { - var v = args.getArg(0); + var v = args.vals[0]; if (v == null) return Values.BOTTOM; if (isDouble) { return Float64Val.new(u64.view(Long.unboxSU(v, false))); @@ -464,7 +471,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { } FloatRoundI(isDouble) => { var itt = args.it(0); - var t = fround_i(isDouble, itt, args.getArg(0)); + var t = fround_i(isDouble, itt, args.vals[0]); return t.0; } FloatRound(isDouble) => { @@ -476,11 +483,11 @@ def evalOp(op: Operator, args: Arguments) -> Result { //---------------------------------------------------------------------------- TupleCreate(length) => { var vals = Array.new(length); - for (i < vals.length) vals[i] = args.getArg(i); + for (i < vals.length) vals[i] = args.vals[i]; return TupleVal.new(vals); } TupleGetElem(index) => { - var tuple = args.getArg(0); + var tuple = args.vals[0]; if (tuple == Values.BOTTOM) return Values.BOTTOM; return (TupleVal.!(tuple)).values[index]; } @@ -493,7 +500,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { } ArrayInit(length) => { var array = args.getProgram().newRecord(args.getTypeArg(0), length); - for (i < length) array.values[i] = args.getArg(i); + for (i < length) array.values[i] = args.vals[i]; return array; } ArrayTupleInit(elems, length) => { @@ -501,7 +508,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { var p = 0; for (i < length) { var vals = Array.new(elems); - for (j < elems) vals[j] = args.getArg(p++); + for (j < elems) vals[j] = args.vals[p++]; array.values[i] = TupleVal.new(vals); } return array; @@ -516,7 +523,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { var array = args.r(0), index = args.i(1); if (array == null) return args.throw(V3Exception.NullCheck, null); if (u32.view(index) >= u32.view(array.values.length)) return args.throw(V3Exception.BoundsCheck, null); - var val = args.getArg(2); + var val = args.vals[2]; array.values[index] = val; return val; } @@ -533,7 +540,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { if (array == null) return args.throw(V3Exception.NullCheck, null); if (u32.view(index) >= u32.view(array.values.length)) return args.throw(V3Exception.BoundsCheck, null); var tval = TupleVal.!(array.values[index]); - var val = args.getArg(2); + var val = args.vals[2]; if (tval == null) { var len = Tuple.length(V3Array.elementType(args.getTypeArg(0))); array.values[index] = tval = TupleVal.new(Array.new(len)); @@ -593,12 +600,12 @@ def evalOp(op: Operator, args: Arguments) -> Result { var range = args.ra(0), index = args.i(1); if (range == null || range.array == null) return args.throw(V3Exception.NullCheck, null); if (u32.view(index) >= u32.view(range.length)) return args.throw(V3Exception.BoundsCheck, null); - var val = args.getArg(2); + var val = args.vals[2]; range.array.values[range.start + index] = val; return val; } RangeGetLength => { - var val = args.getArg(0); + var val = args.vals[0]; if (val == null) return Int.ZERO; return Int.box(ArrayRangeVal.!(val).length); } @@ -626,7 +633,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { ComponentSetField(field) => { var decl = V3.componentDecl(args.getTypeArg(0)); var object = args.getProgram().getComponentRecord(decl); - object.values[field.index] = args.getArg(1); + object.values[field.index] = args.vals[1]; return Values.BOTTOM; } //---------------------------------------------------------------------------- @@ -634,7 +641,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { if (method != null) { var spec = getIrSpec(method, args), prog = args.getProgram(); var record = prog.newRecord(spec.receiver, prog.ir.numFields(spec.receiver)); - return args.tailCall(spec, record, 0, args.numArgs()); + return args.tailCall(spec, record, 0, args.vals.length); } else { var classType = args.getTypeArg(0), prog = args.getProgram(); var record = prog.newRecord(classType, prog.ir.numFields(classType)); @@ -649,14 +656,14 @@ def evalOp(op: Operator, args: Arguments) -> Result { ClassInitField(field) => { var object = args.r(0); if (object == null) return args.throw(V3Exception.NullCheck, null); - var val = args.getArg(1); + var val = args.vals[1]; object.values[field.index] = val; return Values.BOTTOM; } ClassSetField(field) => { var object = args.r(0); if (object == null) return args.throw(V3Exception.NullCheck, null); - var val = args.getArg(1); + var val = args.vals[1]; object.values[field.index] = val; return Values.BOTTOM; } @@ -681,7 +688,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { } //---------------------------------------------------------------------------- VariantGetTag => { - var val = args.getArg(0); + var val = args.vals[0]; return if(Record.?(val), Int.box(V3.getVariantTag(Record.!(val).rtype))); } VariantGetField(field) => { @@ -689,7 +696,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { return if(object != null, object.values[field.index]); } VariantReplaceNull => { - return args.getArg(0); + return args.vals[0]; } VariantGetMethod(method) => { var object = args.r(0); @@ -719,22 +726,22 @@ def evalOp(op: Operator, args: Arguments) -> Result { return Values.BOTTOM; } ConditionalThrow(exception) => { - if (Bool.unbox(args.getArg(0))) return args.throw(exception, null); + if (Bool.unbox(args.vals[0])) return args.throw(exception, null); return Values.BOTTOM; } //---------------------------------------------------------------------------- TypeCast(cast) => { - var val = args.getArg(0), r = Eval.doCast(cast, args.getTypeArg(0), args.getTypeArg(1), val); + var val = args.vals[0], r = Eval.doCast(cast, args.getTypeArg(0), args.getTypeArg(1), val); if (r.0) return r.1; return args.throw(V3Exception.TypeCheck, null); } TypeQuery(query) => { - var val = args.getArg(0), r = Eval.doQuery(query, args.getTypeArg(0), args.getTypeArg(1), val); + var val = args.vals[0], r = Eval.doQuery(query, args.getTypeArg(0), args.getTypeArg(1), val); return Bool.box(r); } TypeSubsume => { // XXX: factor out nop subsumes from non-throwing conversions - var val = args.getArg(0), r = Eval.doCast0(args.getTypeArg(0), args.getTypeArg(1), val); + var val = args.vals[0], r = Eval.doCast0(args.getTypeArg(0), args.getTypeArg(1), val); if (r.0) return r.1; return args.throw(V3Exception.InternalError, "subsume should never fail"); } @@ -742,49 +749,49 @@ def evalOp(op: Operator, args: Arguments) -> Result { CallMethod(method) => { var object = getReceiver(args); var spec = getIrSpec(method, args); - return args.tailCall(spec, object, 1, args.numArgs()); + return args.tailCall(spec, object, 1, args.vals.length); } CallClosure => { - var del = Closure.!(args.getArg(0)); + var del = Closure.!(args.vals[0]); if (del == null) return args.throw(V3Exception.NullCheck, null); - return args.tailCall(del.memberRef, del.val, 1, args.numArgs()); + return args.tailCall(del.memberRef, del.val, 1, args.vals.length); } CallFunction => { - var func = FuncVal.!(args.getArg(0)); - var recvr = args.getArg(1); + var func = FuncVal.!(args.vals[0]); + var recvr = args.vals[1]; if (func == null) return args.throw(V3Exception.NullCheck, null); - return args.tailCall(func.memberRef, recvr, 2, args.numArgs()); + return args.tailCall(func.memberRef, recvr, 2, args.vals.length); } CallClassMethod(method) => { var object = getRecordReceiver(args); if (object == null) return args.throw(V3Exception.NullCheck, null); var spec = getIrSpec(method, args); - return args.tailCall(spec, object, 1, args.numArgs()); + return args.tailCall(spec, object, 1, args.vals.length); } CallClassVirtual(method) => { var object = getRecordReceiver(args); var spec = lookupClassVirtual(args, object, method); if (spec == null) return Values.BOTTOM; - return args.tailCall(spec, object, 1, args.numArgs()); + return args.tailCall(spec, object, 1, args.vals.length); } CallClassSelector(selector) => { var object = getRecordReceiver(args); var spec = lookupClassVirtual(args, object, selector); if (spec == null) return Values.BOTTOM; - return args.tailCall(spec, object, 1, args.numArgs()); + return args.tailCall(spec, object, 1, args.vals.length); } CallVariantVirtual(method) => { var object = getRecordReceiver(args); var spec = lookupVariantVirtual(args, object, method); - return args.tailCall(spec, object, 1, args.numArgs()); + return args.tailCall(spec, object, 1, args.vals.length); } CallVariantSelector(selector) => { var object = getRecordReceiver(args); var spec = lookupVariantVirtual(args, object, selector); - return args.tailCall(spec, object, 1, args.numArgs()); + return args.tailCall(spec, object, 1, args.vals.length); } CreateClosure(method) => { - return Closure.new(args.getArg(0), getIrSpec(method, args)); + return Closure.new(args.vals[0], getIrSpec(method, args)); } //---------------------------------------------------------------------------- RefLayoutAt => { @@ -799,7 +806,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { return ByteArrayOffset.new(object, val); } RefLayoutOf => { - var range = ArrayRangeVal.!(args.getArg(0)); + var range = ArrayRangeVal.!(args.vals[0]); if (range == null || range.array == null) return args.throw(V3Exception.NullCheck, null); var t = RefType.!(args.getTypeArg(0)); var size = u64.view(t.layoutDecl.byteSize); @@ -817,7 +824,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { } RefLayoutSetField(offset) => { var ref = args.ref(0); - return doRefLayoutSetField(args, args.getTypeArg(1), ref, offset, args.getArg(1)); + return doRefLayoutSetField(args, args.getTypeArg(1), ref, offset, args.vals[1]); } RefLayoutAtRepeatedField(offset, scale, max) => { var ref = args.ref(0); @@ -837,7 +844,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { var ref = args.ref(0); var index = args.i(1); if (u32.view(index) >= u32.view(max)) return args.throw(V3Exception.BoundsCheck, null); - return doRefLayoutSetField(args, args.getTypeArg(1), ref, offset + scale * index, args.getArg(2)); + return doRefLayoutSetField(args, args.getTypeArg(1), ref, offset + scale * index, args.vals[2]); } ByteArrayGetField(offset) => { var array = args.r(0); @@ -849,7 +856,7 @@ def evalOp(op: Operator, args: Arguments) -> Result { var array = args.r(0); var i_offset = args.i(1); // XXX: Refactor so no intermediate ByteArrayOffset object needed - return doRefLayoutSetField(args, args.getTypeArg(0), ByteArrayOffset.new(array, offset), i_offset, args.getArg(2)); + return doRefLayoutSetField(args, args.getTypeArg(0), ByteArrayOffset.new(array, offset), i_offset, args.vals[2]); } //---------------------------------------------------------------------------- @@ -998,7 +1005,7 @@ def getIrSpec(member: IrMember, args: Arguments) -> IrSpec { } def getRecordReceiver(args: Arguments) -> Record { // TODO: this a giant hack for adapting arguments to void calls - var r = args.getArg(0); + var r = args.vals[0]; if (Record.?(r)) return Record.!(r); if (TupleVal.?(r)) return Record.!(TupleVal.!(r).values[0]); if (r != null) args.throw(V3Exception.InternalError, "expected record receiver for call"); @@ -1006,7 +1013,7 @@ def getRecordReceiver(args: Arguments) -> Record { } def getReceiver(args: Arguments) -> Val { // TODO: this a giant hack for adapting arguments to void calls - var r = args.getArg(0); + var r = args.vals[0]; if (TupleVal.?(r)) return TupleVal.!(r).values[0]; return r; } diff --git a/aeneas/src/ic/Ic.v3 b/aeneas/src/ic/Ic.v3 index 4750d5cdc..580d4c6bf 100644 --- a/aeneas/src/ic/Ic.v3 +++ b/aeneas/src/ic/Ic.v3 @@ -662,16 +662,9 @@ class IcInterpreter(prog: Program, compile: IrSpec -> IcMethod) extends Argument } // == implementation of Argument interface for operators ================= private var typeArgs: Array; - private var argRegs: Array; private var opDstReg: int; var opTailCall: bool; - def numArgs() -> int { - return argRegs.length; - } - def getArg(i: int) -> Val { - return regs[rp + argRegs[i]]; - } def getTypeArg(i: int) -> Type { var t = typeArgs[i]; if (t.open()) t = topFrame.memberRef.instantiateType(t); @@ -690,7 +683,7 @@ class IcInterpreter(prog: Program, compile: IrSpec -> IcMethod) extends Argument // copy the arguments into the frame var argRp = rp + 1, numArgs = endArg - startArg; for (i < numArgs) { - regs[argRp + i] = regs[oldRp + argRegs[startArg + i]]; + regs[argRp + i] = vals[startArg + i]; } regs[rp] = rcvr; // adjust size of parameters if necessary @@ -702,7 +695,8 @@ class IcInterpreter(prog: Program, compile: IrSpec -> IcMethod) extends Argument if (args.length != op.sig.paramTypes.length) args = adjustOpArgs(op.sig.paramTypes.length, args); typeArgs = op.typeArgs; opDstReg = dst; - argRegs = args; + var v = growVals(args.length); + for (i < args.length) v[i] = regs[rp + args[i]]; return op.evaluate(this); } def throw(ex: string, msg: string) -> Exception { diff --git a/aeneas/src/main/Version.v3 b/aeneas/src/main/Version.v3 index 9e75979ad..f938d87db 100644 --- a/aeneas/src/main/Version.v3 +++ b/aeneas/src/main/Version.v3 @@ -3,6 +3,6 @@ // Updated by VCS scripts. DO NOT EDIT. component Version { - def version: string = "III-7.1660"; + def version: string = "III-7.1661"; var buildData: string; } diff --git a/aeneas/src/ssa/SsaInterpreter.v3 b/aeneas/src/ssa/SsaInterpreter.v3 index 4c08cbb3c..3cad95be7 100644 --- a/aeneas/src/ssa/SsaInterpreter.v3 +++ b/aeneas/src/ssa/SsaInterpreter.v3 @@ -190,10 +190,10 @@ class SsaInterpreter(prog: Program, genSsa: (IrSpec, int) -> SsaGraph) { var n = nextInstr(i); // Set up arguments to Eval.doOp args.frame = frame; - args.args = Arrays.grow(args.args, i.inputs.length); args.typeArgs = i.op.typeArgs; - for (j < i.inputs.length) args.args[j] = getVal(i.inputs[j].dest); - args.nargs = i.inputs.length; + var inputs = i.inputs; + var v = args.growVals(inputs.length); + for (j < inputs.length) v[j] = getVal(inputs[j].dest); // Evaluate the operator var r = Eval.doOp(i.op, args); if (tailCalled) { @@ -331,7 +331,6 @@ class SsaInterpreter(prog: Program, genSsa: (IrSpec, int) -> SsaGraph) { } class SsaIntArguments(prog: Program) extends Arguments { var frame: SsaIntFrame; - var args: Array = Array.new(INITIAL_VALUES); var nargs: int; var typeArgs: Array; var interpreter: SsaInterpreter; @@ -339,9 +338,6 @@ class SsaIntArguments(prog: Program) extends Arguments { def numArgs() -> int { return nargs; } - def getArg(i: int) -> Val { - return args[i]; - } def getTypeArg(i: int) -> Type { var t = typeArgs[i]; if (t.open()) t = frame.spec.instantiateType(t); @@ -362,7 +358,7 @@ class SsaIntArguments(prog: Program) extends Arguments { return interpreter.exception = Exception.new(V3Exception.NullCheck, "null function", interpreter.getStackTrace(null)); } else { interpreter.tailCalled = true; - interpreter.pushFrame(spec, recvr, args[startArg ... endArg]); + interpreter.pushFrame(spec, recvr, vals[startArg ... endArg]); return null; } } diff --git a/aeneas/src/v3/SystemModule.v3 b/aeneas/src/v3/SystemModule.v3 index 07a787af2..004874da5 100644 --- a/aeneas/src/v3/SystemModule.v3 +++ b/aeneas/src/v3/SystemModule.v3 @@ -80,7 +80,7 @@ class SystemCallState { def fileReadK(args: Arguments) -> Result { var start = args.i(2), len = args.i(3); if (start < 0) return args.throw(V3Exception.BoundsCheck, null); - var record = Record.!(args.getArg(1)); + var record = Record.!(args.vals[1]); if (record == null) return args.throw(V3Exception.NullCheck, null); if (start > record.values.length) return args.throw(V3Exception.BoundsCheck, null); var end = u32.view(start) + u32.view(len);