1// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_BUILTINS_BUILTINS_PROMISE_H_
6#define V8_BUILTINS_BUILTINS_PROMISE_H_
7
8#include "src/code-stub-assembler.h"
9#include "src/contexts.h"
10
11namespace v8 {
12namespace internal {
13
14typedef compiler::Node Node;
15typedef CodeStubAssembler::ParameterMode ParameterMode;
16typedef compiler::CodeAssemblerState CodeAssemblerState;
17
18class PromiseBuiltinsAssembler : public CodeStubAssembler {
19 public:
20  enum PromiseResolvingFunctionContextSlot {
21    // Whether the resolve/reject callback was already called.
22    kAlreadyVisitedSlot = Context::MIN_CONTEXT_SLOTS,
23
24    // The promise which resolve/reject callbacks fulfill.
25    kPromiseSlot,
26
27    // Whether to trigger a debug event or not. Used in catch
28    // prediction.
29    kDebugEventSlot,
30    kPromiseContextLength,
31  };
32
33  enum FunctionContextSlot {
34    kCapabilitySlot = Context::MIN_CONTEXT_SLOTS,
35
36    kCapabilitiesContextLength,
37  };
38
39  // This is used by the PromiseThenFinally and PromiseCatchFinally
40  // builtins to store the onFinally in the onFinallySlot.
41  //
42  // This is also used by the PromiseValueThunkFinally to store the
43  // value in the onFinallySlot and PromiseThrowerFinally to store the
44  // reason in the onFinallySlot.
45  enum PromiseFinallyContextSlot {
46    kOnFinallySlot = Context::MIN_CONTEXT_SLOTS,
47
48    kOnFinallyContextLength,
49  };
50
51  explicit PromiseBuiltinsAssembler(CodeAssemblerState* state)
52      : CodeStubAssembler(state) {}
53  // These allocate and initialize a promise with pending state and
54  // undefined fields.
55  //
56  // This uses undefined as the parent promise for the promise init
57  // hook.
58  Node* AllocateAndInitJSPromise(Node* context);
59  // This uses the given parent as the parent promise for the promise
60  // init hook.
61  Node* AllocateAndInitJSPromise(Node* context, Node* parent);
62
63  // This allocates and initializes a promise with the given state and
64  // fields.
65  Node* AllocateAndSetJSPromise(Node* context, Node* status, Node* result);
66
67  Node* AllocatePromiseResolveThenableJobInfo(Node* result, Node* then,
68                                              Node* resolve, Node* reject,
69                                              Node* context);
70
71  std::pair<Node*, Node*> CreatePromiseResolvingFunctions(
72      Node* promise, Node* native_context, Node* promise_context);
73
74  Node* PromiseHasHandler(Node* promise);
75
76  Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
77                                               Node* native_context);
78
79  Node* CreatePromiseGetCapabilitiesExecutorContext(Node* native_context,
80                                                    Node* promise_capability);
81
82  Node* NewPromiseCapability(Node* context, Node* constructor,
83                             Node* debug_event = nullptr);
84
85 protected:
86  void PromiseInit(Node* promise);
87
88  Node* ThrowIfNotJSReceiver(Node* context, Node* value,
89                             MessageTemplate::Template msg_template,
90                             const char* method_name = nullptr);
91
92  Node* SpeciesConstructor(Node* context, Node* object,
93                           Node* default_constructor);
94
95  void PromiseSetHasHandler(Node* promise);
96  void PromiseSetHandledHint(Node* promise);
97
98  void AppendPromiseCallback(int offset, compiler::Node* promise,
99                             compiler::Node* value);
100
101  Node* InternalPromiseThen(Node* context, Node* promise, Node* on_resolve,
102                            Node* on_reject);
103
104  Node* InternalPerformPromiseThen(Node* context, Node* promise,
105                                   Node* on_resolve, Node* on_reject,
106                                   Node* deferred_promise,
107                                   Node* deferred_on_resolve,
108                                   Node* deferred_on_reject);
109
110  void InternalResolvePromise(Node* context, Node* promise, Node* result);
111
112  void BranchIfFastPath(Node* context, Node* promise, Label* if_isunmodified,
113                        Label* if_ismodified);
114
115  void BranchIfFastPath(Node* native_context, Node* promise_fun, Node* promise,
116                        Label* if_isunmodified, Label* if_ismodified);
117
118  Node* CreatePromiseContext(Node* native_context, int slots);
119  void PromiseFulfill(Node* context, Node* promise, Node* result,
120                      v8::Promise::PromiseState status);
121
122  void BranchIfAccessCheckFailed(Node* context, Node* native_context,
123                                 Node* promise_constructor, Node* executor,
124                                 Label* if_noaccess);
125
126  void InternalPromiseReject(Node* context, Node* promise, Node* value,
127                             bool debug_event);
128  void InternalPromiseReject(Node* context, Node* promise, Node* value,
129                             Node* debug_event);
130  std::pair<Node*, Node*> CreatePromiseFinallyFunctions(Node* on_finally,
131                                                        Node* native_context);
132  Node* CreatePromiseFinallyContext(Node* on_finally, Node* native_context);
133
134  Node* CreateValueThunkFunction(Node* value, Node* native_context);
135  Node* CreateValueThunkFunctionContext(Node* value, Node* native_context);
136
137  Node* CreateThrowerFunctionContext(Node* reason, Node* native_context);
138  Node* CreateThrowerFunction(Node* reason, Node* native_context);
139
140 private:
141  Node* AllocateJSPromise(Node* context);
142};
143
144}  // namespace internal
145}  // namespace v8
146
147#endif  // V8_BUILTINS_BUILTINS_PROMISE_H_
148