[wasm-gc] ref.cast null: Always produces a null type independent of input type
This is required to be spec-compliant. The previously implemented behavior was more relaxed allowing one to use `ref.cast null` on non-nullable inputs and still getting a non-nullable result on cast success. Bug: v8:7748 Change-Id: I1297314389b0445a7c8d5a74f37d07a723d7a133 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4091549 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Matthias Liedtke <mliedtke@chromium.org> Cr-Commit-Position: refs/heads/main@{#84776}
This commit is contained in:
parent
d310532598
commit
1bf670ef20
@ -4898,9 +4898,7 @@ class WasmFullDecoder : public WasmDecoder<ValidationTag, decoding_mode> {
|
||||
|
||||
bool null_succeeds = opcode == kExprRefCastNull;
|
||||
Value value = CreateValue(ValueType::RefMaybeNull(
|
||||
imm.type, (obj.type.is_bottom() || !null_succeeds)
|
||||
? kNonNullable
|
||||
: obj.type.nullability()));
|
||||
target_type, null_succeeds ? kNullable : kNonNullable));
|
||||
if (current_code_reachable_and_ok_) {
|
||||
// This logic ensures that code generation can assume that functions
|
||||
// can only be cast to function types, and data objects to data types.
|
||||
|
61
test/mjsunit/wasm/gc-cast-type-inference.js
Normal file
61
test/mjsunit/wasm/gc-cast-type-inference.js
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-gc --no-wasm-gc-structref-as-dataref
|
||||
|
||||
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
(function TestRefCastNullReturnsNullTypeForNonNullInput() {
|
||||
print(arguments.callee.name);
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
let consumeRefI31 =
|
||||
builder.addFunction(`consumeRefI31`,
|
||||
makeSig([wasmRefType(kWasmI31Ref)], []))
|
||||
.addBody([]);
|
||||
|
||||
builder.addFunction(`refCastRemovesNullability`,
|
||||
makeSig([kWasmExternRef], []))
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
kGCPrefix, kExprExternInternalize,
|
||||
kExprRefAsNonNull,
|
||||
kGCPrefix, kExprRefCastNull, kI31RefCode,
|
||||
// ref.cast null pushes a nullable value on the stack even though its input
|
||||
// was non-nullable, therefore this call is not spec-compliant.
|
||||
kExprCallFunction, consumeRefI31.index,
|
||||
]).exportFunc();
|
||||
|
||||
assertThrows(() => builder.instantiate(), WebAssembly.CompileError,
|
||||
/expected type \(ref i31\), found .* type i31ref/);
|
||||
})();
|
||||
|
||||
(function TestRefCastRemovesNullability() {
|
||||
print(arguments.callee.name);
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
let i31ToI32 =
|
||||
builder.addFunction(`i31ToI32`,
|
||||
makeSig([wasmRefType(kWasmI31Ref)], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
kGCPrefix, kExprI31GetS
|
||||
]);
|
||||
|
||||
builder.addFunction(`refCastRemovesNullability`,
|
||||
makeSig([kWasmExternRef], [kWasmI32]))
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
kGCPrefix, kExprExternInternalize,
|
||||
kGCPrefix, kExprRefCast, kI31RefCode,
|
||||
// ref.cast pushes a non-nullable value on the stack even for a nullable
|
||||
// input value as the instruction traps on null.
|
||||
kExprCallFunction, i31ToI32.index,
|
||||
]).exportFunc();
|
||||
|
||||
let wasm = builder.instantiate().exports;
|
||||
assertEquals(42, wasm.refCastRemovesNullability(42));
|
||||
assertEquals(-1, wasm.refCastRemovesNullability(-1));
|
||||
assertTraps(kTrapIllegalCast, () => wasm.refCastRemovesNullability(null));
|
||||
})();
|
Loading…
Reference in New Issue
Block a user