[tq][runtime] Use build flags for JS context promise hooks
Use build_flags_ with @if/@ifnot in torque for the following flags: - V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS - V8_ENABLE_SWISS_NAME_DICTIONARY - Make sure Torque and CSA code actually respect V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS. - Rename V8_ALLOW_JAVASCRIPT_IN_PROMISE_HOOKS to V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS - Rename gn/bazel arg v8_allow_javascript_in_promise_hooks to v8_enable_javascript_promise_hooks - Unship context promise hooks in chrome and enable them only in d8 for testing purposes - Make sure d8 and the API throw when using promise hooks without the compile time feature enabled Bug: chromium:1265186, v8:11025 Change-Id: I69834d44d683a36d0d7be3c3d68888321be0fd7f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3301474 Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Michael Achenbach <machenbach@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/main@{#78362}
This commit is contained in:
parent
4ecf143801
commit
1e4593f3fe
@ -84,7 +84,7 @@ config_setting(
|
||||
# v8_generate_external_defines_header
|
||||
# v8_dict_property_const_tracking
|
||||
# v8_enable_map_packing
|
||||
# v8_allow_javascript_in_promise_hooks
|
||||
# v8_enable_javascript_promise_hooks
|
||||
# v8_enable_allocation_folding
|
||||
# v8_allocation_site_tracking
|
||||
|
||||
|
6
BUILD.gn
6
BUILD.gn
@ -333,7 +333,7 @@ declare_args() {
|
||||
v8_enable_map_packing = false
|
||||
|
||||
# Allow for JS promise hooks (instead of just C++).
|
||||
v8_allow_javascript_in_promise_hooks = false
|
||||
v8_enable_javascript_promise_hooks = false
|
||||
|
||||
# Enable allocation folding globally (sets -dV8_ALLOCATION_FOLDING).
|
||||
# When it's disabled, the --turbo-allocation-folding runtime flag will be ignored.
|
||||
@ -945,8 +945,8 @@ config("features") {
|
||||
if (v8_dict_property_const_tracking) {
|
||||
defines += [ "V8_DICT_PROPERTY_CONST_TRACKING" ]
|
||||
}
|
||||
if (v8_allow_javascript_in_promise_hooks) {
|
||||
defines += [ "V8_ALLOW_JAVASCRIPT_IN_PROMISE_HOOKS" ]
|
||||
if (v8_enable_javascript_promise_hooks) {
|
||||
defines += [ "V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS" ]
|
||||
}
|
||||
if (v8_enable_allocation_folding) {
|
||||
defines += [ "V8_ALLOCATION_FOLDING" ]
|
||||
|
@ -6602,6 +6602,7 @@ void v8::Context::SetPromiseHooks(Local<Function> init_hook,
|
||||
Local<Function> before_hook,
|
||||
Local<Function> after_hook,
|
||||
Local<Function> resolve_hook) {
|
||||
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
i::Handle<i::Context> context = Utils::OpenHandle(this);
|
||||
i::Isolate* isolate = context->GetIsolate();
|
||||
|
||||
@ -6635,6 +6636,10 @@ void v8::Context::SetPromiseHooks(Local<Function> init_hook,
|
||||
context->native_context().set_promise_hook_before_function(*before);
|
||||
context->native_context().set_promise_hook_after_function(*after);
|
||||
context->native_context().set_promise_hook_resolve_function(*resolve);
|
||||
#else // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
Utils::ApiCheck(false, "v8::Context::SetPromiseHook",
|
||||
"V8 was compiled without JavaScript Promise hooks");
|
||||
#endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
}
|
||||
|
||||
MaybeLocal<Context> metrics::Recorder::GetContext(
|
||||
|
@ -485,9 +485,6 @@ const kWasmArrayHeaderSize:
|
||||
const kHeapObjectHeaderSize:
|
||||
constexpr int32 generates 'HeapObject::kHeaderSize';
|
||||
|
||||
const kDictModePrototypes:
|
||||
constexpr bool generates 'V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL';
|
||||
|
||||
type TheHole extends Oddball;
|
||||
type Null extends Oddball;
|
||||
type Undefined extends Oddball;
|
||||
|
@ -183,6 +183,7 @@ void AsyncBuiltinsAssembler::InitAwaitPromise(
|
||||
Goto(&do_nothing);
|
||||
BIND(¬_debugging);
|
||||
|
||||
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
// This call to NewJSPromise is to keep behaviour parity with what happens
|
||||
// in Runtime::kAwaitPromisesInit above if native hooks are set. It will
|
||||
// create a throwaway promise that will trigger an init event and will get
|
||||
@ -191,6 +192,7 @@ void AsyncBuiltinsAssembler::InitAwaitPromise(
|
||||
&do_nothing);
|
||||
BIND(&if_promise_hook);
|
||||
*var_throwaway = NewJSPromise(context, promise);
|
||||
#endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
Goto(&do_nothing);
|
||||
BIND(&do_nothing);
|
||||
}
|
||||
|
@ -99,10 +99,11 @@ transitioning builtin CreateObjectWithoutProperties(implicit context: Context)(
|
||||
case (Null): {
|
||||
map = *NativeContextSlot(
|
||||
ContextSlot::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP);
|
||||
if (kDictModePrototypes) {
|
||||
@if(V8_ENABLE_SWISS_NAME_DICTIONARY) {
|
||||
properties =
|
||||
AllocateSwissNameDictionary(kSwissNameDictionaryInitialCapacity);
|
||||
} else {
|
||||
}
|
||||
@ifnot(V8_ENABLE_SWISS_NAME_DICTIONARY) {
|
||||
properties = AllocateNameDictionary(kNameDictionaryInitialCapacity);
|
||||
}
|
||||
}
|
||||
|
@ -120,10 +120,14 @@ transitioning macro RunContextPromiseHookInit(implicit context: Context)(
|
||||
@export
|
||||
transitioning macro RunContextPromiseHookResolve(implicit context: Context)(
|
||||
promise: JSPromise): void {
|
||||
// Use potentially unused variables.
|
||||
const _unusedPromise = promise;
|
||||
@if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) {
|
||||
RunContextPromiseHook(
|
||||
ContextSlot::PROMISE_HOOK_RESOLVE_FUNCTION_INDEX, promise,
|
||||
PromiseHookFlags());
|
||||
}
|
||||
}
|
||||
|
||||
@export
|
||||
transitioning macro RunContextPromiseHookResolve(implicit context: Context)(
|
||||
@ -135,10 +139,14 @@ transitioning macro RunContextPromiseHookResolve(implicit context: Context)(
|
||||
@export
|
||||
transitioning macro RunContextPromiseHookBefore(implicit context: Context)(
|
||||
promiseOrCapability: JSPromise|PromiseCapability|Undefined): void {
|
||||
// Use potentially unused variables.
|
||||
const _unusedPromiseOrCapability = promiseOrCapability;
|
||||
@if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) {
|
||||
RunContextPromiseHook(
|
||||
ContextSlot::PROMISE_HOOK_BEFORE_FUNCTION_INDEX, promiseOrCapability,
|
||||
PromiseHookFlags());
|
||||
}
|
||||
}
|
||||
|
||||
@export
|
||||
transitioning macro RunContextPromiseHookBefore(implicit context: Context)(
|
||||
@ -152,10 +160,14 @@ transitioning macro RunContextPromiseHookBefore(implicit context: Context)(
|
||||
@export
|
||||
transitioning macro RunContextPromiseHookAfter(implicit context: Context)(
|
||||
promiseOrCapability: JSPromise|PromiseCapability|Undefined): void {
|
||||
// Use potentially unused variables.
|
||||
const _unusedPromiseOrCapability = promiseOrCapability;
|
||||
@if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) {
|
||||
RunContextPromiseHook(
|
||||
ContextSlot::PROMISE_HOOK_AFTER_FUNCTION_INDEX, promiseOrCapability,
|
||||
PromiseHookFlags());
|
||||
}
|
||||
}
|
||||
|
||||
@export
|
||||
transitioning macro RunContextPromiseHookAfter(implicit context: Context)(
|
||||
@ -170,6 +182,11 @@ transitioning macro RunContextPromiseHook(implicit context: Context)(
|
||||
slot: Slot<NativeContext, Undefined|Callable>,
|
||||
promiseOrCapability: JSPromise|PromiseCapability|Undefined,
|
||||
flags: uint32): void {
|
||||
// Use potentially unused variables.
|
||||
const _unusedSlot = slot;
|
||||
const _unusedPromiseOrCapability = promiseOrCapability;
|
||||
const _unusedFlags = flags;
|
||||
@if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) {
|
||||
if (!IsContextPromiseHookEnabled(flags)) return;
|
||||
const maybeHook = *NativeContextSlot(slot);
|
||||
const hook = Cast<Callable>(maybeHook) otherwise return;
|
||||
@ -193,15 +210,18 @@ transitioning macro RunContextPromiseHook(implicit context: Context)(
|
||||
runtime::ReportMessageFromMicrotask(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transitioning macro RunAnyPromiseHookInit(implicit context: Context)(
|
||||
promise: JSPromise, parent: Object): void {
|
||||
const promiseHookFlags = PromiseHookFlags();
|
||||
// Fast return if no hooks are set.
|
||||
if (promiseHookFlags == 0) return;
|
||||
@if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) {
|
||||
if (IsContextPromiseHookEnabled(promiseHookFlags)) {
|
||||
RunContextPromiseHookInit(promise, parent);
|
||||
}
|
||||
}
|
||||
if (IsIsolatePromiseHookEnabledOrHasAsyncEventDelegate(promiseHookFlags)) {
|
||||
runtime::PromiseHookInit(promise, parent);
|
||||
}
|
||||
|
@ -14381,10 +14381,12 @@ TNode<BoolT> CodeStubAssembler::IsAnyPromiseHookEnabled(TNode<Uint32T> flags) {
|
||||
return IsSetWord32(flags, mask);
|
||||
}
|
||||
|
||||
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
TNode<BoolT> CodeStubAssembler::IsContextPromiseHookEnabled(
|
||||
TNode<Uint32T> flags) {
|
||||
return IsSetWord32<Isolate::PromiseHookFields::HasContextPromiseHook>(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
TNode<BoolT> CodeStubAssembler::
|
||||
IsIsolatePromiseHookEnabledOrHasAsyncEventDelegate(TNode<Uint32T> flags) {
|
||||
|
@ -3660,10 +3660,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
// Promise helpers
|
||||
TNode<Uint32T> PromiseHookFlags();
|
||||
TNode<BoolT> HasAsyncEventDelegate();
|
||||
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
TNode<BoolT> IsContextPromiseHookEnabled(TNode<Uint32T> flags);
|
||||
TNode<BoolT> IsContextPromiseHookEnabled() {
|
||||
return IsContextPromiseHookEnabled(PromiseHookFlags());
|
||||
}
|
||||
#endif
|
||||
TNode<BoolT> IsAnyPromiseHookEnabled(TNode<Uint32T> flags);
|
||||
TNode<BoolT> IsAnyPromiseHookEnabled() {
|
||||
return IsAnyPromiseHookEnabled(PromiseHookFlags());
|
||||
|
@ -2164,6 +2164,7 @@ void Shell::SetPromiseHooks(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
"--correctness-fuzzer-suppressions");
|
||||
return;
|
||||
}
|
||||
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
@ -2174,6 +2175,11 @@ void Shell::SetPromiseHooks(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
args[3]->IsFunction() ? args[3].As<Function>() : Local<Function>());
|
||||
|
||||
args.GetReturnValue().Set(v8::Undefined(isolate));
|
||||
#else // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
isolate->ThrowError(
|
||||
"d8.promise.setHooks is disabled due to missing build flag "
|
||||
"v8_enabale_javascript_in_promise_hooks");
|
||||
#endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
}
|
||||
|
||||
void WriteToFile(FILE* file, const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
|
@ -1569,11 +1569,13 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
void SetHasContextPromiseHooks(bool context_promise_hook) {
|
||||
promise_hook_flags_ = PromiseHookFields::HasContextPromiseHook::update(
|
||||
promise_hook_flags_, context_promise_hook);
|
||||
PromiseHookStateUpdated();
|
||||
}
|
||||
#endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
|
||||
bool HasContextPromiseHooks() const {
|
||||
return PromiseHookFields::HasContextPromiseHook::decode(
|
||||
|
@ -78,10 +78,11 @@ macro AllocateFastOrSlowJSObjectFromMap(implicit context: Context)(map: Map):
|
||||
let properties: EmptyFixedArray|NameDictionary|SwissNameDictionary =
|
||||
kEmptyFixedArray;
|
||||
if (IsDictionaryMap(map)) {
|
||||
if (kDictModePrototypes) {
|
||||
@if(V8_ENABLE_SWISS_NAME_DICTIONARY) {
|
||||
properties =
|
||||
AllocateSwissNameDictionary(kSwissNameDictionaryInitialCapacity);
|
||||
} else {
|
||||
}
|
||||
@ifnot(V8_ENABLE_SWISS_NAME_DICTIONARY) {
|
||||
properties = AllocateNameDictionary(kNameDictionaryInitialCapacity);
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,13 @@ class BuildFlags : public ContextualClass<BuildFlags> {
|
||||
build_flags_["V8_SFI_HAS_UNIQUE_ID"] = V8_SFI_HAS_UNIQUE_ID;
|
||||
build_flags_["V8_EXTERNAL_CODE_SPACE"] = V8_EXTERNAL_CODE_SPACE_BOOL;
|
||||
build_flags_["TAGGED_SIZE_8_BYTES"] = TAGGED_SIZE_8_BYTES;
|
||||
build_flags_["V8_ENABLE_SWISS_NAME_DICTIONARY"] =
|
||||
V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL;
|
||||
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
build_flags_["V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS"] = true;
|
||||
#else
|
||||
build_flags_["V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS"] = false;
|
||||
#endif
|
||||
build_flags_["TRUE_FOR_TESTING"] = true;
|
||||
build_flags_["FALSE_FOR_TESTING"] = false;
|
||||
#ifdef V8_SCRIPTORMODULE_LEGACY_LIFETIME
|
||||
|
@ -37,6 +37,14 @@ function printLog(message) {
|
||||
}
|
||||
}
|
||||
|
||||
let has_promise_hooks = false;
|
||||
try {
|
||||
d8.promise.setHooks();
|
||||
has_promise_hooks = true;
|
||||
} catch {
|
||||
has_promise_hooks = false;
|
||||
}
|
||||
|
||||
function assertNextEvent(type, args) {
|
||||
const [ promiseOrId, parentOrId ] = args;
|
||||
const nextEvent = log.shift();
|
||||
@ -212,6 +220,7 @@ function optimizerBailout(test, verify) {
|
||||
d8.promise.setHooks();
|
||||
}
|
||||
|
||||
if (has_promise_hooks) {
|
||||
optimizerBailout(async () => {
|
||||
await Promise.resolve();
|
||||
}, () => {
|
||||
@ -281,3 +290,5 @@ exceptions();
|
||||
%PerformMicrotaskCheckpoint();
|
||||
d8.promise.setHooks();
|
||||
});
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user