2020-04-21 16:45:53 +00:00
|
|
|
// Copyright 2020 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.
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
2021-06-17 15:43:55 +00:00
|
|
|
#include "src/base/vector.h"
|
2022-04-06 17:24:34 +00:00
|
|
|
#include "src/codegen/signature.h"
|
2020-04-21 16:45:53 +00:00
|
|
|
#include "src/utils/utils.h"
|
|
|
|
#include "src/wasm/module-decoder.h"
|
|
|
|
#include "src/wasm/struct-types.h"
|
2020-07-07 19:14:38 +00:00
|
|
|
#include "src/wasm/wasm-arguments.h"
|
2020-04-21 16:45:53 +00:00
|
|
|
#include "src/wasm/wasm-engine.h"
|
|
|
|
#include "src/wasm/wasm-module-builder.h"
|
|
|
|
#include "src/wasm/wasm-module.h"
|
|
|
|
#include "src/wasm/wasm-objects-inl.h"
|
|
|
|
#include "src/wasm/wasm-opcodes.h"
|
|
|
|
#include "test/cctest/cctest.h"
|
|
|
|
#include "test/cctest/compiler/value-helper.h"
|
|
|
|
#include "test/cctest/wasm/wasm-run-utils.h"
|
|
|
|
#include "test/common/wasm/test-signatures.h"
|
|
|
|
#include "test/common/wasm/wasm-macro-gen.h"
|
|
|
|
#include "test/common/wasm/wasm-module-runner.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace wasm {
|
|
|
|
namespace test_gc {
|
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
using F = std::pair<ValueType, bool>;
|
|
|
|
|
|
|
|
class WasmGCTester {
|
|
|
|
public:
|
2020-12-15 12:22:59 +00:00
|
|
|
explicit WasmGCTester(
|
|
|
|
TestExecutionTier execution_tier = TestExecutionTier::kTurbofan)
|
2020-06-03 14:37:37 +00:00
|
|
|
: flag_gc(&v8::internal::FLAG_experimental_wasm_gc, true),
|
|
|
|
flag_typedfuns(&v8::internal::FLAG_experimental_wasm_typed_funcref,
|
|
|
|
true),
|
2021-10-06 13:09:57 +00:00
|
|
|
flag_liftoff(&v8::internal::FLAG_liftoff,
|
|
|
|
execution_tier == TestExecutionTier::kLiftoff),
|
|
|
|
flag_liftoff_only(&v8::internal::FLAG_liftoff_only,
|
|
|
|
execution_tier == TestExecutionTier::kLiftoff),
|
2022-04-11 08:04:06 +00:00
|
|
|
flag_wasm_dynamic_tiering(&v8::internal::FLAG_wasm_dynamic_tiering,
|
|
|
|
v8::internal::FLAG_liftoff_only != true),
|
2022-04-01 13:01:52 +00:00
|
|
|
// Test both setups with canonicalization and without.
|
|
|
|
flag_canonicalization(&v8::internal::FLAG_wasm_type_canonicalization,
|
|
|
|
execution_tier == TestExecutionTier::kTurbofan),
|
2020-12-16 22:29:12 +00:00
|
|
|
flag_tierup(&v8::internal::FLAG_wasm_tier_up, false),
|
2021-04-13 05:40:00 +00:00
|
|
|
zone_(&allocator, ZONE_NAME),
|
|
|
|
builder_(&zone_),
|
2020-06-30 11:17:53 +00:00
|
|
|
isolate_(CcTest::InitIsolateOnce()),
|
|
|
|
scope(isolate_),
|
|
|
|
thrower(isolate_, "Test wasm GC") {
|
|
|
|
testing::SetupIsolateForWasmModule(isolate_);
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
byte AddGlobal(ValueType type, bool mutability, WasmInitExpr init) {
|
2021-11-05 06:10:04 +00:00
|
|
|
return builder_.AddGlobal(type, mutability, init);
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
byte DefineFunction(FunctionSig* sig, std::initializer_list<ValueType> locals,
|
|
|
|
std::initializer_list<byte> code) {
|
2022-01-27 16:24:31 +00:00
|
|
|
return DefineFunctionImpl(builder_.AddFunction(sig), locals, code);
|
|
|
|
}
|
|
|
|
|
|
|
|
byte DefineFunction(uint32_t sig_index,
|
|
|
|
std::initializer_list<ValueType> locals,
|
|
|
|
std::initializer_list<byte> code) {
|
|
|
|
return DefineFunctionImpl(builder_.AddFunction(sig_index), locals, code);
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2020-08-03 18:16:25 +00:00
|
|
|
void DefineExportedFunction(const char* name, FunctionSig* sig,
|
|
|
|
std::initializer_list<byte> code) {
|
|
|
|
WasmFunctionBuilder* fun = builder_.AddFunction(sig);
|
|
|
|
fun->EmitCode(code.begin(), static_cast<uint32_t>(code.size()));
|
2021-06-17 15:43:55 +00:00
|
|
|
builder_.AddExport(base::CStrVector(name), fun);
|
2020-08-03 18:16:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MaybeHandle<Object> CallExportedFunction(const char* name, int argc,
|
|
|
|
Handle<Object> args[]) {
|
|
|
|
Handle<WasmExportedFunction> func =
|
|
|
|
testing::GetExportedFunction(isolate_, instance_, name)
|
|
|
|
.ToHandleChecked();
|
|
|
|
return Execution::Call(isolate_, func,
|
|
|
|
isolate_->factory()->undefined_value(), argc, args);
|
|
|
|
}
|
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
byte DefineStruct(std::initializer_list<F> fields,
|
|
|
|
uint32_t supertype = kNoSuperType) {
|
2021-04-13 05:40:00 +00:00
|
|
|
StructType::Builder type_builder(&zone_,
|
2020-06-03 14:37:37 +00:00
|
|
|
static_cast<uint32_t>(fields.size()));
|
|
|
|
for (F field : fields) {
|
|
|
|
type_builder.AddField(field.first, field.second);
|
|
|
|
}
|
2021-09-15 12:59:42 +00:00
|
|
|
return builder_.AddStructType(type_builder.Build(), supertype);
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
byte DefineArray(ValueType element_type, bool mutability,
|
|
|
|
uint32_t supertype = kNoSuperType) {
|
|
|
|
return builder_.AddArrayType(zone_.New<ArrayType>(element_type, mutability),
|
|
|
|
supertype);
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 16:24:31 +00:00
|
|
|
byte DefineSignature(FunctionSig* sig, uint32_t supertype = kNoSuperType) {
|
|
|
|
return builder_.AddSignature(sig, supertype);
|
|
|
|
}
|
2020-08-05 11:12:29 +00:00
|
|
|
|
2020-10-02 05:31:50 +00:00
|
|
|
byte DefineTable(ValueType type, uint32_t min_size, uint32_t max_size) {
|
|
|
|
return builder_.AddTable(type, min_size, max_size);
|
|
|
|
}
|
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
void CompileModule() {
|
2021-04-13 05:40:00 +00:00
|
|
|
ZoneBuffer buffer(&zone_);
|
2020-07-07 19:14:38 +00:00
|
|
|
builder_.WriteTo(&buffer);
|
2020-06-03 14:37:37 +00:00
|
|
|
MaybeHandle<WasmInstanceObject> maybe_instance =
|
|
|
|
testing::CompileAndInstantiateForTesting(
|
2020-06-30 11:17:53 +00:00
|
|
|
isolate_, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
|
2020-06-03 14:37:37 +00:00
|
|
|
if (thrower.error()) FATAL("%s", thrower.error_msg());
|
2020-06-23 14:18:46 +00:00
|
|
|
instance_ = maybe_instance.ToHandleChecked();
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
void CheckResult(uint32_t function_index, int32_t expected) {
|
2021-05-27 14:52:38 +00:00
|
|
|
const FunctionSig* sig = sigs.i_v();
|
2020-07-07 19:14:38 +00:00
|
|
|
DCHECK(*sig == *instance_->module()->functions[function_index].sig);
|
|
|
|
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
|
2021-05-27 14:52:38 +00:00
|
|
|
CheckResultImpl(function_index, sig, &packer, expected);
|
2020-07-07 19:14:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CheckResult(uint32_t function_index, int32_t expected, int32_t arg) {
|
2021-05-27 14:52:38 +00:00
|
|
|
const FunctionSig* sig = sigs.i_i();
|
2020-07-07 19:14:38 +00:00
|
|
|
DCHECK(*sig == *instance_->module()->functions[function_index].sig);
|
|
|
|
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
|
|
|
|
packer.Push(arg);
|
2021-05-27 14:52:38 +00:00
|
|
|
CheckResultImpl(function_index, sig, &packer, expected);
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
MaybeHandle<Object> GetResultObject(uint32_t function_index) {
|
|
|
|
const FunctionSig* sig = instance_->module()->functions[function_index].sig;
|
2021-05-27 14:52:38 +00:00
|
|
|
DCHECK_EQ(sig->parameter_count(), 0);
|
|
|
|
DCHECK_EQ(sig->return_count(), 1);
|
2020-07-07 19:14:38 +00:00
|
|
|
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
|
|
|
|
CallFunctionImpl(function_index, sig, &packer);
|
2020-11-12 22:30:45 +00:00
|
|
|
CHECK(!isolate_->has_pending_exception());
|
2020-07-07 19:14:38 +00:00
|
|
|
packer.Reset();
|
|
|
|
return Handle<Object>(Object(packer.Pop<Address>()), isolate_);
|
|
|
|
}
|
|
|
|
|
2021-05-26 15:47:27 +00:00
|
|
|
MaybeHandle<Object> GetResultObject(uint32_t function_index, int32_t arg) {
|
|
|
|
const FunctionSig* sig = instance_->module()->functions[function_index].sig;
|
|
|
|
DCHECK_EQ(sig->parameter_count(), 1);
|
2021-05-27 14:52:38 +00:00
|
|
|
DCHECK_EQ(sig->return_count(), 1);
|
2021-05-26 15:47:27 +00:00
|
|
|
DCHECK(sig->parameters()[0] == kWasmI32);
|
|
|
|
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
|
|
|
|
packer.Push(arg);
|
|
|
|
CallFunctionImpl(function_index, sig, &packer);
|
|
|
|
CHECK(!isolate_->has_pending_exception());
|
|
|
|
packer.Reset();
|
|
|
|
return Handle<Object>(Object(packer.Pop<Address>()), isolate_);
|
|
|
|
}
|
|
|
|
|
2021-05-27 14:52:38 +00:00
|
|
|
void CheckHasThrown(uint32_t function_index, const char* expected = "") {
|
2020-11-12 22:30:45 +00:00
|
|
|
const FunctionSig* sig = instance_->module()->functions[function_index].sig;
|
2021-05-27 14:52:38 +00:00
|
|
|
DCHECK_EQ(sig->parameter_count(), 0);
|
2020-11-12 22:30:45 +00:00
|
|
|
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
|
2021-05-27 14:52:38 +00:00
|
|
|
CheckHasThrownImpl(function_index, sig, &packer, expected);
|
2020-11-12 22:30:45 +00:00
|
|
|
}
|
|
|
|
|
2021-05-27 14:52:38 +00:00
|
|
|
void CheckHasThrown(uint32_t function_index, int32_t arg,
|
|
|
|
const char* expected = "") {
|
|
|
|
const FunctionSig* sig = instance_->module()->functions[function_index].sig;
|
|
|
|
DCHECK_EQ(sig->parameter_count(), 1);
|
|
|
|
DCHECK(sig->parameters()[0] == kWasmI32);
|
2020-07-07 19:14:38 +00:00
|
|
|
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
|
|
|
|
packer.Push(arg);
|
2021-05-27 14:52:38 +00:00
|
|
|
CheckHasThrownImpl(function_index, sig, &packer, expected);
|
2020-06-03 14:37:37 +00:00
|
|
|
}
|
|
|
|
|
2022-04-05 16:02:13 +00:00
|
|
|
bool HasSimdSupport(TestExecutionTier tier) const {
|
|
|
|
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
|
|
|
|
// Liftoff does not have a fallback for executing SIMD instructions if
|
|
|
|
// SSE4_1 is not available.
|
|
|
|
if (tier == TestExecutionTier::kLiftoff &&
|
|
|
|
!CpuFeatures::IsSupported(SSE4_1)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
USE(tier);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-23 14:18:46 +00:00
|
|
|
Handle<WasmInstanceObject> instance() { return instance_; }
|
2020-06-30 11:17:53 +00:00
|
|
|
Isolate* isolate() { return isolate_; }
|
2020-07-07 19:14:38 +00:00
|
|
|
WasmModuleBuilder* builder() { return &builder_; }
|
2021-04-13 05:40:00 +00:00
|
|
|
Zone* zone() { return &zone_; }
|
2020-06-23 14:18:46 +00:00
|
|
|
|
2020-04-21 16:45:53 +00:00
|
|
|
TestSignatures sigs;
|
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
private:
|
|
|
|
const FlagScope<bool> flag_gc;
|
|
|
|
const FlagScope<bool> flag_typedfuns;
|
2020-12-15 12:22:59 +00:00
|
|
|
const FlagScope<bool> flag_liftoff;
|
|
|
|
const FlagScope<bool> flag_liftoff_only;
|
2022-04-11 08:04:06 +00:00
|
|
|
const FlagScope<bool> flag_wasm_dynamic_tiering;
|
2022-04-01 13:01:52 +00:00
|
|
|
const FlagScope<bool> flag_canonicalization;
|
2020-12-16 22:29:12 +00:00
|
|
|
const FlagScope<bool> flag_tierup;
|
2020-06-03 14:37:37 +00:00
|
|
|
|
2022-01-27 16:24:31 +00:00
|
|
|
byte DefineFunctionImpl(WasmFunctionBuilder* fun,
|
|
|
|
std::initializer_list<ValueType> locals,
|
|
|
|
std::initializer_list<byte> code) {
|
|
|
|
for (ValueType local : locals) {
|
|
|
|
fun->AddLocal(local);
|
|
|
|
}
|
|
|
|
fun->EmitCode(code.begin(), static_cast<uint32_t>(code.size()));
|
|
|
|
return fun->func_index();
|
|
|
|
}
|
|
|
|
|
2021-05-27 14:52:38 +00:00
|
|
|
void CheckResultImpl(uint32_t function_index, const FunctionSig* sig,
|
|
|
|
CWasmArgumentsPacker* packer, int32_t expected) {
|
|
|
|
CallFunctionImpl(function_index, sig, packer);
|
|
|
|
if (isolate_->has_pending_exception()) {
|
|
|
|
Handle<String> message =
|
|
|
|
ErrorUtils::ToString(isolate_,
|
|
|
|
handle(isolate_->pending_exception(), isolate_))
|
|
|
|
.ToHandleChecked();
|
|
|
|
FATAL("%s", message->ToCString().get());
|
|
|
|
}
|
|
|
|
packer->Reset();
|
|
|
|
CHECK_EQ(expected, packer->Pop<int32_t>());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckHasThrownImpl(uint32_t function_index, const FunctionSig* sig,
|
|
|
|
CWasmArgumentsPacker* packer, const char* expected) {
|
|
|
|
CallFunctionImpl(function_index, sig, packer);
|
|
|
|
CHECK(isolate_->has_pending_exception());
|
|
|
|
Handle<String> message =
|
|
|
|
ErrorUtils::ToString(isolate_,
|
|
|
|
handle(isolate_->pending_exception(), isolate_))
|
|
|
|
.ToHandleChecked();
|
|
|
|
std::string message_str(message->ToCString().get());
|
|
|
|
CHECK_NE(message_str.find(expected), std::string::npos);
|
|
|
|
isolate_->clear_pending_exception();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CallFunctionImpl(uint32_t function_index, const FunctionSig* sig,
|
|
|
|
CWasmArgumentsPacker* packer) {
|
2021-09-24 21:51:13 +00:00
|
|
|
WasmCodeRefScope code_ref_scope;
|
2021-05-27 14:52:38 +00:00
|
|
|
NativeModule* native_module = instance_->module_object().native_module();
|
|
|
|
WasmCode* code = native_module->GetCode(function_index);
|
|
|
|
Address wasm_call_target = code->instruction_start();
|
|
|
|
Handle<Object> object_ref = instance_;
|
2021-06-17 22:10:06 +00:00
|
|
|
Handle<CodeT> c_wasm_entry =
|
2021-05-27 14:52:38 +00:00
|
|
|
compiler::CompileCWasmEntry(isolate_, sig, native_module->module());
|
|
|
|
Execution::CallWasm(isolate_, c_wasm_entry, wasm_call_target, object_ref,
|
|
|
|
packer->argv());
|
|
|
|
}
|
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
v8::internal::AccountingAllocator allocator;
|
2021-04-13 05:40:00 +00:00
|
|
|
Zone zone_;
|
2020-07-07 19:14:38 +00:00
|
|
|
WasmModuleBuilder builder_;
|
2020-06-03 14:37:37 +00:00
|
|
|
|
2020-06-30 11:17:53 +00:00
|
|
|
Isolate* const isolate_;
|
2020-06-03 14:37:37 +00:00
|
|
|
const HandleScope scope;
|
2020-06-23 14:18:46 +00:00
|
|
|
Handle<WasmInstanceObject> instance_;
|
2020-06-03 14:37:37 +00:00
|
|
|
ErrorThrower thrower;
|
|
|
|
};
|
|
|
|
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
ValueType ref(uint32_t type_index) {
|
2020-06-29 09:24:51 +00:00
|
|
|
return ValueType::Ref(type_index, kNonNullable);
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
}
|
|
|
|
ValueType optref(uint32_t type_index) {
|
2020-06-29 09:24:51 +00:00
|
|
|
return ValueType::Ref(type_index, kNullable);
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
}
|
|
|
|
|
2020-12-15 12:22:59 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmBasicStruct) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
|
2022-01-18 09:19:18 +00:00
|
|
|
const byte type_index =
|
2020-06-03 14:37:37 +00:00
|
|
|
tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
|
2022-01-18 09:19:18 +00:00
|
|
|
const byte empty_struct_index = tester.DefineStruct({});
|
|
|
|
ValueType kRefType = ref(type_index);
|
|
|
|
ValueType kEmptyStructType = ref(empty_struct_index);
|
|
|
|
ValueType kOptRefType = optref(type_index);
|
|
|
|
FunctionSig sig_q_v(1, 0, &kRefType);
|
|
|
|
FunctionSig sig_qe_v(1, 0, &kEmptyStructType);
|
2020-04-21 16:45:53 +00:00
|
|
|
|
2020-05-08 10:47:50 +00:00
|
|
|
// Test struct.new and struct.get.
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kGet1 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {},
|
2020-06-03 14:37:37 +00:00
|
|
|
{WASM_STRUCT_GET(
|
2022-01-18 09:19:18 +00:00
|
|
|
type_index, 0,
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
2020-04-21 16:45:53 +00:00
|
|
|
|
2020-05-08 10:47:50 +00:00
|
|
|
// Test struct.new and struct.get.
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kGet2 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {},
|
2020-06-03 14:37:37 +00:00
|
|
|
{WASM_STRUCT_GET(
|
2022-01-18 09:19:18 +00:00
|
|
|
type_index, 1,
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
2020-04-21 16:45:53 +00:00
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
// Test struct.new, returning struct reference.
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kGetStruct = tester.DefineFunction(
|
2022-01-18 09:19:18 +00:00
|
|
|
&sig_q_v, {},
|
|
|
|
{WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
2020-07-21 09:03:20 +00:00
|
|
|
kExprEnd});
|
2020-04-21 16:45:53 +00:00
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
const byte kGetStructNominal = tester.DefineFunction(
|
2022-01-18 09:19:18 +00:00
|
|
|
&sig_q_v, {},
|
|
|
|
{WASM_STRUCT_NEW_DEFAULT(type_index), WASM_DROP,
|
|
|
|
WASM_STRUCT_NEW(type_index, WASM_I32V(42), WASM_I32V(64)), kExprEnd});
|
2021-09-15 12:59:42 +00:00
|
|
|
|
2020-09-21 13:51:42 +00:00
|
|
|
// Test struct.new, returning reference to an empty struct.
|
|
|
|
const byte kGetEmptyStruct = tester.DefineFunction(
|
2022-01-18 09:19:18 +00:00
|
|
|
&sig_qe_v, {},
|
|
|
|
{WASM_STRUCT_NEW_WITH_RTT(empty_struct_index,
|
|
|
|
WASM_RTT_CANON(empty_struct_index)),
|
2020-09-21 13:51:42 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
2020-05-08 10:47:50 +00:00
|
|
|
// Test struct.set, struct refs types in locals.
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte j_local_index = 0;
|
|
|
|
const byte j_field_index = 0;
|
|
|
|
const byte kSet = tester.DefineFunction(
|
2022-01-18 09:19:18 +00:00
|
|
|
tester.sigs.i_v(), {kOptRefType},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(
|
2020-07-21 09:03:20 +00:00
|
|
|
j_local_index,
|
2022-01-18 09:19:18 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(64),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
WASM_STRUCT_SET(type_index, j_field_index, WASM_LOCAL_GET(j_local_index),
|
|
|
|
WASM_I32V(-99)),
|
|
|
|
WASM_STRUCT_GET(type_index, j_field_index,
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(j_local_index)),
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
2020-05-08 10:47:50 +00:00
|
|
|
|
2020-06-19 03:50:30 +00:00
|
|
|
tester.CompileModule();
|
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kGet1, 42);
|
|
|
|
tester.CheckResult(kGet2, 64);
|
|
|
|
CHECK(tester.GetResultObject(kGetStruct).ToHandleChecked()->IsWasmStruct());
|
2021-09-15 12:59:42 +00:00
|
|
|
CHECK(tester.GetResultObject(kGetStructNominal)
|
|
|
|
.ToHandleChecked()
|
|
|
|
->IsWasmStruct());
|
2020-09-21 13:51:42 +00:00
|
|
|
CHECK(tester.GetResultObject(kGetEmptyStruct)
|
|
|
|
.ToHandleChecked()
|
|
|
|
->IsWasmStruct());
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kSet, -99);
|
2020-06-19 03:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 14:26:52 +00:00
|
|
|
// Test struct.get, ref.as_non_null and ref-typed globals.
|
2020-12-15 19:49:59 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmRefAsNonNull) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index =
|
2020-06-19 03:50:30 +00:00
|
|
|
tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
|
|
|
|
ValueType kRefTypes[] = {ref(type_index)};
|
|
|
|
ValueType kOptRefType = optref(type_index);
|
|
|
|
FunctionSig sig_q_v(1, 0, kRefTypes);
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte global_index =
|
2020-07-09 13:21:45 +00:00
|
|
|
tester.AddGlobal(kOptRefType, true,
|
|
|
|
WasmInitExpr::RefNullConst(
|
|
|
|
static_cast<HeapType::Representation>(type_index)));
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte field_index = 0;
|
2021-10-06 14:26:52 +00:00
|
|
|
const byte kNonNull = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {},
|
2020-12-17 16:56:08 +00:00
|
|
|
{WASM_GLOBAL_SET(
|
2020-07-21 09:03:20 +00:00
|
|
|
global_index,
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(55), WASM_I32V(66),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2021-10-06 14:26:52 +00:00
|
|
|
WASM_STRUCT_GET(type_index, field_index,
|
|
|
|
WASM_REF_AS_NON_NULL(WASM_GLOBAL_GET(global_index))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_GLOBAL_SET(global_index, WASM_REF_NULL(type_index)),
|
|
|
|
WASM_STRUCT_GET(type_index, field_index,
|
|
|
|
WASM_REF_AS_NON_NULL(WASM_GLOBAL_GET(global_index))),
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
2020-05-05 10:43:58 +00:00
|
|
|
|
2020-06-19 03:50:30 +00:00
|
|
|
tester.CompileModule();
|
2021-10-06 14:26:52 +00:00
|
|
|
tester.CheckResult(kNonNull, 55);
|
|
|
|
tester.CheckHasThrown(kNull);
|
|
|
|
}
|
|
|
|
|
|
|
|
WASM_COMPILED_EXEC_TEST(WasmRefAsNonNullSkipCheck) {
|
|
|
|
FlagScope<bool> no_check(&FLAG_experimental_wasm_skip_null_checks, true);
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
const byte type_index =
|
|
|
|
tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
|
|
|
|
ValueType kRefType = ref(type_index);
|
|
|
|
FunctionSig sig_q_v(1, 0, &kRefType);
|
|
|
|
|
|
|
|
const byte global_index =
|
|
|
|
tester.AddGlobal(optref(type_index), true,
|
|
|
|
WasmInitExpr::RefNullConst(
|
|
|
|
static_cast<HeapType::Representation>(type_index)));
|
|
|
|
const byte kFunc = tester.DefineFunction(
|
|
|
|
&sig_q_v, {},
|
|
|
|
{WASM_GLOBAL_SET(global_index, WASM_REF_NULL(type_index)),
|
|
|
|
WASM_REF_AS_NON_NULL(WASM_GLOBAL_GET(global_index)), kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
Handle<Object> result = tester.GetResultObject(kFunc).ToHandleChecked();
|
|
|
|
// Without null checks, ref.as_non_null can actually return null.
|
|
|
|
CHECK(result->IsNull());
|
2020-06-19 03:50:30 +00:00
|
|
|
}
|
|
|
|
|
2020-12-15 19:49:59 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmBrOnNull) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index =
|
2020-06-19 03:50:30 +00:00
|
|
|
tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
|
|
|
|
ValueType kRefTypes[] = {ref(type_index)};
|
|
|
|
ValueType kOptRefType = optref(type_index);
|
|
|
|
FunctionSig sig_q_v(1, 0, kRefTypes);
|
2021-05-14 14:31:14 +00:00
|
|
|
const byte local_index = 0;
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kTaken = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {kOptRefType},
|
2020-06-03 14:37:37 +00:00
|
|
|
{WASM_BLOCK_I(WASM_I32V(42),
|
|
|
|
// Branch will be taken.
|
|
|
|
// 42 left on stack outside the block (not 52).
|
2021-05-14 14:31:14 +00:00
|
|
|
WASM_BR_ON_NULL(0, WASM_LOCAL_GET(local_index)),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_I32V(52), WASM_BR(0)),
|
|
|
|
kExprEnd});
|
2020-05-11 15:13:34 +00:00
|
|
|
|
2021-05-14 14:31:14 +00:00
|
|
|
const byte field_index = 0;
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kNotTaken = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {},
|
2020-06-03 14:37:37 +00:00
|
|
|
{WASM_BLOCK_I(
|
|
|
|
WASM_I32V(42),
|
|
|
|
WASM_STRUCT_GET(
|
2021-05-14 14:31:14 +00:00
|
|
|
type_index, field_index,
|
2020-06-03 14:37:37 +00:00
|
|
|
// Branch will not be taken.
|
|
|
|
// 52 left on stack outside the block (not 42).
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_BR_ON_NULL(0, WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(52), WASM_I32V(62),
|
|
|
|
WASM_RTT_CANON(type_index)))),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_BR(0)),
|
|
|
|
kExprEnd});
|
2020-05-11 15:13:34 +00:00
|
|
|
|
2020-06-19 03:50:30 +00:00
|
|
|
tester.CompileModule();
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kTaken, 42);
|
|
|
|
tester.CheckResult(kNotTaken, 52);
|
2020-06-19 03:50:30 +00:00
|
|
|
}
|
|
|
|
|
2021-05-14 14:31:14 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmBrOnNonNull) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
const byte type_index =
|
|
|
|
tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
|
|
|
|
ValueType kRefType = ref(type_index);
|
|
|
|
ValueType kOptRefType = optref(type_index);
|
|
|
|
FunctionSig sig_q_v(1, 0, &kRefType);
|
|
|
|
const byte field_index = 0;
|
|
|
|
|
|
|
|
const byte kTaken = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {kOptRefType, kOptRefType},
|
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(52), WASM_I32V(62),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
WASM_LOCAL_SET(
|
|
|
|
1, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(11), WASM_I32V(22),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
WASM_STRUCT_GET(type_index, field_index,
|
|
|
|
WASM_BLOCK_R(ref(type_index),
|
|
|
|
// Branch will be taken, and the block will
|
|
|
|
// return struct(52, 62).
|
|
|
|
WASM_BR_ON_NON_NULL(0, WASM_LOCAL_GET(0)),
|
|
|
|
WASM_REF_AS_NON_NULL(WASM_LOCAL_GET(1)))),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
const byte kNotTaken = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {kOptRefType, kOptRefType},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_REF_NULL(type_index)),
|
|
|
|
WASM_LOCAL_SET(
|
|
|
|
1, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(11), WASM_I32V(22),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
WASM_STRUCT_GET(type_index, field_index,
|
|
|
|
WASM_BLOCK_R(ref(type_index),
|
|
|
|
// Branch will not be taken, and the block
|
|
|
|
// will return struct(11, 22).
|
|
|
|
WASM_BR_ON_NON_NULL(0, WASM_LOCAL_GET(0)),
|
|
|
|
WASM_REF_AS_NON_NULL(WASM_LOCAL_GET(1)))),
|
|
|
|
kExprEnd});
|
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(kTaken, 52);
|
|
|
|
tester.CheckResult(kNotTaken, 11);
|
|
|
|
}
|
|
|
|
|
2021-10-06 13:09:57 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(RefCast) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
|
|
|
|
const byte supertype_index = tester.DefineStruct({F(kWasmI32, true)});
|
2022-01-27 16:24:31 +00:00
|
|
|
const byte subtype1_index = tester.DefineStruct(
|
|
|
|
{F(kWasmI32, true), F(kWasmF32, false)}, supertype_index);
|
|
|
|
const byte subtype2_index = tester.DefineStruct(
|
|
|
|
{F(kWasmI32, true), F(kWasmI64, false)}, supertype_index);
|
2022-04-06 17:24:34 +00:00
|
|
|
auto super_sig = FixedSizeSignature<ValueType>::Params(
|
|
|
|
ValueType::Ref(subtype1_index, kNullable))
|
|
|
|
.Returns(ValueType::Ref(supertype_index, kNullable));
|
|
|
|
auto sub_sig1 = FixedSizeSignature<ValueType>::Params(
|
|
|
|
ValueType::Ref(supertype_index, kNullable))
|
|
|
|
.Returns(ValueType::Ref(subtype1_index, kNullable));
|
|
|
|
auto sub_sig2 = FixedSizeSignature<ValueType>::Params(
|
|
|
|
ValueType::Ref(supertype_index, kNullable))
|
|
|
|
.Returns(ValueType::Ref(subtype2_index, kNullable));
|
|
|
|
const byte function_type_index = tester.DefineSignature(&super_sig);
|
|
|
|
const byte function_subtype1_index =
|
|
|
|
tester.DefineSignature(&sub_sig1, function_type_index);
|
|
|
|
const byte function_subtype2_index =
|
|
|
|
tester.DefineSignature(&sub_sig2, function_type_index);
|
|
|
|
const byte function_index = tester.DefineFunction(
|
|
|
|
function_subtype1_index, {},
|
|
|
|
{WASM_STRUCT_NEW_DEFAULT_WITH_RTT(subtype1_index,
|
|
|
|
WASM_RTT_CANON(subtype1_index)),
|
|
|
|
WASM_END});
|
|
|
|
// Just so this function counts as "declared".
|
|
|
|
tester.AddGlobal(ValueType::Ref(function_type_index, kNullable), false,
|
|
|
|
WasmInitExpr::RefFuncConst(function_index));
|
2021-10-06 13:09:57 +00:00
|
|
|
|
|
|
|
const byte kTestSuccessful = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
2022-01-27 16:24:31 +00:00
|
|
|
subtype1_index, WASM_RTT_CANON(subtype1_index))),
|
2021-10-06 13:09:57 +00:00
|
|
|
WASM_STRUCT_GET(
|
|
|
|
subtype1_index, 0,
|
2022-01-27 16:24:31 +00:00
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(subtype1_index))),
|
2021-10-06 13:09:57 +00:00
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
const byte kTestFailed = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
2022-01-27 16:24:31 +00:00
|
|
|
subtype1_index, WASM_RTT_CANON(subtype1_index))),
|
2021-10-06 13:09:57 +00:00
|
|
|
WASM_STRUCT_GET(
|
|
|
|
subtype2_index, 0,
|
2022-01-27 16:24:31 +00:00
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(subtype2_index))),
|
2021-10-06 13:09:57 +00:00
|
|
|
WASM_END});
|
|
|
|
|
2022-04-06 17:24:34 +00:00
|
|
|
const byte kFuncTestSuccessfulSuper = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(function_type_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_REF_FUNC(function_index)),
|
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(function_type_index)),
|
|
|
|
WASM_DROP, WASM_I32V(0), WASM_END});
|
|
|
|
|
|
|
|
const byte kFuncTestSuccessfulSub = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(function_type_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_REF_FUNC(function_index)),
|
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(0),
|
|
|
|
WASM_RTT_CANON(function_subtype1_index)),
|
|
|
|
WASM_DROP, WASM_I32V(0), WASM_END});
|
|
|
|
|
|
|
|
const byte kFuncTestFailed = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(function_type_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_REF_FUNC(function_index)),
|
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(0),
|
|
|
|
WASM_RTT_CANON(function_subtype2_index)),
|
|
|
|
WASM_DROP, WASM_I32V(1), WASM_END});
|
|
|
|
|
2021-10-06 13:09:57 +00:00
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(kTestSuccessful, 0);
|
|
|
|
tester.CheckHasThrown(kTestFailed);
|
2022-04-06 17:24:34 +00:00
|
|
|
tester.CheckResult(kFuncTestSuccessfulSuper, 0);
|
|
|
|
tester.CheckResult(kFuncTestSuccessfulSub, 0);
|
|
|
|
tester.CheckHasThrown(kFuncTestFailed);
|
2021-10-06 13:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WASM_COMPILED_EXEC_TEST(RefCastStatic) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
|
2022-01-27 16:24:31 +00:00
|
|
|
const byte supertype_index = tester.DefineStruct({F(kWasmI32, true)});
|
2021-10-06 13:09:57 +00:00
|
|
|
const byte subtype1_index = tester.DefineStruct(
|
|
|
|
{F(kWasmI32, true), F(kWasmF32, false)}, supertype_index);
|
|
|
|
const byte subtype2_index = tester.DefineStruct(
|
|
|
|
{F(kWasmI32, true), F(kWasmI64, false)}, supertype_index);
|
|
|
|
|
|
|
|
const byte kTestSuccessful = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
|
|
|
|
WASM_STRUCT_GET(subtype1_index, 0,
|
|
|
|
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype1_index)),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
const byte kTestFailed = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
|
|
|
|
WASM_STRUCT_GET(subtype2_index, 0,
|
|
|
|
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype2_index)),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(kTestSuccessful, 0);
|
|
|
|
tester.CheckHasThrown(kTestFailed);
|
|
|
|
}
|
|
|
|
|
|
|
|
WASM_COMPILED_EXEC_TEST(RefCastStaticNoChecks) {
|
|
|
|
FlagScope<bool> scope(&FLAG_experimental_wasm_assume_ref_cast_succeeds, true);
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
|
2022-01-27 16:24:31 +00:00
|
|
|
const byte supertype_index = tester.DefineStruct({F(kWasmI32, true)});
|
2021-10-06 13:09:57 +00:00
|
|
|
const byte subtype1_index = tester.DefineStruct(
|
|
|
|
{F(kWasmI32, true), F(kWasmF32, false)}, supertype_index);
|
|
|
|
const byte subtype2_index = tester.DefineStruct(
|
|
|
|
{F(kWasmI32, true), F(kWasmI64, false)}, supertype_index);
|
|
|
|
|
|
|
|
const byte kTestSuccessful = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
|
|
|
|
WASM_STRUCT_GET(subtype1_index, 0,
|
|
|
|
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype1_index)),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
const byte kTestFailed = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(supertype_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
|
|
|
|
WASM_STRUCT_GET(subtype2_index, 0,
|
|
|
|
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype2_index)),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(kTestSuccessful, 0);
|
|
|
|
tester.CheckResult(kTestFailed, 0);
|
|
|
|
}
|
|
|
|
|
2020-12-15 19:49:59 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(BrOnCast) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2021-01-28 16:21:57 +00:00
|
|
|
ValueType kDataRefNull = ValueType::Ref(HeapType::kData, kNullable);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index = tester.DefineStruct({F(kWasmI32, true)});
|
Reland "[wasm-gc] Remove abstract rtts"
This is a reland of b77deeca4bd65b006a3a6c7344c2bbabd4514122
Changes compared to original: Add explicit narrowing casts in tests
for MSVC.
Original change's description:
> [wasm-gc] Remove abstract rtts
>
> In the latest wasm-gc spec, rtts of abstract types are no longer
> allowed. Consequently, canonical rtts of concrete types always have
> a depth of 0.
>
> Changes:
> - Change the immediate argument of rtts to a type index over a heap
> type. Abstract it with TypeIndexImmediate in function body decoding.
> This affects:
> value_type.h, read_value_type(), decoding of relevant opcodes,
> wasm subtyping, WasmInitExpr, consume_init_expr(), and
> wasm-module-builder.cc.
> - In function-body-decoder-impl.h, update rtt.canon to always produce
> an rtt of depth 0.
> - Pass a unit32_t type index over a HeapType to all rtt-related
> utilities.
> - Remove infrastructure for abstract-type rtts from the wasm compilers,
> setup-heap-internal.cc, roots.h, and module-instantiate.cc.
> - Remove ObjectReferenceKnowledge::rtt_is_i31. Remove related branches
> from ref.test, ref.cast and br_on_cast implementations in the wasm
> compilers.
> - Remove unused 'parent' field from WasmTypeInfo.
> - Make the parent argument optional in NewWasmTypeInfo, CreateStructMap,
> and CreateArrayMap.
> - Use more convenient arguments in IsHeapSubtypeOf.
> - Update tests.
>
> Bug: v8:7748
> Change-Id: Ib45efe0741e6558c9b291fc8b4a75ae303146bdc
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2642248
> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#72321}
Bug: v8:7748
Change-Id: I22b204b486fd185077cd6c7f15d492f5143f48fe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2650207
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72355}
2021-01-27 08:33:32 +00:00
|
|
|
const byte other_type_index = tester.DefineStruct({F(kWasmF32, true)});
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte rtt_index =
|
2022-01-28 14:53:45 +00:00
|
|
|
tester.AddGlobal(ValueType::Rtt(type_index), false,
|
2020-07-22 14:22:33 +00:00
|
|
|
WasmInitExpr::RttCanon(
|
|
|
|
static_cast<HeapType::Representation>(type_index)));
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kTestStruct = tester.DefineFunction(
|
2021-01-28 16:21:57 +00:00
|
|
|
tester.sigs.i_v(), {kWasmI32, kDataRefNull},
|
2021-01-31 21:08:05 +00:00
|
|
|
{WASM_BLOCK_R(ValueType::Ref(type_index, kNullable),
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(111)),
|
|
|
|
// Pipe a struct through a local so it's statically typed
|
|
|
|
// as dataref.
|
|
|
|
WASM_LOCAL_SET(1, WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
other_type_index, WASM_F32(1.0),
|
|
|
|
WASM_RTT_CANON(other_type_index))),
|
|
|
|
WASM_LOCAL_GET(1),
|
|
|
|
// The type check fails, so this branch isn't taken.
|
|
|
|
WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)), WASM_DROP,
|
|
|
|
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(221)), // (Final result) - 1
|
|
|
|
WASM_LOCAL_SET(1, WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(1),
|
|
|
|
WASM_GLOBAL_GET(rtt_index))),
|
|
|
|
WASM_LOCAL_GET(1),
|
|
|
|
// This branch is taken.
|
|
|
|
WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)),
|
|
|
|
WASM_GLOBAL_GET(rtt_index), WASM_GC_OP(kExprRefCast),
|
|
|
|
|
|
|
|
// Not executed due to the branch.
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(333))),
|
|
|
|
WASM_GC_OP(kExprStructGet), type_index, 0, WASM_LOCAL_GET(0),
|
|
|
|
kExprI32Add, kExprEnd});
|
2020-07-22 14:22:33 +00:00
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
const byte kTestStructStatic = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {kWasmI32, kDataRefNull},
|
|
|
|
{WASM_BLOCK_R(
|
|
|
|
ValueType::Ref(type_index, kNullable),
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(111)),
|
|
|
|
// Pipe a struct through a local so it's statically typed
|
|
|
|
// as dataref.
|
|
|
|
WASM_LOCAL_SET(1, WASM_STRUCT_NEW(other_type_index, WASM_F32(1.0))),
|
|
|
|
WASM_LOCAL_GET(1),
|
|
|
|
// The type check fails, so this branch isn't taken.
|
|
|
|
WASM_BR_ON_CAST_STATIC(0, type_index), WASM_DROP,
|
|
|
|
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(221)), // (Final result) - 1
|
|
|
|
WASM_LOCAL_SET(1, WASM_STRUCT_NEW(type_index, WASM_I32V(1))),
|
|
|
|
WASM_LOCAL_GET(1),
|
|
|
|
// This branch is taken.
|
|
|
|
WASM_BR_ON_CAST_STATIC(0, type_index),
|
|
|
|
WASM_GC_OP(kExprRefCastStatic), type_index,
|
|
|
|
|
|
|
|
// Not executed due to the branch.
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(333))),
|
|
|
|
WASM_GC_OP(kExprStructGet), type_index, 0, WASM_LOCAL_GET(0),
|
|
|
|
kExprI32Add, kExprEnd});
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kTestNull = tester.DefineFunction(
|
2021-01-28 16:21:57 +00:00
|
|
|
tester.sigs.i_v(), {kWasmI32, kDataRefNull},
|
2021-01-31 21:08:05 +00:00
|
|
|
{WASM_BLOCK_R(ValueType::Ref(type_index, kNullable),
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(111)),
|
|
|
|
WASM_LOCAL_GET(1), // Put a nullref onto the value stack.
|
|
|
|
// Not taken for nullref.
|
|
|
|
WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)),
|
|
|
|
WASM_RTT_CANON(type_index), WASM_GC_OP(kExprRefCast),
|
|
|
|
|
|
|
|
WASM_LOCAL_SET(0, WASM_I32V(222))), // Final result.
|
|
|
|
WASM_DROP, WASM_LOCAL_GET(0), kExprEnd});
|
2020-07-22 14:22:33 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kTypedAfterBranch = tester.DefineFunction(
|
2021-01-28 16:21:57 +00:00
|
|
|
tester.sigs.i_v(), {kWasmI32, kDataRefNull},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(1, WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42),
|
2020-12-17 16:56:08 +00:00
|
|
|
WASM_GLOBAL_GET(rtt_index))),
|
2021-01-31 21:08:05 +00:00
|
|
|
WASM_BLOCK_I(
|
|
|
|
// The inner block should take the early branch with a struct
|
|
|
|
// on the stack.
|
|
|
|
WASM_BLOCK_R(ValueType::Ref(type_index, kNonNullable),
|
|
|
|
WASM_LOCAL_GET(1),
|
|
|
|
WASM_BR_ON_CAST(0, WASM_GLOBAL_GET(rtt_index)),
|
|
|
|
// Returning 123 is the unreachable failure case.
|
|
|
|
WASM_I32V(123), WASM_BR(1)),
|
2020-07-22 14:22:33 +00:00
|
|
|
// The outer block catches the struct left behind by the inner block
|
|
|
|
// and reads its field.
|
2021-01-31 21:08:05 +00:00
|
|
|
WASM_GC_OP(kExprStructGet), type_index, 0),
|
|
|
|
kExprEnd});
|
2020-07-22 14:22:33 +00:00
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(kTestStruct, 222);
|
2021-09-15 12:59:42 +00:00
|
|
|
tester.CheckResult(kTestStructStatic, 222);
|
2021-01-31 21:08:05 +00:00
|
|
|
tester.CheckResult(kTestNull, 222);
|
2020-07-22 14:22:33 +00:00
|
|
|
tester.CheckResult(kTypedAfterBranch, 42);
|
|
|
|
}
|
|
|
|
|
2021-05-19 15:41:14 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(BrOnCastFail) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
ValueType kDataRefNull = ValueType::Ref(HeapType::kData, kNullable);
|
|
|
|
const byte type0 = tester.DefineStruct({F(kWasmI32, true)});
|
|
|
|
const byte type1 =
|
|
|
|
tester.DefineStruct({F(kWasmI64, true), F(kWasmI32, true)});
|
|
|
|
|
|
|
|
const int field0_value = 5;
|
|
|
|
const int field1_value = 25;
|
|
|
|
const int null_value = 45;
|
|
|
|
|
|
|
|
// local_0 = value;
|
|
|
|
// if (!(local_0 instanceof type0)) goto block1;
|
|
|
|
// return static_cast<type0>(local_0).field_0;
|
|
|
|
// block1:
|
|
|
|
// if (local_0 == nullptr) goto block2;
|
|
|
|
// return static_cast<type1>(local_0).field_1;
|
|
|
|
// block2:
|
|
|
|
// return null_value;
|
|
|
|
#define FUNCTION_BODY(value) \
|
|
|
|
WASM_LOCAL_SET(0, WASM_SEQ(value)), \
|
|
|
|
WASM_BLOCK( \
|
|
|
|
WASM_BLOCK_R(kDataRefNull, WASM_LOCAL_GET(0), \
|
|
|
|
WASM_BR_ON_CAST_FAIL(0, WASM_RTT_CANON(type0)), \
|
|
|
|
WASM_GC_OP(kExprStructGet), type0, 0, kExprReturn), \
|
|
|
|
kExprBrOnNull, 0, WASM_RTT_CANON(type1), WASM_GC_OP(kExprRefCast), \
|
|
|
|
WASM_GC_OP(kExprStructGet), type1, 1, kExprReturn), \
|
|
|
|
WASM_I32V(null_value), kExprEnd
|
|
|
|
|
|
|
|
const byte kBranchTaken =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {kDataRefNull},
|
|
|
|
{FUNCTION_BODY(WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
type1, WASM_I64V(10), WASM_I32V(field1_value),
|
|
|
|
WASM_RTT_CANON(type1)))});
|
|
|
|
|
|
|
|
const byte kBranchNotTaken = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {kDataRefNull},
|
|
|
|
{FUNCTION_BODY(WASM_STRUCT_NEW_WITH_RTT(type0, WASM_I32V(field0_value),
|
|
|
|
WASM_RTT_CANON(type0)))});
|
|
|
|
|
|
|
|
const byte kNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {kDataRefNull}, {FUNCTION_BODY(WASM_REF_NULL(type0))});
|
|
|
|
|
|
|
|
const byte kUnrelatedTypes = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(type1, kNullable)},
|
|
|
|
{FUNCTION_BODY(WASM_STRUCT_NEW_WITH_RTT(type1, WASM_I64V(10),
|
|
|
|
WASM_I32V(field1_value),
|
|
|
|
WASM_RTT_CANON(type1)))});
|
|
|
|
#undef FUNCTION_BODY
|
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
const byte kBranchTakenStatic = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {kDataRefNull},
|
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_STRUCT_NEW(type1, WASM_I64V(10), WASM_I32V(field1_value))),
|
|
|
|
WASM_BLOCK(
|
|
|
|
WASM_BLOCK_R(kDataRefNull, WASM_LOCAL_GET(0),
|
|
|
|
WASM_BR_ON_CAST_STATIC_FAIL(0, type0),
|
|
|
|
WASM_GC_OP(kExprStructGet), type0, 0, kExprReturn),
|
|
|
|
kExprBrOnNull, 0, WASM_GC_OP(kExprRefCastStatic), type1,
|
|
|
|
WASM_GC_OP(kExprStructGet), type1, 1, kExprReturn),
|
|
|
|
WASM_I32V(null_value), kExprEnd});
|
|
|
|
|
2021-05-19 15:41:14 +00:00
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(kBranchTaken, field1_value);
|
2021-09-15 12:59:42 +00:00
|
|
|
tester.CheckResult(kBranchTakenStatic, field1_value);
|
2021-05-19 15:41:14 +00:00
|
|
|
tester.CheckResult(kBranchNotTaken, field0_value);
|
|
|
|
tester.CheckResult(kNull, null_value);
|
|
|
|
tester.CheckResult(kUnrelatedTypes, field1_value);
|
|
|
|
}
|
|
|
|
|
2020-12-16 15:22:52 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmRefEq) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-04 09:13:30 +00:00
|
|
|
byte type_index = tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
|
2020-06-19 03:50:30 +00:00
|
|
|
ValueType kRefTypes[] = {ref(type_index)};
|
|
|
|
ValueType kOptRefType = optref(type_index);
|
|
|
|
FunctionSig sig_q_v(1, 0, kRefTypes);
|
|
|
|
|
2020-07-02 11:18:47 +00:00
|
|
|
byte local_index = 0;
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kFunc = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {kOptRefType},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(local_index, WASM_STRUCT_NEW_WITH_RTT(
|
2020-07-21 09:03:20 +00:00
|
|
|
type_index, WASM_I32V(55), WASM_I32V(66),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_I32_ADD(
|
2020-07-02 11:18:47 +00:00
|
|
|
WASM_I32_SHL(
|
|
|
|
WASM_REF_EQ( // true
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(local_index), WASM_LOCAL_GET(local_index)),
|
2020-07-02 11:18:47 +00:00
|
|
|
WASM_I32V(0)),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_I32_ADD(
|
|
|
|
WASM_I32_SHL(WASM_REF_EQ( // false
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(local_index),
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(55), WASM_I32V(66),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_I32V(1)),
|
|
|
|
WASM_I32_ADD(WASM_I32_SHL( // false
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_REF_EQ(WASM_LOCAL_GET(local_index),
|
2020-06-24 17:29:00 +00:00
|
|
|
WASM_REF_NULL(type_index)),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_I32V(2)),
|
|
|
|
WASM_I32_SHL(WASM_REF_EQ( // true
|
2020-06-24 17:29:00 +00:00
|
|
|
WASM_REF_NULL(type_index),
|
|
|
|
WASM_REF_NULL(type_index)),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_I32V(3))))),
|
|
|
|
kExprEnd});
|
2020-05-20 22:29:59 +00:00
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
tester.CompileModule();
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kFunc, 0b1001);
|
2020-04-21 16:45:53 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 15:22:52 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmPackedStructU) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-06-05 20:22:45 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index = tester.DefineStruct(
|
2020-06-05 20:22:45 +00:00
|
|
|
{F(kWasmI8, true), F(kWasmI16, true), F(kWasmI32, true)});
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
ValueType struct_type = optref(type_index);
|
2020-06-05 20:22:45 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte local_index = 0;
|
2020-06-05 20:22:45 +00:00
|
|
|
|
|
|
|
int32_t expected_output_0 = 0x1234;
|
|
|
|
int32_t expected_output_1 = -1;
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kF0 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {struct_type},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(local_index,
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(expected_output_0),
|
|
|
|
WASM_I32V(expected_output_1), WASM_I32V(0x12345678),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_STRUCT_GET_U(type_index, 0, WASM_LOCAL_GET(local_index)),
|
2020-06-05 20:22:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kF1 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {struct_type},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(local_index,
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(expected_output_0),
|
|
|
|
WASM_I32V(expected_output_1), WASM_I32V(0x12345678),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_STRUCT_GET_U(type_index, 1, WASM_LOCAL_GET(local_index)),
|
2020-06-05 20:22:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
tester.CompileModule();
|
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kF0, static_cast<uint8_t>(expected_output_0));
|
|
|
|
tester.CheckResult(kF1, static_cast<uint16_t>(expected_output_1));
|
2020-06-05 20:22:45 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 15:22:52 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmPackedStructS) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-06-05 20:22:45 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index = tester.DefineStruct(
|
2020-06-05 20:22:45 +00:00
|
|
|
{F(kWasmI8, true), F(kWasmI16, true), F(kWasmI32, true)});
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
ValueType struct_type = optref(type_index);
|
2020-06-05 20:22:45 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte local_index = 0;
|
2020-06-05 20:22:45 +00:00
|
|
|
|
|
|
|
int32_t expected_output_0 = 0x80;
|
|
|
|
int32_t expected_output_1 = 42;
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kF0 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {struct_type},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(
|
2020-06-05 20:22:45 +00:00
|
|
|
local_index,
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(expected_output_0),
|
|
|
|
WASM_I32V(expected_output_1), WASM_I32V(0),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_STRUCT_GET_S(type_index, 0, WASM_LOCAL_GET(local_index)),
|
2020-06-05 20:22:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kF1 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {struct_type},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(
|
2020-07-21 09:03:20 +00:00
|
|
|
local_index,
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(0x80),
|
|
|
|
WASM_I32V(expected_output_1), WASM_I32V(0),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_STRUCT_GET_S(type_index, 1, WASM_LOCAL_GET(local_index)),
|
2020-06-05 20:22:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kF0, static_cast<int8_t>(expected_output_0));
|
|
|
|
tester.CheckResult(kF1, static_cast<int16_t>(expected_output_1));
|
2020-06-05 20:22:45 +00:00
|
|
|
}
|
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
TEST(WasmLetInstruction) {
|
|
|
|
WasmGCTester tester;
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index =
|
2020-06-03 14:37:37 +00:00
|
|
|
tester.DefineStruct({F(kWasmI32, true), F(kWasmI32, true)});
|
2020-05-20 22:29:59 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte let_local_index = 0;
|
|
|
|
const byte let_field_index = 0;
|
|
|
|
const byte kLetTest1 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {},
|
2020-07-21 09:03:20 +00:00
|
|
|
{WASM_LET_1_I(
|
2020-09-29 07:46:36 +00:00
|
|
|
WASM_SEQ(kRefCode, type_index),
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(52),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_STRUCT_GET(type_index, let_field_index,
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(let_local_index))),
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte let_2_field_index = 0;
|
|
|
|
const byte kLetTest2 = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {},
|
2020-07-21 09:03:20 +00:00
|
|
|
{WASM_LET_2_I(
|
2020-09-29 07:46:36 +00:00
|
|
|
kI32Code, WASM_I32_ADD(WASM_I32V(42), WASM_I32V(-32)),
|
|
|
|
WASM_SEQ(kRefCode, type_index),
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(52),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_I32_MUL(WASM_STRUCT_GET(type_index, let_2_field_index,
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(1)),
|
|
|
|
WASM_LOCAL_GET(0))),
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kLetTestLocals = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_i(), {kWasmI32},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(1, WASM_I32V(100)),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_LET_2_I(
|
2020-09-29 07:46:36 +00:00
|
|
|
kI32Code, WASM_I32V(1), kI32Code, WASM_I32V(10),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_I32_SUB(WASM_I32_ADD(WASM_LOCAL_GET(0), // 1st let-local
|
|
|
|
WASM_LOCAL_GET(2)), // Parameter
|
|
|
|
WASM_I32_ADD(WASM_LOCAL_GET(1), // 2nd let-local
|
|
|
|
WASM_LOCAL_GET(3)))), // Function local
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
2020-05-20 22:29:59 +00:00
|
|
|
// Result: (1 + 1000) - (10 + 100) = 891
|
2020-06-03 14:37:37 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte let_erase_local_index = 0;
|
|
|
|
const byte kLetTestErase = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {kWasmI32},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(let_erase_local_index, WASM_I32V(0)),
|
2020-09-29 07:46:36 +00:00
|
|
|
WASM_LET_1_V(kI32Code, WASM_I32V(1), WASM_NOP),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(let_erase_local_index), kExprEnd});
|
2020-05-20 22:29:59 +00:00
|
|
|
// The result should be 0 and not 1, as local_get(0) refers to the original
|
|
|
|
// local.
|
|
|
|
|
2021-01-08 08:19:18 +00:00
|
|
|
const byte kLetInLoop = tester.DefineFunction(
|
|
|
|
tester.sigs.i_i(), {},
|
|
|
|
{WASM_LOOP(WASM_LET_1_V(
|
|
|
|
kI32Code, WASM_I32V(10), // --
|
|
|
|
WASM_LOCAL_SET(1, WASM_I32_SUB(WASM_LOCAL_GET(1), WASM_I32V(10))),
|
|
|
|
WASM_BR_IF(1, WASM_I32_GES(WASM_LOCAL_GET(1), WASM_LOCAL_GET(0))))),
|
|
|
|
WASM_LOCAL_GET(0), WASM_END});
|
|
|
|
|
|
|
|
const byte kLetInBlock = tester.DefineFunction(
|
|
|
|
tester.sigs.i_i(), {},
|
|
|
|
{WASM_BLOCK(WASM_LET_1_V(
|
|
|
|
kI32Code, WASM_I32V(10), // --
|
|
|
|
WASM_BR_IF(1, WASM_I32_GES(WASM_LOCAL_GET(1), WASM_LOCAL_GET(0))),
|
|
|
|
WASM_LOCAL_SET(1, WASM_I32V(30)))),
|
|
|
|
WASM_LOCAL_GET(0), WASM_END});
|
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
tester.CompileModule();
|
2020-05-20 22:29:59 +00:00
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kLetTest1, 42);
|
|
|
|
tester.CheckResult(kLetTest2, 420);
|
|
|
|
tester.CheckResult(kLetTestLocals, 891, 1000);
|
|
|
|
tester.CheckResult(kLetTestErase, 0);
|
2021-01-08 08:19:18 +00:00
|
|
|
tester.CheckResult(kLetInLoop, 2, 52);
|
|
|
|
tester.CheckResult(kLetInLoop, -11, -1);
|
|
|
|
tester.CheckResult(kLetInBlock, 15, 15);
|
|
|
|
tester.CheckResult(kLetInBlock, 30, 5);
|
2020-05-20 22:29:59 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 15:22:52 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2022-04-05 16:02:13 +00:00
|
|
|
if (!tester.HasSimdSupport(execution_tier)) return;
|
2020-12-16 15:22:52 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index = tester.DefineArray(wasm::kWasmI32, true);
|
2021-03-29 09:24:54 +00:00
|
|
|
const byte fp_type_index = tester.DefineArray(wasm::kWasmF64, true);
|
2021-10-14 12:15:55 +00:00
|
|
|
const byte immut_type_index = tester.DefineArray(wasm::kWasmI32, false);
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
ValueType kRefTypes[] = {ref(type_index)};
|
2020-05-07 14:55:58 +00:00
|
|
|
FunctionSig sig_q_v(1, 0, kRefTypes);
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
ValueType kOptRefType = optref(type_index);
|
2020-05-11 15:17:49 +00:00
|
|
|
|
|
|
|
// f: a = [12, 12, 12]; a[1] = 42; return a[arg0]
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte local_index = 1;
|
|
|
|
const byte kGetElem = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_i(), {kOptRefType},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(local_index, WASM_ARRAY_NEW_WITH_RTT(
|
2020-07-21 09:03:20 +00:00
|
|
|
type_index, WASM_I32V(12), WASM_I32V(3),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(type_index, WASM_LOCAL_GET(local_index), WASM_I32V(1),
|
2020-06-03 14:37:37 +00:00
|
|
|
WASM_I32V(42)),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_GET(type_index, WASM_LOCAL_GET(local_index),
|
|
|
|
WASM_LOCAL_GET(0)),
|
2020-06-03 14:37:37 +00:00
|
|
|
kExprEnd});
|
2020-05-07 14:55:58 +00:00
|
|
|
|
2020-05-11 16:19:06 +00:00
|
|
|
// Reads and returns an array's length.
|
2022-01-11 12:55:55 +00:00
|
|
|
const byte kGetLength =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_ARRAY_LEN(WASM_ARRAY_NEW_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(0), WASM_I32V(42),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
kExprEnd});
|
2020-06-03 14:37:37 +00:00
|
|
|
|
2020-05-07 14:55:58 +00:00
|
|
|
// Create an array of length 2, initialized to [42, 42].
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kAllocate = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
&sig_q_v, {},
|
2020-07-21 09:03:20 +00:00
|
|
|
{WASM_ARRAY_NEW_WITH_RTT(type_index, WASM_I32V(42), WASM_I32V(2),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
2020-05-11 15:17:49 +00:00
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
const byte kAllocateStatic = tester.DefineFunction(
|
|
|
|
&sig_q_v, {},
|
|
|
|
{WASM_ARRAY_NEW_DEFAULT(type_index, WASM_I32V(2)), WASM_DROP,
|
|
|
|
WASM_ARRAY_NEW(type_index, WASM_I32V(42), WASM_I32V(2)), kExprEnd});
|
|
|
|
|
2021-09-17 14:30:07 +00:00
|
|
|
const byte kInit = tester.DefineFunction(
|
|
|
|
&sig_q_v, {},
|
|
|
|
{WASM_ARRAY_INIT(type_index, 3, WASM_I32V(10), WASM_I32V(20),
|
|
|
|
WASM_I32V(30), WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
|
|
|
|
2021-10-14 12:15:55 +00:00
|
|
|
const byte kImmutable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_ARRAY_GET(
|
|
|
|
immut_type_index,
|
|
|
|
WASM_ARRAY_INIT(immut_type_index, 2, WASM_I32V(42), WASM_I32V(43),
|
|
|
|
WASM_RTT_CANON(immut_type_index)),
|
|
|
|
WASM_I32V(0)),
|
|
|
|
kExprEnd});
|
|
|
|
|
2020-11-16 22:30:52 +00:00
|
|
|
const uint32_t kLongLength = 1u << 16;
|
2020-11-12 22:30:45 +00:00
|
|
|
const byte kAllocateLarge = tester.DefineFunction(
|
|
|
|
&sig_q_v, {},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_ARRAY_NEW_DEFAULT_WITH_RTT(type_index, WASM_I32V(kLongLength),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
2020-11-12 22:30:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
2021-08-16 08:55:14 +00:00
|
|
|
ArrayType array_type(kWasmI32, true);
|
|
|
|
const uint32_t kTooLong = WasmArray::MaxLength(&array_type) + 1;
|
2020-11-12 22:30:45 +00:00
|
|
|
const byte kAllocateTooLarge = tester.DefineFunction(
|
|
|
|
&sig_q_v, {},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_ARRAY_NEW_DEFAULT_WITH_RTT(type_index, WASM_I32V(kTooLong),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
2020-11-12 22:30:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
2021-03-29 09:24:54 +00:00
|
|
|
// Tests that fp arrays work properly.
|
|
|
|
// f: a = [10.0, 10.0, 10.0]; a[1] = 42.42; return static_cast<int64>(a[1]);
|
|
|
|
double result_value = 42.42;
|
|
|
|
const byte kTestFpArray = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {optref(fp_type_index)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_ARRAY_NEW_WITH_RTT(
|
|
|
|
fp_type_index, WASM_F64(10.0), WASM_I32V(3),
|
|
|
|
WASM_RTT_CANON(fp_type_index))),
|
|
|
|
WASM_ARRAY_SET(fp_type_index, WASM_LOCAL_GET(0), WASM_I32V(1),
|
|
|
|
WASM_F64(result_value)),
|
|
|
|
WASM_I32_SCONVERT_F64(
|
|
|
|
WASM_ARRAY_GET(fp_type_index, WASM_LOCAL_GET(0), WASM_I32V(1))),
|
|
|
|
kExprEnd});
|
|
|
|
|
2020-06-03 14:37:37 +00:00
|
|
|
tester.CompileModule();
|
2020-05-11 16:19:06 +00:00
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kGetElem, 12, 0);
|
|
|
|
tester.CheckResult(kGetElem, 42, 1);
|
|
|
|
tester.CheckResult(kGetElem, 12, 2);
|
|
|
|
tester.CheckHasThrown(kGetElem, 3);
|
|
|
|
tester.CheckHasThrown(kGetElem, -1);
|
|
|
|
tester.CheckResult(kGetLength, 42);
|
2021-10-14 12:15:55 +00:00
|
|
|
tester.CheckResult(kImmutable, 42);
|
2021-03-29 09:24:54 +00:00
|
|
|
tester.CheckResult(kTestFpArray, static_cast<int32_t>(result_value));
|
2020-06-03 14:37:37 +00:00
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
Handle<Object> h_result = tester.GetResultObject(kAllocate).ToHandleChecked();
|
|
|
|
CHECK(h_result->IsWasmArray());
|
|
|
|
CHECK_EQ(2, Handle<WasmArray>::cast(h_result)->length());
|
|
|
|
|
|
|
|
h_result = tester.GetResultObject(kAllocateStatic).ToHandleChecked();
|
|
|
|
CHECK(h_result->IsWasmArray());
|
|
|
|
CHECK_EQ(2, Handle<WasmArray>::cast(h_result)->length());
|
2020-11-12 22:30:45 +00:00
|
|
|
|
2021-09-17 14:30:07 +00:00
|
|
|
Handle<Object> init_result = tester.GetResultObject(kInit).ToHandleChecked();
|
|
|
|
CHECK(init_result->IsWasmArray());
|
|
|
|
CHECK_EQ(3, Handle<WasmArray>::cast(init_result)->length());
|
|
|
|
CHECK_EQ(10, Handle<WasmArray>::cast(init_result)->GetElement(0).to_i32());
|
|
|
|
CHECK_EQ(20, Handle<WasmArray>::cast(init_result)->GetElement(1).to_i32());
|
|
|
|
CHECK_EQ(30, Handle<WasmArray>::cast(init_result)->GetElement(2).to_i32());
|
|
|
|
|
2020-11-12 22:30:45 +00:00
|
|
|
MaybeHandle<Object> maybe_large_result =
|
|
|
|
tester.GetResultObject(kAllocateLarge);
|
|
|
|
Handle<Object> large_result = maybe_large_result.ToHandleChecked();
|
|
|
|
CHECK(large_result->IsWasmArray());
|
|
|
|
CHECK(Handle<WasmArray>::cast(large_result)->Size() >
|
|
|
|
kMaxRegularHeapObjectSize);
|
|
|
|
|
2021-05-27 14:52:38 +00:00
|
|
|
tester.CheckHasThrown(kAllocateTooLarge, "requested new array is too large");
|
2020-05-07 14:55:58 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 15:22:52 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmPackedArrayU) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte array_index = tester.DefineArray(kWasmI8, true);
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
ValueType array_type = optref(array_index);
|
2020-06-05 20:22:45 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte param_index = 0;
|
|
|
|
const byte local_index = 1;
|
2020-06-05 20:22:45 +00:00
|
|
|
|
|
|
|
int32_t expected_output_3 = 258;
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kF = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_i(), {array_type},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(local_index, WASM_ARRAY_NEW_WITH_RTT(
|
2020-07-21 09:03:20 +00:00
|
|
|
array_index, WASM_I32V(0), WASM_I32V(4),
|
|
|
|
WASM_RTT_CANON(array_index))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(array_index, WASM_LOCAL_GET(local_index), WASM_I32V(0),
|
2020-06-05 20:22:45 +00:00
|
|
|
WASM_I32V(1)),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(array_index, WASM_LOCAL_GET(local_index), WASM_I32V(1),
|
2020-06-05 20:22:45 +00:00
|
|
|
WASM_I32V(10)),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(array_index, WASM_LOCAL_GET(local_index), WASM_I32V(2),
|
2020-06-05 20:22:45 +00:00
|
|
|
WASM_I32V(200)),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(array_index, WASM_LOCAL_GET(local_index), WASM_I32V(3),
|
2020-06-05 20:22:45 +00:00
|
|
|
WASM_I32V(expected_output_3)),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_GET_U(array_index, WASM_LOCAL_GET(local_index),
|
|
|
|
WASM_LOCAL_GET(param_index)),
|
2020-06-05 20:22:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kF, 1, 0);
|
|
|
|
tester.CheckResult(kF, 10, 1);
|
|
|
|
tester.CheckResult(kF, 200, 2);
|
2020-06-05 20:22:45 +00:00
|
|
|
// Only the 2 lsb's of 258 should be stored in the array.
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kF, static_cast<uint8_t>(expected_output_3), 3);
|
2020-06-05 20:22:45 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 15:22:52 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(WasmPackedArrayS) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte array_index = tester.DefineArray(kWasmI16, true);
|
[wasm-gc] Change ValueType representation to account for new types
Motivation:
Changes to the typed function references and gc proposals solidified
the notion of heap type, clarified nullable vs. non-nullable reference
types, and introduced rtts, which contain an integer depth field in
addition to a heap type. This required us to overhaul our ValueType
representation, which results in extensive changes.
To keep this CL "small", we do not try to implement the binary encoding
as described in the proposals, but rather devise a simpler one of our
own (see below). Also, we do not try to implement additional
functionality for the new types.
Changes:
- Introduce HeapType. Move heap types from ValueType to HeapType.
- Introduce Nullability for reference types.
- Rework ValueType helper methods.
- Introduce rtts in ValueType with an integer depth field. Include depth
in the ValueType encoding.
- Make the constructor of ValueType private, instead expose static
functions which explicitly state what they create.
- Change every switch statement on ValueType::Kind. Sometimes, we need
nested switches.
- Introduce temporary constants in ValueTypeCode for nullable types,
use them for decoding.
- In WasmGlobalObject, split 'flags' into 'raw_type' and 'is_mutable'.
- Change IsSubtypeOfRef to IsSubtypeOfHeap and implement changes in
subtyping.
- kWasmFuncRef initializers are now non-nullable. Initializers are
only required to be subtypes of the declared global type.
- Change tests and fuzzers as needed.
Bug: v8:7748
Change-Id: If41f783bd4128443b07e94188cea7dd53ab0bfa5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247657
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68408}
2020-06-18 11:24:07 +00:00
|
|
|
ValueType array_type = optref(array_index);
|
2020-06-05 20:22:45 +00:00
|
|
|
|
2021-05-26 15:47:27 +00:00
|
|
|
int32_t array_elements[] = {0x12345678, 10, 0xFEDC, 0xFF1234};
|
2020-06-05 20:22:45 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte param_index = 0;
|
|
|
|
const byte local_index = 1;
|
|
|
|
const byte kF = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_i(), {array_type},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(
|
2020-06-05 20:22:45 +00:00
|
|
|
local_index,
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_NEW_WITH_RTT(array_index, WASM_I32V(array_elements[0]),
|
2020-07-21 09:03:20 +00:00
|
|
|
WASM_I32V(4), WASM_RTT_CANON(array_index))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(array_index, WASM_LOCAL_GET(local_index), WASM_I32V(1),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_I32V(array_elements[1])),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(array_index, WASM_LOCAL_GET(local_index), WASM_I32V(2),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_I32V(array_elements[2])),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_SET(array_index, WASM_LOCAL_GET(local_index), WASM_I32V(3),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_I32V(array_elements[3])),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_GET_S(array_index, WASM_LOCAL_GET(local_index),
|
|
|
|
WASM_LOCAL_GET(param_index)),
|
2020-06-05 20:22:45 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
// Exactly the 2 lsb's should be stored by array.new.
|
2021-05-26 15:47:27 +00:00
|
|
|
tester.CheckResult(kF, static_cast<int16_t>(array_elements[0]), 0);
|
|
|
|
tester.CheckResult(kF, static_cast<int16_t>(array_elements[1]), 1);
|
2020-06-05 20:22:45 +00:00
|
|
|
// Sign should be extended.
|
2021-05-26 15:47:27 +00:00
|
|
|
tester.CheckResult(kF, static_cast<int16_t>(array_elements[2]), 2);
|
2020-06-05 20:22:45 +00:00
|
|
|
// Exactly the 2 lsb's should be stored by array.set.
|
2021-05-26 15:47:27 +00:00
|
|
|
tester.CheckResult(kF, static_cast<int16_t>(array_elements[3]), 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
WASM_COMPILED_EXEC_TEST(WasmArrayCopy) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
const byte array32_index = tester.DefineArray(kWasmI32, true);
|
|
|
|
const byte array16_index = tester.DefineArray(kWasmI16, true);
|
|
|
|
const byte arrayref_index = tester.DefineArray(optref(array32_index), true);
|
|
|
|
|
|
|
|
// Copies i32 ranges: local1[0..3] to local2[6..9].
|
|
|
|
const byte kCopyI32 = tester.DefineFunction(
|
|
|
|
tester.sigs.i_i(), {optref(array32_index), optref(array32_index)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
1, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_SET(array32_index, WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_I32V(0)),
|
|
|
|
WASM_ARRAY_SET(array32_index, WASM_LOCAL_GET(1), WASM_I32V(1),
|
|
|
|
WASM_I32V(1)),
|
|
|
|
WASM_ARRAY_SET(array32_index, WASM_LOCAL_GET(1), WASM_I32V(2),
|
|
|
|
WASM_I32V(2)),
|
|
|
|
WASM_ARRAY_SET(array32_index, WASM_LOCAL_GET(1), WASM_I32V(3),
|
|
|
|
WASM_I32V(3)),
|
2021-09-15 12:59:42 +00:00
|
|
|
WASM_LOCAL_SET(
|
|
|
|
2, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_COPY(array32_index, array32_index, WASM_LOCAL_GET(2),
|
|
|
|
WASM_I32V(6), WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_I32V(4)),
|
|
|
|
WASM_ARRAY_GET(array32_index, WASM_LOCAL_GET(2), WASM_LOCAL_GET(0)),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
// Copies i16 ranges: local1[0..3] to local2[6..9].
|
|
|
|
const byte kCopyI16 = tester.DefineFunction(
|
|
|
|
tester.sigs.i_i(), {optref(array16_index), optref(array16_index)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
1, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array16_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array16_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_SET(array16_index, WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_I32V(0)),
|
|
|
|
WASM_ARRAY_SET(array16_index, WASM_LOCAL_GET(1), WASM_I32V(1),
|
|
|
|
WASM_I32V(1)),
|
|
|
|
WASM_ARRAY_SET(array16_index, WASM_LOCAL_GET(1), WASM_I32V(2),
|
|
|
|
WASM_I32V(2)),
|
|
|
|
WASM_ARRAY_SET(array16_index, WASM_LOCAL_GET(1), WASM_I32V(3),
|
|
|
|
WASM_I32V(3)),
|
2021-09-15 12:59:42 +00:00
|
|
|
WASM_LOCAL_SET(
|
|
|
|
2, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array16_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array16_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_COPY(array16_index, array16_index, WASM_LOCAL_GET(2),
|
|
|
|
WASM_I32V(6), WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_I32V(4)),
|
|
|
|
WASM_ARRAY_GET_S(array16_index, WASM_LOCAL_GET(2), WASM_LOCAL_GET(0)),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
// Copies reference ranges: local1[0..3] to local2[6..9].
|
|
|
|
const byte kCopyRef = tester.DefineFunction(
|
|
|
|
FunctionSig::Build(tester.zone(), {optref(array32_index)}, {kWasmI32}),
|
|
|
|
{optref(arrayref_index), optref(arrayref_index)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
1, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(arrayref_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(arrayref_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(6),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(1),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(7),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(2),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(8),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(3),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(9),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_LOCAL_SET(
|
|
|
|
2, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(arrayref_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(arrayref_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_COPY(arrayref_index, arrayref_index, WASM_LOCAL_GET(2),
|
|
|
|
WASM_I32V(6), WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_I32V(4)),
|
|
|
|
WASM_ARRAY_GET(arrayref_index, WASM_LOCAL_GET(2), WASM_LOCAL_GET(0)),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
// Copies overlapping reference ranges: local1[0..3] to local1[2..5].
|
|
|
|
const byte kCopyRefOverlapping = tester.DefineFunction(
|
|
|
|
FunctionSig::Build(tester.zone(), {optref(array32_index)}, {kWasmI32}),
|
|
|
|
{optref(arrayref_index)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
1, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(arrayref_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(arrayref_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(2),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(1),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(3),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(2),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(4),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_ARRAY_SET(
|
|
|
|
arrayref_index, WASM_LOCAL_GET(1), WASM_I32V(3),
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(5),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_COPY(arrayref_index, arrayref_index, WASM_LOCAL_GET(1),
|
|
|
|
WASM_I32V(2), WASM_LOCAL_GET(1), WASM_I32V(0),
|
|
|
|
WASM_I32V(4)),
|
|
|
|
WASM_ARRAY_GET(arrayref_index, WASM_LOCAL_GET(1), WASM_LOCAL_GET(0)),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
const byte kOobSource = tester.DefineFunction(
|
|
|
|
tester.sigs.v_v(), {optref(array32_index), optref(array32_index)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_LOCAL_SET(
|
|
|
|
1, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_COPY(array32_index, array32_index, WASM_LOCAL_GET(1),
|
|
|
|
WASM_I32V(6), WASM_LOCAL_GET(0), WASM_I32V(8),
|
|
|
|
WASM_I32V(4)),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
const byte kOobDestination = tester.DefineFunction(
|
|
|
|
tester.sigs.v_v(), {optref(array32_index), optref(array32_index)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
|
|
|
WASM_LOCAL_SET(
|
|
|
|
1, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array32_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array32_index))),
|
2021-05-26 15:47:27 +00:00
|
|
|
WASM_ARRAY_COPY(array32_index, array32_index, WASM_LOCAL_GET(1),
|
|
|
|
WASM_I32V(6), WASM_LOCAL_GET(0), WASM_I32V(3),
|
|
|
|
WASM_I32V(5)),
|
|
|
|
kExprEnd});
|
|
|
|
|
2021-09-30 12:02:45 +00:00
|
|
|
const byte kZeroLength = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {optref(arrayref_index), optref(arrayref_index)},
|
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(arrayref_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(arrayref_index))),
|
|
|
|
WASM_LOCAL_SET(
|
|
|
|
1, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(arrayref_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(arrayref_index))),
|
|
|
|
WASM_ARRAY_COPY(arrayref_index, arrayref_index, WASM_LOCAL_GET(1),
|
|
|
|
WASM_I32V(6), WASM_LOCAL_GET(0), WASM_I32V(3),
|
|
|
|
WASM_I32V(0)),
|
|
|
|
WASM_I32V(0), kExprEnd});
|
|
|
|
|
2021-05-26 15:47:27 +00:00
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(kCopyI32, 0, 5);
|
|
|
|
tester.CheckResult(kCopyI32, 0, 6);
|
|
|
|
tester.CheckResult(kCopyI32, 1, 7);
|
|
|
|
tester.CheckResult(kCopyI32, 2, 8);
|
|
|
|
tester.CheckResult(kCopyI32, 3, 9);
|
|
|
|
|
|
|
|
tester.CheckResult(kCopyI16, 0, 5);
|
|
|
|
tester.CheckResult(kCopyI16, 0, 6);
|
|
|
|
tester.CheckResult(kCopyI16, 1, 7);
|
|
|
|
tester.CheckResult(kCopyI16, 2, 8);
|
|
|
|
tester.CheckResult(kCopyI16, 3, 9);
|
|
|
|
|
|
|
|
{
|
|
|
|
Handle<Object> result5 =
|
|
|
|
tester.GetResultObject(kCopyRef, 5).ToHandleChecked();
|
|
|
|
CHECK(result5->IsNull());
|
|
|
|
for (int i = 6; i <= 9; i++) {
|
|
|
|
Handle<Object> res =
|
|
|
|
tester.GetResultObject(kCopyRef, i).ToHandleChecked();
|
|
|
|
CHECK(res->IsWasmArray());
|
|
|
|
CHECK_EQ(Handle<WasmArray>::cast(res)->length(),
|
|
|
|
static_cast<uint32_t>(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CHECK(tester.GetResultObject(kCopyRefOverlapping, 6)
|
|
|
|
.ToHandleChecked()
|
|
|
|
->IsNull());
|
|
|
|
Handle<Object> res0 =
|
|
|
|
tester.GetResultObject(kCopyRefOverlapping, 0).ToHandleChecked();
|
|
|
|
CHECK(res0->IsWasmArray());
|
|
|
|
CHECK_EQ(Handle<WasmArray>::cast(res0)->length(), static_cast<uint32_t>(2));
|
|
|
|
for (int i = 2; i <= 5; i++) {
|
|
|
|
Handle<Object> res =
|
|
|
|
tester.GetResultObject(kCopyRefOverlapping, i).ToHandleChecked();
|
|
|
|
CHECK(res->IsWasmArray());
|
|
|
|
CHECK_EQ(Handle<WasmArray>::cast(res)->length(), static_cast<uint32_t>(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
tester.CheckHasThrown(kOobSource);
|
|
|
|
tester.CheckHasThrown(kOobDestination);
|
2021-09-30 12:02:45 +00:00
|
|
|
tester.CheckResult(kZeroLength, 0); // Does not throw.
|
2020-06-05 20:22:45 +00:00
|
|
|
}
|
|
|
|
|
2020-12-17 00:37:09 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(NewDefault) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2022-04-05 16:02:13 +00:00
|
|
|
if (!tester.HasSimdSupport(execution_tier)) return;
|
2022-03-31 11:40:19 +00:00
|
|
|
|
|
|
|
tester.builder()->StartRecursiveTypeGroup();
|
2020-08-07 13:14:23 +00:00
|
|
|
const byte struct_type = tester.DefineStruct(
|
|
|
|
{F(wasm::kWasmI32, true), F(wasm::kWasmF64, true), F(optref(0), true)});
|
2022-03-31 11:40:19 +00:00
|
|
|
tester.builder()->EndRecursiveTypeGroup();
|
|
|
|
|
2020-08-07 13:14:23 +00:00
|
|
|
const byte array_type = tester.DefineArray(wasm::kWasmI32, true);
|
|
|
|
// Returns: struct[0] + f64_to_i32(struct[1]) + (struct[2].is_null ^ 1) == 0.
|
|
|
|
const byte allocate_struct = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {optref(struct_type)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
struct_type, WASM_RTT_CANON(struct_type))),
|
2020-08-07 13:14:23 +00:00
|
|
|
WASM_I32_ADD(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_I32_ADD(WASM_STRUCT_GET(struct_type, 0, WASM_LOCAL_GET(0)),
|
2020-08-07 13:14:23 +00:00
|
|
|
WASM_I32_SCONVERT_F64(WASM_STRUCT_GET(
|
2020-12-17 16:55:33 +00:00
|
|
|
struct_type, 1, WASM_LOCAL_GET(0)))),
|
2020-08-07 13:14:23 +00:00
|
|
|
WASM_I32_XOR(WASM_REF_IS_NULL(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_STRUCT_GET(struct_type, 2, WASM_LOCAL_GET(0))),
|
2020-08-07 13:14:23 +00:00
|
|
|
WASM_I32V(1))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte allocate_array = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {optref(array_type)},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_type, WASM_I32V(2),
|
|
|
|
WASM_RTT_CANON(array_type))),
|
2020-08-07 13:14:23 +00:00
|
|
|
WASM_I32_ADD(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_ARRAY_GET(array_type, WASM_LOCAL_GET(0), WASM_I32V(0)),
|
|
|
|
WASM_ARRAY_GET(array_type, WASM_LOCAL_GET(0), WASM_I32V(1))),
|
2020-08-07 13:14:23 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(allocate_struct, 0);
|
|
|
|
tester.CheckResult(allocate_array, 0);
|
|
|
|
}
|
|
|
|
|
2021-02-05 05:14:32 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(BasicRtt) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2021-01-27 15:13:43 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
2022-01-27 16:24:31 +00:00
|
|
|
const byte subtype_index = tester.DefineStruct(
|
|
|
|
{F(wasm::kWasmI32, true), F(wasm::kWasmI32, true)}, type_index);
|
2021-01-27 15:13:43 +00:00
|
|
|
|
2022-01-28 14:53:45 +00:00
|
|
|
ValueType kRttTypes[] = {ValueType::Rtt(type_index)};
|
2020-06-23 14:18:46 +00:00
|
|
|
FunctionSig sig_t_v(1, 0, kRttTypes);
|
2022-01-28 14:53:45 +00:00
|
|
|
ValueType kRttSubtypes[] = {ValueType::Rtt(subtype_index)};
|
2020-06-29 14:15:41 +00:00
|
|
|
FunctionSig sig_t2_v(1, 0, kRttSubtypes);
|
2022-01-28 14:53:45 +00:00
|
|
|
ValueType kRttTypesDeeper[] = {ValueType::Rtt(type_index)};
|
2020-07-09 12:44:30 +00:00
|
|
|
FunctionSig sig_t3_v(1, 0, kRttTypesDeeper);
|
2020-07-01 20:44:47 +00:00
|
|
|
ValueType kRefTypes[] = {ref(type_index)};
|
2020-06-30 18:11:27 +00:00
|
|
|
FunctionSig sig_q_v(1, 0, kRefTypes);
|
2020-06-23 14:18:46 +00:00
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kRttCanon = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
&sig_t_v, {}, {WASM_RTT_CANON(type_index), kExprEnd});
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kRttSub = tester.DefineFunction(
|
2022-01-27 16:24:31 +00:00
|
|
|
&sig_t2_v, {}, {WASM_RTT_CANON(subtype_index), kExprEnd});
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kStructWithRtt = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
&sig_q_v, {},
|
|
|
|
{WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
2021-01-27 15:13:43 +00:00
|
|
|
|
2020-07-01 20:44:47 +00:00
|
|
|
const int kFieldIndex = 1;
|
2021-02-05 05:14:32 +00:00
|
|
|
const int kStructIndexCode = 0;
|
2020-07-01 20:44:47 +00:00
|
|
|
// This implements the following function:
|
|
|
|
// var local_struct: type0;
|
2021-02-05 05:14:32 +00:00
|
|
|
// local_struct = new type1 with rtt 'kRttSub()';
|
|
|
|
// return (ref.test local_struct kRttSub()) +
|
|
|
|
// ((ref.cast local_struct kRttSub())[field0]);
|
2020-07-01 20:44:47 +00:00
|
|
|
// }
|
|
|
|
// The expected return value is 1+42 = 43.
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kRefCast = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_v(), {optref(type_index)},
|
2021-02-05 05:14:32 +00:00
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
kStructIndexCode,
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(subtype_index, WASM_I32V(11), WASM_I32V(42),
|
|
|
|
WASM_CALL_FUNCTION0(kRttSub))),
|
|
|
|
WASM_I32_ADD(
|
|
|
|
WASM_REF_TEST(WASM_LOCAL_GET(kStructIndexCode),
|
|
|
|
WASM_CALL_FUNCTION0(kRttSub)),
|
|
|
|
WASM_STRUCT_GET(subtype_index, kFieldIndex,
|
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(kStructIndexCode),
|
|
|
|
WASM_CALL_FUNCTION0(kRttSub)))),
|
2021-01-27 15:13:43 +00:00
|
|
|
kExprEnd});
|
2020-06-23 14:18:46 +00:00
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
Handle<Object> ref_result =
|
|
|
|
tester.GetResultObject(kRttCanon).ToHandleChecked();
|
2020-06-23 14:18:46 +00:00
|
|
|
|
|
|
|
CHECK(ref_result->IsMap());
|
|
|
|
Handle<Map> map = Handle<Map>::cast(ref_result);
|
|
|
|
CHECK(map->IsWasmStructMap());
|
|
|
|
CHECK_EQ(reinterpret_cast<Address>(
|
|
|
|
tester.instance()->module()->struct_type(type_index)),
|
|
|
|
map->wasm_type_info().foreign_address());
|
2020-06-29 14:15:41 +00:00
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
Handle<Object> subref_result =
|
|
|
|
tester.GetResultObject(kRttSub).ToHandleChecked();
|
2020-06-29 14:15:41 +00:00
|
|
|
CHECK(subref_result->IsMap());
|
|
|
|
Handle<Map> submap = Handle<Map>::cast(subref_result);
|
|
|
|
CHECK_EQ(reinterpret_cast<Address>(
|
|
|
|
tester.instance()->module()->struct_type(subtype_index)),
|
|
|
|
submap->wasm_type_info().foreign_address());
|
2020-07-09 12:44:30 +00:00
|
|
|
Handle<Object> subref_result_canonicalized =
|
|
|
|
tester.GetResultObject(kRttSub).ToHandleChecked();
|
|
|
|
CHECK(subref_result.is_identical_to(subref_result_canonicalized));
|
|
|
|
|
2020-07-07 19:14:38 +00:00
|
|
|
Handle<Object> s = tester.GetResultObject(kStructWithRtt).ToHandleChecked();
|
2020-06-30 18:11:27 +00:00
|
|
|
CHECK(s->IsWasmStruct());
|
|
|
|
CHECK_EQ(Handle<WasmStruct>::cast(s)->map(), *map);
|
2020-07-07 19:14:38 +00:00
|
|
|
|
|
|
|
tester.CheckResult(kRefCast, 43);
|
2020-06-23 14:18:46 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 08:27:47 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(RefTrivialCasts) {
|
2021-12-02 06:23:07 +00:00
|
|
|
// TODO(7748): Add tests for branch_on_*.
|
2021-03-16 08:27:47 +00:00
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
2022-01-27 16:24:31 +00:00
|
|
|
byte subtype_index = tester.DefineStruct(
|
|
|
|
{F(wasm::kWasmI32, true), F(wasm::kWasmS128, false)}, type_index);
|
2021-03-16 08:27:47 +00:00
|
|
|
ValueType sig_types[] = {kWasmS128, kWasmI32, kWasmF64};
|
|
|
|
FunctionSig sig(1, 2, sig_types);
|
|
|
|
byte sig_index = tester.DefineSignature(&sig);
|
|
|
|
|
|
|
|
const byte kRefTestNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST(WASM_REF_NULL(type_index), WASM_RTT_CANON(subtype_index)),
|
|
|
|
kExprEnd});
|
2021-12-02 06:23:07 +00:00
|
|
|
// Upcasts should not be optimized away for structural types.
|
2021-03-16 08:27:47 +00:00
|
|
|
const byte kRefTestUpcast = tester.DefineFunction(
|
2021-12-02 06:23:07 +00:00
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST(WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
subtype_index, WASM_RTT_CANON(subtype_index)),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
2021-03-16 08:27:47 +00:00
|
|
|
const byte kRefTestUpcastNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST(WASM_REF_NULL(subtype_index), WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefTestUnrelated = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
2022-01-27 16:24:31 +00:00
|
|
|
{WASM_REF_TEST(WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
subtype_index, WASM_RTT_CANON(subtype_index)),
|
|
|
|
WASM_RTT_CANON(sig_index)),
|
2021-03-16 08:27:47 +00:00
|
|
|
kExprEnd});
|
|
|
|
const byte kRefTestUnrelatedNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST(WASM_REF_NULL(subtype_index), WASM_RTT_CANON(sig_index)),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefTestUnrelatedNonNullable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_REF_TEST(WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
type_index, WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_RTT_CANON(sig_index)),
|
2021-03-16 08:27:47 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
const byte kRefCastNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST(WASM_REF_NULL(type_index),
|
|
|
|
WASM_RTT_CANON(subtype_index))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUpcast = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
2022-01-27 16:24:31 +00:00
|
|
|
{WASM_REF_IS_NULL(
|
|
|
|
WASM_REF_CAST(WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
subtype_index, WASM_RTT_CANON(subtype_index)),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
2021-03-16 08:27:47 +00:00
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUpcastNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST(WASM_REF_NULL(subtype_index),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUnrelated = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
2022-01-27 16:24:31 +00:00
|
|
|
{WASM_REF_IS_NULL(
|
|
|
|
WASM_REF_CAST(WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
subtype_index, WASM_RTT_CANON(subtype_index)),
|
|
|
|
WASM_RTT_CANON(sig_index))),
|
2021-03-16 08:27:47 +00:00
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUnrelatedNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST(WASM_REF_NULL(subtype_index),
|
|
|
|
WASM_RTT_CANON(sig_index))),
|
|
|
|
kExprEnd});
|
2021-09-15 12:59:42 +00:00
|
|
|
const byte kRefCastUnrelatedNonNullable =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST(
|
|
|
|
WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
type_index, WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_RTT_CANON(sig_index))),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(kRefTestNull, 0);
|
|
|
|
tester.CheckResult(kRefTestUpcast, 1);
|
|
|
|
tester.CheckResult(kRefTestUpcastNull, 0);
|
|
|
|
tester.CheckResult(kRefTestUnrelated, 0);
|
|
|
|
tester.CheckResult(kRefTestUnrelatedNull, 0);
|
|
|
|
tester.CheckResult(kRefTestUnrelatedNonNullable, 0);
|
|
|
|
|
|
|
|
tester.CheckResult(kRefCastNull, 1);
|
|
|
|
tester.CheckResult(kRefCastUpcast, 0);
|
|
|
|
tester.CheckResult(kRefCastUpcastNull, 1);
|
|
|
|
tester.CheckHasThrown(kRefCastUnrelated);
|
|
|
|
tester.CheckResult(kRefCastUnrelatedNull, 1);
|
|
|
|
tester.CheckHasThrown(kRefCastUnrelatedNonNullable);
|
|
|
|
}
|
|
|
|
|
|
|
|
WASM_COMPILED_EXEC_TEST(RefTrivialCastsStatic) {
|
2021-12-02 06:23:07 +00:00
|
|
|
// TODO(7748): Add tests for branch_on_*.
|
2021-09-15 12:59:42 +00:00
|
|
|
WasmGCTester tester(execution_tier);
|
2022-01-27 16:24:31 +00:00
|
|
|
byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
2021-09-15 12:59:42 +00:00
|
|
|
byte subtype_index = tester.DefineStruct(
|
|
|
|
{F(wasm::kWasmI32, true), F(wasm::kWasmS128, false)}, type_index);
|
|
|
|
ValueType sig_types[] = {kWasmS128, kWasmI32, kWasmF64};
|
|
|
|
FunctionSig sig(1, 2, sig_types);
|
|
|
|
byte sig_index = tester.DefineSignature(&sig);
|
|
|
|
|
|
|
|
const byte kRefTestNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST_STATIC(WASM_REF_NULL(type_index), subtype_index),
|
|
|
|
kExprEnd});
|
2021-12-02 06:23:07 +00:00
|
|
|
// Upcasts should be optimized away for nominal types.
|
2021-09-15 12:59:42 +00:00
|
|
|
const byte kRefTestUpcast = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST_STATIC(WASM_STRUCT_NEW_DEFAULT(subtype_index), type_index),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefTestUpcastNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST_STATIC(WASM_REF_NULL(subtype_index), type_index),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefTestUnrelated = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST_STATIC(WASM_STRUCT_NEW_DEFAULT(subtype_index), sig_index),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefTestUnrelatedNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST_STATIC(WASM_REF_NULL(subtype_index), sig_index),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefTestUnrelatedNonNullable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_TEST_STATIC(WASM_STRUCT_NEW_DEFAULT(type_index), sig_index),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
const byte kRefCastNull =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST_STATIC(
|
|
|
|
WASM_REF_NULL(type_index), subtype_index)),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUpcast = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST_STATIC(
|
|
|
|
WASM_STRUCT_NEW_DEFAULT(subtype_index), type_index)),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUpcastNull =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST_STATIC(
|
|
|
|
WASM_REF_NULL(subtype_index), type_index)),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUnrelated = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST_STATIC(
|
|
|
|
WASM_STRUCT_NEW_DEFAULT(subtype_index), sig_index)),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kRefCastUnrelatedNull =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST_STATIC(
|
|
|
|
WASM_REF_NULL(subtype_index), sig_index)),
|
|
|
|
kExprEnd});
|
2021-03-16 08:27:47 +00:00
|
|
|
const byte kRefCastUnrelatedNonNullable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
2021-09-15 12:59:42 +00:00
|
|
|
{WASM_REF_IS_NULL(WASM_REF_CAST_STATIC(
|
|
|
|
WASM_STRUCT_NEW_DEFAULT(type_index), sig_index)),
|
2021-03-16 08:27:47 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(kRefTestNull, 0);
|
|
|
|
tester.CheckResult(kRefTestUpcast, 1);
|
|
|
|
tester.CheckResult(kRefTestUpcastNull, 0);
|
|
|
|
tester.CheckResult(kRefTestUnrelated, 0);
|
|
|
|
tester.CheckResult(kRefTestUnrelatedNull, 0);
|
|
|
|
tester.CheckResult(kRefTestUnrelatedNonNullable, 0);
|
|
|
|
|
|
|
|
tester.CheckResult(kRefCastNull, 1);
|
|
|
|
tester.CheckResult(kRefCastUpcast, 0);
|
|
|
|
tester.CheckResult(kRefCastUpcastNull, 1);
|
|
|
|
tester.CheckHasThrown(kRefCastUnrelated);
|
|
|
|
tester.CheckResult(kRefCastUnrelatedNull, 1);
|
|
|
|
tester.CheckHasThrown(kRefCastUnrelatedNonNullable);
|
|
|
|
}
|
|
|
|
|
2022-02-13 22:57:59 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(TrivialAbstractCasts) {
|
|
|
|
// TODO(7748): Add tests for branch_on_*.
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
byte type_index = tester.DefineArray(wasm::kWasmI32, true);
|
|
|
|
byte struct_type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
|
|
|
ValueType sig_types[] = {kWasmS128, kWasmI32, kWasmF64};
|
|
|
|
FunctionSig sig(1, 2, sig_types);
|
|
|
|
|
|
|
|
const byte kIsArrayNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_ARRAY(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
|
|
|
const byte kIsArrayUpcast = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_ARRAY(WASM_ARRAY_NEW_DEFAULT_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(10), WASM_RTT_CANON(type_index))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kIsArrayUpcastNullable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(type_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(type_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
WASM_REF_IS_ARRAY(WASM_LOCAL_GET(0)), kExprEnd});
|
|
|
|
const byte kIsArrayUpcastNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_ARRAY(WASM_REF_NULL(type_index)), kExprEnd});
|
|
|
|
const byte kIsArrayUnrelated = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(struct_type_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
struct_type_index, WASM_RTT_CANON(struct_type_index))),
|
|
|
|
WASM_REF_IS_ARRAY(WASM_LOCAL_GET(0)), kExprEnd});
|
|
|
|
const byte kIsArrayUnrelatedNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_ARRAY(WASM_REF_NULL(kI31RefCode)), kExprEnd});
|
|
|
|
const byte kIsArrayUnrelatedNonNullable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_ARRAY(WASM_I31_NEW(WASM_I32V(10))), kExprEnd});
|
|
|
|
|
|
|
|
const byte kAsArrayNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_REF_NULL(kAnyRefCode))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kAsArrayUpcast = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_ARRAY_NEW_DEFAULT_WITH_RTT(
|
|
|
|
type_index, WASM_I32V(10), WASM_RTT_CANON(type_index)))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kAsArrayUpcastNullable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(type_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(type_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(type_index))),
|
|
|
|
WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_LOCAL_GET(0))), kExprEnd});
|
|
|
|
const byte kAsArrayUpcastNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_REF_NULL(type_index))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kAsArrayUnrelated = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {ValueType::Ref(struct_type_index, kNullable)},
|
|
|
|
{WASM_LOCAL_SET(
|
|
|
|
0, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
struct_type_index, WASM_RTT_CANON(struct_type_index))),
|
|
|
|
WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_LOCAL_GET(0))), kExprEnd});
|
|
|
|
const byte kAsArrayUnrelatedNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_REF_NULL(kI31RefCode))),
|
|
|
|
kExprEnd});
|
|
|
|
const byte kAsArrayUnrelatedNonNullable = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_NULL(WASM_REF_AS_ARRAY(WASM_I31_NEW(WASM_I32V(10)))),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(kIsArrayNull, 0);
|
|
|
|
tester.CheckResult(kIsArrayUpcast, 1);
|
|
|
|
tester.CheckResult(kIsArrayUpcastNullable, 1);
|
|
|
|
tester.CheckResult(kIsArrayUpcastNull, 0);
|
|
|
|
tester.CheckResult(kIsArrayUnrelated, 0);
|
|
|
|
tester.CheckResult(kIsArrayUnrelatedNull, 0);
|
|
|
|
tester.CheckResult(kIsArrayUnrelatedNonNullable, 0);
|
|
|
|
|
|
|
|
tester.CheckHasThrown(kAsArrayNull);
|
|
|
|
tester.CheckResult(kAsArrayUpcast, 0);
|
|
|
|
tester.CheckResult(kAsArrayUpcastNullable, 0);
|
|
|
|
tester.CheckHasThrown(kAsArrayUpcastNull);
|
|
|
|
tester.CheckHasThrown(kAsArrayUnrelated);
|
|
|
|
tester.CheckHasThrown(kAsArrayUnrelatedNull);
|
|
|
|
tester.CheckHasThrown(kAsArrayUnrelatedNonNullable);
|
|
|
|
}
|
|
|
|
|
2021-02-05 03:35:19 +00:00
|
|
|
WASM_EXEC_TEST(NoDepthRtt) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2021-01-27 15:13:43 +00:00
|
|
|
|
|
|
|
const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
2022-01-27 16:24:31 +00:00
|
|
|
const byte subtype_index = tester.DefineStruct(
|
|
|
|
{F(wasm::kWasmI32, true), F(wasm::kWasmI32, true)}, type_index);
|
2021-01-27 15:13:43 +00:00
|
|
|
|
2021-03-16 08:27:47 +00:00
|
|
|
ValueType kRttTypeNoDepth = ValueType::Rtt(type_index);
|
|
|
|
FunctionSig sig_t1_v_nd(1, 0, &kRttTypeNoDepth);
|
2021-01-27 15:13:43 +00:00
|
|
|
ValueType kRttSubtypeNoDepth = ValueType::Rtt(subtype_index);
|
|
|
|
FunctionSig sig_t2_v_nd(1, 0, &kRttSubtypeNoDepth);
|
|
|
|
|
|
|
|
const byte kRttSubtypeCanon = tester.DefineFunction(
|
|
|
|
&sig_t2_v_nd, {}, {WASM_RTT_CANON(subtype_index), kExprEnd});
|
|
|
|
|
|
|
|
const byte kTestCanon = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {optref(type_index)},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_WITH_RTT(
|
|
|
|
subtype_index, WASM_I32V(11), WASM_I32V(42),
|
|
|
|
WASM_RTT_CANON(subtype_index))),
|
2021-01-28 15:18:41 +00:00
|
|
|
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_CALL_FUNCTION0(kRttSubtypeCanon)),
|
2021-01-27 15:13:43 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(kTestCanon, 1);
|
|
|
|
}
|
|
|
|
|
2020-12-17 00:37:09 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(ArrayNewMap) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte type_index = tester.DefineArray(kWasmI32, true);
|
2020-07-21 07:57:27 +00:00
|
|
|
|
|
|
|
ValueType array_type = ValueType::Ref(type_index, kNonNullable);
|
|
|
|
FunctionSig sig(1, 0, &array_type);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte array_new_with_rtt = tester.DefineFunction(
|
2020-07-21 07:57:27 +00:00
|
|
|
&sig, {},
|
|
|
|
{WASM_ARRAY_NEW_WITH_RTT(type_index, WASM_I32V(10), WASM_I32V(42),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
2021-09-15 12:59:42 +00:00
|
|
|
const byte array_new_nominal = tester.DefineFunction(
|
|
|
|
&sig, {},
|
|
|
|
{WASM_ARRAY_NEW(type_index, WASM_I32V(10), WASM_I32V(42)), kExprEnd});
|
2020-07-21 07:57:27 +00:00
|
|
|
|
2022-01-28 14:53:45 +00:00
|
|
|
ValueType rtt_type = ValueType::Rtt(type_index);
|
2020-07-21 07:57:27 +00:00
|
|
|
FunctionSig rtt_canon_sig(1, 0, &rtt_type);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kRttCanon = tester.DefineFunction(
|
2020-07-21 07:57:27 +00:00
|
|
|
&rtt_canon_sig, {}, {WASM_RTT_CANON(type_index), kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
Handle<Object> map = tester.GetResultObject(kRttCanon).ToHandleChecked();
|
|
|
|
|
|
|
|
Handle<Object> result =
|
|
|
|
tester.GetResultObject(array_new_with_rtt).ToHandleChecked();
|
|
|
|
CHECK(result->IsWasmArray());
|
|
|
|
CHECK_EQ(Handle<WasmArray>::cast(result)->map(), *map);
|
2021-09-15 12:59:42 +00:00
|
|
|
|
|
|
|
result = tester.GetResultObject(array_new_nominal).ToHandleChecked();
|
|
|
|
CHECK(result->IsWasmArray());
|
|
|
|
CHECK_EQ(Handle<WasmArray>::cast(result)->map(), *map);
|
2020-07-21 07:57:27 +00:00
|
|
|
}
|
|
|
|
|
2021-01-22 20:44:31 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(FunctionRefs) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-05 11:12:29 +00:00
|
|
|
const byte func_index =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {}, {WASM_I32V(42), kExprEnd});
|
|
|
|
const byte sig_index = 0;
|
|
|
|
|
|
|
|
const byte other_sig_index = tester.DefineSignature(tester.sigs.d_d());
|
|
|
|
|
|
|
|
// This is just so func_index counts as "declared".
|
|
|
|
tester.AddGlobal(ValueType::Ref(sig_index, kNullable), false,
|
|
|
|
WasmInitExpr::RefFuncConst(func_index));
|
|
|
|
|
2021-01-27 09:58:43 +00:00
|
|
|
ValueType func_type = ValueType::Ref(sig_index, kNullable);
|
2020-08-05 11:12:29 +00:00
|
|
|
FunctionSig sig_func(1, 0, &func_type);
|
|
|
|
|
2022-01-28 14:53:45 +00:00
|
|
|
ValueType rtt0 = ValueType::Rtt(sig_index);
|
Reland "[wasm-gc] Remove abstract rtts"
This is a reland of b77deeca4bd65b006a3a6c7344c2bbabd4514122
Changes compared to original: Add explicit narrowing casts in tests
for MSVC.
Original change's description:
> [wasm-gc] Remove abstract rtts
>
> In the latest wasm-gc spec, rtts of abstract types are no longer
> allowed. Consequently, canonical rtts of concrete types always have
> a depth of 0.
>
> Changes:
> - Change the immediate argument of rtts to a type index over a heap
> type. Abstract it with TypeIndexImmediate in function body decoding.
> This affects:
> value_type.h, read_value_type(), decoding of relevant opcodes,
> wasm subtyping, WasmInitExpr, consume_init_expr(), and
> wasm-module-builder.cc.
> - In function-body-decoder-impl.h, update rtt.canon to always produce
> an rtt of depth 0.
> - Pass a unit32_t type index over a HeapType to all rtt-related
> utilities.
> - Remove infrastructure for abstract-type rtts from the wasm compilers,
> setup-heap-internal.cc, roots.h, and module-instantiate.cc.
> - Remove ObjectReferenceKnowledge::rtt_is_i31. Remove related branches
> from ref.test, ref.cast and br_on_cast implementations in the wasm
> compilers.
> - Remove unused 'parent' field from WasmTypeInfo.
> - Make the parent argument optional in NewWasmTypeInfo, CreateStructMap,
> and CreateArrayMap.
> - Use more convenient arguments in IsHeapSubtypeOf.
> - Update tests.
>
> Bug: v8:7748
> Change-Id: Ib45efe0741e6558c9b291fc8b4a75ae303146bdc
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2642248
> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#72321}
Bug: v8:7748
Change-Id: I22b204b486fd185077cd6c7f15d492f5143f48fe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2650207
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72355}
2021-01-27 08:33:32 +00:00
|
|
|
FunctionSig sig_rtt0(1, 0, &rtt0);
|
2020-08-05 11:12:29 +00:00
|
|
|
const byte rtt_canon = tester.DefineFunction(
|
Reland "[wasm-gc] Remove abstract rtts"
This is a reland of b77deeca4bd65b006a3a6c7344c2bbabd4514122
Changes compared to original: Add explicit narrowing casts in tests
for MSVC.
Original change's description:
> [wasm-gc] Remove abstract rtts
>
> In the latest wasm-gc spec, rtts of abstract types are no longer
> allowed. Consequently, canonical rtts of concrete types always have
> a depth of 0.
>
> Changes:
> - Change the immediate argument of rtts to a type index over a heap
> type. Abstract it with TypeIndexImmediate in function body decoding.
> This affects:
> value_type.h, read_value_type(), decoding of relevant opcodes,
> wasm subtyping, WasmInitExpr, consume_init_expr(), and
> wasm-module-builder.cc.
> - In function-body-decoder-impl.h, update rtt.canon to always produce
> an rtt of depth 0.
> - Pass a unit32_t type index over a HeapType to all rtt-related
> utilities.
> - Remove infrastructure for abstract-type rtts from the wasm compilers,
> setup-heap-internal.cc, roots.h, and module-instantiate.cc.
> - Remove ObjectReferenceKnowledge::rtt_is_i31. Remove related branches
> from ref.test, ref.cast and br_on_cast implementations in the wasm
> compilers.
> - Remove unused 'parent' field from WasmTypeInfo.
> - Make the parent argument optional in NewWasmTypeInfo, CreateStructMap,
> and CreateArrayMap.
> - Use more convenient arguments in IsHeapSubtypeOf.
> - Update tests.
>
> Bug: v8:7748
> Change-Id: Ib45efe0741e6558c9b291fc8b4a75ae303146bdc
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2642248
> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#72321}
Bug: v8:7748
Change-Id: I22b204b486fd185077cd6c7f15d492f5143f48fe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2650207
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72355}
2021-01-27 08:33:32 +00:00
|
|
|
&sig_rtt0, {}, {WASM_RTT_CANON(sig_index), kExprEnd});
|
2020-08-05 11:12:29 +00:00
|
|
|
|
|
|
|
const byte cast = tester.DefineFunction(
|
|
|
|
&sig_func, {kWasmFuncRef},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)),
|
2021-01-28 15:18:41 +00:00
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(sig_index)), kExprEnd});
|
2020-08-05 11:12:29 +00:00
|
|
|
|
|
|
|
const byte cast_reference = tester.DefineFunction(
|
|
|
|
&sig_func, {}, {WASM_REF_FUNC(sig_index), kExprEnd});
|
|
|
|
|
2021-01-28 15:18:41 +00:00
|
|
|
const byte test = tester.DefineFunction(
|
2021-02-01 06:39:50 +00:00
|
|
|
tester.sigs.i_v(), {kWasmFuncRef},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)),
|
|
|
|
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_RTT_CANON(sig_index)), kExprEnd});
|
|
|
|
|
2022-01-27 16:24:31 +00:00
|
|
|
const byte test_fail = tester.DefineFunction(
|
2021-01-28 15:18:41 +00:00
|
|
|
tester.sigs.i_v(), {kWasmFuncRef},
|
|
|
|
{WASM_LOCAL_SET(0, WASM_REF_FUNC(func_index)),
|
|
|
|
WASM_REF_TEST(WASM_LOCAL_GET(0), WASM_RTT_CANON(other_sig_index)),
|
|
|
|
kExprEnd});
|
2020-08-05 11:12:29 +00:00
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
Handle<Object> result_canon =
|
|
|
|
tester.GetResultObject(rtt_canon).ToHandleChecked();
|
|
|
|
CHECK(result_canon->IsMap());
|
|
|
|
Handle<Map> map_canon = Handle<Map>::cast(result_canon);
|
[wasm] Internal representation for function references
Design doc: bit.ly/3jEVgzz
We separate the internal representation of function references in Wasm
from their JSFunction-based (external) representation. This improves
performance of call_ref by requiring less indirections to load the
context and call target from a function reference. In the boundary
between wasm and JS/the C API, we add transformations between the two
representations.
Detailed changes:
- Introduce WasmInternalFunction, containing fields required by
call_ref, as well as a reference to the corresponding
WasmExternalFunction. Add a reference to the WasmInternalFunction in
WasmFunctionData. The {WasmInternalFunction::FromExternal} helper
extracts the internal out of an external function.
- Change {WasmInstanceObject::external_functions()} to internal
functions.
- Change wasm function tables to contain internal functions.
- Change the following code to use internal functions:
- call_ref in liftoff and Turbofan
- function type checks in liftoff and Turbofan
- CallRefIC and GenericJSToWasmWrapper builtins
- {InitExprInterface::RefFunc}
- module-compiler.cc in {ProcessTypeFeedback}
- In module-instantiate.cc, in function-rtt creation.
- Add transformations between internal and external functions in:
- WasmWrapperGraphBuilder::{ToJS, BuildUnpackObjectWrapper, FromJS,
BuildJSToJSWrapper}.
- debug-wasm-objects.cc in {FunctionProxy::Get},
{WasmValueObject::New} and {AddWasmTableObjectInternalProperties}.
- runtime-wasm.cc in ReplaceWrapper
- the C and JS APIs
- module-instantiate.cc, in import and export processing, as well as
{InitializeIndirectFunctionTables}
- WasmTableObject::{IsValidElement, SetFunctionTableEntry}
- {WasmGlobalObject::SetFuncRef}
- Simplify body descriptors of WasmExternalFunction variants.
- Adjust tests.
Bug: v8:11510
Change-Id: I8377f46f55c3771391ae1c5c8201a83854ee7878
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3277878
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78068}
2021-11-23 14:31:18 +00:00
|
|
|
CHECK(map_canon->IsWasmInternalFunctionMap());
|
2020-08-05 11:12:29 +00:00
|
|
|
|
|
|
|
Handle<Object> result_cast = tester.GetResultObject(cast).ToHandleChecked();
|
[wasm] Internal representation for function references
Design doc: bit.ly/3jEVgzz
We separate the internal representation of function references in Wasm
from their JSFunction-based (external) representation. This improves
performance of call_ref by requiring less indirections to load the
context and call target from a function reference. In the boundary
between wasm and JS/the C API, we add transformations between the two
representations.
Detailed changes:
- Introduce WasmInternalFunction, containing fields required by
call_ref, as well as a reference to the corresponding
WasmExternalFunction. Add a reference to the WasmInternalFunction in
WasmFunctionData. The {WasmInternalFunction::FromExternal} helper
extracts the internal out of an external function.
- Change {WasmInstanceObject::external_functions()} to internal
functions.
- Change wasm function tables to contain internal functions.
- Change the following code to use internal functions:
- call_ref in liftoff and Turbofan
- function type checks in liftoff and Turbofan
- CallRefIC and GenericJSToWasmWrapper builtins
- {InitExprInterface::RefFunc}
- module-compiler.cc in {ProcessTypeFeedback}
- In module-instantiate.cc, in function-rtt creation.
- Add transformations between internal and external functions in:
- WasmWrapperGraphBuilder::{ToJS, BuildUnpackObjectWrapper, FromJS,
BuildJSToJSWrapper}.
- debug-wasm-objects.cc in {FunctionProxy::Get},
{WasmValueObject::New} and {AddWasmTableObjectInternalProperties}.
- runtime-wasm.cc in ReplaceWrapper
- the C and JS APIs
- module-instantiate.cc, in import and export processing, as well as
{InitializeIndirectFunctionTables}
- WasmTableObject::{IsValidElement, SetFunctionTableEntry}
- {WasmGlobalObject::SetFuncRef}
- Simplify body descriptors of WasmExternalFunction variants.
- Adjust tests.
Bug: v8:11510
Change-Id: I8377f46f55c3771391ae1c5c8201a83854ee7878
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3277878
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78068}
2021-11-23 14:31:18 +00:00
|
|
|
CHECK(result_cast->IsWasmInternalFunction());
|
|
|
|
Handle<JSFunction> cast_function = Handle<JSFunction>::cast(
|
|
|
|
handle(Handle<WasmInternalFunction>::cast(result_cast)->external(),
|
|
|
|
tester.isolate()));
|
2020-08-05 11:12:29 +00:00
|
|
|
|
|
|
|
Handle<Object> result_cast_reference =
|
|
|
|
tester.GetResultObject(cast_reference).ToHandleChecked();
|
[wasm] Internal representation for function references
Design doc: bit.ly/3jEVgzz
We separate the internal representation of function references in Wasm
from their JSFunction-based (external) representation. This improves
performance of call_ref by requiring less indirections to load the
context and call target from a function reference. In the boundary
between wasm and JS/the C API, we add transformations between the two
representations.
Detailed changes:
- Introduce WasmInternalFunction, containing fields required by
call_ref, as well as a reference to the corresponding
WasmExternalFunction. Add a reference to the WasmInternalFunction in
WasmFunctionData. The {WasmInternalFunction::FromExternal} helper
extracts the internal out of an external function.
- Change {WasmInstanceObject::external_functions()} to internal
functions.
- Change wasm function tables to contain internal functions.
- Change the following code to use internal functions:
- call_ref in liftoff and Turbofan
- function type checks in liftoff and Turbofan
- CallRefIC and GenericJSToWasmWrapper builtins
- {InitExprInterface::RefFunc}
- module-compiler.cc in {ProcessTypeFeedback}
- In module-instantiate.cc, in function-rtt creation.
- Add transformations between internal and external functions in:
- WasmWrapperGraphBuilder::{ToJS, BuildUnpackObjectWrapper, FromJS,
BuildJSToJSWrapper}.
- debug-wasm-objects.cc in {FunctionProxy::Get},
{WasmValueObject::New} and {AddWasmTableObjectInternalProperties}.
- runtime-wasm.cc in ReplaceWrapper
- the C and JS APIs
- module-instantiate.cc, in import and export processing, as well as
{InitializeIndirectFunctionTables}
- WasmTableObject::{IsValidElement, SetFunctionTableEntry}
- {WasmGlobalObject::SetFuncRef}
- Simplify body descriptors of WasmExternalFunction variants.
- Adjust tests.
Bug: v8:11510
Change-Id: I8377f46f55c3771391ae1c5c8201a83854ee7878
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3277878
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78068}
2021-11-23 14:31:18 +00:00
|
|
|
CHECK(result_cast_reference->IsWasmInternalFunction());
|
|
|
|
Handle<JSFunction> cast_function_reference = Handle<JSFunction>::cast(handle(
|
|
|
|
Handle<WasmInternalFunction>::cast(result_cast_reference)->external(),
|
|
|
|
tester.isolate()));
|
2020-08-05 11:12:29 +00:00
|
|
|
|
2021-12-14 17:07:38 +00:00
|
|
|
CHECK_EQ(cast_function->code().raw_instruction_start(),
|
|
|
|
cast_function_reference->code().raw_instruction_start());
|
2020-08-05 11:12:29 +00:00
|
|
|
|
2021-02-01 06:39:50 +00:00
|
|
|
tester.CheckResult(test, 1);
|
2022-01-27 16:24:31 +00:00
|
|
|
tester.CheckResult(test_fail, 0);
|
2020-08-05 11:12:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-22 20:44:31 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(CallRef) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-14 17:17:54 +00:00
|
|
|
byte callee = tester.DefineFunction(
|
|
|
|
tester.sigs.i_ii(), {},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_I32_ADD(WASM_LOCAL_GET(0), WASM_LOCAL_GET(1)), kExprEnd});
|
2020-08-14 17:17:54 +00:00
|
|
|
byte caller = tester.DefineFunction(
|
|
|
|
tester.sigs.i_i(), {},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_CALL_REF(WASM_REF_FUNC(callee), WASM_I32V(42), WASM_LOCAL_GET(0)),
|
2020-08-14 17:17:54 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
// This is just so func_index counts as "declared".
|
|
|
|
tester.AddGlobal(ValueType::Ref(0, kNullable), false,
|
|
|
|
WasmInitExpr::RefFuncConst(callee));
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(caller, 47, 5);
|
|
|
|
}
|
|
|
|
|
2021-03-24 11:17:58 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(CallReftypeParameters) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
|
|
|
byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
|
|
|
ValueType kRefType{optref(type_index)};
|
|
|
|
ValueType sig_types[] = {kWasmI32, kRefType, kRefType, kRefType, kRefType,
|
|
|
|
kWasmI32, kWasmI32, kWasmI32, kWasmI32};
|
|
|
|
FunctionSig sig(1, 8, sig_types);
|
|
|
|
byte adder = tester.DefineFunction(
|
|
|
|
&sig, {},
|
|
|
|
{WASM_I32_ADD(
|
|
|
|
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(0)),
|
|
|
|
WASM_I32_ADD(
|
|
|
|
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(1)),
|
|
|
|
WASM_I32_ADD(
|
|
|
|
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(2)),
|
|
|
|
WASM_I32_ADD(
|
|
|
|
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(3)),
|
|
|
|
WASM_I32_ADD(
|
|
|
|
WASM_LOCAL_GET(4),
|
|
|
|
WASM_I32_ADD(WASM_LOCAL_GET(5),
|
|
|
|
WASM_I32_ADD(WASM_LOCAL_GET(6),
|
|
|
|
WASM_LOCAL_GET(7)))))))),
|
|
|
|
kExprEnd});
|
|
|
|
byte caller = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_CALL_FUNCTION(adder,
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(2),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(4),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(8),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(16),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
WASM_I32V(32), WASM_I32V(64), WASM_I32V(128),
|
|
|
|
WASM_I32V(256)),
|
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(caller, 510);
|
|
|
|
}
|
|
|
|
|
2021-02-01 06:11:17 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2021-01-29 13:58:08 +00:00
|
|
|
|
|
|
|
byte array_index = tester.DefineArray(kWasmI32, true);
|
2022-01-12 06:32:48 +00:00
|
|
|
byte struct_index = tester.DefineStruct({F(kWasmI32, true)});
|
2021-01-29 13:58:08 +00:00
|
|
|
byte function_index =
|
|
|
|
tester.DefineFunction(tester.sigs.v_v(), {}, {kExprEnd});
|
2022-01-12 06:32:48 +00:00
|
|
|
byte sig_index = 2;
|
2021-01-29 13:58:08 +00:00
|
|
|
|
|
|
|
// This is just so func_index counts as "declared".
|
|
|
|
tester.AddGlobal(ValueType::Ref(sig_index, kNullable), false,
|
|
|
|
WasmInitExpr::RefFuncConst(function_index));
|
|
|
|
|
|
|
|
byte kDataCheckNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_DATA(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
2022-01-12 06:32:48 +00:00
|
|
|
byte kArrayCheckNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_ARRAY(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kFuncCheckNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_FUNC(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
|
|
|
byte kI31CheckNull = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_IS_I31(WASM_REF_NULL(kAnyRefCode)), kExprEnd});
|
|
|
|
|
|
|
|
byte kDataCastNull =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_AS_DATA(WASM_REF_NULL(kAnyRefCode)),
|
|
|
|
WASM_DROP, WASM_I32V(1), kExprEnd});
|
2022-01-12 06:32:48 +00:00
|
|
|
byte kArrayCastNull =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_AS_ARRAY(WASM_REF_NULL(kAnyRefCode)),
|
|
|
|
WASM_DROP, WASM_I32V(1), kExprEnd});
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kFuncCastNull =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_AS_FUNC(WASM_REF_NULL(kAnyRefCode)),
|
|
|
|
WASM_DROP, WASM_I32V(1), kExprEnd});
|
|
|
|
byte kI31CastNull =
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {},
|
|
|
|
{WASM_REF_AS_I31(WASM_REF_NULL(kAnyRefCode)),
|
|
|
|
WASM_DROP, WASM_I32V(1), kExprEnd});
|
|
|
|
|
|
|
|
#define TYPE_CHECK(type, value) \
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {kWasmAnyRef}, \
|
|
|
|
{WASM_LOCAL_SET(0, WASM_SEQ(value)), \
|
|
|
|
WASM_REF_IS_##type(WASM_LOCAL_GET(0)), kExprEnd})
|
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
byte kDataCheckSuccess = TYPE_CHECK(
|
|
|
|
DATA, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kDataCheckFailure = TYPE_CHECK(DATA, WASM_I31_NEW(WASM_I32V(42)));
|
2022-01-12 06:32:48 +00:00
|
|
|
byte kArrayCheckSuccess = TYPE_CHECK(
|
|
|
|
ARRAY, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
|
|
|
byte kArrayCheckFailure =
|
|
|
|
TYPE_CHECK(ARRAY, WASM_STRUCT_NEW_DEFAULT_WITH_RTT(
|
|
|
|
struct_index, WASM_RTT_CANON(struct_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kFuncCheckSuccess = TYPE_CHECK(FUNC, WASM_REF_FUNC(function_index));
|
2021-09-15 12:59:42 +00:00
|
|
|
byte kFuncCheckFailure = TYPE_CHECK(
|
|
|
|
FUNC, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kI31CheckSuccess = TYPE_CHECK(I31, WASM_I31_NEW(WASM_I32V(42)));
|
2021-09-15 12:59:42 +00:00
|
|
|
byte kI31CheckFailure = TYPE_CHECK(
|
|
|
|
I31, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
#undef TYPE_CHECK
|
|
|
|
|
|
|
|
#define TYPE_CAST(type, value) \
|
|
|
|
tester.DefineFunction(tester.sigs.i_v(), {kWasmAnyRef}, \
|
|
|
|
{WASM_LOCAL_SET(0, WASM_SEQ(value)), \
|
|
|
|
WASM_REF_AS_##type(WASM_LOCAL_GET(0)), WASM_DROP, \
|
|
|
|
WASM_I32V(1), kExprEnd})
|
|
|
|
|
2021-09-15 12:59:42 +00:00
|
|
|
byte kDataCastSuccess = TYPE_CAST(
|
|
|
|
DATA, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kDataCastFailure = TYPE_CAST(DATA, WASM_I31_NEW(WASM_I32V(42)));
|
2022-01-12 06:32:48 +00:00
|
|
|
byte kArrayCastSuccess = TYPE_CAST(
|
|
|
|
DATA, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
|
|
|
byte kArrayCastFailure = TYPE_CAST(DATA, WASM_I31_NEW(WASM_I32V(42)));
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kFuncCastSuccess = TYPE_CAST(FUNC, WASM_REF_FUNC(function_index));
|
2021-09-15 12:59:42 +00:00
|
|
|
byte kFuncCastFailure = TYPE_CAST(
|
|
|
|
FUNC, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
2021-01-29 13:58:08 +00:00
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-09-15 12:59:42 +00:00
|
|
|
byte kI31CastSuccess = TYPE_CAST(I31, WASM_I31_NEW(WASM_I32V(42)));
|
|
|
|
byte kI31CastFailure = TYPE_CAST(
|
|
|
|
I31, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
#undef TYPE_CAST
|
|
|
|
|
|
|
|
// If the branch is not taken, we return 0. If it is taken, then the respective
|
|
|
|
// type check should succeed, and we return 1.
|
2021-05-20 11:28:20 +00:00
|
|
|
#define BR_ON(TYPE, type, value) \
|
|
|
|
tester.DefineFunction( \
|
|
|
|
tester.sigs.i_v(), {kWasmAnyRef}, \
|
|
|
|
{WASM_LOCAL_SET(0, WASM_SEQ(value)), \
|
|
|
|
WASM_REF_IS_##TYPE(WASM_BLOCK_R(kWasm##type##Ref, WASM_LOCAL_GET(0), \
|
|
|
|
WASM_BR_ON_##TYPE(0), \
|
|
|
|
WASM_RETURN(WASM_I32V(0)))), \
|
2021-01-29 13:58:08 +00:00
|
|
|
kExprEnd})
|
|
|
|
|
|
|
|
byte kBrOnDataTaken =
|
|
|
|
BR_ON(DATA, Data,
|
2021-09-15 12:59:42 +00:00
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kBrOnDataNotTaken = BR_ON(DATA, Data, WASM_REF_FUNC(function_index));
|
|
|
|
byte kBrOnFuncTaken = BR_ON(FUNC, Func, WASM_REF_FUNC(function_index));
|
|
|
|
byte kBrOnFuncNotTaken = BR_ON(FUNC, Func, WASM_I31_NEW(WASM_I32V(42)));
|
2022-01-12 10:03:54 +00:00
|
|
|
byte kBrOnArrayTaken =
|
|
|
|
BR_ON(ARRAY, Array,
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
|
|
|
byte kBrOnArrayNotTaken = BR_ON(ARRAY, Array, WASM_I31_NEW(WASM_I32V(42)));
|
2021-01-29 13:58:08 +00:00
|
|
|
byte kBrOnI31Taken = BR_ON(I31, I31, WASM_I31_NEW(WASM_I32V(42)));
|
|
|
|
byte kBrOnI31NotTaken =
|
|
|
|
BR_ON(I31, I31,
|
2021-09-15 12:59:42 +00:00
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-01-29 13:58:08 +00:00
|
|
|
#undef BR_ON
|
|
|
|
|
2021-05-20 11:28:20 +00:00
|
|
|
// If the branch is not taken, we return 1. If it is taken, then the respective
|
|
|
|
// type check should fail, and we return 0.
|
|
|
|
#define BR_ON_NON(TYPE, type, value) \
|
|
|
|
tester.DefineFunction( \
|
|
|
|
tester.sigs.i_v(), {kWasmAnyRef}, \
|
|
|
|
{WASM_LOCAL_SET(0, WASM_SEQ(value)), \
|
|
|
|
WASM_REF_IS_##TYPE(WASM_BLOCK_R(kWasmAnyRef, WASM_LOCAL_GET(0), \
|
|
|
|
WASM_BR_ON_NON_##TYPE(0), \
|
|
|
|
WASM_RETURN(WASM_I32V(1)))), \
|
|
|
|
kExprEnd})
|
|
|
|
|
|
|
|
byte kBrOnNonDataNotTaken =
|
|
|
|
BR_ON_NON(DATA, Data,
|
2021-09-15 12:59:42 +00:00
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-05-20 11:28:20 +00:00
|
|
|
byte kBrOnNonDataTaken = BR_ON_NON(DATA, Data, WASM_REF_FUNC(function_index));
|
|
|
|
byte kBrOnNonFuncNotTaken =
|
|
|
|
BR_ON_NON(FUNC, Func, WASM_REF_FUNC(function_index));
|
|
|
|
byte kBrOnNonFuncTaken = BR_ON_NON(FUNC, Func, WASM_I31_NEW(WASM_I32V(42)));
|
2022-01-12 10:03:54 +00:00
|
|
|
byte kBrOnNonArrayNotTaken =
|
|
|
|
BR_ON_NON(ARRAY, Array,
|
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
|
|
|
byte kBrOnNonArrayTaken =
|
|
|
|
BR_ON_NON(ARRAY, Array, WASM_I31_NEW(WASM_I32V(42)));
|
2021-05-20 11:28:20 +00:00
|
|
|
byte kBrOnNonI31NotTaken = BR_ON_NON(I31, I31, WASM_I31_NEW(WASM_I32V(42)));
|
|
|
|
byte kBrOnNonI31Taken =
|
|
|
|
BR_ON_NON(I31, I31,
|
2021-09-15 12:59:42 +00:00
|
|
|
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
|
|
|
|
WASM_RTT_CANON(array_index)));
|
2021-05-20 11:28:20 +00:00
|
|
|
#undef BR_ON_NON
|
|
|
|
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(kDataCheckNull, 0);
|
2022-01-12 06:32:48 +00:00
|
|
|
tester.CheckResult(kArrayCheckNull, 0);
|
2021-05-20 11:28:20 +00:00
|
|
|
tester.CheckResult(kFuncCheckNull, 0);
|
|
|
|
tester.CheckResult(kI31CheckNull, 0);
|
|
|
|
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CheckHasThrown(kDataCastNull);
|
2022-01-12 06:32:48 +00:00
|
|
|
tester.CheckHasThrown(kArrayCastNull);
|
2021-05-20 11:28:20 +00:00
|
|
|
tester.CheckHasThrown(kFuncCastNull);
|
|
|
|
tester.CheckHasThrown(kI31CastNull);
|
|
|
|
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CheckResult(kDataCheckSuccess, 1);
|
2022-01-12 06:32:48 +00:00
|
|
|
tester.CheckResult(kArrayCheckSuccess, 1);
|
2021-05-20 11:28:20 +00:00
|
|
|
tester.CheckResult(kFuncCheckSuccess, 1);
|
|
|
|
tester.CheckResult(kI31CheckSuccess, 1);
|
|
|
|
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CheckResult(kDataCheckFailure, 0);
|
2022-01-12 06:32:48 +00:00
|
|
|
tester.CheckResult(kArrayCheckFailure, 0);
|
2021-05-20 11:28:20 +00:00
|
|
|
tester.CheckResult(kFuncCheckFailure, 0);
|
|
|
|
tester.CheckResult(kI31CheckFailure, 0);
|
|
|
|
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CheckResult(kDataCastSuccess, 1);
|
2022-01-12 06:32:48 +00:00
|
|
|
tester.CheckResult(kArrayCastSuccess, 1);
|
2021-05-20 11:28:20 +00:00
|
|
|
tester.CheckResult(kFuncCastSuccess, 1);
|
|
|
|
tester.CheckResult(kI31CastSuccess, 1);
|
|
|
|
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CheckHasThrown(kDataCastFailure);
|
2022-01-12 06:32:48 +00:00
|
|
|
tester.CheckHasThrown(kArrayCastFailure);
|
2021-05-20 11:28:20 +00:00
|
|
|
tester.CheckHasThrown(kFuncCastFailure);
|
|
|
|
tester.CheckHasThrown(kI31CastFailure);
|
|
|
|
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CheckResult(kBrOnDataTaken, 1);
|
|
|
|
tester.CheckResult(kBrOnDataNotTaken, 0);
|
|
|
|
tester.CheckResult(kBrOnFuncTaken, 1);
|
|
|
|
tester.CheckResult(kBrOnFuncNotTaken, 0);
|
2022-01-12 10:03:54 +00:00
|
|
|
tester.CheckResult(kBrOnArrayTaken, 1);
|
|
|
|
tester.CheckResult(kBrOnArrayNotTaken, 0);
|
2021-01-29 13:58:08 +00:00
|
|
|
tester.CheckResult(kBrOnI31Taken, 1);
|
|
|
|
tester.CheckResult(kBrOnI31NotTaken, 0);
|
2021-05-20 11:28:20 +00:00
|
|
|
|
|
|
|
tester.CheckResult(kBrOnNonDataTaken, 0);
|
|
|
|
tester.CheckResult(kBrOnNonDataNotTaken, 1);
|
|
|
|
tester.CheckResult(kBrOnNonFuncTaken, 0);
|
|
|
|
tester.CheckResult(kBrOnNonFuncNotTaken, 1);
|
2022-01-12 10:03:54 +00:00
|
|
|
tester.CheckResult(kBrOnNonArrayTaken, 0);
|
|
|
|
tester.CheckResult(kBrOnNonArrayNotTaken, 1);
|
2021-05-20 11:28:20 +00:00
|
|
|
tester.CheckResult(kBrOnNonI31Taken, 0);
|
|
|
|
tester.CheckResult(kBrOnNonI31NotTaken, 1);
|
2021-01-29 13:58:08 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 22:29:12 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(BasicI31) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kSigned = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_i(), {},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_I31_GET_S(WASM_I31_NEW(WASM_LOCAL_GET(0))), kExprEnd});
|
2020-08-04 09:13:30 +00:00
|
|
|
const byte kUnsigned = tester.DefineFunction(
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.sigs.i_i(), {},
|
2020-12-17 16:55:33 +00:00
|
|
|
{WASM_I31_GET_U(WASM_I31_NEW(WASM_LOCAL_GET(0))), kExprEnd});
|
2020-06-30 11:17:53 +00:00
|
|
|
tester.CompileModule();
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kSigned, 123, 123);
|
|
|
|
tester.CheckResult(kUnsigned, 123, 123);
|
2020-06-30 11:17:53 +00:00
|
|
|
// Truncation:
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kSigned, 0x1234, static_cast<int32_t>(0x80001234));
|
|
|
|
tester.CheckResult(kUnsigned, 0x1234, static_cast<int32_t>(0x80001234));
|
2020-06-30 11:17:53 +00:00
|
|
|
// Sign/zero extension:
|
2020-07-07 19:14:38 +00:00
|
|
|
tester.CheckResult(kSigned, -1, 0x7FFFFFFF);
|
|
|
|
tester.CheckResult(kUnsigned, 0x7FFFFFFF, 0x7FFFFFFF);
|
|
|
|
}
|
|
|
|
|
2020-11-12 22:30:45 +00:00
|
|
|
// This flushed out a few bugs, so it serves as a regression test. It can also
|
|
|
|
// be modified (made to run longer) to measure performance of casts.
|
2020-12-16 22:29:12 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(CastsBenchmark) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-11-12 22:30:45 +00:00
|
|
|
const byte SuperType = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
2022-01-27 16:24:31 +00:00
|
|
|
const byte SubType = tester.DefineStruct(
|
|
|
|
{F(wasm::kWasmI32, true), F(wasm::kWasmI32, true)}, SuperType);
|
2021-01-28 16:21:57 +00:00
|
|
|
|
|
|
|
ValueType kDataRefNull = ValueType::Ref(HeapType::kData, kNullable);
|
|
|
|
const byte ListType = tester.DefineArray(kDataRefNull, true);
|
2020-11-12 22:30:45 +00:00
|
|
|
|
|
|
|
const byte List =
|
|
|
|
tester.AddGlobal(ValueType::Ref(ListType, kNullable), true,
|
|
|
|
WasmInitExpr::RefNullConst(
|
|
|
|
static_cast<HeapType::Representation>(ListType)));
|
|
|
|
const byte RttSuper = tester.AddGlobal(
|
2022-01-28 14:53:45 +00:00
|
|
|
ValueType::Rtt(SuperType), false,
|
2020-11-12 22:30:45 +00:00
|
|
|
WasmInitExpr::RttCanon(static_cast<HeapType::Representation>(SuperType)));
|
2022-01-28 14:53:45 +00:00
|
|
|
const byte RttSub = tester.AddGlobal(ValueType::Rtt(SubType), false,
|
2022-01-27 16:24:31 +00:00
|
|
|
WasmInitExpr::RttCanon(SubType));
|
2020-11-12 22:30:45 +00:00
|
|
|
const byte RttList = tester.AddGlobal(
|
2022-01-28 14:53:45 +00:00
|
|
|
ValueType::Rtt(ListType), false,
|
2020-11-12 22:30:45 +00:00
|
|
|
WasmInitExpr::RttCanon(static_cast<HeapType::Representation>(ListType)));
|
|
|
|
|
|
|
|
const uint32_t kListLength = 1024;
|
|
|
|
const uint32_t i = 0;
|
|
|
|
const byte Prepare = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {wasm::kWasmI32},
|
|
|
|
{// List = new eqref[kListLength];
|
2021-09-15 12:59:42 +00:00
|
|
|
WASM_GLOBAL_SET(List, WASM_ARRAY_NEW_DEFAULT_WITH_RTT(
|
|
|
|
ListType, WASM_I32V(kListLength),
|
|
|
|
WASM_GLOBAL_GET(RttList))),
|
2020-11-12 22:30:45 +00:00
|
|
|
// for (int i = 0; i < kListLength; ) {
|
|
|
|
// List[i] = new Super(i);
|
|
|
|
// i++;
|
|
|
|
// List[i] = new Sub(i, 0);
|
|
|
|
// i++;
|
|
|
|
// }
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(i, WASM_I32V_1(0)),
|
2020-11-12 22:30:45 +00:00
|
|
|
WASM_LOOP(
|
2020-12-17 16:56:08 +00:00
|
|
|
WASM_ARRAY_SET(ListType, WASM_GLOBAL_GET(List), WASM_LOCAL_GET(i),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(SuperType, WASM_LOCAL_GET(i),
|
2020-12-17 16:56:08 +00:00
|
|
|
WASM_GLOBAL_GET(RttSuper))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(i, WASM_I32_ADD(WASM_LOCAL_GET(i), WASM_I32V_1(1))),
|
2020-12-17 16:56:08 +00:00
|
|
|
WASM_ARRAY_SET(ListType, WASM_GLOBAL_GET(List), WASM_LOCAL_GET(i),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_STRUCT_NEW_WITH_RTT(SubType, WASM_LOCAL_GET(i),
|
2020-11-12 22:30:45 +00:00
|
|
|
WASM_I32V_1(0),
|
2020-12-17 16:56:08 +00:00
|
|
|
WASM_GLOBAL_GET(RttSub))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(i, WASM_I32_ADD(WASM_LOCAL_GET(i), WASM_I32V_1(1))),
|
2020-11-12 22:30:45 +00:00
|
|
|
WASM_BR_IF(0,
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_I32_NE(WASM_LOCAL_GET(i), WASM_I32V(kListLength)))),
|
2020-11-12 22:30:45 +00:00
|
|
|
// return 42; // Dummy value, due to test framework.
|
|
|
|
WASM_I32V_1(42), kExprEnd});
|
|
|
|
|
|
|
|
const uint32_t sum = 1; // Index of the local.
|
|
|
|
const uint32_t list = 2;
|
|
|
|
const uint32_t kLoops = 2;
|
|
|
|
const uint32_t kIterations = kLoops * kListLength;
|
|
|
|
const byte Main = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(),
|
|
|
|
{
|
|
|
|
wasm::kWasmI32,
|
|
|
|
wasm::kWasmI32,
|
|
|
|
ValueType::Ref(ListType, kNullable),
|
|
|
|
},
|
2020-12-17 16:56:08 +00:00
|
|
|
{WASM_LOCAL_SET(list, WASM_GLOBAL_GET(List)),
|
2020-11-12 22:30:45 +00:00
|
|
|
// sum = 0;
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(sum, WASM_I32V_1(0)),
|
2020-11-12 22:30:45 +00:00
|
|
|
// for (int i = 0; i < kIterations; i++) {
|
|
|
|
// sum += ref.cast<super>(List[i & kListLength]).x
|
|
|
|
// }
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(i, WASM_I32V_1(0)),
|
2020-11-12 22:30:45 +00:00
|
|
|
WASM_LOOP(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(
|
2020-11-12 22:30:45 +00:00
|
|
|
sum, WASM_I32_ADD(
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(sum),
|
2020-11-12 22:30:45 +00:00
|
|
|
WASM_STRUCT_GET(
|
|
|
|
SuperType, 0,
|
|
|
|
WASM_REF_CAST(
|
|
|
|
WASM_ARRAY_GET(
|
2020-12-17 16:55:33 +00:00
|
|
|
ListType, WASM_LOCAL_GET(list),
|
|
|
|
WASM_I32_AND(WASM_LOCAL_GET(i),
|
2020-11-12 22:30:45 +00:00
|
|
|
WASM_I32V(kListLength - 1))),
|
2020-12-17 16:56:08 +00:00
|
|
|
WASM_GLOBAL_GET(RttSuper))))),
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_SET(i, WASM_I32_ADD(WASM_LOCAL_GET(i), WASM_I32V_1(1))),
|
2020-11-12 22:30:45 +00:00
|
|
|
WASM_BR_IF(0,
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_I32_LTS(WASM_LOCAL_GET(i), WASM_I32V(kIterations)))),
|
2020-11-12 22:30:45 +00:00
|
|
|
// return sum;
|
2020-12-17 16:55:33 +00:00
|
|
|
WASM_LOCAL_GET(sum), kExprEnd});
|
2020-11-12 22:30:45 +00:00
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
tester.CheckResult(Prepare, 42);
|
|
|
|
|
|
|
|
// Time this section to get a benchmark for subtyping checks.
|
|
|
|
// Note: if you bump kIterations or kListLength, you may have to take i32
|
|
|
|
// overflow into account.
|
|
|
|
tester.CheckResult(Main, (kListLength * (kListLength - 1) / 2) * kLoops);
|
|
|
|
}
|
|
|
|
|
2020-12-17 00:37:09 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(GlobalInitReferencingGlobal) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2020-09-28 18:30:35 +00:00
|
|
|
const byte from = tester.AddGlobal(kWasmI32, false, WasmInitExpr(42));
|
|
|
|
const byte to =
|
|
|
|
tester.AddGlobal(kWasmI32, false, WasmInitExpr::GlobalGet(from));
|
|
|
|
|
|
|
|
const byte func = tester.DefineFunction(tester.sigs.i_v(), {},
|
2020-12-17 16:56:08 +00:00
|
|
|
{WASM_GLOBAL_GET(to), kExprEnd});
|
2020-09-28 18:30:35 +00:00
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
|
|
|
tester.CheckResult(func, 42);
|
|
|
|
}
|
|
|
|
|
2021-04-13 05:40:00 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(GCTables) {
|
2020-12-17 00:37:09 +00:00
|
|
|
WasmGCTester tester(execution_tier);
|
2021-04-13 05:40:00 +00:00
|
|
|
|
|
|
|
byte super_struct = tester.DefineStruct({F(kWasmI32, false)});
|
2022-01-27 16:24:31 +00:00
|
|
|
byte sub_struct = tester.DefineStruct({F(kWasmI32, false), F(kWasmI32, true)},
|
|
|
|
super_struct);
|
2021-04-13 05:40:00 +00:00
|
|
|
FunctionSig* super_sig =
|
|
|
|
FunctionSig::Build(tester.zone(), {kWasmI32}, {optref(sub_struct)});
|
|
|
|
byte super_sig_index = tester.DefineSignature(super_sig);
|
|
|
|
FunctionSig* sub_sig =
|
|
|
|
FunctionSig::Build(tester.zone(), {kWasmI32}, {optref(super_struct)});
|
2022-01-27 16:24:31 +00:00
|
|
|
byte sub_sig_index = tester.DefineSignature(sub_sig, super_sig_index);
|
2021-04-13 05:40:00 +00:00
|
|
|
|
|
|
|
tester.DefineTable(optref(super_sig_index), 10, 10);
|
|
|
|
|
|
|
|
byte super_func = tester.DefineFunction(
|
2022-01-27 16:24:31 +00:00
|
|
|
super_sig_index, {},
|
2021-04-13 05:40:00 +00:00
|
|
|
{WASM_I32_ADD(WASM_STRUCT_GET(sub_struct, 0, WASM_LOCAL_GET(0)),
|
|
|
|
WASM_STRUCT_GET(sub_struct, 1, WASM_LOCAL_GET(0))),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
byte sub_func = tester.DefineFunction(
|
2022-01-27 16:24:31 +00:00
|
|
|
sub_sig_index, {},
|
2021-04-13 05:40:00 +00:00
|
|
|
{WASM_STRUCT_GET(super_struct, 0, WASM_LOCAL_GET(0)), WASM_END});
|
|
|
|
|
|
|
|
byte setup_func = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_TABLE_SET(0, WASM_I32V(0), WASM_REF_NULL(super_sig_index)),
|
|
|
|
WASM_TABLE_SET(0, WASM_I32V(1), WASM_REF_FUNC(super_func)),
|
|
|
|
WASM_TABLE_SET(0, WASM_I32V(2), WASM_REF_FUNC(sub_func)), WASM_I32V(0),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
byte super_struct_producer = tester.DefineFunction(
|
|
|
|
FunctionSig::Build(tester.zone(), {ref(super_struct)}, {}), {},
|
|
|
|
{WASM_STRUCT_NEW_WITH_RTT(super_struct, WASM_I32V(-5),
|
|
|
|
WASM_RTT_CANON(super_struct)),
|
|
|
|
WASM_END});
|
|
|
|
byte sub_struct_producer = tester.DefineFunction(
|
|
|
|
FunctionSig::Build(tester.zone(), {ref(sub_struct)}, {}), {},
|
|
|
|
{WASM_STRUCT_NEW_WITH_RTT(sub_struct, WASM_I32V(7), WASM_I32V(11),
|
|
|
|
WASM_RTT_CANON(sub_struct)),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
// Calling a null entry should trap.
|
|
|
|
byte call_null = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_CALL_INDIRECT(super_sig_index,
|
|
|
|
WASM_CALL_FUNCTION0(sub_struct_producer),
|
|
|
|
WASM_I32V(0)),
|
|
|
|
WASM_END});
|
|
|
|
// Calling with a signature identical to the type of the table should work,
|
|
|
|
// provided the entry has the same signature.
|
|
|
|
byte call_same_type = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_CALL_INDIRECT(super_sig_index,
|
|
|
|
WASM_CALL_FUNCTION0(sub_struct_producer),
|
|
|
|
WASM_I32V(1)),
|
|
|
|
WASM_END});
|
|
|
|
// Calling with a signature that is a subtype of the type of the table should
|
|
|
|
// work, provided the entry has the same signature.
|
|
|
|
byte call_subtype = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_CALL_INDIRECT(sub_sig_index,
|
|
|
|
WASM_CALL_FUNCTION0(super_struct_producer),
|
|
|
|
WASM_I32V(2)),
|
|
|
|
WASM_END});
|
|
|
|
// Calling with a signature that is mismatched to that of the entry should
|
|
|
|
// trap.
|
|
|
|
byte call_type_mismatch = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_CALL_INDIRECT(super_sig_index,
|
|
|
|
WASM_CALL_FUNCTION0(sub_struct_producer),
|
|
|
|
WASM_I32V(2)),
|
|
|
|
WASM_END});
|
|
|
|
// Getting a table element and then calling it with call_ref should work.
|
|
|
|
byte table_get_and_call_ref = tester.DefineFunction(
|
|
|
|
tester.sigs.i_v(), {},
|
|
|
|
{WASM_CALL_REF(WASM_TABLE_GET(0, WASM_I32V(2)),
|
|
|
|
WASM_CALL_FUNCTION0(sub_struct_producer)),
|
|
|
|
WASM_END});
|
|
|
|
|
|
|
|
// Only here so these functions count as "declared".
|
|
|
|
tester.AddGlobal(optref(super_sig_index), false,
|
|
|
|
WasmInitExpr::RefFuncConst(super_func));
|
|
|
|
tester.AddGlobal(optref(sub_sig_index), false,
|
|
|
|
WasmInitExpr::RefFuncConst(sub_func));
|
2020-10-02 05:31:50 +00:00
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
|
2021-04-13 05:40:00 +00:00
|
|
|
tester.CheckResult(setup_func, 0);
|
|
|
|
tester.CheckHasThrown(call_null);
|
|
|
|
tester.CheckResult(call_same_type, 18);
|
|
|
|
tester.CheckResult(call_subtype, -5);
|
|
|
|
tester.CheckHasThrown(call_type_mismatch);
|
|
|
|
tester.CheckResult(table_get_and_call_ref, 7);
|
2020-10-02 05:31:50 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 06:12:34 +00:00
|
|
|
WASM_COMPILED_EXEC_TEST(JsAccess) {
|
|
|
|
WasmGCTester tester(execution_tier);
|
2021-01-28 11:53:37 +00:00
|
|
|
const byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
|
|
|
|
ValueType kRefType = ref(type_index);
|
|
|
|
ValueType kSupertypeToI[] = {kWasmI32, kWasmDataRef};
|
|
|
|
FunctionSig sig_t_v(1, 0, &kRefType);
|
|
|
|
FunctionSig sig_super_v(1, 0, &kWasmDataRef);
|
|
|
|
FunctionSig sig_i_super(1, 1, kSupertypeToI);
|
|
|
|
|
|
|
|
tester.DefineExportedFunction(
|
|
|
|
"disallowed", &sig_t_v,
|
|
|
|
{WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
|
|
|
// Same code, different signature.
|
|
|
|
tester.DefineExportedFunction(
|
|
|
|
"producer", &sig_super_v,
|
|
|
|
{WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(42),
|
|
|
|
WASM_RTT_CANON(type_index)),
|
|
|
|
kExprEnd});
|
|
|
|
tester.DefineExportedFunction(
|
|
|
|
"consumer", &sig_i_super,
|
2021-01-28 15:18:41 +00:00
|
|
|
{WASM_STRUCT_GET(
|
|
|
|
type_index, 0,
|
|
|
|
WASM_REF_CAST(WASM_LOCAL_GET(0), WASM_RTT_CANON(type_index))),
|
2021-01-28 11:53:37 +00:00
|
|
|
kExprEnd});
|
|
|
|
|
|
|
|
tester.CompileModule();
|
|
|
|
Isolate* isolate = tester.isolate();
|
|
|
|
TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
|
|
|
|
MaybeHandle<Object> maybe_result =
|
|
|
|
tester.CallExportedFunction("disallowed", 0, nullptr);
|
|
|
|
CHECK(maybe_result.is_null());
|
|
|
|
CHECK(try_catch.HasCaught());
|
|
|
|
try_catch.Reset();
|
|
|
|
isolate->clear_pending_exception();
|
|
|
|
|
|
|
|
maybe_result = tester.CallExportedFunction("producer", 0, nullptr);
|
|
|
|
if (maybe_result.is_null()) {
|
|
|
|
FATAL("Calling 'producer' failed: %s",
|
|
|
|
*v8::String::Utf8Value(reinterpret_cast<v8::Isolate*>(isolate),
|
|
|
|
try_catch.Message()->Get()));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
Handle<Object> args[] = {maybe_result.ToHandleChecked()};
|
|
|
|
maybe_result = tester.CallExportedFunction("consumer", 1, args);
|
|
|
|
}
|
|
|
|
if (maybe_result.is_null()) {
|
|
|
|
FATAL("Calling 'consumer' failed: %s",
|
|
|
|
*v8::String::Utf8Value(reinterpret_cast<v8::Isolate*>(isolate),
|
|
|
|
try_catch.Message()->Get()));
|
|
|
|
}
|
|
|
|
Handle<Object> result = maybe_result.ToHandleChecked();
|
|
|
|
CHECK(result->IsSmi());
|
|
|
|
CHECK_EQ(42, Smi::cast(*result).value());
|
|
|
|
// Calling {consumer} with any other object (e.g. the Smi we just got as
|
|
|
|
// {result}) should trap.
|
|
|
|
{
|
|
|
|
Handle<Object> args[] = {result};
|
|
|
|
maybe_result = tester.CallExportedFunction("consumer", 1, args);
|
2020-08-03 18:16:25 +00:00
|
|
|
}
|
2021-01-28 11:53:37 +00:00
|
|
|
CHECK(maybe_result.is_null());
|
|
|
|
CHECK(try_catch.HasCaught());
|
|
|
|
try_catch.Reset();
|
|
|
|
isolate->clear_pending_exception();
|
2020-06-30 11:17:53 +00:00
|
|
|
}
|
|
|
|
|
2020-04-21 16:45:53 +00:00
|
|
|
} // namespace test_gc
|
|
|
|
} // namespace wasm
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|