[wasm-gc] Fix br_on_null behavior in unreachable code
br_on_null should push a value on the stack, even in unreachable code. Bug: v8:9495 Change-Id: Ic227c2f889b863a267a7ff5f33e539b43e66b42f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2567966 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Cr-Commit-Position: refs/heads/master@{#71582}
This commit is contained in:
parent
818ba36e31
commit
e2f858a887
@ -2474,31 +2474,40 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
||||
Value ref_object = Pop(0);
|
||||
Control* c = control_at(imm.depth);
|
||||
TypeCheckBranchResult check_result = TypeCheckBranch(c, true);
|
||||
if (V8_LIKELY(check_result == kReachableBranch)) {
|
||||
switch (ref_object.type.kind()) {
|
||||
// For bottom and non-nullable reference, simply forward the popped
|
||||
// argument to the result.
|
||||
case ValueType::kBottom:
|
||||
UNREACHABLE(); // This can only happen in unreachable code.
|
||||
DCHECK(check_result != kReachableBranch);
|
||||
V8_FALLTHROUGH;
|
||||
case ValueType::kRef: {
|
||||
Value* result = Push(ref_object.type);
|
||||
if (V8_LIKELY(check_result == kReachableBranch)) {
|
||||
CALL_INTERFACE(PassThrough, ref_object, result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ValueType::kOptRef: {
|
||||
// We need to Push the result value after calling BrOnNull on
|
||||
// the interface. Therefore we must sync the ref_object and
|
||||
// result nodes afterwards (in PassThrough).
|
||||
if (V8_LIKELY(check_result == kReachableBranch)) {
|
||||
CALL_INTERFACE_IF_REACHABLE(BrOnNull, ref_object, imm.depth);
|
||||
}
|
||||
Value* result =
|
||||
Push(ValueType::Ref(ref_object.type.heap_type(), kNonNullable));
|
||||
if (V8_LIKELY(check_result == kReachableBranch)) {
|
||||
CALL_INTERFACE(PassThrough, ref_object, result);
|
||||
c->br_merge()->reached = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this->DecodeError("invalid argument type to br_on_null");
|
||||
this->DecodeError(
|
||||
"br_on_null[0]: Expected object reference, found %s of type %s",
|
||||
SafeOpcodeNameAt(ref_object.pc()), ref_object.type.name().c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1 + imm.length;
|
||||
}
|
||||
|
||||
|
@ -1096,7 +1096,6 @@ TEST_F(FunctionBodyDecoderTest, UnreachableRefTypes) {
|
||||
FunctionSig sig_v_s(0, 1, &struct_type);
|
||||
byte struct_consumer = builder.AddFunction(&sig_v_s);
|
||||
|
||||
ExpectValidates(sigs.v_v(), {WASM_BLOCK(WASM_UNREACHABLE, kExprBrOnNull, 0)});
|
||||
ExpectValidates(sigs.i_v(), {WASM_UNREACHABLE, kExprRefIsNull});
|
||||
ExpectValidates(sigs.v_v(), {WASM_UNREACHABLE, kExprRefAsNonNull, kExprDrop});
|
||||
|
||||
@ -1153,6 +1152,22 @@ TEST_F(FunctionBodyDecoderTest, UnreachableRefTypes) {
|
||||
ExpectValidates(sigs.v_v(),
|
||||
{WASM_UNREACHABLE, WASM_GC_OP(kExprRttSub), array_index,
|
||||
WASM_GC_OP(kExprRttSub), array_index, kExprDrop});
|
||||
|
||||
ExpectValidates(sigs.v_v(), {WASM_UNREACHABLE, kExprBrOnNull, 0, WASM_DROP});
|
||||
|
||||
ExpectValidates(&sig_v_s, {WASM_UNREACHABLE, WASM_GET_LOCAL(0), kExprBrOnNull,
|
||||
0, kExprCallFunction, struct_consumer});
|
||||
|
||||
ValueType opt_struct_type = ValueType::Ref(struct_index, kNullable);
|
||||
FunctionSig sig_v_os(0, 1, &opt_struct_type);
|
||||
ExpectValidates(&sig_v_os,
|
||||
{WASM_UNREACHABLE, WASM_GET_LOCAL(0), kExprBrOnNull, 0,
|
||||
kExprCallFunction, struct_consumer});
|
||||
|
||||
ExpectFailure(
|
||||
sigs.v_v(), {WASM_UNREACHABLE, WASM_I32V(42), kExprBrOnNull, 0},
|
||||
kAppendEnd,
|
||||
"br_on_null[0]: Expected object reference, found i32.const of type i32");
|
||||
}
|
||||
|
||||
TEST_F(FunctionBodyDecoderTest, If1) {
|
||||
|
Loading…
Reference in New Issue
Block a user