Skip to content

Commit

Permalink
Replace TupleVal with BoxVal
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer committed Jun 23, 2024
1 parent d9c21d8 commit 76f4080
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 59 deletions.
32 changes: 16 additions & 16 deletions aeneas/src/core/Eval.v3
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ component Eval {
// recursively check nested types of tuples
var values: Array<Val>;
if (val == null) values = Array<Val>.new(Lists.length(ft.nested));
else if (!TupleVal.?(val)) return throw;
else values = TupleVal.!(val).values;
else if (!BoxVal.?(val)) return throw;
else values = BoxVal.!(val).values;

var a = ft.nested, b = tt.nested, i = 0, rv = Array<Val>.new(values.length);
while (a != null) {
Expand All @@ -33,7 +33,7 @@ component Eval {
rv[i] = r.1;
a = a.tail; b = b.tail; i++;
}
if (b == null) return (true, TupleVal.new(rv));
if (b == null) return (true, BoxVal.new(null, rv));
return throw;
}
CLASS_CAST, VARIANT_CAST => {
Expand Down Expand Up @@ -110,8 +110,8 @@ component Eval {
TUPLE_QUERY => {
var values: Array<Val>;
if (val == null) values = Array<Val>.new(Lists.length(ft.nested));
else if (!TupleVal.?(val)) return false;
else values = TupleVal.!(val).values;
else if (!BoxVal.?(val)) return false;
else values = BoxVal.!(val).values;

var a = ft.nested, b = tt.nested, i = 0;
while (a != null) {
Expand Down Expand Up @@ -486,12 +486,12 @@ def evalOp(op: Operator, args: Arguments) -> Result {
TupleCreate(length) => {
var vals = Array<Val>.new(length);
for (i < vals.length) vals[i] = args.vals[i];
return TupleVal.new(vals);
return BoxVal.new(null, vals);
}
TupleGetElem(index) => {
var tuple = args.vals[0];
if (tuple == Values.BOTTOM) return Values.BOTTOM;
return (TupleVal.!(tuple)).values[index];
return (BoxVal.!(tuple)).values[index];
}
//----------------------------------------------------------------------------
ArrayAlloc => {
Expand All @@ -511,7 +511,7 @@ def evalOp(op: Operator, args: Arguments) -> Result {
for (i < length) {
var vals = Array<Val>.new(elems);
for (j < elems) vals[j] = args.vals[p++];
array.values[i] = TupleVal.new(vals);
array.values[i] = BoxVal.new(null, vals);
}
return array;
}
Expand All @@ -535,17 +535,17 @@ def evalOp(op: Operator, args: Arguments) -> Result {
if (u32.view(index) >= u32.view(array.values.length)) return args.throw(V3Exception.BoundsCheck, null);
var val = array.values[index];
if (val == null) return null;
return TupleVal.!(val).values[elem];
return BoxVal.!(val).values[elem];
}
ArraySetElemElem(elem) => {
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 tval = TupleVal.!(array.values[index]);
var tval = BoxVal.!(array.values[index]);
var val = args.vals[2];
if (tval == null) {
var len = Tuple.length(V3Array.elementType(args.getTypeArg(0)));
array.values[index] = tval = TupleVal.new(Array<Val>.new(len));
array.values[index] = tval = BoxVal.new(null, Array<Val>.new(len));
}
tval.values[elem] = val;
return val;
Expand Down Expand Up @@ -629,7 +629,7 @@ def evalOp(op: Operator, args: Arguments) -> Result {
var array = args.r(0), start = args.vals[1], index = args.i(2);
if (array == null) return args.throw(V3Exception.NullCheck, null); // TODO: should not happen because prior bounds check
if (start != null) index += ArrayRangeStart.!(start).start;
var tval = TupleVal.!(array.values[index]);
var tval = BoxVal.!(array.values[index]);
if (tval == null) return null;
return tval.values[elem];
}
Expand All @@ -643,10 +643,10 @@ def evalOp(op: Operator, args: Arguments) -> Result {
var array = args.r(0), start = args.vals[1], index = args.i(2);
if (array == null) return args.throw(V3Exception.NullCheck, null); // TODO: should not happen because prior bounds check
if (start != null) index += ArrayRangeStart.!(start).start;
var tval = TupleVal.!(array.values[index]);
var tval = BoxVal.!(array.values[index]);
if (tval == null) {
var len = Tuple.length(V3Array.elementType(args.getTypeArg(0)));
array.values[index] = tval = TupleVal.new(Array<Val>.new(len));
array.values[index] = tval = BoxVal.new(null, Array<Val>.new(len));
}
return tval.values[elem] = args.vals[3]; // TODO: in-place mutation of tuple element
}
Expand Down Expand Up @@ -1056,13 +1056,13 @@ def getRecordReceiver(args: Arguments) -> Record {
// TODO: this a giant hack for adapting arguments to void calls
var r = args.vals[0];
if (Record.?(r)) return Record.!(r);
if (TupleVal.?(r)) return Record.!(TupleVal.!(r).values[0]);
if (BoxVal.?(r)) return Record.!(BoxVal.!(r).values[0]);
if (r != null) args.throw(V3Exception.InternalError, "expected record receiver for call");
return null;
}
def getReceiver(args: Arguments) -> Val {
// TODO: this a giant hack for adapting arguments to void calls
var r = args.vals[0];
if (TupleVal.?(r)) return TupleVal.!(r).values[0];
if (BoxVal.?(r)) return BoxVal.!(r).values[0];
return r;
}
15 changes: 7 additions & 8 deletions aeneas/src/core/Program.v3
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,16 @@ class Program {
VOID, BOOL, INT, FLOAT, ARRAY, COMPONENT, CLASS,
CLOSURE, FUNCREF, ANYFUNC, ENUM, ENUM_SET, POINTER, REF, RANGE, RANGE_START => return Values.BOTTOM;
VARIANT => {
if (ir.defaultRecords != null) {
var record = ir.defaultRecords[t];
if (record != null) return record;
} else {
ir.defaultRecords = TypeUtil.newTypeMap();
}
var prev = ir.getDefaultVal(t);
if (prev != null) return prev;
var ct = ClassType.!(t);
var decl = ct.classDecl;
if (decl.superclass == null) {
if (decl.cases.length > 0) t = decl.cases[0].decl.typeCon.create(t.nested);
}
var ic = ir.makeIrClass(t);
var record = newRecord(t, ic.fields.length);
ir.defaultRecords[t] = record;
ir.defaultValues[t] = record;
var typeArgs = ct.getTypeArgs();
for (i < ic.fields.length) {
var ft = ic.fields[i].fieldType;
Expand All @@ -116,8 +112,11 @@ class Program {
return record;
}
TUPLE => {
var prev = ir.getDefaultVal(t);
if (prev != null) return prev;
var at = Tuple.toTypeArray(t);
var tv = TupleVal.new(Array<Val>.new(at.length));
var tv = BoxVal.new(null, Array<Val>.new(at.length));
ir.defaultValues[t] = tv;
for (i < at.length) tv.values[i] = getDefaultValue(at[i]);
return tv;
}
Expand Down
35 changes: 35 additions & 0 deletions aeneas/src/core/Value.v3
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,38 @@ component Values {
return if(v != null, v.hash());
}
}

def UNDEFINED_HASH = -1;
def RECURSIVE_HASH = -2;
class BoxVal(t: Type, values: Array<Val>) extends Val {
private var id = UID.next++;
private var h0: int = 0;

def equals(other: Val) -> bool {
if (this == other) return true;
match (other) {
that: BoxVal => {
if (this.id == that.id) return true;
if (this.t != that.t) return false;
if (this.hash() != that.hash()) return false;
for (i < values.length) if(!Values.equal(this.values[i], that.values[i])) return false;
if (this.id < that.id) that.id = this.id;
else this.id = that.id;
return true;
}
null => return t == null && Values.deepEqualBottom(values);
_ => return false;
}
}
def hash() -> int {
if (h0 >= 0) return h0;
var nhash = if(t == null, values.length, t.hash); // initial new hash
if (h0 == RECURSIVE_HASH) return h0 = int.max & nhash; // cycle check
h0 = RECURSIVE_HASH;
for (v in values) {
nhash = nhash * 33 + Values.hash(v); // recursive hash
if (h0 >= 0) return h0; // recursive cycle detected
}
return h0 = int.max & nhash;
}
}
6 changes: 3 additions & 3 deletions aeneas/src/ic/Ic.v3
Original file line number Diff line number Diff line change
Expand Up @@ -726,13 +726,13 @@ class IcInterpreter(prog: Program, compile: IrSpec -> IcMethod) extends Argument
}
} else if (numParams == 1) {
// collapse into tuple
regs[argRp] = TupleVal.new(Arrays.range(regs, argRp, argRp + numArgs));
regs[argRp] = BoxVal.new(null, Arrays.range(regs, argRp, argRp + numArgs));
} else {
// expand tuple
var last = argRp + numArgs - 1, v = regs[last];
if (TupleVal.?(v)) {
if (BoxVal.?(v)) {
// expand tuple
var tv = TupleVal.!(v);
var tv = BoxVal.!(v);
for (i = 0; last < max; i++) {
regs[last++] = tv.values[i];
}
Expand Down
9 changes: 8 additions & 1 deletion aeneas/src/ir/Ir.v3
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ class IrModule {
def methods = Vector<IrMethod>.new();
def init = Vector<IrMethod>.new();
def roots = Vector<IrRoot>.new();
var defaultRecords: HashMap<Type, Record>;
var defaultValues: HashMap<Type, Val>;

def addRoot(name: string, meth: IrSpec) -> int {
var index = roots.length;
Expand Down Expand Up @@ -352,4 +352,11 @@ class IrModule {
def isEnum(t: Type) -> bool {
return makeIrClass(t).facts.C_ENUM;
}
def getDefaultVal(t: Type) -> Val {
if (defaultValues == null) {
defaultValues = TypeUtil.newTypeMap();
return Values.BOTTOM;
}
return defaultValues[t];
}
}
10 changes: 5 additions & 5 deletions aeneas/src/ir/Normalization.v3
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ class ReachabilityNormalizer(config: NormalizerConfig, ra: ReachabilityAnalyzer)
if (constructor == null || constructor.source != null) constructor = rc.orig.methods[0] = getClassAllocIr(vn);
var r = variantInterp.invoke(Closure.new(Values.BOTTOM, IrSpec.new(vn.oldType, TypeUtil.NO_TYPES, constructor)), inputs.extract());
match (r) {
x: TupleVal => for (i < x.values.length) result[i] = x.values[i];
x: BoxVal => for (i < x.values.length) result[i] = x.values[i];
x: Val => result[0] = x;
}
} else {
Expand All @@ -425,7 +425,7 @@ class ReachabilityNormalizer(config: NormalizerConfig, ra: ReachabilityAnalyzer)
// normalize the live instances of a mixed array type
def normMixedArrayRecord(rt: ArrayNorm, oldRecord: Record, newRecord: Record) {
def v = oldRecord.values;
for (i < v.length) newRecord.values[i] = normAsTupleVal(v[i], rt.enorm);
for (i < v.length) newRecord.values[i] = normAsBoxVal(v[i], rt.enorm);
}
// normalize the live instances of a complex (i.e. size-N element) array type
def normComplexArrayRecord(rt: ArrayNorm, oldRecord: Record, newRecords: Array<Record>) {
Expand All @@ -452,12 +452,12 @@ class ReachabilityNormalizer(config: NormalizerConfig, ra: ReachabilityAnalyzer)
_ => return v;
}
}
def normAsTupleVal(v: Val, tn: TypeNorm) -> Val {
def normAsBoxVal(v: Val, tn: TypeNorm) -> Val {
if (v == null) return v;
var values = Array<Val>.new(tn.size);
normValIntoArray(v, tn, values, 0);
if (tn.size == 1) return values[0];
return TupleVal.new(values);
return BoxVal.new(null, values);
}
def layoutVtable(rc: RaClass) {
var vtable = Vector<IrMethod>.new();
Expand Down Expand Up @@ -560,7 +560,7 @@ class ReachabilityNormalizer(config: NormalizerConfig, ra: ReachabilityAnalyzer)
array[index] = FuncVal.new(ref);
normValIntoArray(x.val, norm(ref.receiver), array, index + 1);
}
x: TupleVal => {
x: BoxVal => {
// tuple: recursively normalize all of the sub
var tnn = TupleNorm.!(tn).nested;
for (i < tnn.length) {
Expand Down
4 changes: 2 additions & 2 deletions aeneas/src/ir/Reachability.v3
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class ReachabilityAnalyzer(compilation: Compilation) {
null => ;
x: Record => queue.add(analyzeRecord, x);
x: Closure => queue.add(analyzeValue, x);
x: TupleVal => queue.add(analyzeValue, x);
x: BoxVal => queue.add(analyzeValue, x);
x: ArrayRangeVal => queue.add(analyzeRecord, x.array);
}
}
Expand All @@ -149,7 +149,7 @@ class ReachabilityAnalyzer(compilation: Compilation) {
getMethod(null, rm);
if (x.val != null) analyzeValue(x.val);
}
x: TupleVal => for(e in x.values) analyzeValue(e);
x: BoxVal => for(e in x.values) analyzeValue(e);
}
}
// analyze a record
Expand Down
4 changes: 2 additions & 2 deletions aeneas/src/mach/MachProgram.v3
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ class MachProgram extends TargetProgram {
// mixed array
var et = V3Array.elementType(r.rtype), ets = Tuple.toTypeArray(et);
for (i < v.length) {
var tv = TupleVal.!(v[i]), elemBegin = start + i * rep.elemScale + rep.headerSize;
var tv = BoxVal.!(v[i]), elemBegin = start + i * rep.elemScale + rep.headerSize;
for (j < ets.length) {
// XXX: special case Array<byte>, Array<Record>, Array<int> for performance
encodeVal(w.at(elemBegin + rep.offsets[j]), if(tv == null, null, tv.values[j]), ets[j]);
Expand Down Expand Up @@ -564,7 +564,7 @@ class MachProgram extends TargetProgram {
x: Record => addrOfRecord(x);
x: FuncVal => addrOfMethod(x.memberRef.asMethod());
x: Closure => { layoutVal(x.val); addrOfMethod(x.memberRef.asMethod()); }
x: TupleVal => for (e in x.values) layoutVal(e);
x: BoxVal => for (e in x.values) layoutVal(e);
}
}
def encodeRegion(region: Region, w: MachDataWriter) {
Expand Down
2 changes: 1 addition & 1 deletion aeneas/src/main/Version.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

// Updated by VCS scripts. DO NOT EDIT.
component Version {
def version: string = "III-7.1741";
def version: string = "III-7.1742";
var buildData: string;
}
6 changes: 3 additions & 3 deletions aeneas/src/ssa/SsaInterpreter.v3
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class SsaInterpreter(prog: Program, genSsa: (IrSpec, int) -> SsaGraph) {
_ => {
var vals = Array<Val>.new(x.inputs.length);
for (i < x.inputs.length) vals[i] = getVal(x.inputs[i].dest);
r = TupleVal.new(vals);
r = BoxVal.new(null, vals);
}
}
if (frame.prev == null) {
Expand Down Expand Up @@ -293,14 +293,14 @@ class SsaInterpreter(prog: Program, genSsa: (IrSpec, int) -> SsaGraph) {
// collapse into tuple
var vals = Array<Val>.new(args.length);
for (i < vals.length) vals[i] = args[i]; // XXX: manual array copy
setVal(params[0], TupleVal.new(vals));
setVal(params[0], BoxVal.new(null, vals));
return;
}
// Deal with fewer arguments than parameters by expanding the last tuple.
var last = args.length - 1;
setArgs0(params[0 ... last], args[0 ... last]);
match (args[last]) {
x: TupleVal => {
x: BoxVal => {
// expand tuple
for (j = last; j < params.length; j++) {
setVal(params[j], x.values[j - last]);
Expand Down
4 changes: 2 additions & 2 deletions aeneas/src/ssa/SsaOptimizer.v3
Original file line number Diff line number Diff line change
Expand Up @@ -829,14 +829,14 @@ class SsaInstrReducer(context: SsaContext) extends SsaInstrMatcher {
var inputs = i.inputs;
var vals = Array<Val>.new(inputs.length);
for (j < inputs.length) vals[j] = SsaConst.!(inputs[j].dest).val;
return graph.valConst(i.op.sig.returnType(), TupleVal.new(vals));
return graph.valConst(i.op.sig.returnType(), BoxVal.new(null, vals));
}
TupleGetElem(index) => {
var xval = unop(i);
if (xconst) {
// fold K.N
var tupleType = i.op.typeArgs[0];
var val = TupleVal.!(xval), t = Lists.get(tupleType.nested, index);
var val = BoxVal.!(xval), t = Lists.get(tupleType.nested, index);
return graph.valConst(t, if(val != null, val.values[index], null));
}
if (x.optag() == Opcode.TupleCreate.tag) {
Expand Down
12 changes: 0 additions & 12 deletions aeneas/src/types/Tuple.v3
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,3 @@ class Tuple_TypeCon extends TypeCon {
class TupleType extends Type {
new(hash: int, typeCon: TypeCon, nested: List<Type>) super(hash, typeCon, nested) { }
}
// A value representing a tuple of multiple values.
class TupleVal(values: Array<Val>) extends Val {
def equals(other: Val) -> bool {
if (other == this) return true;
if (other == null) return Values.deepEqualBottom(values);
if (!TupleVal.?(other)) return false;
return Values.deepEqual(this.values, TupleVal.!(other).values);
}
def hash() -> int {
return Arrays.hash(22, values, Values.hash);
}
}
2 changes: 1 addition & 1 deletion aeneas/src/v3/V3.v3
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ component V3 {
x: Box<long> => buf.putd(x.val);
x: Box<bool> => buf.putz(x.val);
x: Record => buf.put2("#%d:%q", x.id, x.rtype.render);
x: TupleVal => {
x: BoxVal => {
var vals = x.values;
var list: List<Type> = null;
if (vtype != null) list = vtype.nested;
Expand Down
4 changes: 2 additions & 2 deletions aeneas/test/SsaInstrReducerTest.v3
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class SsaInstrReducerTester {
def assertTK(vals: Array<Val>, i: SsaInstr) {
var j = opt1(null, i);
TEST.eq(true, SsaConst.?(j));
TEST.eq(true, Values.equal(TupleVal.new(vals), SsaConst.!(j).val));
TEST.eq(true, Values.equal(BoxVal.new(null, vals), SsaConst.!(j).val));
}
def assertBK(val: bool, i: SsaInstr) {
TEST.eq(val, SsaConst.!(opt1(null, i)).unbox<bool>());
Expand Down Expand Up @@ -212,7 +212,7 @@ class SsaInstrReducerTester {
return graph.valConst(rtype, r);
}
def tupleConst(rtype: Type, vals: Array<Val>) -> SsaConst {
var r = TupleVal.new(vals);
var r = BoxVal.new(null, vals);
return graph.valConst(rtype, r);
}
}
Expand Down
Loading

0 comments on commit 76f4080

Please sign in to comment.