[wasm] Add WebAssembly's i64<>JavaScript's BigInt conversions - 64 bits
Uses the JavaScript BigInt Object to represent Wasm's 64bits integers. Attention, 32 bits architectures are not supported yet. Bug: v8:7741 Change-Id: I28b718fa567bca5103b2f38a879049cd20a46f12 Reviewed-on: https://chromium-review.googlesource.com/c/1355144 Commit-Queue: Andreas Haas <ahaas@chromium.org> Reviewed-by: Adam Klein <adamk@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#58152}
This commit is contained in:
parent
3f3e2993ec
commit
2b92afd054
1
BUILD.gn
1
BUILD.gn
@ -1420,6 +1420,7 @@ v8_source_set("v8_initializers") {
|
|||||||
"src/builtins/builtins-async-gen.h",
|
"src/builtins/builtins-async-gen.h",
|
||||||
"src/builtins/builtins-async-generator-gen.cc",
|
"src/builtins/builtins-async-generator-gen.cc",
|
||||||
"src/builtins/builtins-async-iterator-gen.cc",
|
"src/builtins/builtins-async-iterator-gen.cc",
|
||||||
|
"src/builtins/builtins-bigint-gen.cc",
|
||||||
"src/builtins/builtins-boolean-gen.cc",
|
"src/builtins/builtins-boolean-gen.cc",
|
||||||
"src/builtins/builtins-call-gen.cc",
|
"src/builtins/builtins-call-gen.cc",
|
||||||
"src/builtins/builtins-call-gen.h",
|
"src/builtins/builtins-call-gen.h",
|
||||||
|
46
src/builtins/builtins-bigint-gen.cc
Normal file
46
src/builtins/builtins-bigint-gen.cc
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2017 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 "src/builtins/builtins-utils-gen.h"
|
||||||
|
#include "src/builtins/builtins.h"
|
||||||
|
#include "src/code-stub-assembler.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// https://tc39.github.io/proposal-bigint/#sec-to-big-int64
|
||||||
|
TF_BUILTIN(BigIntToI64, CodeStubAssembler) {
|
||||||
|
if (!Is64()) {
|
||||||
|
Unreachable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TNode<Object> value = CAST(Parameter(Descriptor::kArgument));
|
||||||
|
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
|
||||||
|
TNode<BigInt> bigint = ToBigInt(context, value);
|
||||||
|
|
||||||
|
TVARIABLE(UintPtrT, var_low);
|
||||||
|
TVARIABLE(UintPtrT, var_high);
|
||||||
|
|
||||||
|
// 2. Let int64bit be n modulo 2^64.
|
||||||
|
// 3. If int64bit ≥ 2^63, return int64bit - 2^64;
|
||||||
|
BigIntToRawBytes(bigint, &var_low, &var_high);
|
||||||
|
ReturnRaw(var_low.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://tc39.github.io/proposal-bigint/#sec-bigint-constructor-number-value
|
||||||
|
TF_BUILTIN(I64ToBigInt, CodeStubAssembler) {
|
||||||
|
if (!Is64()) {
|
||||||
|
Unreachable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TNode<IntPtrT> argument =
|
||||||
|
UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument));
|
||||||
|
|
||||||
|
Return(BigIntFromInt64(argument));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
@ -201,6 +201,8 @@ namespace internal {
|
|||||||
TFC(ToLength, TypeConversion, 1) \
|
TFC(ToLength, TypeConversion, 1) \
|
||||||
TFC(Typeof, Typeof, 1) \
|
TFC(Typeof, Typeof, 1) \
|
||||||
TFC(GetSuperConstructor, Typeof, 1) \
|
TFC(GetSuperConstructor, Typeof, 1) \
|
||||||
|
TFC(BigIntToI64, BigIntToI64, 1) \
|
||||||
|
TFC(I64ToBigInt, BigIntToWasmI64, 1) \
|
||||||
\
|
\
|
||||||
/* Type conversions continuations */ \
|
/* Type conversions continuations */ \
|
||||||
TFC(ToBooleanLazyDeoptContinuation, TypeConversionStackParameter, 1) \
|
TFC(ToBooleanLazyDeoptContinuation, TypeConversionStackParameter, 1) \
|
||||||
@ -1260,6 +1262,7 @@ namespace internal {
|
|||||||
TFS(ThrowWasmTrapFloatUnrepresentable) \
|
TFS(ThrowWasmTrapFloatUnrepresentable) \
|
||||||
TFS(ThrowWasmTrapFuncInvalid) \
|
TFS(ThrowWasmTrapFuncInvalid) \
|
||||||
TFS(ThrowWasmTrapFuncSigMismatch) \
|
TFS(ThrowWasmTrapFuncSigMismatch) \
|
||||||
|
TFC(BigIntToWasmI64, BigIntToWasmI64, 1) \
|
||||||
\
|
\
|
||||||
/* WeakMap */ \
|
/* WeakMap */ \
|
||||||
TFJ(WeakMapConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
TFJ(WeakMapConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||||
@ -1550,7 +1553,8 @@ namespace internal {
|
|||||||
V(WasmStackGuard) \
|
V(WasmStackGuard) \
|
||||||
V(WasmToNumber) \
|
V(WasmToNumber) \
|
||||||
V(WasmThrow) \
|
V(WasmThrow) \
|
||||||
V(DoubleToI)
|
V(DoubleToI) \
|
||||||
|
V(BigIntToWasmI64)
|
||||||
|
|
||||||
// The exception thrown in the following builtins are caught internally and will
|
// The exception thrown in the following builtins are caught internally and will
|
||||||
// not be propagated further or re-thrown
|
// not be propagated further or re-thrown
|
||||||
|
@ -219,6 +219,20 @@ TF_BUILTIN(WasmMemoryGrow, WasmBuiltinsAssembler) {
|
|||||||
ReturnRaw(Int32Constant(-1));
|
ReturnRaw(Int32Constant(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TF_BUILTIN(BigIntToWasmI64, WasmBuiltinsAssembler) {
|
||||||
|
if (!Is64()) {
|
||||||
|
Unreachable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TNode<Code> target = LoadBuiltinFromFrame(Builtins::kI64ToBigInt);
|
||||||
|
TNode<IntPtrT> argument =
|
||||||
|
UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument));
|
||||||
|
|
||||||
|
TailCallStub(BigIntToWasmI64Descriptor(), target, NoContextConstant(),
|
||||||
|
argument);
|
||||||
|
}
|
||||||
|
|
||||||
#define DECLARE_ENUM(name) \
|
#define DECLARE_ENUM(name) \
|
||||||
TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \
|
TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \
|
||||||
TNode<Object> instance = LoadInstanceFromFrame(); \
|
TNode<Object> instance = LoadInstanceFromFrame(); \
|
||||||
|
@ -4315,7 +4315,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
: WasmGraphBuilder(nullptr, zone, jsgraph, sig, spt),
|
: WasmGraphBuilder(nullptr, zone, jsgraph, sig, spt),
|
||||||
isolate_(jsgraph->isolate()),
|
isolate_(jsgraph->isolate()),
|
||||||
jsgraph_(jsgraph),
|
jsgraph_(jsgraph),
|
||||||
stub_mode_(stub_mode) {}
|
stub_mode_(stub_mode),
|
||||||
|
enabled_features_(wasm::WasmFeaturesFromIsolate(isolate_)) {}
|
||||||
|
|
||||||
Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control) {
|
Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control) {
|
||||||
MachineOperatorBuilder* machine = mcgraph()->machine();
|
MachineOperatorBuilder* machine = mcgraph()->machine();
|
||||||
@ -4567,8 +4568,11 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
case wasm::kWasmI32:
|
case wasm::kWasmI32:
|
||||||
return BuildChangeInt32ToTagged(node);
|
return BuildChangeInt32ToTagged(node);
|
||||||
case wasm::kWasmS128:
|
case wasm::kWasmS128:
|
||||||
case wasm::kWasmI64:
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
case wasm::kWasmI64: {
|
||||||
|
DCHECK(enabled_features_.bigint);
|
||||||
|
return BuildChangeInt64ToBigInt(node);
|
||||||
|
}
|
||||||
case wasm::kWasmF32:
|
case wasm::kWasmF32:
|
||||||
node = graph()->NewNode(mcgraph()->machine()->ChangeFloat32ToFloat64(),
|
node = graph()->NewNode(mcgraph()->machine()->ChangeFloat32ToFloat64(),
|
||||||
node);
|
node);
|
||||||
@ -4582,6 +4586,48 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* BuildChangeInt64ToBigInt(Node* input) {
|
||||||
|
BigIntToWasmI64Descriptor interface_descriptor;
|
||||||
|
|
||||||
|
auto call_descriptor = Linkage::GetStubCallDescriptor(
|
||||||
|
mcgraph()->zone(), // zone
|
||||||
|
interface_descriptor, // descriptor
|
||||||
|
interface_descriptor.GetStackParameterCount(), // stack parameter count
|
||||||
|
CallDescriptor::kNoFlags, // flags
|
||||||
|
Operator::kNoProperties, // properties
|
||||||
|
stub_mode_); // stub call mode
|
||||||
|
|
||||||
|
Node* target =
|
||||||
|
(stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
|
||||||
|
? mcgraph()->RelocatableIntPtrConstant(
|
||||||
|
wasm::WasmCode::kBigIntToWasmI64, RelocInfo::WASM_STUB_CALL)
|
||||||
|
: jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, I64ToBigInt));
|
||||||
|
|
||||||
|
return SetEffect(
|
||||||
|
SetControl(graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
|
||||||
|
target, input, Effect(), Control())));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* BuildChangeBigIntToInt64(Node* input, Node* context) {
|
||||||
|
DCHECK_EQ(stub_mode_, StubCallMode::kCallOnHeapBuiltin);
|
||||||
|
|
||||||
|
BigIntToI64Descriptor interface_descriptor;
|
||||||
|
|
||||||
|
auto call_descriptor = Linkage::GetStubCallDescriptor(
|
||||||
|
mcgraph()->zone(), // zone
|
||||||
|
interface_descriptor, // descriptor
|
||||||
|
interface_descriptor.GetStackParameterCount(), // stack parameter count
|
||||||
|
CallDescriptor::kNoFlags, // flags
|
||||||
|
Operator::kNoProperties, // properties
|
||||||
|
StubCallMode::kCallOnHeapBuiltin); // stub call mode
|
||||||
|
|
||||||
|
Node* target = jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, BigIntToI64));
|
||||||
|
|
||||||
|
return SetEffect(SetControl(
|
||||||
|
graph()->NewNode(mcgraph()->common()->Call(call_descriptor), target,
|
||||||
|
input, context, Effect(), Control())));
|
||||||
|
}
|
||||||
|
|
||||||
Node* FromJS(Node* node, Node* js_context, wasm::ValueType type) {
|
Node* FromJS(Node* node, Node* js_context, wasm::ValueType type) {
|
||||||
DCHECK_NE(wasm::kWasmStmt, type);
|
DCHECK_NE(wasm::kWasmStmt, type);
|
||||||
|
|
||||||
@ -4590,11 +4636,15 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a JavaScript ToNumber.
|
Node* num = nullptr;
|
||||||
Node* num = BuildJavaScriptToNumber(node, js_context);
|
|
||||||
|
|
||||||
// Change representation.
|
if (type != wasm::kWasmI64) {
|
||||||
num = BuildChangeTaggedToFloat64(num);
|
// Do a JavaScript ToNumber.
|
||||||
|
num = BuildJavaScriptToNumber(node, js_context);
|
||||||
|
|
||||||
|
// Change representation.
|
||||||
|
num = BuildChangeTaggedToFloat64(num);
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case wasm::kWasmI32: {
|
case wasm::kWasmI32: {
|
||||||
@ -4602,18 +4652,24 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
num);
|
num);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case wasm::kWasmS128:
|
case wasm::kWasmI64: {
|
||||||
case wasm::kWasmI64:
|
DCHECK(enabled_features_.bigint);
|
||||||
UNREACHABLE();
|
num = BuildChangeBigIntToInt64(node, js_context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case wasm::kWasmF32:
|
case wasm::kWasmF32:
|
||||||
num = graph()->NewNode(mcgraph()->machine()->TruncateFloat64ToFloat32(),
|
num = graph()->NewNode(mcgraph()->machine()->TruncateFloat64ToFloat32(),
|
||||||
num);
|
num);
|
||||||
break;
|
break;
|
||||||
case wasm::kWasmF64:
|
case wasm::kWasmF64:
|
||||||
break;
|
break;
|
||||||
|
case wasm::kWasmS128:
|
||||||
|
UNREACHABLE();
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
DCHECK_NOT_NULL(num);
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4724,7 +4780,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
instance_node_.set(
|
instance_node_.set(
|
||||||
BuildLoadInstanceFromExportedFunctionData(function_data));
|
BuildLoadInstanceFromExportedFunctionData(function_data));
|
||||||
|
|
||||||
if (!wasm::IsJSCompatibleSignature(sig_)) {
|
if (!wasm::IsJSCompatibleSignature(sig_, enabled_features_.bigint)) {
|
||||||
// Throw a TypeError. Use the js_context of the calling javascript
|
// Throw a TypeError. Use the js_context of the calling javascript
|
||||||
// function (passed as a parameter), such that the generated code is
|
// function (passed as a parameter), such that the generated code is
|
||||||
// js_context independent.
|
// js_context independent.
|
||||||
@ -5113,6 +5169,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
JSGraph* jsgraph_;
|
JSGraph* jsgraph_;
|
||||||
StubCallMode stub_mode_;
|
StubCallMode stub_mode_;
|
||||||
SetOncePointer<const Operator> allocate_heap_number_operator_;
|
SetOncePointer<const Operator> allocate_heap_number_operator_;
|
||||||
|
wasm::WasmFeatures enabled_features_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AppendSignature(char* buffer, size_t max_name_len,
|
void AppendSignature(char* buffer, size_t max_name_len,
|
||||||
@ -5195,7 +5252,8 @@ MaybeHandle<Code> CompileJSToWasmWrapper(Isolate* isolate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target,
|
WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target,
|
||||||
wasm::FunctionSig* expected_sig) {
|
wasm::FunctionSig* expected_sig,
|
||||||
|
bool has_bigint_feature) {
|
||||||
if (WasmExportedFunction::IsWasmExportedFunction(*target)) {
|
if (WasmExportedFunction::IsWasmExportedFunction(*target)) {
|
||||||
auto imported_function = WasmExportedFunction::cast(*target);
|
auto imported_function = WasmExportedFunction::cast(*target);
|
||||||
wasm::FunctionSig* imported_sig =
|
wasm::FunctionSig* imported_sig =
|
||||||
@ -5209,7 +5267,7 @@ WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target,
|
|||||||
return WasmImportCallKind::kWasmToWasm;
|
return WasmImportCallKind::kWasmToWasm;
|
||||||
}
|
}
|
||||||
// Assuming we are calling to JS, check whether this would be a runtime error.
|
// Assuming we are calling to JS, check whether this would be a runtime error.
|
||||||
if (!wasm::IsJSCompatibleSignature(expected_sig)) {
|
if (!wasm::IsJSCompatibleSignature(expected_sig, has_bigint_feature)) {
|
||||||
return WasmImportCallKind::kRuntimeTypeError;
|
return WasmImportCallKind::kRuntimeTypeError;
|
||||||
}
|
}
|
||||||
// For JavaScript calls, determine whether the target has an arity match
|
// For JavaScript calls, determine whether the target has an arity match
|
||||||
|
@ -108,7 +108,8 @@ enum class WasmImportCallKind : uint8_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> callable,
|
WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> callable,
|
||||||
wasm::FunctionSig* sig);
|
wasm::FunctionSig* sig,
|
||||||
|
bool has_bigint_feature);
|
||||||
|
|
||||||
// Compiles an import call wrapper, which allows WASM to call imports.
|
// Compiles an import call wrapper, which allows WASM to call imports.
|
||||||
wasm::WasmCode* CompileWasmImportCallWrapper(Isolate*, wasm::NativeModule*,
|
wasm::WasmCode* CompileWasmImportCallWrapper(Isolate*, wasm::NativeModule*,
|
||||||
|
@ -379,5 +379,15 @@ void CloneObjectWithVectorDescriptor::InitializePlatformSpecific(
|
|||||||
DefaultInitializePlatformSpecific(data, kParameterCount);
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BigIntToWasmI64Descriptor::InitializePlatformSpecific(
|
||||||
|
CallInterfaceDescriptorData* data) {
|
||||||
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BigIntToI64Descriptor::InitializePlatformSpecific(
|
||||||
|
CallInterfaceDescriptorData* data) {
|
||||||
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -79,6 +79,8 @@ namespace internal {
|
|||||||
V(WasmI32AtomicWait) \
|
V(WasmI32AtomicWait) \
|
||||||
V(WasmI64AtomicWait) \
|
V(WasmI64AtomicWait) \
|
||||||
V(CloneObjectWithVector) \
|
V(CloneObjectWithVector) \
|
||||||
|
V(BigIntToWasmI64) \
|
||||||
|
V(BigIntToI64) \
|
||||||
BUILTIN_LIST_TFS(V)
|
BUILTIN_LIST_TFS(V)
|
||||||
|
|
||||||
class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
|
class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
|
||||||
@ -1103,6 +1105,21 @@ class WasmThrowDescriptor final : public CallInterfaceDescriptor {
|
|||||||
DECLARE_DESCRIPTOR(WasmThrowDescriptor, CallInterfaceDescriptor)
|
DECLARE_DESCRIPTOR(WasmThrowDescriptor, CallInterfaceDescriptor)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BigIntToWasmI64Descriptor final : public CallInterfaceDescriptor {
|
||||||
|
public:
|
||||||
|
DEFINE_PARAMETERS_NO_CONTEXT(kArgument)
|
||||||
|
DEFINE_PARAMETER_TYPES(MachineType::Int64()) // kArgument
|
||||||
|
DECLARE_DESCRIPTOR(BigIntToWasmI64Descriptor, CallInterfaceDescriptor)
|
||||||
|
};
|
||||||
|
|
||||||
|
class BigIntToI64Descriptor final : public CallInterfaceDescriptor {
|
||||||
|
public:
|
||||||
|
DEFINE_PARAMETERS(kArgument)
|
||||||
|
DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::Int64(), // result 1
|
||||||
|
MachineType::AnyTagged()) // kArgument
|
||||||
|
DECLARE_DESCRIPTOR(BigIntToI64Descriptor, CallInterfaceDescriptor)
|
||||||
|
};
|
||||||
|
|
||||||
class WasmAtomicWakeDescriptor final : public CallInterfaceDescriptor {
|
class WasmAtomicWakeDescriptor final : public CallInterfaceDescriptor {
|
||||||
public:
|
public:
|
||||||
DEFINE_PARAMETERS_NO_CONTEXT(kAddress, kCount)
|
DEFINE_PARAMETERS_NO_CONTEXT(kAddress, kCount)
|
||||||
|
@ -1444,8 +1444,8 @@ void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
|
|||||||
static_cast<int32_t>(num));
|
static_cast<int32_t>(num));
|
||||||
break;
|
break;
|
||||||
case kWasmI64:
|
case kWasmI64:
|
||||||
// TODO(titzer): initialization of imported i64 globals.
|
WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
|
||||||
UNREACHABLE();
|
static_cast<int64_t>(num));
|
||||||
break;
|
break;
|
||||||
case kWasmF32:
|
case kWasmF32:
|
||||||
WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
|
WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
|
||||||
@ -1562,6 +1562,8 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
|
|||||||
int num_imported_tables = 0;
|
int num_imported_tables = 0;
|
||||||
int num_imported_mutable_globals = 0;
|
int num_imported_mutable_globals = 0;
|
||||||
|
|
||||||
|
WasmFeatures enabled_features = WasmFeaturesFromIsolate(isolate_);
|
||||||
|
|
||||||
DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
|
DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
|
||||||
int num_imports = static_cast<int>(module_->import_table.size());
|
int num_imports = static_cast<int>(module_->import_table.size());
|
||||||
NativeModule* native_module = instance->module_object()->native_module();
|
NativeModule* native_module = instance->module_object()->native_module();
|
||||||
@ -1584,7 +1586,8 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
|
|||||||
DCHECK_EQ(num_imported_functions, func_index);
|
DCHECK_EQ(num_imported_functions, func_index);
|
||||||
auto js_receiver = Handle<JSReceiver>::cast(value);
|
auto js_receiver = Handle<JSReceiver>::cast(value);
|
||||||
FunctionSig* expected_sig = module_->functions[func_index].sig;
|
FunctionSig* expected_sig = module_->functions[func_index].sig;
|
||||||
auto kind = compiler::GetWasmImportCallKind(js_receiver, expected_sig);
|
auto kind = compiler::GetWasmImportCallKind(js_receiver, expected_sig,
|
||||||
|
enabled_features.bigint);
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case compiler::WasmImportCallKind::kLinkError:
|
case compiler::WasmImportCallKind::kLinkError:
|
||||||
ReportLinkError(
|
ReportLinkError(
|
||||||
@ -1757,7 +1760,10 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
|
|||||||
|
|
||||||
// The mutable-global proposal allows importing i64 values, but only if
|
// The mutable-global proposal allows importing i64 values, but only if
|
||||||
// they are passed as a WebAssembly.Global object.
|
// they are passed as a WebAssembly.Global object.
|
||||||
if (global.type == kWasmI64 &&
|
//
|
||||||
|
// However, the bigint proposal allows importing constant i64 values,
|
||||||
|
// as non WebAssembly.Global object.
|
||||||
|
if (global.type == kWasmI64 && !enabled_.bigint &&
|
||||||
!(enabled_.mut_global && value->IsWasmGlobalObject())) {
|
!(enabled_.mut_global && value->IsWasmGlobalObject())) {
|
||||||
ReportLinkError("global import cannot have type i64", index,
|
ReportLinkError("global import cannot have type i64", index,
|
||||||
module_name, import_name);
|
module_name, import_name);
|
||||||
@ -1816,6 +1822,19 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
WriteGlobalValue(global, value->Number());
|
WriteGlobalValue(global, value->Number());
|
||||||
|
} else if (enabled_.bigint && global.type == kWasmI64) {
|
||||||
|
if (global.mutability) {
|
||||||
|
ReportLinkError(
|
||||||
|
"imported mutable global must be a WebAssembly.Global object",
|
||||||
|
index, module_name, import_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Handle<BigInt> bigint;
|
||||||
|
|
||||||
|
if (!BigInt::FromObject(isolate_, value).ToHandle(&bigint)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
WriteGlobalValue(global, bigint->AsInt64());
|
||||||
} else {
|
} else {
|
||||||
ReportLinkError(
|
ReportLinkError(
|
||||||
"global import must be a number or WebAssembly.Global object",
|
"global import must be a number or WebAssembly.Global object",
|
||||||
@ -1825,6 +1844,13 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
|
|||||||
} else {
|
} else {
|
||||||
if (value->IsNumber()) {
|
if (value->IsNumber()) {
|
||||||
WriteGlobalValue(global, value->Number());
|
WriteGlobalValue(global, value->Number());
|
||||||
|
} else if (enabled_.bigint && global.type == kWasmI64) {
|
||||||
|
Handle<BigInt> bigint;
|
||||||
|
|
||||||
|
if (!BigInt::FromObject(isolate_, value).ToHandle(&bigint)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
WriteGlobalValue(global, bigint->AsInt64());
|
||||||
} else {
|
} else {
|
||||||
ReportLinkError("global import must be a number", index,
|
ReportLinkError("global import must be a number", index,
|
||||||
module_name, import_name);
|
module_name, import_name);
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
SEPARATOR \
|
SEPARATOR \
|
||||||
V(mut_global, "import/export mutable global support", true) \
|
V(mut_global, "import/export mutable global support", true) \
|
||||||
SEPARATOR \
|
SEPARATOR \
|
||||||
|
V(bigint, "JS BigInt support", false) \
|
||||||
|
SEPARATOR \
|
||||||
V(bulk_memory, "bulk memory opcodes", false)
|
V(bulk_memory, "bulk memory opcodes", false)
|
||||||
|
|
||||||
#endif // V8_WASM_WASM_FEATURE_FLAGS_H_
|
#endif // V8_WASM_WASM_FEATURE_FLAGS_H_
|
||||||
|
@ -2714,8 +2714,11 @@ class ThreadImpl {
|
|||||||
Handle<Object> object_ref,
|
Handle<Object> object_ref,
|
||||||
const WasmCode* code,
|
const WasmCode* code,
|
||||||
FunctionSig* sig) {
|
FunctionSig* sig) {
|
||||||
|
wasm::WasmFeatures enabled_features =
|
||||||
|
wasm::WasmFeaturesFromIsolate(isolate);
|
||||||
|
|
||||||
if (code->kind() == WasmCode::kWasmToJsWrapper &&
|
if (code->kind() == WasmCode::kWasmToJsWrapper &&
|
||||||
!IsJSCompatibleSignature(sig)) {
|
!IsJSCompatibleSignature(sig, enabled_features.bigint)) {
|
||||||
isolate->Throw(*isolate->factory()->NewTypeError(
|
isolate->Throw(*isolate->factory()->NewTypeError(
|
||||||
MessageTemplate::kWasmTrapTypeError));
|
MessageTemplate::kWasmTrapTypeError));
|
||||||
return TryHandleException(isolate);
|
return TryHandleException(isolate);
|
||||||
|
@ -1102,6 +1102,8 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
|
||||||
|
|
||||||
// The descriptor's type, called 'value'. It is called 'value' because this
|
// The descriptor's type, called 'value'. It is called 'value' because this
|
||||||
// descriptor is planned to be re-used as the global's type for reflection,
|
// descriptor is planned to be re-used as the global's type for reflection,
|
||||||
// so calling it 'type' is redundant.
|
// so calling it 'type' is redundant.
|
||||||
@ -1118,11 +1120,20 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||||||
type = i::wasm::kWasmI32;
|
type = i::wasm::kWasmI32;
|
||||||
} else if (string->StringEquals(v8_str(isolate, "f32"))) {
|
} else if (string->StringEquals(v8_str(isolate, "f32"))) {
|
||||||
type = i::wasm::kWasmF32;
|
type = i::wasm::kWasmF32;
|
||||||
|
} else if (enabled_features.bigint &&
|
||||||
|
string->StringEquals(v8_str(isolate, "i64"))) {
|
||||||
|
type = i::wasm::kWasmI64;
|
||||||
} else if (string->StringEquals(v8_str(isolate, "f64"))) {
|
} else if (string->StringEquals(v8_str(isolate, "f64"))) {
|
||||||
type = i::wasm::kWasmF64;
|
type = i::wasm::kWasmF64;
|
||||||
} else {
|
} else {
|
||||||
thrower.TypeError(
|
if (enabled_features.bigint) {
|
||||||
"Descriptor property 'value' must be 'i32', 'f32', or 'f64'");
|
thrower.TypeError(
|
||||||
|
"Descriptor property 'value' must be 'i32', 'i64', 'f32' or 'f64'");
|
||||||
|
} else {
|
||||||
|
thrower.TypeError(
|
||||||
|
"Descriptor property 'value' must be 'i32', 'f32' or 'f64'");
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1151,6 +1162,18 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||||||
global_obj->SetI32(i32_value);
|
global_obj->SetI32(i32_value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case i::wasm::kWasmI64: {
|
||||||
|
DCHECK(enabled_features.bigint);
|
||||||
|
|
||||||
|
int64_t i64_value = 0;
|
||||||
|
if (!value->IsUndefined()) {
|
||||||
|
v8::Local<v8::BigInt> bigint_value;
|
||||||
|
if (!value->ToBigInt(context).ToLocal(&bigint_value)) return;
|
||||||
|
i64_value = bigint_value->Int64Value();
|
||||||
|
}
|
||||||
|
global_obj->SetI64(i64_value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case i::wasm::kWasmF32: {
|
case i::wasm::kWasmF32: {
|
||||||
float f32_value = 0;
|
float f32_value = 0;
|
||||||
if (!value->IsUndefined()) {
|
if (!value->IsUndefined()) {
|
||||||
@ -1403,9 +1426,17 @@ void WebAssemblyGlobalGetValueCommon(
|
|||||||
case i::wasm::kWasmI32:
|
case i::wasm::kWasmI32:
|
||||||
return_value.Set(receiver->GetI32());
|
return_value.Set(receiver->GetI32());
|
||||||
break;
|
break;
|
||||||
case i::wasm::kWasmI64:
|
case i::wasm::kWasmI64: {
|
||||||
thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
|
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
|
||||||
|
if (enabled_features.bigint) {
|
||||||
|
Local<BigInt> value = BigInt::New(isolate, receiver->GetI64());
|
||||||
|
|
||||||
|
return_value.Set(value);
|
||||||
|
} else {
|
||||||
|
thrower.TypeError("Can't get the value of i64 WebAssembly.Global");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case i::wasm::kWasmF32:
|
case i::wasm::kWasmF32:
|
||||||
return_value.Set(receiver->GetF32());
|
return_value.Set(receiver->GetF32());
|
||||||
break;
|
break;
|
||||||
@ -1450,9 +1481,17 @@ void WebAssemblyGlobalSetValue(
|
|||||||
receiver->SetI32(i32_value);
|
receiver->SetI32(i32_value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case i::wasm::kWasmI64:
|
case i::wasm::kWasmI64: {
|
||||||
thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
|
auto enabled_features = i::wasm::WasmFeaturesFromIsolate(i_isolate);
|
||||||
|
if (enabled_features.bigint) {
|
||||||
|
v8::Local<v8::BigInt> bigint_value;
|
||||||
|
if (!args[0]->ToBigInt(context).ToLocal(&bigint_value)) return;
|
||||||
|
receiver->SetI64(bigint_value->Int64Value());
|
||||||
|
} else {
|
||||||
|
thrower.TypeError("Can't set the value of i64 WebAssembly.Global");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case i::wasm::kWasmF32: {
|
case i::wasm::kWasmF32: {
|
||||||
double f64_value = 0;
|
double f64_value = 0;
|
||||||
if (!args[0]->NumberValue(context).To(&f64_value)) return;
|
if (!args[0]->NumberValue(context).To(&f64_value)) return;
|
||||||
|
@ -381,11 +381,18 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsJSCompatibleSignature(const FunctionSig* sig) {
|
bool IsJSCompatibleSignature(const FunctionSig* sig, bool has_bigint_feature) {
|
||||||
for (auto type : sig->all()) {
|
if (sig->return_count() > 1) {
|
||||||
if (type == kWasmI64 || type == kWasmS128) return false;
|
return false;
|
||||||
}
|
}
|
||||||
return sig->return_count() <= 1;
|
for (auto type : sig->all()) {
|
||||||
|
if (!has_bigint_feature && type == kWasmI64) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == kWasmS128) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -16,7 +16,7 @@ namespace internal {
|
|||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
|
std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
|
||||||
bool IsJSCompatibleSignature(const FunctionSig* sig);
|
bool IsJSCompatibleSignature(const FunctionSig* sig, bool hasBigIntFeature);
|
||||||
|
|
||||||
// Control expressions and blocks.
|
// Control expressions and blocks.
|
||||||
#define FOREACH_CONTROL_OPCODE(V) \
|
#define FOREACH_CONTROL_OPCODE(V) \
|
||||||
|
@ -44,7 +44,7 @@ TestingModuleBuilder::TestingModuleBuilder(
|
|||||||
// Manually compile an import wrapper and insert it into the instance.
|
// Manually compile an import wrapper and insert it into the instance.
|
||||||
CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
|
CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
|
||||||
auto kind = compiler::GetWasmImportCallKind(maybe_import->js_function,
|
auto kind = compiler::GetWasmImportCallKind(maybe_import->js_function,
|
||||||
maybe_import->sig);
|
maybe_import->sig, false);
|
||||||
auto import_wrapper = native_module_->import_wrapper_cache()->GetOrCompile(
|
auto import_wrapper = native_module_->import_wrapper_cache()->GetOrCompile(
|
||||||
isolate_, kind, maybe_import->sig);
|
isolate_, kind, maybe_import->sig);
|
||||||
|
|
||||||
|
@ -929,4 +929,10 @@
|
|||||||
'wasm/asm-wasm-f64': [SKIP],
|
'wasm/asm-wasm-f64': [SKIP],
|
||||||
}], # arch == x64
|
}], # arch == x64
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
['arch in [arm, android_arm, android_ia32, ia32, ppc, s390, s390x, mipsel, mips]', {
|
||||||
|
# TODO(ssauleau): implement BigInt<>Wasm conversion for other arch -
|
||||||
|
# crbug.com/v8/7741
|
||||||
|
'wasm/bigint': [SKIP],
|
||||||
|
}], # arch in [arm, android_arm, android_ia32, ia32, ppc, s390, s390x, mipsel, mips]
|
||||||
]
|
]
|
||||||
|
206
test/mjsunit/wasm/bigint.js
Normal file
206
test/mjsunit/wasm/bigint.js
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --experimental-wasm-bigint
|
||||||
|
|
||||||
|
load("test/mjsunit/wasm/wasm-constants.js");
|
||||||
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||||
|
|
||||||
|
(function TestWasmI64ToJSBigInt() {
|
||||||
|
var builder = new WasmModuleBuilder();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.addFunction("fn", kSig_l_v) // () -> i64
|
||||||
|
.addBody([
|
||||||
|
kExprI64Const, 0x3,
|
||||||
|
])
|
||||||
|
.exportFunc();
|
||||||
|
|
||||||
|
var module = builder.instantiate();
|
||||||
|
|
||||||
|
assertEquals(typeof module.exports.fn(), "bigint");
|
||||||
|
assertEquals(module.exports.fn(), 3n);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestWasmI64ToJSBigIntImportedFunc() {
|
||||||
|
var builder = new WasmModuleBuilder();
|
||||||
|
|
||||||
|
var a_index = builder
|
||||||
|
.addImport("a", "a", kSig_v_l) // i64 -> ()
|
||||||
|
|
||||||
|
builder
|
||||||
|
.addFunction("fn", kSig_v_v) // () -> ()
|
||||||
|
.addBody([
|
||||||
|
kExprI64Const, 0x1,
|
||||||
|
kExprCallFunction, a_index
|
||||||
|
])
|
||||||
|
.exportFunc();
|
||||||
|
|
||||||
|
a_was_called = false;
|
||||||
|
|
||||||
|
var module = builder.instantiate({
|
||||||
|
a: {
|
||||||
|
a(param) {
|
||||||
|
assertEquals(typeof param, "bigint");
|
||||||
|
assertEquals(param, 1n);
|
||||||
|
a_was_called = true;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports.fn();
|
||||||
|
|
||||||
|
assertTrue(a_was_called);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestJSBigIntToWasmI64Global() {
|
||||||
|
var builder = new WasmModuleBuilder();
|
||||||
|
|
||||||
|
var a_global_index = builder
|
||||||
|
.addImportedGlobal("mod", "a", kWasmI64)
|
||||||
|
|
||||||
|
var b_global_index = builder
|
||||||
|
.addImportedGlobal("mod", "b", kWasmI64);
|
||||||
|
|
||||||
|
var c_global_index = builder
|
||||||
|
.addImportedGlobal("mod", "c", kWasmI64);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.addExportOfKind('a', kExternalGlobal, a_global_index)
|
||||||
|
.addExportOfKind('b', kExternalGlobal, b_global_index)
|
||||||
|
.addExportOfKind('c', kExternalGlobal, c_global_index);
|
||||||
|
|
||||||
|
var module = builder.instantiate({
|
||||||
|
mod: {
|
||||||
|
a: 1n,
|
||||||
|
b: 2n ** 63n,
|
||||||
|
c: "123",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(module.exports.a.value, 1n);
|
||||||
|
assertEquals(module.exports.b.value, - (2n ** 63n));
|
||||||
|
assertEquals(module.exports.c.value, 123n);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestJSBigIntToWasmI64MutableGlobal() {
|
||||||
|
var builder = new WasmModuleBuilder();
|
||||||
|
|
||||||
|
var a_global_index = builder
|
||||||
|
.addImportedGlobal("mod", "a", kWasmI64, /* mutable = */ true)
|
||||||
|
|
||||||
|
builder
|
||||||
|
.addExportOfKind('a', kExternalGlobal, a_global_index);
|
||||||
|
|
||||||
|
// as non object
|
||||||
|
var fn = () => builder.instantiate({
|
||||||
|
mod: {
|
||||||
|
a: 1n,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThrows(fn, WebAssembly.LinkError);
|
||||||
|
|
||||||
|
// as WebAssembly.Global object
|
||||||
|
var module = builder.instantiate({
|
||||||
|
mod: {
|
||||||
|
a: new WebAssembly.Global({ value: "i64", mutable: true }, 1n),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(module.exports.a.value, 1n);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestJSBigIntToWasmI64Identity() {
|
||||||
|
var builder = new WasmModuleBuilder();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.addFunction("f", kSig_l_l) // i64 -> i64
|
||||||
|
.addBody([
|
||||||
|
kExprGetLocal, 0x0,
|
||||||
|
])
|
||||||
|
.exportFunc();
|
||||||
|
|
||||||
|
var module = builder.instantiate();
|
||||||
|
var f = module.exports.f;
|
||||||
|
|
||||||
|
assertEquals(f(0n), 0n);
|
||||||
|
assertEquals(f(-0n), -0n);
|
||||||
|
assertEquals(f(123n), 123n);
|
||||||
|
assertEquals(f(-123n), -123n);
|
||||||
|
|
||||||
|
assertEquals(f("5"), 5n);
|
||||||
|
|
||||||
|
assertThrows(() => f(5), TypeError);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestI64Global() {
|
||||||
|
var argument = { "value": "i64", "mutable": true };
|
||||||
|
var global = new WebAssembly.Global(argument);
|
||||||
|
|
||||||
|
assertEquals(global.value, 0n); // initial value
|
||||||
|
|
||||||
|
global.value = 123n;
|
||||||
|
assertEquals(global.valueOf(), 123n);
|
||||||
|
|
||||||
|
global.value = 2n ** 63n;
|
||||||
|
assertEquals(global.valueOf(), - (2n ** 63n));
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestI64GlobalValueOf() {
|
||||||
|
var argument = { "value": "i64" };
|
||||||
|
|
||||||
|
// as literal
|
||||||
|
var global = new WebAssembly.Global(argument, {
|
||||||
|
valueOf() {
|
||||||
|
return 123n;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(global.value, 123n);
|
||||||
|
|
||||||
|
// as string
|
||||||
|
var global2 = new WebAssembly.Global(argument, {
|
||||||
|
valueOf() {
|
||||||
|
return "321";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(global2.value, 321n);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestInvalidValtypeGlobalErrorMessage() {
|
||||||
|
var argument = { "value": "some string" };
|
||||||
|
assertThrows(() => new WebAssembly.Global(argument), TypeError);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new WebAssembly.Global(argument);
|
||||||
|
} catch (e) {
|
||||||
|
assertContains("'value' must be", e.message);
|
||||||
|
assertContains("i64", e.message);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestGlobalI64ValueWrongType() {
|
||||||
|
var argument = { "value": "i64" };
|
||||||
|
assertThrows(() => new WebAssembly.Global(argument, 666), TypeError);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestGlobalI64SetWrongType() {
|
||||||
|
var argument = { "value": "i64", "mutable": true };
|
||||||
|
var global = new WebAssembly.Global(argument);
|
||||||
|
|
||||||
|
assertThrows(() => global.value = 1, TypeError);
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function TestFuncParamF64PassingBigInt() {
|
||||||
|
var builder = new WasmModuleBuilder();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.addFunction("f", kSig_v_d) // f64 -> ()
|
||||||
|
.addBody([])
|
||||||
|
.exportFunc();
|
||||||
|
|
||||||
|
var module = builder.instantiate();
|
||||||
|
|
||||||
|
assertThrows(() => module.exports.f(123n), TypeError);
|
||||||
|
})();
|
Loading…
Reference in New Issue
Block a user