[wasm-gc] Add callback for Wasm GC origin trial
The callback can be used to enable / disable Wasm GC from Chrome or other users. For more simplicity and as many users of Wasm GC also use stringrefs, enabling it via the callback will also stringrefs. Bug: v8:7748 Change-Id: I474034eabe438f0ce9759c1d34dda12a99aa491e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4165090 Auto-Submit: Matthias Liedtke <mliedtke@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Adam Klein <adamk@chromium.org> Commit-Queue: Matthias Liedtke <mliedtke@chromium.org> Cr-Commit-Position: refs/heads/main@{#85306}
This commit is contained in:
parent
6ca23f83ee
commit
debcabf7b5
@ -328,6 +328,10 @@ using WasmSimdEnabledCallback = bool (*)(Local<Context> context);
|
|||||||
// --- Callback for checking if WebAssembly exceptions are enabled ---
|
// --- Callback for checking if WebAssembly exceptions are enabled ---
|
||||||
using WasmExceptionsEnabledCallback = bool (*)(Local<Context> context);
|
using WasmExceptionsEnabledCallback = bool (*)(Local<Context> context);
|
||||||
|
|
||||||
|
// --- Callback for checking if WebAssembly GC is enabled ---
|
||||||
|
// If the callback returns true, it will also enable Wasm stringrefs.
|
||||||
|
using WasmGCEnabledCallback = bool (*)(Local<Context> context);
|
||||||
|
|
||||||
// --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
|
// --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
|
||||||
using SharedArrayBufferConstructorEnabledCallback =
|
using SharedArrayBufferConstructorEnabledCallback =
|
||||||
bool (*)(Local<Context> context);
|
bool (*)(Local<Context> context);
|
||||||
|
@ -1513,6 +1513,13 @@ class V8_EXPORT Isolate {
|
|||||||
V8_DEPRECATED("Wasm exceptions are always enabled")
|
V8_DEPRECATED("Wasm exceptions are always enabled")
|
||||||
void SetWasmExceptionsEnabledCallback(WasmExceptionsEnabledCallback callback);
|
void SetWasmExceptionsEnabledCallback(WasmExceptionsEnabledCallback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register callback to control whehter Wasm GC is enabled.
|
||||||
|
* The callback overwrites the value of the flag.
|
||||||
|
* If the callback returns true, it will also enable Wasm stringrefs.
|
||||||
|
*/
|
||||||
|
void SetWasmGCEnabledCallback(WasmGCEnabledCallback callback);
|
||||||
|
|
||||||
void SetSharedArrayBufferConstructorEnabledCallback(
|
void SetSharedArrayBufferConstructorEnabledCallback(
|
||||||
SharedArrayBufferConstructorEnabledCallback callback);
|
SharedArrayBufferConstructorEnabledCallback callback);
|
||||||
|
|
||||||
|
@ -9766,6 +9766,9 @@ CALLBACK_SETTER(WasmAsyncResolvePromiseCallback,
|
|||||||
CALLBACK_SETTER(WasmLoadSourceMapCallback, WasmLoadSourceMapCallback,
|
CALLBACK_SETTER(WasmLoadSourceMapCallback, WasmLoadSourceMapCallback,
|
||||||
wasm_load_source_map_callback)
|
wasm_load_source_map_callback)
|
||||||
|
|
||||||
|
CALLBACK_SETTER(WasmGCEnabledCallback, WasmGCEnabledCallback,
|
||||||
|
wasm_gc_enabled_callback)
|
||||||
|
|
||||||
CALLBACK_SETTER(SharedArrayBufferConstructorEnabledCallback,
|
CALLBACK_SETTER(SharedArrayBufferConstructorEnabledCallback,
|
||||||
SharedArrayBufferConstructorEnabledCallback,
|
SharedArrayBufferConstructorEnabledCallback,
|
||||||
sharedarraybuffer_constructor_enabled_callback)
|
sharedarraybuffer_constructor_enabled_callback)
|
||||||
|
@ -2940,6 +2940,31 @@ bool Isolate::IsSharedArrayBufferConstructorEnabled(Handle<Context> context) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Isolate::IsWasmGCEnabled(Handle<Context> context) {
|
||||||
|
#ifdef V8_ENABLE_WEBASSEMBLY
|
||||||
|
if (wasm_gc_enabled_callback()) {
|
||||||
|
v8::Local<v8::Context> api_context = v8::Utils::ToLocal(context);
|
||||||
|
return wasm_gc_enabled_callback()(api_context);
|
||||||
|
}
|
||||||
|
return v8_flags.experimental_wasm_gc;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Isolate::IsWasmStringRefEnabled(Handle<Context> context) {
|
||||||
|
// If Wasm GC is explicitly enabled via a callback, also enable stringref.
|
||||||
|
#ifdef V8_ENABLE_WEBASSEMBLY
|
||||||
|
if (wasm_gc_enabled_callback()) {
|
||||||
|
v8::Local<v8::Context> api_context = v8::Utils::ToLocal(context);
|
||||||
|
return wasm_gc_enabled_callback()(api_context);
|
||||||
|
}
|
||||||
|
return v8_flags.experimental_wasm_stringref;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Handle<Context> Isolate::GetIncumbentContext() {
|
Handle<Context> Isolate::GetIncumbentContext() {
|
||||||
JavaScriptFrameIterator it(this);
|
JavaScriptFrameIterator it(this);
|
||||||
|
|
||||||
|
@ -510,6 +510,7 @@ using DebugObjectCache = std::vector<Handle<HeapObject>>;
|
|||||||
V(WasmLoadSourceMapCallback, wasm_load_source_map_callback, nullptr) \
|
V(WasmLoadSourceMapCallback, wasm_load_source_map_callback, nullptr) \
|
||||||
V(WasmSimdEnabledCallback, wasm_simd_enabled_callback, nullptr) \
|
V(WasmSimdEnabledCallback, wasm_simd_enabled_callback, nullptr) \
|
||||||
V(WasmExceptionsEnabledCallback, wasm_exceptions_enabled_callback, nullptr) \
|
V(WasmExceptionsEnabledCallback, wasm_exceptions_enabled_callback, nullptr) \
|
||||||
|
V(WasmGCEnabledCallback, wasm_gc_enabled_callback, nullptr) \
|
||||||
/* State for Relocatable. */ \
|
/* State for Relocatable. */ \
|
||||||
V(Relocatable*, relocatable_top, nullptr) \
|
V(Relocatable*, relocatable_top, nullptr) \
|
||||||
V(DebugObjectCache*, string_stream_debug_object_cache, nullptr) \
|
V(DebugObjectCache*, string_stream_debug_object_cache, nullptr) \
|
||||||
@ -769,6 +770,9 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
|||||||
|
|
||||||
bool IsSharedArrayBufferConstructorEnabled(Handle<Context> context);
|
bool IsSharedArrayBufferConstructorEnabled(Handle<Context> context);
|
||||||
|
|
||||||
|
bool IsWasmGCEnabled(Handle<Context> context);
|
||||||
|
bool IsWasmStringRefEnabled(Handle<Context> context);
|
||||||
|
|
||||||
THREAD_LOCAL_TOP_ADDRESS(Context, pending_handler_context)
|
THREAD_LOCAL_TOP_ADDRESS(Context, pending_handler_context)
|
||||||
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_entrypoint)
|
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_entrypoint)
|
||||||
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_constant_pool)
|
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_constant_pool)
|
||||||
|
@ -494,5 +494,17 @@ RUNTIME_FUNCTION(Runtime_FreezeWasmLazyCompilation) {
|
|||||||
return ReadOnlyRoots(isolate).undefined_value();
|
return ReadOnlyRoots(isolate).undefined_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This runtime function enables WebAssembly GC through an embedder
|
||||||
|
// callback and thereby bypasses the value in v8_flags.
|
||||||
|
RUNTIME_FUNCTION(Runtime_SetWasmGCEnabled) {
|
||||||
|
DCHECK_EQ(1, args.length());
|
||||||
|
bool enable = args.at(0)->BooleanValue(isolate);
|
||||||
|
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
|
||||||
|
WasmGCEnabledCallback enabled = [](v8::Local<v8::Context>) { return true; };
|
||||||
|
WasmGCEnabledCallback disabled = [](v8::Local<v8::Context>) { return false; };
|
||||||
|
v8_isolate->SetWasmGCEnabledCallback(enable ? enabled : disabled);
|
||||||
|
return ReadOnlyRoots(isolate).undefined_value();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -668,6 +668,7 @@ namespace internal {
|
|||||||
F(SerializeWasmModule, 1, 1) \
|
F(SerializeWasmModule, 1, 1) \
|
||||||
F(SetWasmCompileControls, 2, 1) \
|
F(SetWasmCompileControls, 2, 1) \
|
||||||
F(SetWasmInstantiateControls, 0, 1) \
|
F(SetWasmInstantiateControls, 0, 1) \
|
||||||
|
F(SetWasmGCEnabled, 1, 1) \
|
||||||
F(WasmGetNumberOfInstances, 1, 1) \
|
F(WasmGetNumberOfInstances, 1, 1) \
|
||||||
F(WasmNumCodeSpaces, 1, 1) \
|
F(WasmNumCodeSpaces, 1, 1) \
|
||||||
F(WasmEnterDebugging, 0, 1) \
|
F(WasmEnterDebugging, 0, 1) \
|
||||||
|
@ -33,6 +33,12 @@ WasmFeatures WasmFeatures::FromIsolate(Isolate* isolate) {
|
|||||||
WasmFeatures WasmFeatures::FromContext(Isolate* isolate,
|
WasmFeatures WasmFeatures::FromContext(Isolate* isolate,
|
||||||
Handle<Context> context) {
|
Handle<Context> context) {
|
||||||
WasmFeatures features = WasmFeatures::FromFlags();
|
WasmFeatures features = WasmFeatures::FromFlags();
|
||||||
|
if (isolate->IsWasmGCEnabled(handle(isolate->context(), isolate))) {
|
||||||
|
features.Add(kFeature_gc);
|
||||||
|
}
|
||||||
|
if (isolate->IsWasmStringRefEnabled(handle(isolate->context(), isolate))) {
|
||||||
|
features.Add(kFeature_stringref);
|
||||||
|
}
|
||||||
// This space intentionally left blank for future Wasm origin trials.
|
// This space intentionally left blank for future Wasm origin trials.
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
46
test/mjsunit/wasm/origin-trial-flags.js
Normal file
46
test/mjsunit/wasm/origin-trial-flags.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2023 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: --noexperimental-wasm-gc --no-experimental-wasm-stringref
|
||||||
|
// Flags: --allow-natives-syntax
|
||||||
|
|
||||||
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||||
|
|
||||||
|
function instantiateModuleWithGC() {
|
||||||
|
// Build a WebAssembly module which uses Wasm GC features.
|
||||||
|
const builder = new WasmModuleBuilder();
|
||||||
|
builder.addFunction('main', makeSig([], [kWasmAnyRef]))
|
||||||
|
.addBody([
|
||||||
|
kExprI32Const, 42,
|
||||||
|
kGCPrefix, kExprI31New,
|
||||||
|
])
|
||||||
|
.exportFunc();
|
||||||
|
|
||||||
|
return builder.instantiate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function instantiateModuleWithStringRef() {
|
||||||
|
// Build a WebAssembly module which uses stringref features.
|
||||||
|
const builder = new WasmModuleBuilder();
|
||||||
|
builder.addFunction("main",
|
||||||
|
makeSig([kWasmStringRef], [kWasmStringRef]))
|
||||||
|
.addBody([kExprLocalGet, 0])
|
||||||
|
.exportFunc();
|
||||||
|
return builder.instantiate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Due to --noexperimental-wasm-gc GC is disabled.
|
||||||
|
assertThrows(instantiateModuleWithGC, WebAssembly.CompileError);
|
||||||
|
// Due to --noexperimental-wasm-stringref stringrefs are not supported.
|
||||||
|
assertThrows(instantiateModuleWithStringRef, WebAssembly.CompileError);
|
||||||
|
// Disable WebAssembly GC explicitly.
|
||||||
|
%SetWasmGCEnabled(false);
|
||||||
|
assertThrows(instantiateModuleWithGC, WebAssembly.CompileError);
|
||||||
|
assertThrows(instantiateModuleWithStringRef, WebAssembly.CompileError);
|
||||||
|
// Enable WebAssembly GC explicitly.
|
||||||
|
%SetWasmGCEnabled(true);
|
||||||
|
assertEquals(42, instantiateModuleWithGC().exports.main());
|
||||||
|
// Enabling Wasm GC via callback will also enable wasm stringref.
|
||||||
|
let str = "Hello World!";
|
||||||
|
assertSame(str, instantiateModuleWithStringRef().exports.main(str));
|
@ -13,6 +13,7 @@
|
|||||||
#include "include/v8-wasm.h"
|
#include "include/v8-wasm.h"
|
||||||
#include "src/api/api-inl.h"
|
#include "src/api/api-inl.h"
|
||||||
#include "src/handles/global-handles.h"
|
#include "src/handles/global-handles.h"
|
||||||
|
#include "test/common/flag-utils.h"
|
||||||
#include "test/unittests/test-utils.h"
|
#include "test/unittests/test-utils.h"
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
@ -156,4 +157,33 @@ TEST_F(ApiWasmTest, WasmStreamingSetCallback) {
|
|||||||
Promise::kPending);
|
Promise::kPending);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ApiWasmTest, WasmEnableDisableGC) {
|
||||||
|
Local<Context> context_local = Context::New(isolate());
|
||||||
|
Context::Scope context_scope(context_local);
|
||||||
|
i::Handle<i::Context> context = v8::Utils::OpenHandle(*context_local);
|
||||||
|
// When using the flags, stringref and GC are controlled independently.
|
||||||
|
{
|
||||||
|
i::FlagScope<bool> flag_gc(&i::v8_flags.experimental_wasm_gc, false);
|
||||||
|
i::FlagScope<bool> flag_stringref(&i::v8_flags.experimental_wasm_stringref,
|
||||||
|
true);
|
||||||
|
EXPECT_FALSE(i_isolate()->IsWasmGCEnabled(context));
|
||||||
|
EXPECT_TRUE(i_isolate()->IsWasmStringRefEnabled(context));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
i::FlagScope<bool> flag_gc(&i::v8_flags.experimental_wasm_gc, true);
|
||||||
|
i::FlagScope<bool> flag_stringref(&i::v8_flags.experimental_wasm_stringref,
|
||||||
|
false);
|
||||||
|
EXPECT_TRUE(i_isolate()->IsWasmGCEnabled(context));
|
||||||
|
EXPECT_FALSE(i_isolate()->IsWasmStringRefEnabled(context));
|
||||||
|
}
|
||||||
|
// When providing a callback, the callback will control GC and stringref.
|
||||||
|
isolate()->SetWasmGCEnabledCallback([](auto) { return true; });
|
||||||
|
EXPECT_TRUE(i_isolate()->IsWasmGCEnabled(context));
|
||||||
|
EXPECT_TRUE(i_isolate()->IsWasmStringRefEnabled(context));
|
||||||
|
isolate()->SetWasmGCEnabledCallback([](auto) { return false; });
|
||||||
|
EXPECT_FALSE(i_isolate()->IsWasmGCEnabled(context));
|
||||||
|
EXPECT_FALSE(i_isolate()->IsWasmStringRefEnabled(context));
|
||||||
|
isolate()->SetWasmGCEnabledCallback(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
Loading…
Reference in New Issue
Block a user