Skip to content

Commit e57b500

Browse files
bmeurerCommit Bot
authored andcommitted
[async-generators] Add fast-path for primitives in AsyncGeneratorYield.
For async generators that yield primitives, there's not really a point in creating temporary promises first, just to immediately fulfill them with the primitive values passed to `yield`. Instead we can skip those steps and just directly schedule a PromiseFulfillReactionJobTask to do the job. This improves the execution time of fibonacci-async-es2017-native from around 189ms to roughly 183ms, which corresponds to almost a ~3% boost here. Bug: v8:7253 Change-Id: I91413d2cc5ffdc6c851f72f91ff5c207e048c19d Reviewed-on: https://chromium-review.googlesource.com/966607 Commit-Queue: Benedikt Meurer <[email protected]> Reviewed-by: Georg Neis <[email protected]> Reviewed-by: Benedikt Meurer <[email protected]> Cr-Commit-Position: refs/heads/master@{#52016}
1 parent 5460f9c commit e57b500

1 file changed

Lines changed: 35 additions & 4 deletions

File tree

src/builtins/builtins-async-generator-gen.cc

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,42 @@ TF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) {
548548
Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator);
549549
Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(request);
550550

551+
// Mark the generator as "awaiting".
551552
SetGeneratorAwaiting(generator);
552-
Await(context, generator, value, outer_promise,
553-
Builtins::kAsyncGeneratorYieldFulfill,
554-
Builtins::kAsyncGeneratorAwaitReject, is_caught);
555-
Return(UndefinedConstant());
553+
554+
// We can skip the creation of a temporary promise and the whole
555+
// [[Resolve]] logic if we already know that the {value} that's
556+
// being yielded is a primitive, as in that case we would immediately
557+
// fulfill the temporary promise anyways and schedule a fulfill
558+
// reaction job. This gives a nice performance boost for async
559+
// generators that yield only primitives, e.g. numbers or strings.
560+
Label if_primitive(this), if_generic(this);
561+
GotoIfForceSlowPath(&if_generic);
562+
GotoIf(IsPromiseHookEnabledOrDebugIsActive(), &if_generic);
563+
GotoIf(TaggedIsSmi(value), &if_primitive);
564+
Branch(IsJSReceiver(value), &if_generic, &if_primitive);
565+
566+
BIND(&if_generic);
567+
{
568+
Await(context, generator, value, outer_promise,
569+
Builtins::kAsyncGeneratorYieldFulfill,
570+
Builtins::kAsyncGeneratorAwaitReject, is_caught);
571+
Return(UndefinedConstant());
572+
}
573+
574+
BIND(&if_primitive);
575+
{
576+
// For primitive {value}s we can skip the allocation of the temporary
577+
// promise and the resolution of that, and directly allocate the fulfill
578+
// reaction job.
579+
Node* const microtask = AllocatePromiseReactionJobTask(
580+
Heap::kPromiseFulfillReactionJobTaskMapRootIndex, context, value,
581+
HeapConstant(Builtins::CallableFor(
582+
isolate(), Builtins::kAsyncGeneratorYieldFulfill)
583+
.code()),
584+
generator);
585+
TailCallBuiltin(Builtins::kEnqueueMicrotask, context, microtask);
586+
}
556587
}
557588

558589
TF_BUILTIN(AsyncGeneratorYieldFulfill, AsyncGeneratorBuiltinsAssembler) {

0 commit comments

Comments
 (0)