Line data Source code
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_GEN_H_
6 : #define V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
7 :
8 : #include "src/code-stub-assembler.h"
9 : #include "src/objects/promise.h"
10 : #include "torque-generated/builtins-base-from-dsl-gen.h"
11 : #include "torque-generated/builtins-iterator-from-dsl-gen.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : typedef compiler::CodeAssemblerState CodeAssemblerState;
17 :
18 3396 : class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
19 : public:
20 : explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state)
21 3396 : : CodeStubAssembler(state) {}
22 : // These allocate and initialize a promise with pending state and
23 : // undefined fields.
24 : //
25 : // This uses undefined as the parent promise for the promise init
26 : // hook.
27 : Node* AllocateAndInitJSPromise(Node* context);
28 : // This uses the given parent as the parent promise for the promise
29 : // init hook.
30 : Node* AllocateAndInitJSPromise(Node* context, Node* parent);
31 :
32 : // This allocates and initializes a promise with the given state and
33 : // fields.
34 : Node* AllocateAndSetJSPromise(Node* context, v8::Promise::PromiseState status,
35 : Node* result);
36 :
37 : Node* AllocatePromiseReaction(Node* next, Node* promise_or_capability,
38 : Node* fulfill_handler, Node* reject_handler);
39 :
40 : Node* AllocatePromiseReactionJobTask(RootIndex map_root_index, Node* context,
41 : Node* argument, Node* handler,
42 : Node* promise_or_capability);
43 : Node* AllocatePromiseReactionJobTask(Node* map, Node* context, Node* argument,
44 : Node* handler,
45 : Node* promise_or_capability);
46 : Node* AllocatePromiseResolveThenableJobTask(Node* promise_to_resolve,
47 : Node* then, Node* thenable,
48 : Node* context);
49 :
50 : std::pair<Node*, Node*> CreatePromiseResolvingFunctions(Node* promise,
51 : Node* debug_event,
52 : Node* native_context);
53 :
54 : Node* PromiseHasHandler(Node* promise);
55 :
56 : // Creates the context used by all Promise.all resolve element closures,
57 : // together with the values array. Since all closures for a single Promise.all
58 : // call use the same context, we need to store the indices for the individual
59 : // closures somewhere else (we put them into the identity hash field of the
60 : // closures), and we also need to have a separate marker for when the closure
61 : // was called already (we slap the native context onto the closure in that
62 : // case to mark it's done).
63 : Node* CreatePromiseAllResolveElementContext(Node* promise_capability,
64 : Node* native_context);
65 : TNode<JSFunction> CreatePromiseAllResolveElementFunction(Node* context,
66 : TNode<Smi> index,
67 : Node* native_context,
68 : int slot_index);
69 :
70 : Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
71 : Node* native_context);
72 :
73 : Node* CreatePromiseGetCapabilitiesExecutorContext(Node* promise_capability,
74 : Node* native_context);
75 :
76 : protected:
77 : void PromiseInit(Node* promise);
78 :
79 : void PromiseSetHasHandler(Node* promise);
80 : void PromiseSetHandledHint(Node* promise);
81 :
82 : void PerformPromiseThen(Node* context, Node* promise, Node* on_fulfilled,
83 : Node* on_rejected,
84 : Node* result_promise_or_capability);
85 :
86 : Node* CreatePromiseContext(Node* native_context, int slots);
87 :
88 : Node* TriggerPromiseReactions(Node* context, Node* promise, Node* result,
89 : PromiseReaction::Type type);
90 :
91 : // We can skip the "resolve" lookup on {constructor} if it's the (initial)
92 : // Promise constructor and the Promise.resolve() protector is intact, as
93 : // that guards the lookup path for the "resolve" property on the %Promise%
94 : // intrinsic object.
95 : void BranchIfPromiseResolveLookupChainIntact(Node* native_context,
96 : Node* constructor,
97 : Label* if_fast, Label* if_slow);
98 : void GotoIfNotPromiseResolveLookupChainIntact(Node* native_context,
99 : Node* constructor,
100 : Label* if_slow);
101 :
102 : // We can shortcut the SpeciesConstructor on {promise_map} if it's
103 : // [[Prototype]] is the (initial) Promise.prototype and the @@species
104 : // protector is intact, as that guards the lookup path for the "constructor"
105 : // property on JSPromise instances which have the %PromisePrototype%.
106 : void BranchIfPromiseSpeciesLookupChainIntact(Node* native_context,
107 : Node* promise_map,
108 : Label* if_fast, Label* if_slow);
109 :
110 : // We can skip the "then" lookup on {receiver_map} if it's [[Prototype]]
111 : // is the (initial) Promise.prototype and the Promise#then() protector
112 : // is intact, as that guards the lookup path for the "then" property
113 : // on JSPromise instances which have the (initial) %PromisePrototype%.
114 : void BranchIfPromiseThenLookupChainIntact(Node* native_context,
115 : Node* receiver_map, Label* if_fast,
116 : Label* if_slow);
117 :
118 : Node* InvokeResolve(Node* native_context, Node* constructor, Node* value,
119 : Label* if_exception, Variable* var_exception);
120 : template <typename... TArgs>
121 : Node* InvokeThen(Node* native_context, Node* receiver, TArgs... args);
122 :
123 : void BranchIfAccessCheckFailed(Node* context, Node* native_context,
124 : Node* promise_constructor, Node* executor,
125 : Label* if_noaccess);
126 :
127 : std::pair<Node*, Node*> CreatePromiseFinallyFunctions(Node* on_finally,
128 : Node* constructor,
129 : Node* native_context);
130 : Node* CreateValueThunkFunction(Node* value, Node* native_context);
131 :
132 : Node* CreateThrowerFunction(Node* reason, Node* native_context);
133 :
134 : typedef std::function<TNode<Object>(TNode<Context> context, TNode<Smi> index,
135 : TNode<NativeContext> native_context,
136 : TNode<PromiseCapability> capability)>
137 : PromiseAllResolvingElementFunction;
138 :
139 : Node* PerformPromiseAll(
140 : Node* context, Node* constructor, Node* capability,
141 : const IteratorBuiltinsFromDSLAssembler::IteratorRecord& record,
142 : const PromiseAllResolvingElementFunction& create_resolve_element_function,
143 : const PromiseAllResolvingElementFunction& create_reject_element_function,
144 : Label* if_exception, Variable* var_exception);
145 :
146 : void SetForwardingHandlerIfTrue(Node* context, Node* condition,
147 : const NodeGenerator& object);
148 168 : inline void SetForwardingHandlerIfTrue(Node* context, Node* condition,
149 : Node* object) {
150 168 : return SetForwardingHandlerIfTrue(context, condition,
151 504 : [object]() -> Node* { return object; });
152 : }
153 : void SetPromiseHandledByIfTrue(Node* context, Node* condition, Node* promise,
154 : const NodeGenerator& handled_by);
155 :
156 : Node* PromiseStatus(Node* promise);
157 :
158 : void PromiseReactionJob(Node* context, Node* argument, Node* handler,
159 : Node* promise_or_capability,
160 : PromiseReaction::Type type);
161 :
162 : Node* IsPromiseStatus(Node* actual, v8::Promise::PromiseState expected);
163 : void PromiseSetStatus(Node* promise, v8::Promise::PromiseState status);
164 :
165 : Node* AllocateJSPromise(Node* context);
166 :
167 : void ExtractHandlerContext(Node* handler, Variable* var_context);
168 : void Generate_PromiseAll(
169 : TNode<Context> context, TNode<Object> receiver, TNode<Object> iterable,
170 : const PromiseAllResolvingElementFunction& create_resolve_element_function,
171 : const PromiseAllResolvingElementFunction& create_reject_element_function);
172 :
173 : typedef std::function<TNode<Object>(TNode<Context> context,
174 : TNode<NativeContext> native_context,
175 : TNode<Object> value)>
176 : CreatePromiseAllResolveElementFunctionValue;
177 :
178 : void Generate_PromiseAllResolveElementClosure(
179 : TNode<Context> context, TNode<Object> value, TNode<JSFunction> function,
180 : const CreatePromiseAllResolveElementFunctionValue& callback);
181 : };
182 :
183 : } // namespace internal
184 : } // namespace v8
185 :
186 : #endif // V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
|