Skip to content

Commit

Permalink
[gc] Add final to heap type declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer committed Sep 14, 2023
1 parent 1c05104 commit 1c9a435
Show file tree
Hide file tree
Showing 23 changed files with 173 additions and 158 deletions.
48 changes: 27 additions & 21 deletions src/engine/BinParser.v3
Original file line number Diff line number Diff line change
Expand Up @@ -861,53 +861,59 @@ class WasmParser(extensions: Extension.set, limits: Limits, module: Module,
return readByte("deftype code", BpConstants.renderDefTypeCode); // XXX: LEB not allowed here
}
def readDefSingleType(pt: int, code: byte, supertypes: Array<HeapType>) {
if (extensions.GC && code == BpDefTypeCode.SUB.code) {
var count = readU32_i("supertype count", limits.max_supertypes);
supertypes = Array<HeapType>.new(count);
for (i < count) {
var pt = decoder.pos;
var index = readU32_i("type index", u32.view(module.heaptypes.length));
supertypes[i] = toHeapType(pt, index);
}
pt = decoder.pos;
code = readDefTypeCode();
var final = 1;
if (extensions.GC) {
if (code == BpDefTypeCode.SUB.code) final = 0;
else if (code == BpDefTypeCode.SUB_FINAL.code) final = 1;
else final = 2;
if (final != 2) {
var count = readU32_i("supertype count", limits.max_supertypes);
supertypes = Array<HeapType>.new(count);
for (i < count) {
var pt = decoder.pos;
var index = readU32_i("type index", u32.view(module.heaptypes.length));
supertypes[i] = toHeapType(pt, index);
}
pt = decoder.pos;
code = readDefTypeCode();

if (subtype_list == null) subtype_list = Vector.new();
subtype_list.put(pt, module.heaptypes.length);
if (subtype_list == null) subtype_list = Vector.new();
subtype_list.put(pt, module.heaptypes.length);
}
}

match (code) {
BpDefTypeCode.Function.code => return readDefFuncType(supertypes);
BpDefTypeCode.Struct.code => if (extensions.GC) return readDefStructType(supertypes);
BpDefTypeCode.Array.code => if (extensions.GC) return readDefArrayType(supertypes);
BpDefTypeCode.Function.code => return readDefFuncType(final != 0, supertypes);
BpDefTypeCode.Struct.code => if (extensions.GC) return readDefStructType(final != 0, supertypes);
BpDefTypeCode.Array.code => if (extensions.GC) return readDefArrayType(final != 0, supertypes);
}
err.rel(decoder, pt).InvalidTypeDeclCode(code);
}
def readDefFuncType(supertypes: Array<HeapType>) {
def readDefFuncType(final: bool, supertypes: Array<HeapType>) {
var ptypes = readValueTypes("param count", limits.max_num_func_params);
if (!err.ok()) return;
var rtypes = readValueTypes("result count", limits.max_num_func_results);
if (!err.ok()) return;
var decl = SigDecl.new(supertypes, ptypes, rtypes);
var decl = SigDecl.new(final, supertypes, ptypes, rtypes);
module.addDecl(decl);
decl.recgrp_index = decl.heaptype_index - max_fw_index;
}
def readDefStructType(supertypes: Array<HeapType>) {
def readDefStructType(final: bool, supertypes: Array<HeapType>) {
var count = readU32_i("field count", limits.max_num_struct_fields);
if (!err.ok()) return;
var field_types = Array<StorageType>.new(count);
for (j < field_types.length) {
field_types[j] = readStorageType();
}
if (!err.ok()) return;
var decl = StructDecl.new(supertypes, field_types);
var decl = StructDecl.new(final, supertypes, field_types);
module.addDecl(decl);
decl.recgrp_index = decl.heaptype_index - max_fw_index;
}
def readDefArrayType(supertypes: Array<HeapType>) {
def readDefArrayType(final: bool, supertypes: Array<HeapType>) {
var elem_type = readStorageType();
if (!err.ok()) return;
var decl = ArrayDecl.new(supertypes, [elem_type]);
var decl = ArrayDecl.new(final, supertypes, [elem_type]);
module.addDecl(decl);
decl.recgrp_index = decl.heaptype_index - max_fw_index;
}
Expand Down
20 changes: 10 additions & 10 deletions src/engine/Canon.v3
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ component Canon {
return SigDecl.!(globalCache.doOne(s));
}
def sigPR(params: Array<ValueType>, results: Array<ValueType>) -> SigDecl {
return sig(SigDecl.new(ValueTypes.NO_HEAPTYPES, params, results));
return sig(SigDecl.new(true, ValueTypes.NO_HEAPTYPES, params, results));
}
}

Expand Down Expand Up @@ -133,16 +133,16 @@ class RecGroup(length: int) {
decls[cursor++] = d;
hash = hash * 33 + hashHeapTypeDecl(d);
}
def addStruct(supertypes: Array<HeapType>, fields: Array<StorageType>) -> this {
var d = decls[cursor++] = StructDecl.new(supertypes, fields);
def addStruct(final: bool, supertypes: Array<HeapType>, fields: Array<StorageType>) -> this {
var d = decls[cursor++] = StructDecl.new(final, supertypes, fields);
hash = hash * 33 + hashStructDecl(d);
}
def addArray(supertypes: Array<HeapType>, elems: Array<StorageType>) -> this {
var d = decls[cursor++] = ArrayDecl.new(supertypes, elems);
def addArray(final: bool, supertypes: Array<HeapType>, elems: Array<StorageType>) -> this {
var d = decls[cursor++] = ArrayDecl.new(final, supertypes, elems);
hash = hash * 33 + hashArrayDecl(d);
}
def addSig(supertypes: Array<HeapType>, params: Array<ValueType>, results: Array<ValueType>) -> this {
var d = decls[cursor++] = SigDecl.new(supertypes, params, results);
def addSig(final: bool, supertypes: Array<HeapType>, params: Array<ValueType>, results: Array<ValueType>) -> this {
var d = decls[cursor++] = SigDecl.new(final, supertypes, params, results);
hash = hash * 33 + hashSigDecl(d);
}

Expand Down Expand Up @@ -182,17 +182,17 @@ class RecGroup(length: int) {
match (d) {
x: StructDecl => {
if (isOpen || hasOpenStorageType(x.field_types)) {
d = StructDecl.new(ns, Arrays.dup(x.field_types));
d = StructDecl.new(x.final, ns, Arrays.dup(x.field_types));
}
}
x: ArrayDecl => {
if (isOpen || hasOpenStorageType(x.elem_types)) {
d = ArrayDecl.new(ns, Arrays.dup(x.elem_types));
d = ArrayDecl.new(x.final, ns, Arrays.dup(x.elem_types));
}
}
x: SigDecl => {
if (isOpen || hasOpenValueType(x.params) || hasOpenValueType(x.results)) {
d = SigDecl.new(ns, Arrays.dup(x.params), Arrays.dup(x.results));
d = SigDecl.new(x.final, ns, Arrays.dup(x.params), Arrays.dup(x.results));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/engine/Opcodes.v3
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ class InstrTracer {
} else if (pl == 0 && rl == 1) {
pr.1[0].render(out);
} else {
SigDecl.new(null, pr.0, pr.1).render(out);
SigDecl.new(true, null, pr.0, pr.1).render(out);
}
}
LABEL => out.put1("depth=%d", parser.readLabel());
Expand Down
2 changes: 1 addition & 1 deletion src/engine/SigCache.v3
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ component SigCache {
def is_v = S(arr_is, arr_v);

private def S(params: Array<ValueType>, results: Array<ValueType>) -> SigDecl {
var sig = SigDecl.new(ValueTypes.NO_HEAPTYPES, params, results);
var sig = SigDecl.new(true, ValueTypes.NO_HEAPTYPES, params, results);
Canon.globalCache.insert(sig);
return sig;
}
Expand Down
15 changes: 9 additions & 6 deletions src/engine/Type.v3
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ component ValueTypes {
def NONE = Array<ValueType>.new(0);
def NO_HEAPTYPES = Array<HeapType>.new(0);

// Helper utility for a final signature type with no supertypes.
def newSig = SigDecl.new(true, NO_HEAPTYPES, _, _);

// Render a value type, careful not to recurse into any type in {seen}.
def render(vt: ValueType, seen: List<Decl>, buf: StringBuilder) -> StringBuilder {
var s: string;
Expand Down Expand Up @@ -389,7 +392,7 @@ component TypeRelation {
}

// Heap type declarations.
class HeapTypeDecl(supertypes: Array<HeapType>) extends Decl {
class HeapTypeDecl(final: bool, supertypes: Array<HeapType>) extends Decl {
var hash = 0;
var heaptype_index = -1;
var canon_id = -1;
Expand Down Expand Up @@ -420,7 +423,7 @@ class StructDecl extends HeapTypeDecl {
def field_types: Array<StorageType>;
def defaultable = allHaveDefaultValues(field_types);

new(supertypes: Array<HeapType>, field_types) super(supertypes) {}
new(final: bool, supertypes: Array<HeapType>, field_types) super(final, supertypes) {}

def render(buf: StringBuilder) -> StringBuilder {
return putUid(buf.put1("struct #%d", heaptype_index));
Expand All @@ -432,7 +435,7 @@ class ArrayDecl extends HeapTypeDecl {
def elem_types: Array<StorageType>;
def defaultable = allHaveDefaultValues(elem_types);

new(supertypes: Array<HeapType>, elem_types) super(supertypes) {}
new(final: bool, supertypes: Array<HeapType>, elem_types) super(final, supertypes) {}

def render(buf: StringBuilder) -> StringBuilder {
return putUid(buf.put1("array #%d", heaptype_index));
Expand All @@ -444,12 +447,12 @@ class SigDecl extends HeapTypeDecl {
def params: Array<ValueType>;
def results: Array<ValueType>;

new(supertypes: Array<HeapType>, params, results) super(supertypes) {}
new(final: bool, supertypes: Array<HeapType>, params, results) super(final, supertypes) {}

def bindLeft(count: int) -> SigDecl {
var p = params, np = Array<ValueType>.new(p.length - count);
for (i < np.length) np[i] = p[i + count];
return SigDecl.new(ValueTypes.NO_HEAPTYPES, np, results); // TODO: bindLeft of SigDecl.supertypes
return SigDecl.new(final, ValueTypes.NO_HEAPTYPES, np, results); // TODO: bindLeft of SigDecl.supertypes
}
def isAssignableSig(that: SigDecl) -> bool {
if (that == null) return false;
Expand Down Expand Up @@ -478,7 +481,7 @@ class SigDecl extends HeapTypeDecl {
return putUid(buf);
}
def dup() -> SigDecl {
var ns = SigDecl.new(supertypes, params, results);
var ns = SigDecl.new(final, supertypes, params, results);
ns.canon_id = this.canon_id;
return ns;
}
Expand Down
2 changes: 1 addition & 1 deletion src/jawa/JawaClass.v3
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ enum JawaFieldAttr(code: u16) {
ENUM (0x2000)
}

def newSig = SigDecl.new(ValueTypes.NO_HEAPTYPES, _, _);
def newSig = ValueTypes.newSig;

// Method representation: attributes, signatures, and method declarations.
class JawaMethod(name: JawaString, attrs: JawaMethodAttr.set, sig: JawaMethodSig, var impl: Function) {
Expand Down
6 changes: 3 additions & 3 deletions src/jawa/JawaGcRuntime.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

// Implementation of the Jawa runtime using the GC extension to Wasm.
def OUT = Trace.OUT;
def newSig = SigDecl.new(ValueTypes.NO_HEAPTYPES, _, _);
def newSig = ValueTypes.newSig;

class JawaGcRuntime extends JawaRuntime {
def arrayReps = HashMap<JawaArrayType, JawaGcRuntimeArrayRep>.new(JawaRefType.hashI32, JawaArrayType.==);
Expand Down Expand Up @@ -40,7 +40,7 @@ class JawaGcRuntime extends JawaRuntime {
var pair = newStructs(at, 1, parent.vtable.length),
objStruct = pair.1, metaStruct = pair.0;

var array = ArrayDecl.new(ValueTypes.NO_HEAPTYPES, Array.new(1));
var array = ArrayDecl.new(true, ValueTypes.NO_HEAPTYPES, Array.new(1));
comodule.addDecl(array);
arrayReps[at] = gcrep = JawaGcRuntimeArrayRep.new(metaStruct, objStruct, array);

Expand Down Expand Up @@ -201,7 +201,7 @@ class JawaGcRuntime extends JawaRuntime {
return gcrep;
}
def newStruct(t: JawaRefType, field_types: Array<StorageType>) -> StructDecl {
var objStruct = StructDecl.new(ValueTypes.NO_HEAPTYPES, field_types); // TODO: supertypes
var objStruct = StructDecl.new(true, ValueTypes.NO_HEAPTYPES, field_types); // TODO: supertypes
comodule.addDecl(objStruct);
if (t != null) reftypes.set(objStruct.heaptype_index, t);
return objStruct;
Expand Down
2 changes: 1 addition & 1 deletion src/jawa/JawaHostRuntime.v3
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2020 Ben L. Titzer. All rights reserved.
// See LICENSE for details of Apache 2.0 license.

def newSig = SigDecl.new(ValueTypes.NO_HEAPTYPES, _, _);
def newSig = ValueTypes.newSig;

// Implementation of the Jawa runtime using only the host language, Virgil.
class JawaHostRuntime extends JawaRuntime {
Expand Down
4 changes: 2 additions & 2 deletions src/jawa/JawaSysFuncs.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@

// All the system functions supported by Jawa in the "SYSTEM" bytecode.
enum JawaSysFunc(sig: SigDecl, eval: Array<Value> -> HostResult) {
puts(SigDecl.new(ValueTypes.NO_HEAPTYPES, [ValueType.Host(JawaTypes.STRING)], SigCache.arr_v), eval_puts),
puts(SigDecl.new(true, ValueTypes.NO_HEAPTYPES, [ValueType.Host(JawaTypes.STRING)], SigCache.arr_v), eval_puts),
puti(SigCache.i_v, eval_puti),
millis(SigCache.v_i, eval_millis),
micros(SigCache.v_i, eval_micros),
random(SigCache.v_l, eval_random),
exp(SigCache.d_d, eval_exp),
log(SigCache.d_d, eval_log),
sqrt(SigCache.d_d, eval_sqrt),
idhash(SigDecl.new(ValueTypes.NO_HEAPTYPES, [ValueType.Host(JawaTypes.OBJECT)], SigCache.arr_i), eval_idhash)
idhash(SigDecl.new(true, ValueTypes.NO_HEAPTYPES, [ValueType.Host(JawaTypes.OBJECT)], SigCache.arr_i), eval_idhash)
}

// System functions that can be imported by code.
Expand Down
2 changes: 1 addition & 1 deletion src/modules/wasi/WspOneModule.v3
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ private enum PreopenType(code: byte) {
// Registered functions in the "wasi_snapshot_preview1" module.
def funcMap = Strings.newMap<(SigDecl, (WspOneModule, Array<Value>) -> HostResult)>(), X = init();
def init() {
def i_ = ValueType.I32, l_ = ValueType.I64, s = SigDecl.new(ValueTypes.NO_HEAPTYPES, _, _);
def i_ = ValueType.I32, l_ = ValueType.I64, s = SigDecl.new(true, ValueTypes.NO_HEAPTYPES, _, _);
def S: SigCache;
for (t in [
("args_get", S.ii_i, WspOneModule.args_get),
Expand Down
2 changes: 1 addition & 1 deletion src/modules/wizeng/WizengModule.v3
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class WizengModule extends HostModule("wizeng") {

var sig_index = 0; // TODO: get correct sig index?
var func = new_funcref(sig, sig_index, _);
var imported_sig = SigDecl.new([], SigCache.arr_ii, [rtype]);
var imported_sig = SigDecl.new(true, [], SigCache.arr_ii, [rtype]);
result[j] = HostFunctionN.new("new_funcref", imported_sig, func);
}
}
Expand Down
6 changes: 3 additions & 3 deletions test/unittest/CanonTest.v3
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ def X = [
()
];

def newSig = SigDecl.new(ValueTypes.NO_HEAPTYPES, _, _);
def newStruct = StructDecl.new(ValueTypes.NO_HEAPTYPES, _);
def newArray = ArrayDecl.new(ValueTypes.NO_HEAPTYPES, _);
def newSig = SigDecl.new(true, ValueTypes.NO_HEAPTYPES, _, _);
def newStruct = StructDecl.new(true, ValueTypes.NO_HEAPTYPES, _);
def newArray = ArrayDecl.new(true, ValueTypes.NO_HEAPTYPES, _);

class CanonTester(t: Tester) {
def assertSigId(sig: SigDecl) {
Expand Down
6 changes: 3 additions & 3 deletions test/unittest/CodeValidatorTest.v3
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def X = [
()
];

def newSig = SigDecl.new(ValueTypes.NO_HEAPTYPES, _, _);
def newSig = ValueTypes.newSig;

class CodeValidatorTester(t: Tester) extends ModuleBuilder {
def err = ErrorGen.new("CodeValidatorTest.v3");
Expand Down Expand Up @@ -1522,7 +1522,7 @@ def test_call_ref0(t: CodeValidatorTester) {
t.sig(sig);
t.TypeError(code1, 1);

t.sig(SigDecl.new(null, [ref_v_v], SigCache.arr_v));
t.sig(newSig([ref_v_v], SigCache.arr_v));
var code2: Array<byte> = [Opcode.LOCAL_GET.code, 0, Opcode.CALL_REF.code, heapIndexByte(sig)];
if (sig == sig_v_v) t.valid(code2);
else t.TypeError(code2, 3);
Expand Down Expand Up @@ -1676,7 +1676,7 @@ def test_struct_newdef(t: CodeValidatorTester) {

def test_struct_get(t: CodeValidatorTester) {
t.setExtensions(Extension.GC);
var st = StructDecl.new(ValueTypes.NO_HEAPTYPES, [unpackedT(ValueType.I32, true), unpackedT(ValueType.F32, true)]);
var st = StructDecl.new(true, ValueTypes.NO_HEAPTYPES, [unpackedT(ValueType.I32, true), unpackedT(ValueType.F32, true)]);
t.module.addDecl(st);

t.sig0([ValueTypes.RefStruct(false, st)], SigCache.arr_i);
Expand Down
10 changes: 5 additions & 5 deletions test/unittest/ExeTest.v3
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,7 @@ component TestTiers {

def NO_IMPORTS = Array<Exportable>.new(0);

def newSig = SigDecl.new(ValueTypes.NO_HEAPTYPES, _, _);
def newSig = ValueTypes.newSig;

class ExeTester(t: Tester, tiering: ExecutionStrategy) extends ModuleBuilder {
var max_call_depth = 100u;
Expand Down Expand Up @@ -1301,7 +1301,7 @@ def test_block1(i: ExeTester) {

def test_block2(i: ExeTester) {
i.extensions |= Extension.GC;
i.sig(SigDecl.new(ValueTypes.NO_HEAPTYPES, SigCache.arr_g, SigCache.arr_g));
i.sig(newSig(SigCache.arr_g, SigCache.arr_g));
i.code([Opcode.BLOCK.code, BpTypeCode.REF_NULL.code, BpTypeCode.FUNCREF.code,
Opcode.LOCAL_GET.code, 0,
Opcode.END.code]);
Expand Down Expand Up @@ -2010,7 +2010,7 @@ def test_locals4(i: ExeTester) {
def test_locals5(i: ExeTester) {
var sig_v_i = i.addSig(SigCache.v_i);
var ft = ValueType.Ref(true, HeapType.Func(sig_v_i));
i.sig(SigDecl.new(ValueTypes.NO_HEAPTYPES, SigCache.arr_g, SigCache.arr_g));
i.sig(newSig(SigCache.arr_g, SigCache.arr_g));
var l = i.addLocals(1, ft);
i.code([
Opcode.LOCAL_GET.code, byte.!(l)
Expand Down Expand Up @@ -2705,7 +2705,7 @@ def uvu(a: u32, b: Value, c: u32) -> Array<Value> {
}

def test_table_fill(i: ExeTester) {
i.sig(SigDecl.new(ValueTypes.NO_HEAPTYPES, [ValueType.I32, ValueTypes.FUNCREF, ValueType.I32], SigCache.arr_v));
i.sig(newSig([ValueType.I32, ValueTypes.FUNCREF, ValueType.I32], SigCache.arr_v));
i.addTable(6, 0, []);
i.code([
Opcode.LOCAL_GET.code, 0,
Expand Down Expand Up @@ -3304,7 +3304,7 @@ def test_abstype_default(t: ExeTester) {
var module = Module.new(null);
var abs = AbsTypeDecl.new(true, c.0 == ValueTypes.EXTERNREF, []);
var at = ValueType.Abstract(abs);
var sig = SigDecl.new(ValueTypes.NO_HEAPTYPES, SigCache.arr_v, [at]);
var sig = newSig(SigCache.arr_v, [at]);
module.addDecl(abs);
module.addImport("foo", "bar", [], abs);
module.addDecl(sig);
Expand Down
Loading

0 comments on commit 1c9a435

Please sign in to comment.