blob: 71443ca920c330d359029ce4c617f9ac8d79fa77 [file] [log] [blame]
// Copyright 2016 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.
#ifndef V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
#define V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
#include "src/codegen/code-stub-assembler.h"
#include "src/objects/promise.h"
namespace v8 {
namespace internal {
using CodeAssemblerState = compiler::CodeAssemblerState;
class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
public:
explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
// These allocate and initialize a promise with pending state and
// undefined fields.
//
// This uses undefined as the parent promise for the promise init
// hook.
Node* AllocateAndInitJSPromise(Node* context);
// This uses the given parent as the parent promise for the promise
// init hook.
Node* AllocateAndInitJSPromise(Node* context, Node* parent);
// This allocates and initializes a promise with the given state and
// fields.
Node* AllocateAndSetJSPromise(Node* context, v8::Promise::PromiseState status,
Node* result);
Node* AllocatePromiseReaction(Node* next, Node* promise_or_capability,
Node* fulfill_handler, Node* reject_handler);
Node* AllocatePromiseReactionJobTask(RootIndex map_root_index, Node* context,
Node* argument, Node* handler,
Node* promise_or_capability);
Node* AllocatePromiseReactionJobTask(Node* map, Node* context, Node* argument,
Node* handler,
Node* promise_or_capability);
Node* AllocatePromiseResolveThenableJobTask(Node* promise_to_resolve,
Node* then, Node* thenable,
Node* context);
std::pair<Node*, Node*> CreatePromiseResolvingFunctions(Node* promise,
Node* debug_event,
Node* native_context);
Node* PromiseHasHandler(Node* promise);
// Creates the context used by all Promise.all resolve element closures,
// together with the values array. Since all closures for a single Promise.all
// call use the same context, we need to store the indices for the individual
// closures somewhere else (we put them into the identity hash field of the
// closures), and we also need to have a separate marker for when the closure
// was called already (we slap the native context onto the closure in that
// case to mark it's done).
Node* CreatePromiseAllResolveElementContext(Node* promise_capability,
Node* native_context);
TNode<JSFunction> CreatePromiseAllResolveElementFunction(Node* context,
TNode<Smi> index,
Node* native_context,
int slot_index);
Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
Node* native_context);
Node* CreatePromiseGetCapabilitiesExecutorContext(Node* promise_capability,
Node* native_context);
protected:
void PromiseInit(Node* promise);
void PromiseSetHasHandler(Node* promise);
void PromiseSetHandledHint(Node* promise);
void PerformPromiseThen(Node* context, Node* promise, Node* on_fulfilled,
Node* on_rejected,
Node* result_promise_or_capability);
Node* CreatePromiseContext(Node* native_context, int slots);
Node* TriggerPromiseReactions(Node* context, Node* promise, Node* result,
PromiseReaction::Type type);
// We can skip the "resolve" lookup on {constructor} if it's the (initial)
// Promise constructor and the Promise.resolve() protector is intact, as
// that guards the lookup path for the "resolve" property on the %Promise%
// intrinsic object.
void BranchIfPromiseResolveLookupChainIntact(Node* native_context,
Node* constructor,
Label* if_fast, Label* if_slow);
void GotoIfNotPromiseResolveLookupChainIntact(Node* native_context,
Node* constructor,
Label* if_slow);
// We can shortcut the SpeciesConstructor on {promise_map} if it's
// [[Prototype]] is the (initial) Promise.prototype and the @@species
// protector is intact, as that guards the lookup path for the "constructor"
// property on JSPromise instances which have the %PromisePrototype%.
void BranchIfPromiseSpeciesLookupChainIntact(Node* native_context,
Node* promise_map,
Label* if_fast, Label* if_slow);
// We can skip the "then" lookup on {receiver_map} if it's [[Prototype]]
// is the (initial) Promise.prototype and the Promise#then() protector
// is intact, as that guards the lookup path for the "then" property
// on JSPromise instances which have the (initial) %PromisePrototype%.
void BranchIfPromiseThenLookupChainIntact(Node* native_context,
Node* receiver_map, Label* if_fast,
Label* if_slow);
// If resolve is Undefined, we use the builtin %PromiseResolve%
// intrinsic, otherwise we use the given resolve function.
Node* CallResolve(Node* native_context, Node* constructor, Node* resolve,
Node* value, Label* if_exception, Variable* var_exception);
template <typename... TArgs>
Node* InvokeThen(Node* native_context, Node* receiver, TArgs... args);
void BranchIfAccessCheckFailed(Node* context, Node* native_context,
Node* promise_constructor, Node* executor,
Label* if_noaccess);
std::pair<Node*, Node*> CreatePromiseFinallyFunctions(Node* on_finally,
Node* constructor,
Node* native_context);
Node* CreateValueThunkFunction(Node* value, Node* native_context);
Node* CreateThrowerFunction(Node* reason, Node* native_context);
using PromiseAllResolvingElementFunction =
std::function<TNode<Object>(TNode<Context> context, TNode<Smi> index,
TNode<NativeContext> native_context,
TNode<PromiseCapability> capability)>;
Node* PerformPromiseAll(
Node* context, Node* constructor, Node* capability,
const TorqueStructIteratorRecord& record,
const PromiseAllResolvingElementFunction& create_resolve_element_function,
const PromiseAllResolvingElementFunction& create_reject_element_function,
Label* if_exception, Variable* var_exception);
void SetForwardingHandlerIfTrue(Node* context, Node* condition,
const NodeGenerator& object);
inline void SetForwardingHandlerIfTrue(Node* context, Node* condition,
Node* object) {
return SetForwardingHandlerIfTrue(context, condition,
[object]() -> Node* { return object; });
}
void SetPromiseHandledByIfTrue(Node* context, Node* condition, Node* promise,
const NodeGenerator& handled_by);
Node* PromiseStatus(Node* promise);
void PromiseReactionJob(Node* context, Node* argument, Node* handler,
Node* promise_or_capability,
PromiseReaction::Type type);
Node* IsPromiseStatus(Node* actual, v8::Promise::PromiseState expected);
void PromiseSetStatus(Node* promise, v8::Promise::PromiseState status);
Node* AllocateJSPromise(Node* context);
void ExtractHandlerContext(Node* handler, Variable* var_context);
void Generate_PromiseAll(
TNode<Context> context, TNode<Object> receiver, TNode<Object> iterable,
const PromiseAllResolvingElementFunction& create_resolve_element_function,
const PromiseAllResolvingElementFunction& create_reject_element_function);
using CreatePromiseAllResolveElementFunctionValue =
std::function<TNode<Object>(TNode<Context> context,
TNode<NativeContext> native_context,
TNode<Object> value)>;
void Generate_PromiseAllResolveElementClosure(
TNode<Context> context, TNode<Object> value, TNode<JSFunction> function,
const CreatePromiseAllResolveElementFunctionValue& callback);
};
} // namespace internal
} // namespace v8
#endif // V8_BUILTINS_BUILTINS_PROMISE_GEN_H_