v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-async-function-gen.cc
Go to the documentation of this file.
1// Copyright 2017 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
12
13namespace v8 {
14namespace internal {
15
17
19 public:
22
23 protected:
24 template <typename Descriptor>
25 void AsyncFunctionAwait();
26
28 const TNode<Context> context, const TNode<Object> sent_value,
30};
31
33 TNode<Context> context, TNode<Object> sent_value,
35 DCHECK(resume_mode == JSGeneratorObject::kNext ||
36 resume_mode == JSGeneratorObject::kThrow);
37
38 TNode<JSAsyncFunctionObject> async_function_object =
39 CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
40
41 // Inline version of GeneratorPrototypeNext / GeneratorPrototypeReturn with
42 // unnecessary runtime checks removed.
43
44 // Ensure that the {async_function_object} is neither closed nor running.
46 this, SmiGreaterThan(
47 LoadObjectField<Smi>(async_function_object,
48 JSGeneratorObject::kContinuationOffset),
50
51 // Remember the {resume_mode} for the {async_function_object}.
52 StoreObjectFieldNoWriteBarrier(async_function_object,
53 JSGeneratorObject::kResumeModeOffset,
54 SmiConstant(resume_mode));
55
56 // Resume the {receiver} using our trampoline.
57 CallBuiltin(Builtin::kResumeGeneratorTrampoline, context, sent_value,
58 async_function_object);
59
60 // The resulting Promise is a throwaway, so it doesn't matter what it
61 // resolves to. What is important is that we don't end up keeping the
62 // whole chain of intermediate Promises alive by returning the return value
63 // of ResumeGenerator, as that would create a memory leak.
64}
65
67 auto closure = Parameter<JSFunction>(Descriptor::kClosure);
68 auto receiver = Parameter<Object>(Descriptor::kReceiver);
69 auto context = Parameter<Context>(Descriptor::kContext);
70
71 // Compute the number of registers and parameters.
72 TNode<SharedFunctionInfo> shared = LoadObjectField<SharedFunctionInfo>(
73 closure, JSFunction::kSharedFunctionInfoOffset);
74 TNode<IntPtrT> formal_parameter_count = ChangeInt32ToIntPtr(
75 LoadSharedFunctionInfoFormalParameterCountWithoutReceiver(shared));
76 TNode<BytecodeArray> bytecode_array =
77 LoadSharedFunctionInfoBytecodeArray(shared);
78 TNode<IntPtrT> frame_size = ChangeInt32ToIntPtr(LoadObjectField<Uint32T>(
79 bytecode_array, BytecodeArray::kFrameSizeOffset));
80 TNode<IntPtrT> parameters_and_register_length =
81 Signed(IntPtrAdd(WordSar(frame_size, IntPtrConstant(kTaggedSizeLog2)),
82 formal_parameter_count));
83
84 // Allocate and initialize the register file.
85 TNode<FixedArrayBase> parameters_and_registers =
86 AllocateFixedArray(HOLEY_ELEMENTS, parameters_and_register_length);
87 FillFixedArrayWithValue(HOLEY_ELEMENTS, parameters_and_registers,
88 IntPtrConstant(0), parameters_and_register_length,
89 RootIndex::kUndefinedValue);
90
91 // Allocate and initialize the promise.
92 TNode<JSPromise> promise = NewJSPromise(context);
93
94 // Allocate and initialize the async function object.
95 TNode<NativeContext> native_context = LoadNativeContext(context);
96 TNode<Map> async_function_object_map = CAST(LoadContextElement(
97 native_context, Context::ASYNC_FUNCTION_OBJECT_MAP_INDEX));
98 TNode<JSAsyncFunctionObject> async_function_object =
100 AllocateInNewSpace(JSAsyncFunctionObject::kHeaderSize));
101 StoreMapNoWriteBarrier(async_function_object, async_function_object_map);
102 StoreObjectFieldRoot(async_function_object,
103 JSAsyncFunctionObject::kPropertiesOrHashOffset,
104 RootIndex::kEmptyFixedArray);
105 StoreObjectFieldRoot(async_function_object,
106 JSAsyncFunctionObject::kElementsOffset,
107 RootIndex::kEmptyFixedArray);
108 StoreObjectFieldNoWriteBarrier(
109 async_function_object, JSAsyncFunctionObject::kFunctionOffset, closure);
110 StoreObjectFieldNoWriteBarrier(
111 async_function_object, JSAsyncFunctionObject::kContextOffset, context);
112 StoreObjectFieldNoWriteBarrier(
113 async_function_object, JSAsyncFunctionObject::kReceiverOffset, receiver);
114 StoreObjectFieldNoWriteBarrier(async_function_object,
115 JSAsyncFunctionObject::kInputOrDebugPosOffset,
116 SmiConstant(0));
117 StoreObjectFieldNoWriteBarrier(async_function_object,
118 JSAsyncFunctionObject::kResumeModeOffset,
119 SmiConstant(JSAsyncFunctionObject::kNext));
120 StoreObjectFieldNoWriteBarrier(
121 async_function_object, JSAsyncFunctionObject::kContinuationOffset,
122 SmiConstant(JSAsyncFunctionObject::kGeneratorExecuting));
123 StoreObjectFieldNoWriteBarrier(
124 async_function_object,
125 JSAsyncFunctionObject::kParametersAndRegistersOffset,
126 parameters_and_registers);
127 StoreObjectFieldNoWriteBarrier(
128 async_function_object, JSAsyncFunctionObject::kPromiseOffset, promise);
129
130 Return(async_function_object);
131}
132
134 auto async_function_object =
135 Parameter<JSAsyncFunctionObject>(Descriptor::kAsyncFunctionObject);
136 auto reason = Parameter<Object>(Descriptor::kReason);
137 auto context = Parameter<Context>(Descriptor::kContext);
138 TNode<JSPromise> promise = LoadObjectField<JSPromise>(
139 async_function_object, JSAsyncFunctionObject::kPromiseOffset);
140
141 // Reject the {promise} for the given {reason}, disabling the
142 // additional debug event for the rejection since a debug event
143 // already happend for the exception that got us here.
144 CallBuiltin(Builtin::kRejectPromise, context, promise, reason,
145 FalseConstant());
146
147 Return(promise);
148}
149
151 auto async_function_object =
152 Parameter<JSAsyncFunctionObject>(Descriptor::kAsyncFunctionObject);
153 auto value = Parameter<Object>(Descriptor::kValue);
154 auto context = Parameter<Context>(Descriptor::kContext);
155 TNode<JSPromise> promise = LoadObjectField<JSPromise>(
156 async_function_object, JSAsyncFunctionObject::kPromiseOffset);
157
158 CallBuiltin(Builtin::kResolvePromise, context, promise, value);
159
160 Return(promise);
161}
162
163// AsyncFunctionReject and AsyncFunctionResolve are both required to return
164// the promise instead of the result of RejectPromise or ResolvePromise
165// respectively from a lazy deoptimization.
166TF_BUILTIN(AsyncFunctionLazyDeoptContinuation, AsyncFunctionBuiltinsAssembler) {
167 auto promise = Parameter<JSPromise>(Descriptor::kPromise);
168 Return(promise);
169}
170
171TF_BUILTIN(AsyncFunctionAwaitRejectClosure, AsyncFunctionBuiltinsAssembler) {
172 CSA_DCHECK_JS_ARGC_EQ(this, 1);
173 const auto sentError = Parameter<Object>(Descriptor::kSentError);
174 const auto context = Parameter<Context>(Descriptor::kContext);
175
176 AsyncFunctionAwaitResumeClosure(context, sentError,
178 Return(UndefinedConstant());
179}
180
181TF_BUILTIN(AsyncFunctionAwaitResolveClosure, AsyncFunctionBuiltinsAssembler) {
182 CSA_DCHECK_JS_ARGC_EQ(this, 1);
183 const auto sentValue = Parameter<Object>(Descriptor::kSentValue);
184 const auto context = Parameter<Context>(Descriptor::kContext);
185
186 AsyncFunctionAwaitResumeClosure(context, sentValue, JSGeneratorObject::kNext);
187 Return(UndefinedConstant());
188}
189
190// ES#abstract-ops-async-function-await
191// AsyncFunctionAwait ( value )
192// Shared logic for the core of await. The parser desugars
193// await value
194// into
195// yield AsyncFunctionAwait{Caught,Uncaught}(.generator_object, value)
196// The 'value' parameter is the value; the .generator_object stands in
197// for the asyncContext.
198template <typename Descriptor>
200 auto async_function_object =
201 Parameter<JSAsyncFunctionObject>(Descriptor::kAsyncFunctionObject);
202 auto value = Parameter<JSAny>(Descriptor::kValue);
203 auto context = Parameter<Context>(Descriptor::kContext);
204
206 async_function_object, JSAsyncFunctionObject::kPromiseOffset);
207 Await(context, async_function_object, value, outer_promise,
208 RootIndex::kAsyncFunctionAwaitResolveClosureSharedFun,
209 RootIndex::kAsyncFunctionAwaitRejectClosureSharedFun);
210
211 // Return outer promise to avoid adding an load of the outer promise before
212 // suspending in BytecodeGenerator.
213 Return(outer_promise);
214}
215
216// Called by the parser from the desugaring of 'await'.
218 AsyncFunctionAwait<Descriptor>();
219}
220
222
223} // namespace internal
224} // namespace v8
#define CSA_DCHECK_JS_ARGC_EQ(csa, expected)
#define CSA_SLOW_DCHECK(csa,...)
#define TF_BUILTIN(Name, AssemblerBase)
TNode< Object > Await(TNode< Context > context, TNode< JSGeneratorObject > generator, TNode< JSAny > value, TNode< JSPromise > outer_promise, const CreateClosures &CreateClosures)
AsyncFunctionBuiltinsAssembler(compiler::CodeAssemblerState *state)
void AsyncFunctionAwaitResumeClosure(const TNode< Context > context, const TNode< Object > sent_value, JSGeneratorObject::ResumeMode resume_mode)
TNode< T > LoadObjectField(TNode< HeapObject > object, int offset)
void StoreObjectFieldNoWriteBarrier(TNode< HeapObject > object, TNode< IntPtrT > offset, TNode< T > value)
static const int kGeneratorClosed
void Return(TNode< Object > value)
TNode< Smi > SmiConstant(Tagged< Smi > value)
TNode< T > CallBuiltin(Builtin id, TNode< Object > context, TArgs... args)
TNode< T > Parameter(int value, const SourceLocation &loc=SourceLocation::Current())
#define CAST(x)
TNode< Object > receiver
Handle< To > UncheckedCast(Handle< From > value)
Definition handles-inl.h:55
constexpr int kTaggedSizeLog2
Definition globals.h:543
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
#define DCHECK(condition)
Definition logging.h:482