diff options
author | Michaël Zasso <targos@protonmail.com> | 2018-05-31 11:11:57 +0200 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2018-06-01 09:58:27 +0200 |
commit | 352a525eb984b8fa2d6f0f6fd68395e6a080bba4 (patch) | |
tree | a105ae93f8fd8f533cce19a429f1b6e95d6e11ca /deps/v8/src/builtins/builtins-async-generator-gen.cc | |
parent | faf449ca0490f5371dc6cbbc94a87eb697b00fcc (diff) | |
download | node-new-352a525eb984b8fa2d6f0f6fd68395e6a080bba4.tar.gz |
deps: update V8 to 6.7.288.43
PR-URL: https://github.com/nodejs/node/pull/19989
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matheus Marchini <matheus@sthima.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/v8/src/builtins/builtins-async-generator-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-async-generator-gen.cc | 80 |
1 files changed, 67 insertions, 13 deletions
diff --git a/deps/v8/src/builtins/builtins-async-generator-gen.cc b/deps/v8/src/builtins/builtins-async-generator-gen.cc index b78747aaa9..290252da62 100644 --- a/deps/v8/src/builtins/builtins-async-generator-gen.cc +++ b/deps/v8/src/builtins/builtins-async-generator-gen.cc @@ -29,13 +29,13 @@ class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler { : AsyncBuiltinsAssembler(state) {} inline Node* TaggedIsAsyncGenerator(Node* tagged_object) { - Node* if_notsmi = TaggedIsNotSmi(tagged_object); - return Select(if_notsmi, - [=]() { - return HasInstanceType(tagged_object, - JS_ASYNC_GENERATOR_OBJECT_TYPE); - }, - [=]() { return if_notsmi; }, MachineRepresentation::kBit); + TNode<BoolT> if_notsmi = TaggedIsNotSmi(tagged_object); + return Select<BoolT>(if_notsmi, + [=] { + return HasInstanceType( + tagged_object, JS_ASYNC_GENERATOR_OBJECT_TYPE); + }, + [=] { return if_notsmi; }); } inline Node* LoadGeneratorState(Node* const generator) { return LoadObjectField(generator, JSGeneratorObject::kContinuationOffset); @@ -518,11 +518,34 @@ TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) { done); } - // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»). - CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result); + // We know that {iter_result} itself doesn't have any "then" property and + // we also know that the [[Prototype]] of {iter_result} is the intrinsic + // %ObjectPrototype%. So we can skip the [[Resolve]] logic here completely + // and directly call into the FulfillPromise operation if we can prove + // that the %ObjectPrototype% also doesn't have any "then" property. This + // is guarded by the Promise#then protector. + Label if_fast(this), if_slow(this, Label::kDeferred), return_promise(this); + GotoIfForceSlowPath(&if_slow); + Branch(IsPromiseThenProtectorCellInvalid(), &if_slow, &if_fast); + + BIND(&if_fast); + { + // Skip the "then" on {iter_result} and directly fulfill the {promise} + // with the {iter_result}. + CallBuiltin(Builtins::kFulfillPromise, context, promise, iter_result); + Goto(&return_promise); + } + + BIND(&if_slow); + { + // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»). + CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result); + Goto(&return_promise); + } // Per spec, AsyncGeneratorResolve() returns undefined. However, for the // benefit of %TraceExit(), return the Promise. + BIND(&return_promise); Return(promise); } @@ -548,11 +571,42 @@ TF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) { Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator); Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(request); + // Mark the generator as "awaiting". SetGeneratorAwaiting(generator); - Await(context, generator, value, outer_promise, - Builtins::kAsyncGeneratorYieldFulfill, - Builtins::kAsyncGeneratorAwaitReject, is_caught); - Return(UndefinedConstant()); + + // We can skip the creation of a temporary promise and the whole + // [[Resolve]] logic if we already know that the {value} that's + // being yielded is a primitive, as in that case we would immediately + // fulfill the temporary promise anyways and schedule a fulfill + // reaction job. This gives a nice performance boost for async + // generators that yield only primitives, e.g. numbers or strings. + Label if_primitive(this), if_generic(this); + GotoIfForceSlowPath(&if_generic); + GotoIf(IsPromiseHookEnabledOrDebugIsActive(), &if_generic); + GotoIf(TaggedIsSmi(value), &if_primitive); + Branch(IsJSReceiver(value), &if_generic, &if_primitive); + + BIND(&if_generic); + { + Await(context, generator, value, outer_promise, + Builtins::kAsyncGeneratorYieldFulfill, + Builtins::kAsyncGeneratorAwaitReject, is_caught); + Return(UndefinedConstant()); + } + + BIND(&if_primitive); + { + // For primitive {value}s we can skip the allocation of the temporary + // promise and the resolution of that, and directly allocate the fulfill + // reaction job. + Node* const microtask = AllocatePromiseReactionJobTask( + Heap::kPromiseFulfillReactionJobTaskMapRootIndex, context, value, + HeapConstant(Builtins::CallableFor( + isolate(), Builtins::kAsyncGeneratorYieldFulfill) + .code()), + generator); + TailCallBuiltin(Builtins::kEnqueueMicrotask, context, microtask); + } } TF_BUILTIN(AsyncGeneratorYieldFulfill, AsyncGeneratorBuiltinsAssembler) { |