Skip to content

Commit 57bef0d

Browse files
authored
Add ref.cast_nop_static (#4656)
This unsafe experimental instruction is semantically equivalent to ref.cast_static, but V8 will unsafely turn it into a nop. This is meant to help us measure cast overhead more precisely than we can by globally turning all casts into nops.
1 parent bad3f9e commit 57bef0d

File tree

11 files changed

+63
-9
lines changed

11 files changed

+63
-9
lines changed

scripts/gen-s-parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@
573573
("ref.test_static", "makeRefTestStatic(s)"),
574574
("ref.cast", "makeRefCast(s)"),
575575
("ref.cast_static", "makeRefCastStatic(s)"),
576+
("ref.cast_nop_static", "makeRefCastNopStatic(s)"),
576577
("br_on_null", "makeBrOn(s, BrOnNull)"),
577578
("br_on_non_null", "makeBrOn(s, BrOnNonNull)"),
578579
("br_on_cast", "makeBrOn(s, BrOnCast)"),

src/gen-s-parser.inc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3027,9 +3027,17 @@ switch (op[0]) {
30273027
case '\0':
30283028
if (strcmp(op, "ref.cast") == 0) { return makeRefCast(s); }
30293029
goto parse_error;
3030-
case '_':
3031-
if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); }
3032-
goto parse_error;
3030+
case '_': {
3031+
switch (op[9]) {
3032+
case 'n':
3033+
if (strcmp(op, "ref.cast_nop_static") == 0) { return makeRefCastNopStatic(s); }
3034+
goto parse_error;
3035+
case 's':
3036+
if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); }
3037+
goto parse_error;
3038+
default: goto parse_error;
3039+
}
3040+
}
30333041
default: goto parse_error;
30343042
}
30353043
}

src/passes/Print.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,11 @@ struct PrintExpressionContents
19841984
if (curr->rtt) {
19851985
printMedium(o, "ref.cast");
19861986
} else {
1987-
printMedium(o, "ref.cast_static ");
1987+
if (curr->safety == RefCast::Unsafe) {
1988+
printMedium(o, "ref.cast_nop_static ");
1989+
} else {
1990+
printMedium(o, "ref.cast_static ");
1991+
}
19881992
printHeapType(o, curr->intendedType, wasm);
19891993
}
19901994
}

src/wasm-binary.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,7 @@ enum ASTNodes {
11121112
RefCastStatic = 0x45,
11131113
BrOnCastStatic = 0x46,
11141114
BrOnCastStaticFail = 0x47,
1115+
RefCastNopStatic = 0x48,
11151116
RefIsFunc = 0x50,
11161117
RefIsData = 0x51,
11171118
RefIsI31 = 0x52,

src/wasm-builder.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,10 +810,13 @@ class Builder {
810810
ret->finalize();
811811
return ret;
812812
}
813-
RefCast* makeRefCast(Expression* ref, HeapType intendedType) {
813+
814+
RefCast*
815+
makeRefCast(Expression* ref, HeapType intendedType, RefCast::Safety safety) {
814816
auto* ret = wasm.allocator.alloc<RefCast>();
815817
ret->ref = ref;
816818
ret->intendedType = intendedType;
819+
ret->safety = safety;
817820
ret->finalize();
818821
return ret;
819822
}

src/wasm-s-parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ class SExpressionWasmBuilder {
282282
Expression* makeRefTestStatic(Element& s);
283283
Expression* makeRefCast(Element& s);
284284
Expression* makeRefCastStatic(Element& s);
285+
Expression* makeRefCastNopStatic(Element& s);
285286
Expression* makeBrOn(Element& s, BrOnOp op);
286287
Expression* makeBrOnStatic(Element& s, BrOnOp op);
287288
Expression* makeRttCanon(Element& s);

src/wasm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,11 @@ class RefCast : public SpecificExpression<Expression::RefCastId> {
14571457
Expression* rtt = nullptr;
14581458
HeapType intendedType;
14591459

1460+
// Support the unsafe `ref.cast_nop_static` to enable precise cast overhead
1461+
// measurements.
1462+
enum Safety { Safe, Unsafe };
1463+
Safety safety;
1464+
14601465
void finalize();
14611466

14621467
// Returns the type we intend to cast to.

src/wasm/wasm-binary.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6712,10 +6712,13 @@ bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) {
67126712
auto* ref = popNonVoidExpression();
67136713
out = Builder(wasm).makeRefCast(ref, rtt);
67146714
return true;
6715-
} else if (code == BinaryConsts::RefCastStatic) {
6715+
} else if (code == BinaryConsts::RefCastStatic ||
6716+
code == BinaryConsts::RefCastNopStatic) {
67166717
auto intendedType = getIndexedHeapType();
67176718
auto* ref = popNonVoidExpression();
6718-
out = Builder(wasm).makeRefCast(ref, intendedType);
6719+
auto safety =
6720+
code == BinaryConsts::RefCastNopStatic ? RefCast::Unsafe : RefCast::Safe;
6721+
out = Builder(wasm).makeRefCast(ref, intendedType, safety);
67196722
return true;
67206723
}
67216724
return false;

src/wasm/wasm-s-parser.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2702,7 +2702,13 @@ Expression* SExpressionWasmBuilder::makeRefCast(Element& s) {
27022702
Expression* SExpressionWasmBuilder::makeRefCastStatic(Element& s) {
27032703
auto heapType = parseHeapType(*s[1]);
27042704
auto* ref = parseExpression(*s[2]);
2705-
return Builder(wasm).makeRefCast(ref, heapType);
2705+
return Builder(wasm).makeRefCast(ref, heapType, RefCast::Safe);
2706+
}
2707+
2708+
Expression* SExpressionWasmBuilder::makeRefCastNopStatic(Element& s) {
2709+
auto heapType = parseHeapType(*s[1]);
2710+
auto* ref = parseExpression(*s[2]);
2711+
return Builder(wasm).makeRefCast(ref, heapType, RefCast::Unsafe);
27062712
}
27072713

27082714
Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) {

src/wasm/wasm-stack.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2051,7 +2051,11 @@ void BinaryInstWriter::visitRefCast(RefCast* curr) {
20512051
if (curr->rtt) {
20522052
o << U32LEB(BinaryConsts::RefCast);
20532053
} else {
2054-
o << U32LEB(BinaryConsts::RefCastStatic);
2054+
if (curr->safety == RefCast::Unsafe) {
2055+
o << U32LEB(BinaryConsts::RefCastNopStatic);
2056+
} else {
2057+
o << U32LEB(BinaryConsts::RefCastStatic);
2058+
}
20552059
parent.writeIndexedHeapType(curr->intendedType);
20562060
}
20572061
}

0 commit comments

Comments
 (0)