Commit 5bcaca3a authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[promise] Refactor Promise.all

The resolve/reject callbacks to PerformPromiseAll is refactored out so
that we can just pass different closures for PerformPromiseAllSettled.

Similarly, a closure to update the value is passed to
Generate_PromiseAllResolveElementClosure so that we can create a
diferrent value in case of Promise.allSettled.

Bug: v8:9060
Change-Id: I4e1bebe6da4ea0965a67cccc8365ed91cf4683c7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1559216
Auto-Submit: Sathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60732}
parent 4e0b0c65
...@@ -288,8 +288,9 @@ Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementContext( ...@@ -288,8 +288,9 @@ Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementContext(
return context; return context;
} }
Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction( TNode<JSFunction>
Node* context, TNode<Smi> index, Node* native_context) { PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction(
Node* context, TNode<Smi> index, Node* native_context, int slot_index) {
CSA_ASSERT(this, SmiGreaterThan(index, SmiConstant(0))); CSA_ASSERT(this, SmiGreaterThan(index, SmiConstant(0)));
CSA_ASSERT(this, SmiLessThanOrEqual( CSA_ASSERT(this, SmiLessThanOrEqual(
index, SmiConstant(PropertyArray::HashField::kMax))); index, SmiConstant(PropertyArray::HashField::kMax)));
...@@ -297,10 +298,9 @@ Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction( ...@@ -297,10 +298,9 @@ Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction(
Node* const map = LoadContextElement( Node* const map = LoadContextElement(
native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
Node* const resolve_info = LoadContextElement( Node* const resolve_info = LoadContextElement(native_context, slot_index);
native_context, Context::PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN); TNode<JSFunction> resolve =
Node* const resolve = Cast(AllocateFunctionWithMapAndContext(map, resolve_info, context));
AllocateFunctionWithMapAndContext(map, resolve_info, context);
STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0); STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0);
StoreObjectFieldNoWriteBarrier(resolve, JSFunction::kPropertiesOrHashOffset, StoreObjectFieldNoWriteBarrier(resolve, JSFunction::kPropertiesOrHashOffset,
...@@ -2027,11 +2027,13 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { ...@@ -2027,11 +2027,13 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
Node* PromiseBuiltinsAssembler::PerformPromiseAll( Node* PromiseBuiltinsAssembler::PerformPromiseAll(
Node* context, Node* constructor, Node* capability, Node* context, Node* constructor, Node* capability,
const IteratorRecord& iterator, Label* if_exception, const IteratorRecord& iterator,
Variable* var_exception) { const PromiseAllResolvingElementFunction& create_resolve_element_function,
const PromiseAllResolvingElementFunction& create_reject_element_function,
Label* if_exception, Variable* var_exception) {
IteratorBuiltinsAssembler iter_assembler(state()); IteratorBuiltinsAssembler iter_assembler(state());
Node* const native_context = LoadNativeContext(context); TNode<NativeContext> native_context = Cast(LoadNativeContext(context));
// For catch prediction, don't treat the .then calls as handling it; // For catch prediction, don't treat the .then calls as handling it;
// instead, recurse outwards. // instead, recurse outwards.
...@@ -2039,8 +2041,8 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( ...@@ -2039,8 +2041,8 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll(
native_context, IsDebugActive(), native_context, IsDebugActive(),
LoadObjectField(capability, PromiseCapability::kRejectOffset)); LoadObjectField(capability, PromiseCapability::kRejectOffset));
Node* const resolve_element_context = TNode<Context> resolve_element_context =
CreatePromiseAllResolveElementContext(capability, native_context); Cast(CreatePromiseAllResolveElementContext(capability, native_context));
TVARIABLE(Smi, var_index, SmiConstant(1)); TVARIABLE(Smi, var_index, SmiConstant(1));
Label loop(this, &var_index), done_loop(this), Label loop(this, &var_index), done_loop(this),
...@@ -2095,8 +2097,10 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( ...@@ -2095,8 +2097,10 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll(
// Set resolveElement.[[Values]] to values. // Set resolveElement.[[Values]] to values.
// Set resolveElement.[[Capability]] to resultCapability. // Set resolveElement.[[Capability]] to resultCapability.
// Set resolveElement.[[RemainingElements]] to remainingElementsCount. // Set resolveElement.[[RemainingElements]] to remainingElementsCount.
Node* const resolve_element_fun = CreatePromiseAllResolveElementFunction( Node* const resolve_element_fun = create_resolve_element_function(
resolve_element_context, index, native_context); resolve_element_context, index, native_context, Cast(capability));
Node* const reject_element_fun = create_reject_element_function(
resolve_element_context, index, native_context, Cast(capability));
// We can skip the "resolve" lookup on the {constructor} as well as the // We can skip the "resolve" lookup on the {constructor} as well as the
// "then" lookup on the result of the "resolve" call, and immediately // "then" lookup on the result of the "resolve" call, and immediately
...@@ -2155,7 +2159,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( ...@@ -2155,7 +2159,7 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll(
CallJS(CodeFactory::Call(isolate(), CallJS(CodeFactory::Call(isolate(),
ConvertReceiverMode::kNotNullOrUndefined), ConvertReceiverMode::kNotNullOrUndefined),
native_context, then, next_promise, resolve_element_fun, native_context, then, next_promise, resolve_element_fun,
LoadObjectField(capability, PromiseCapability::kRejectOffset)); reject_element_fun);
GotoIfException(then_call, &close_iterator, var_exception); GotoIfException(then_call, &close_iterator, var_exception);
// For catch prediction, mark that rejections here are semantically // For catch prediction, mark that rejections here are semantically
...@@ -2259,15 +2263,14 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll( ...@@ -2259,15 +2263,14 @@ Node* PromiseBuiltinsAssembler::PerformPromiseAll(
return promise; return promise;
} }
// ES#sec-promise.all void PromiseBuiltinsAssembler::Generate_PromiseAll(
// Promise.all ( iterable ) TNode<Context> context, TNode<Object> receiver, TNode<Object> iterable,
TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { const PromiseAllResolvingElementFunction& create_resolve_element_function,
const PromiseAllResolvingElementFunction& create_reject_element_function) {
IteratorBuiltinsAssembler iter_assembler(state()); IteratorBuiltinsAssembler iter_assembler(state());
// Let C be the this value. // Let C be the this value.
// If Type(C) is not Object, throw a TypeError exception. // If Type(C) is not Object, throw a TypeError exception.
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject, ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
"Promise.all"); "Promise.all");
...@@ -2283,7 +2286,6 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { ...@@ -2283,7 +2286,6 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
// Let iterator be GetIterator(iterable). // Let iterator be GetIterator(iterable).
// IfAbruptRejectPromise(iterator, promiseCapability). // IfAbruptRejectPromise(iterator, promiseCapability).
Node* const iterable = Parameter(Descriptor::kIterable);
IteratorRecord iterator = iter_assembler.GetIterator( IteratorRecord iterator = iter_assembler.GetIterator(
context, iterable, &reject_promise, &var_exception); context, iterable, &reject_promise, &var_exception);
...@@ -2293,7 +2295,8 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { ...@@ -2293,7 +2295,8 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
// IteratorClose(iterator, result). // IteratorClose(iterator, result).
// IfAbruptRejectPromise(result, promiseCapability). // IfAbruptRejectPromise(result, promiseCapability).
Node* const result = PerformPromiseAll( Node* const result = PerformPromiseAll(
context, receiver, capability, iterator, &reject_promise, &var_exception); context, receiver, capability, iterator, create_resolve_element_function,
create_reject_element_function, &reject_promise, &var_exception);
Return(result); Return(result);
...@@ -2312,11 +2315,31 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { ...@@ -2312,11 +2315,31 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
} }
} }
TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { // ES#sec-promise.all
TNode<Object> value = CAST(Parameter(Descriptor::kValue)); // Promise.all ( iterable )
TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget)); TNode<Object> receiver = Cast(Parameter(Descriptor::kReceiver));
TNode<Context> context = Cast(Parameter(Descriptor::kContext));
TNode<Object> iterable = Cast(Parameter(Descriptor::kIterable));
Generate_PromiseAll(
context, receiver, iterable,
[this](TNode<Context> context, TNode<Smi> index,
TNode<NativeContext> native_context,
TNode<PromiseCapability> capability) {
return CreatePromiseAllResolveElementFunction(
context, index, native_context,
Context::PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN);
},
[this](TNode<Context> context, TNode<Smi> index,
TNode<NativeContext> native_context,
TNode<PromiseCapability> capability) {
return LoadObjectField(capability, PromiseCapability::kRejectOffset);
});
}
void PromiseBuiltinsAssembler::Generate_PromiseAllResolveElementClosure(
TNode<Context> context, TNode<Object> value, TNode<JSFunction> function,
const CreatePromiseAllResolveElementFunctionValue& callback) {
Label already_called(this, Label::kDeferred), resolve_promise(this); Label already_called(this, Label::kDeferred), resolve_promise(this);
// We use the {function}s context as the marker to remember whether this // We use the {function}s context as the marker to remember whether this
...@@ -2332,6 +2355,10 @@ TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { ...@@ -2332,6 +2355,10 @@ TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) {
TNode<Context> native_context = LoadNativeContext(context); TNode<Context> native_context = LoadNativeContext(context);
StoreObjectField(function, JSFunction::kContextOffset, native_context); StoreObjectField(function, JSFunction::kContextOffset, native_context);
// Update the value depending on whether Promise.all or
// Promise.allSettled is called.
value = callback(context, value);
// Determine the index from the {function}. // Determine the index from the {function}.
Label unreachable(this, Label::kDeferred); Label unreachable(this, Label::kDeferred);
STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0); STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0);
...@@ -2426,6 +2453,16 @@ TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { ...@@ -2426,6 +2453,16 @@ TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) {
Unreachable(); Unreachable();
} }
TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) {
TNode<Object> value = CAST(Parameter(Descriptor::kValue));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget));
Generate_PromiseAllResolveElementClosure(
context, value, function,
[](TNode<Object> context, TNode<Object> value) { return value; });
}
// ES#sec-promise.race // ES#sec-promise.race
// Promise.race ( iterable ) // Promise.race ( iterable )
TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) { TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) {
......
...@@ -62,8 +62,10 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { ...@@ -62,8 +62,10 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
// case to mark it's done). // case to mark it's done).
Node* CreatePromiseAllResolveElementContext(Node* promise_capability, Node* CreatePromiseAllResolveElementContext(Node* promise_capability,
Node* native_context); Node* native_context);
Node* CreatePromiseAllResolveElementFunction(Node* context, TNode<Smi> index, TNode<JSFunction> CreatePromiseAllResolveElementFunction(Node* context,
Node* native_context); TNode<Smi> index,
Node* native_context,
int slot_index);
Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event, Node* CreatePromiseResolvingFunctionsContext(Node* promise, Node* debug_event,
Node* native_context); Node* native_context);
...@@ -129,9 +131,16 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { ...@@ -129,9 +131,16 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
Node* CreateThrowerFunction(Node* reason, Node* native_context); Node* CreateThrowerFunction(Node* reason, Node* native_context);
typedef std::function<TNode<Object>(TNode<Context> context, TNode<Smi> index,
TNode<NativeContext> native_context,
TNode<PromiseCapability> capability)>
PromiseAllResolvingElementFunction;
Node* PerformPromiseAll( Node* PerformPromiseAll(
Node* context, Node* constructor, Node* capability, Node* context, Node* constructor, Node* capability,
const IteratorBuiltinsFromDSLAssembler::IteratorRecord& record, const IteratorBuiltinsFromDSLAssembler::IteratorRecord& record,
const PromiseAllResolvingElementFunction& create_resolve_element_function,
const PromiseAllResolvingElementFunction& create_reject_element_function,
Label* if_exception, Variable* var_exception); Label* if_exception, Variable* var_exception);
void SetForwardingHandlerIfTrue(Node* context, Node* condition, void SetForwardingHandlerIfTrue(Node* context, Node* condition,
...@@ -156,6 +165,18 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { ...@@ -156,6 +165,18 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
Node* AllocateJSPromise(Node* context); Node* AllocateJSPromise(Node* context);
void ExtractHandlerContext(Node* handler, Variable* var_context); void ExtractHandlerContext(Node* handler, Variable* var_context);
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,
TNode<Object> value)>
CreatePromiseAllResolveElementFunctionValue;
void Generate_PromiseAllResolveElementClosure(
TNode<Context> context, TNode<Object> value, TNode<JSFunction> function,
const CreatePromiseAllResolveElementFunctionValue& callback);
}; };
} // namespace internal } // namespace internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment