162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// found in the LICENSE file.
462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#ifndef V8_BUILTINS_BUILTINS_PROMISE_H_
662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define V8_BUILTINS_BUILTINS_PROMISE_H_
762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-stub-assembler.h"
962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/contexts.h"
1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace v8 {
1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace internal {
1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtypedef compiler::Node Node;
1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtypedef CodeStubAssembler::ParameterMode ParameterMode;
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtypedef compiler::CodeAssemblerState CodeAssemblerState;
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass PromiseBuiltinsAssembler : public CodeStubAssembler {
1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public:
2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  enum PromiseResolvingFunctionContextSlot {
2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Whether the resolve/reject callback was already called.
2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kAlreadyVisitedSlot = Context::MIN_CONTEXT_SLOTS,
2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // The promise which resolve/reject callbacks fulfill.
2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kPromiseSlot,
2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Whether to trigger a debug event or not. Used in catch
2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // prediction.
2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kDebugEventSlot,
3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kPromiseContextLength,
3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  };
3262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  enum FunctionContextSlot {
3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kCapabilitySlot = Context::MIN_CONTEXT_SLOTS,
3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kCapabilitiesContextLength,
3762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  };
3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // This is used by the PromiseThenFinally and PromiseCatchFinally
4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // builtins to store the onFinally in the onFinallySlot.
4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //
4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // This is also used by the PromiseValueThunkFinally to store the
4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // value in the onFinallySlot and PromiseThrowerFinally to store the
4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // reason in the onFinallySlot.
4562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  enum PromiseFinallyContextSlot {
4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kOnFinallySlot = Context::MIN_CONTEXT_SLOTS,
4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kOnFinallyContextLength,
4962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  };
5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
5162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  explicit PromiseBuiltinsAssembler(CodeAssemblerState* state)
5262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      : CodeStubAssembler(state) {}
5362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // These allocate and initialize a promise with pending state and
5462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // undefined fields.
5562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //
5662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // This uses undefined as the parent promise for the promise init
5762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // hook.
5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* AllocateAndInitJSPromise(Node* context);
5962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // This uses the given parent as the parent promise for the promise
6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // init hook.
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* AllocateAndInitJSPromise(Node* context, Node* parent);
6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // This allocates and initializes a promise with the given state and
6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // fields.
6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* AllocateAndSetJSPromise(Node* context, Node* status, Node* result);
6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
6762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* AllocatePromiseResolveThenableJobInfo(Node* result, Node* then,
6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                              Node* resolve, Node* reject,
6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                              Node* context);
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  std::pair<Node*, Node*> CreatePromiseResolvingFunctions(
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* promise, Node* native_context, Node* promise_context);
7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* PromiseHasHandler(Node* promise);
7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                               Node* native_context);
7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreatePromiseGetCapabilitiesExecutorContext(Node* native_context,
8062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* promise_capability);
8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* NewPromiseCapability(Node* context, Node* constructor,
8362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             Node* debug_event = nullptr);
8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch protected:
8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void PromiseInit(Node* promise);
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* ThrowIfNotJSReceiver(Node* context, Node* value,
8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             MessageTemplate::Template msg_template,
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             const char* method_name = nullptr);
9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
9262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* SpeciesConstructor(Node* context, Node* object,
9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                           Node* default_constructor);
9462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
9562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void PromiseSetHasHandler(Node* promise);
9662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void PromiseSetHandledHint(Node* promise);
9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
9862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void AppendPromiseCallback(int offset, compiler::Node* promise,
9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             compiler::Node* value);
10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
10162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* InternalPromiseThen(Node* context, Node* promise, Node* on_resolve,
10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            Node* on_reject);
10362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
10462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* InternalPerformPromiseThen(Node* context, Node* promise,
10562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   Node* on_resolve, Node* on_reject,
10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   Node* deferred_promise,
10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   Node* deferred_on_resolve,
10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   Node* deferred_on_reject);
10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void InternalResolvePromise(Node* context, Node* promise, Node* result);
11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
11262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void BranchIfFastPath(Node* context, Node* promise, Label* if_isunmodified,
11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        Label* if_ismodified);
11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void BranchIfFastPath(Node* native_context, Node* promise_fun, Node* promise,
11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        Label* if_isunmodified, Label* if_ismodified);
11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreatePromiseContext(Node* native_context, int slots);
11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void PromiseFulfill(Node* context, Node* promise, Node* result,
12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      v8::Promise::PromiseState status);
12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void BranchIfAccessCheckFailed(Node* context, Node* native_context,
12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                 Node* promise_constructor, Node* executor,
12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                 Label* if_noaccess);
12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void InternalPromiseReject(Node* context, Node* promise, Node* value,
12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             bool debug_event);
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void InternalPromiseReject(Node* context, Node* promise, Node* value,
12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             Node* debug_event);
13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  std::pair<Node*, Node*> CreatePromiseFinallyFunctions(Node* on_finally,
13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                        Node* native_context);
13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreatePromiseFinallyContext(Node* on_finally, Node* native_context);
13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreateValueThunkFunction(Node* value, Node* native_context);
13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreateValueThunkFunctionContext(Node* value, Node* native_context);
13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreateThrowerFunctionContext(Node* reason, Node* native_context);
13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CreateThrowerFunction(Node* reason, Node* native_context);
13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private:
14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* AllocateJSPromise(Node* context);
14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch};
14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
14462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace internal
14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace v8
14662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif  // V8_BUILTINS_BUILTINS_PROMISE_H_
148