5 #include "src/builtins/builtins-async-gen.h" 6 #include "src/builtins/builtins-utils-gen.h" 7 #include "src/builtins/builtins.h" 8 #include "src/code-factory.h" 9 #include "src/code-stub-assembler.h" 10 #include "src/frames-inl.h" 18 class AsyncFromSyncBuiltinsAssembler :
public AsyncBuiltinsAssembler {
20 explicit AsyncFromSyncBuiltinsAssembler(compiler::CodeAssemblerState* state)
21 : AsyncBuiltinsAssembler(state) {}
23 void ThrowIfNotAsyncFromSyncIterator(Node*
const context, Node*
const object,
25 Variable* var_exception,
26 const char* method_name);
28 typedef std::function<void(Node*
const context, Node*
const promise,
30 UndefinedMethodHandler;
31 typedef std::function<Node*(Node*)> SyncIteratorNodeGenerator;
32 void Generate_AsyncFromSyncIteratorMethod(
33 Node*
const context, Node*
const iterator, Node*
const sent_value,
34 const SyncIteratorNodeGenerator& get_method,
35 const UndefinedMethodHandler& if_method_undefined,
36 const char* operation_name,
37 Label::Type reject_label_type = Label::kDeferred,
38 Node*
const initial_exception_value =
nullptr);
39 void Generate_AsyncFromSyncIteratorMethodOptimized(
40 Node*
const context, Node*
const iterator, Node*
const sent_value,
41 const SyncIteratorNodeGenerator& get_method,
42 const UndefinedMethodHandler& if_method_undefined,
43 const char* operation_name,
44 Label::Type reject_label_type = Label::kDeferred,
45 Node*
const initial_exception_value =
nullptr);
47 void Generate_AsyncFromSyncIteratorMethod(
48 Node*
const context, Node*
const iterator, Node*
const sent_value,
49 Handle<String> name,
const UndefinedMethodHandler& if_method_undefined,
50 const char* operation_name,
51 Label::Type reject_label_type = Label::kDeferred,
52 Node*
const initial_exception_value =
nullptr) {
53 auto get_method = [=](Node*
const sync_iterator) {
54 return GetProperty(context, sync_iterator, name);
56 return Generate_AsyncFromSyncIteratorMethod(
57 context, iterator, sent_value, get_method, if_method_undefined,
58 operation_name, reject_label_type, initial_exception_value);
60 void Generate_AsyncFromSyncIteratorMethodOptimized(
61 Node*
const context, Node*
const iterator, Node*
const sent_value,
62 Handle<String> name,
const UndefinedMethodHandler& if_method_undefined,
63 const char* operation_name,
64 Label::Type reject_label_type = Label::kDeferred,
65 Node*
const initial_exception_value =
nullptr) {
66 auto get_method = [=](Node*
const sync_iterator) {
67 return GetProperty(context, sync_iterator, name);
69 return Generate_AsyncFromSyncIteratorMethodOptimized(
70 context, iterator, sent_value, get_method, if_method_undefined,
71 operation_name, reject_label_type, initial_exception_value);
81 std::pair<Node*, Node*> LoadIteratorResult(Node*
const context,
82 Node*
const native_context,
83 Node*
const iter_result,
85 Variable* var_exception);
88 void AsyncFromSyncBuiltinsAssembler::ThrowIfNotAsyncFromSyncIterator(
89 Node*
const context, Node*
const object, Label* if_exception,
90 Variable* var_exception,
const char* method_name) {
91 Label if_receiverisincompatible(
this, Label::kDeferred), done(
this);
93 GotoIf(TaggedIsSmi(
object), &if_receiverisincompatible);
94 Branch(HasInstanceType(
object, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE), &done,
95 &if_receiverisincompatible);
97 BIND(&if_receiverisincompatible);
104 MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, context,
105 StringConstant(method_name),
object);
109 var_exception->Bind(error);
116 void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
117 Node*
const context, Node*
const iterator, Node*
const sent_value,
118 const SyncIteratorNodeGenerator& get_method,
119 const UndefinedMethodHandler& if_method_undefined,
120 const char* operation_name, Label::Type reject_label_type,
121 Node*
const initial_exception_value) {
122 Node*
const native_context = LoadNativeContext(context);
123 Node*
const promise = AllocateAndInitJSPromise(context);
125 VARIABLE(var_exception, MachineRepresentation::kTagged,
126 initial_exception_value ==
nullptr ? UndefinedConstant()
127 : initial_exception_value);
128 Label reject_promise(
this, reject_label_type);
130 ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise,
131 &var_exception, operation_name);
133 Node*
const sync_iterator =
134 LoadObjectField(iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset);
136 Node*
const method = get_method(sync_iterator);
138 if (if_method_undefined) {
139 Label if_isnotundefined(
this);
141 GotoIfNot(IsUndefined(method), &if_isnotundefined);
142 if_method_undefined(native_context, promise, &reject_promise);
144 BIND(&if_isnotundefined);
147 Node*
const iter_result = CallJS(CodeFactory::Call(isolate()), context,
148 method, sync_iterator, sent_value);
149 GotoIfException(iter_result, &reject_promise, &var_exception);
153 std::tie(value, done) = LoadIteratorResult(
154 context, native_context, iter_result, &reject_promise, &var_exception);
155 Node*
const wrapper = AllocateAndInitJSPromise(context);
159 CallBuiltin(Builtins::kResolvePromise, context, wrapper, value);
164 Node*
const on_fulfilled = CreateUnwrapClosure(native_context, done);
168 Return(CallBuiltin(Builtins::kPerformPromiseThen, context, wrapper,
169 on_fulfilled, UndefinedConstant(), promise));
171 BIND(&reject_promise);
173 Node*
const exception = var_exception.value();
174 CallBuiltin(Builtins::kRejectPromise, context, promise, exception,
180 void AsyncFromSyncBuiltinsAssembler::
181 Generate_AsyncFromSyncIteratorMethodOptimized(
182 Node*
const context, Node*
const iterator, Node*
const sent_value,
183 const SyncIteratorNodeGenerator& get_method,
184 const UndefinedMethodHandler& if_method_undefined,
185 const char* operation_name, Label::Type reject_label_type,
186 Node*
const initial_exception_value) {
187 Node*
const native_context = LoadNativeContext(context);
188 Node*
const promise = AllocateAndInitJSPromise(context);
190 VARIABLE(var_exception, MachineRepresentation::kTagged,
191 initial_exception_value ==
nullptr ? UndefinedConstant()
192 : initial_exception_value);
193 Label reject_promise(
this, reject_label_type);
195 ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise,
196 &var_exception, operation_name);
198 Node*
const sync_iterator =
199 LoadObjectField(iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset);
201 Node*
const method = get_method(sync_iterator);
203 if (if_method_undefined) {
204 Label if_isnotundefined(
this);
206 GotoIfNot(IsUndefined(method), &if_isnotundefined);
207 if_method_undefined(native_context, promise, &reject_promise);
209 BIND(&if_isnotundefined);
212 Node*
const iter_result = CallJS(CodeFactory::Call(isolate()), context,
213 method, sync_iterator, sent_value);
214 GotoIfException(iter_result, &reject_promise, &var_exception);
218 std::tie(value, done) = LoadIteratorResult(
219 context, native_context, iter_result, &reject_promise, &var_exception);
221 Node*
const promise_fun =
222 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
223 CSA_ASSERT(
this, IsConstructor(promise_fun));
226 Node*
const valueWrapper = CallBuiltin(Builtins::kPromiseResolve,
227 native_context, promise_fun, value);
232 Node*
const on_fulfilled = CreateUnwrapClosure(native_context, done);
236 Return(CallBuiltin(Builtins::kPerformPromiseThen, context, valueWrapper,
237 on_fulfilled, UndefinedConstant(), promise));
239 BIND(&reject_promise);
241 Node*
const exception = var_exception.value();
242 CallBuiltin(Builtins::kRejectPromise, context, promise, exception,
247 std::pair<Node*, Node*> AsyncFromSyncBuiltinsAssembler::LoadIteratorResult(
248 Node*
const context, Node*
const native_context, Node*
const iter_result,
249 Label* if_exception, Variable* var_exception) {
250 Label if_fastpath(
this), if_slowpath(
this), merge(
this), to_boolean(
this),
251 done(
this), if_notanobject(
this, Label::kDeferred);
252 GotoIf(TaggedIsSmi(iter_result), &if_notanobject);
254 Node*
const iter_result_map = LoadMap(iter_result);
255 GotoIfNot(IsJSReceiverMap(iter_result_map), &if_notanobject);
257 Node*
const fast_iter_result_map =
258 LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
260 VARIABLE(var_value, MachineRepresentation::kTagged);
261 VARIABLE(var_done, MachineRepresentation::kTagged);
262 Branch(WordEqual(iter_result_map, fast_iter_result_map), &if_fastpath,
267 var_done.Bind(LoadObjectField(iter_result, JSIteratorResult::kDoneOffset));
269 LoadObjectField(iter_result, JSIteratorResult::kValueOffset));
278 GetProperty(context, iter_result, factory()->done_string());
279 GotoIfException(done, if_exception, var_exception);
284 GetProperty(context, iter_result, factory()->value_string());
285 GotoIfException(value, if_exception, var_exception);
287 var_value.Bind(value);
292 BIND(&if_notanobject);
296 Node*
const error = MakeTypeError(
297 MessageTemplate::kIteratorResultNotAnObject, context, iter_result);
298 var_exception->Bind(error);
304 GotoIf(TaggedIsSmi(var_done.value()), &to_boolean);
305 Branch(IsBoolean(var_done.value()), &done, &to_boolean);
310 CallBuiltin(Builtins::kToBoolean, context, var_done.value());
311 var_done.Bind(result);
316 return std::make_pair(var_value.value(), var_done.value());
323 TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
324 Node*
const iterator = Parameter(Descriptor::kReceiver);
325 Node*
const value = Parameter(Descriptor::kValue);
326 Node*
const context = Parameter(Descriptor::kContext);
328 auto get_method = [=](Node*
const unused) {
329 return LoadObjectField(iterator, JSAsyncFromSyncIterator::kNextOffset);
331 Generate_AsyncFromSyncIteratorMethod(
332 context, iterator, value, get_method, UndefinedMethodHandler(),
333 "[Async-from-Sync Iterator].prototype.next");
338 TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
339 AsyncFromSyncBuiltinsAssembler) {
340 Node*
const iterator = Parameter(Descriptor::kReceiver);
341 Node*
const value = Parameter(Descriptor::kValue);
342 Node*
const context = Parameter(Descriptor::kContext);
344 auto if_return_undefined = [=](Node*
const native_context,
345 Node*
const promise, Label* if_exception) {
348 Node*
const iter_result = CallBuiltin(Builtins::kCreateIterResultObject,
349 context, value, TrueConstant());
354 CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result);
358 Generate_AsyncFromSyncIteratorMethod(
359 context, iterator, value, factory()->return_string(), if_return_undefined,
360 "[Async-from-Sync Iterator].prototype.return");
365 TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
366 AsyncFromSyncBuiltinsAssembler) {
367 Node*
const iterator = Parameter(Descriptor::kReceiver);
368 Node*
const reason = Parameter(Descriptor::kReason);
369 Node*
const context = Parameter(Descriptor::kContext);
371 auto if_throw_undefined = [=](Node*
const native_context, Node*
const promise,
372 Label* if_exception) { Goto(if_exception); };
374 Generate_AsyncFromSyncIteratorMethod(
375 context, iterator, reason, factory()->throw_string(), if_throw_undefined,
376 "[Async-from-Sync Iterator].prototype.throw", Label::kNonDeferred,