builtins-promise-gen.h 9.07 KB
Newer Older
1 2 3 4
// 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.

5 6
#ifndef V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
#define V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
7

8
#include "src/codegen/code-stub-assembler.h"
9
#include "src/objects/promise.h"
10 11
#include "torque-generated/builtins-base-gen-tq.h"
#include "torque-generated/builtins-iterator-gen-tq.h"
12 13 14 15 16 17

namespace v8 {
namespace internal {

typedef compiler::CodeAssemblerState CodeAssemblerState;

18
class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
19
 public:
20
  explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state)
21
      : CodeStubAssembler(state) {}
gsathya's avatar
gsathya committed
22 23 24 25 26 27 28 29 30 31 32 33
  // 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.
34 35
  Node* AllocateAndSetJSPromise(Node* context, v8::Promise::PromiseState status,
                                Node* result);
36

37
  Node* AllocatePromiseReaction(Node* next, Node* promise_or_capability,
38 39
                                Node* fulfill_handler, Node* reject_handler);

40 41
  Node* AllocatePromiseReactionJobTask(RootIndex map_root_index, Node* context,
                                       Node* argument, Node* handler,
42
                                       Node* promise_or_capability);
43
  Node* AllocatePromiseReactionJobTask(Node* map, Node* context, Node* argument,
44 45
                                       Node* handler,
                                       Node* promise_or_capability);
46 47
  Node* AllocatePromiseResolveThenableJobTask(Node* promise_to_resolve,
                                              Node* then, Node* thenable,
48 49
                                              Node* context);

50 51 52
  std::pair<Node*, Node*> CreatePromiseResolvingFunctions(Node* promise,
                                                          Node* debug_event,
                                                          Node* native_context);
53 54 55

  Node* PromiseHasHandler(Node* promise);

56 57 58 59 60 61 62 63 64
  // 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);
65 66 67 68
  TNode<JSFunction> CreatePromiseAllResolveElementFunction(Node* context,
                                                           TNode<Smi> index,
                                                           Node* native_context,
                                                           int slot_index);
69

70 71 72
  Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
                                               Node* native_context);

73 74
  Node* CreatePromiseGetCapabilitiesExecutorContext(Node* promise_capability,
                                                    Node* native_context);
75 76 77 78

 protected:
  void PromiseInit(Node* promise);

79
  void PromiseSetHasHandler(Node* promise);
80
  void PromiseSetHandledHint(Node* promise);
81

82 83 84
  void PerformPromiseThen(Node* context, Node* promise, Node* on_fulfilled,
                          Node* on_rejected,
                          Node* result_promise_or_capability);
85

86
  Node* CreatePromiseContext(Node* native_context, int slots);
87 88 89

  Node* TriggerPromiseReactions(Node* context, Node* promise, Node* result,
                                PromiseReaction::Type type);
90

91 92 93 94 95 96 97
  // 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);
98 99 100
  void GotoIfNotPromiseResolveLookupChainIntact(Node* native_context,
                                                Node* constructor,
                                                Label* if_slow);
101

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
  // 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);

118 119 120 121
  // 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);
122 123 124
  template <typename... TArgs>
  Node* InvokeThen(Node* native_context, Node* receiver, TArgs... args);

125 126 127 128
  void BranchIfAccessCheckFailed(Node* context, Node* native_context,
                                 Node* promise_constructor, Node* executor,
                                 Label* if_noaccess);

129
  std::pair<Node*, Node*> CreatePromiseFinallyFunctions(Node* on_finally,
130
                                                        Node* constructor,
131 132 133 134
                                                        Node* native_context);
  Node* CreateValueThunkFunction(Node* value, Node* native_context);

  Node* CreateThrowerFunction(Node* reason, Node* native_context);
gsathya's avatar
gsathya committed
135

136 137 138 139 140
  typedef std::function<TNode<Object>(TNode<Context> context, TNode<Smi> index,
                                      TNode<NativeContext> native_context,
                                      TNode<PromiseCapability> capability)>
      PromiseAllResolvingElementFunction;

141 142
  Node* PerformPromiseAll(
      Node* context, Node* constructor, Node* capability,
143
      const TorqueGeneratedIteratorBuiltinsAssembler::IteratorRecord& record,
144 145
      const PromiseAllResolvingElementFunction& create_resolve_element_function,
      const PromiseAllResolvingElementFunction& create_reject_element_function,
146
      Label* if_exception, Variable* var_exception);
147

148 149 150 151 152 153 154 155 156 157
  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);

158
  Node* PromiseStatus(Node* promise);
159 160

  void PromiseReactionJob(Node* context, Node* argument, Node* handler,
161 162
                          Node* promise_or_capability,
                          PromiseReaction::Type type);
163 164 165 166

  Node* IsPromiseStatus(Node* actual, v8::Promise::PromiseState expected);
  void PromiseSetStatus(Node* promise, v8::Promise::PromiseState status);

gsathya's avatar
gsathya committed
167
  Node* AllocateJSPromise(Node* context);
168 169

  void ExtractHandlerContext(Node* handler, Variable* var_context);
170 171 172 173 174 175
  void Generate_PromiseAll(
      TNode<Context> context, TNode<Object> receiver, TNode<Object> iterable,
      const PromiseAllResolvingElementFunction& create_resolve_element_function,
      const PromiseAllResolvingElementFunction& create_reject_element_function);

  typedef std::function<TNode<Object>(TNode<Context> context,
176
                                      TNode<NativeContext> native_context,
177 178 179 180 181 182
                                      TNode<Object> value)>
      CreatePromiseAllResolveElementFunctionValue;

  void Generate_PromiseAllResolveElementClosure(
      TNode<Context> context, TNode<Object> value, TNode<JSFunction> function,
      const CreatePromiseAllResolveElementFunctionValue& callback);
183 184 185 186
};

}  // namespace internal
}  // namespace v8
187

188
#endif  // V8_BUILTINS_BUILTINS_PROMISE_GEN_H_