Commit 2f8d4406 authored by Joshua Litt's avatar Joshua Litt Committed by Commit Bot

[promises] Port FulfillPromise to torque.

Bug: v8:9838
Change-Id: I0675b124b2377ff32cb8ae7bbc5eac8ce60314ff
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1854011
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64328}
parent 1f0e8d42
...@@ -1023,6 +1023,7 @@ torque_files = [ ...@@ -1023,6 +1023,7 @@ torque_files = [
"src/builtins/math.tq", "src/builtins/math.tq",
"src/builtins/object-fromentries.tq", "src/builtins/object-fromentries.tq",
"src/builtins/object.tq", "src/builtins/object.tq",
"src/builtins/promise-abstract-operations.tq",
"src/builtins/proxy-constructor.tq", "src/builtins/proxy-constructor.tq",
"src/builtins/proxy-delete-property.tq", "src/builtins/proxy-delete-property.tq",
"src/builtins/proxy-get-property.tq", "src/builtins/proxy-get-property.tq",
......
...@@ -1150,11 +1150,38 @@ extern class JSAsyncGeneratorObject extends JSGeneratorObject { ...@@ -1150,11 +1150,38 @@ extern class JSAsyncGeneratorObject extends JSGeneratorObject {
is_awaiting: Smi; is_awaiting: Smi;
} }
// Promise constants
type PromiseState extends int31 constexpr 'Promise::PromiseState';
const kPromisePending: constexpr PromiseState
generates 'Promise::kPending';
const kPromiseFulfilled: constexpr PromiseState
generates 'Promise::kFulfilled';
// JSPromise constants
const kJSPromiseStatusMask: constexpr int31
generates 'JSPromise::kStatusMask';
const kJSPromiseStatusShift: constexpr int31
generates 'JSPromise::kStatusShift';
@generateCppClass @generateCppClass
extern class JSPromise extends JSObject { extern class JSPromise extends JSObject {
Status(): PromiseState {
StaticAssert(kJSPromiseStatusShift == 0);
const status: int32 = Convert<int32>(this.flags) & kJSPromiseStatusMask;
return Convert<PromiseState>(status);
}
SetStatus(status: constexpr PromiseState): void {
assert(this.Status() == kPromisePending);
assert(status != kPromisePending);
const mask: Smi = SmiConstant(status);
this.flags = this.flags | mask;
}
// Smi 0 terminated list of PromiseReaction objects in case the JSPromise was // Smi 0 terminated list of PromiseReaction objects in case the JSPromise was
// not settled yet, otherwise the result. // not settled yet, otherwise the result.
reactions_or_result: Object; reactions_or_result: Smi | PromiseReaction | JSAny;
flags: Smi; flags: Smi;
} }
...@@ -1498,6 +1525,11 @@ extern class PromiseCapability extends Struct { ...@@ -1498,6 +1525,11 @@ extern class PromiseCapability extends Struct {
reject: Object; reject: Object;
} }
// PromiseReaction constants
type PromiseReactionType extends int31 constexpr 'PromiseReaction::Type';
const kPromiseReactionFulfill: constexpr PromiseReactionType
generates 'PromiseReaction::kFulfill';
@generateCppClass @generateCppClass
extern class PromiseReaction extends Struct { extern class PromiseReaction extends Struct {
next: PromiseReaction | Zero; next: PromiseReaction | Zero;
...@@ -2165,6 +2197,11 @@ operator '+' macro StringAdd(implicit context: Context)( ...@@ -2165,6 +2197,11 @@ operator '+' macro StringAdd(implicit context: Context)(
return StringAdd_CheckNone(a, b); return StringAdd_CheckNone(a, b);
} }
operator '==' macro PromiseStateEquals(
s1: PromiseState, s2: PromiseState): bool {
return Word32Equal(s1, s2);
}
extern macro TaggedIsSmi(Object): bool; extern macro TaggedIsSmi(Object): bool;
extern macro TaggedIsNotSmi(Object): bool; extern macro TaggedIsNotSmi(Object): bool;
extern macro TaggedIsPositiveSmi(Object): bool; extern macro TaggedIsPositiveSmi(Object): bool;
...@@ -2705,6 +2742,26 @@ Cast<JSReceiver | Null>(o: HeapObject): JSReceiver | Null ...@@ -2705,6 +2742,26 @@ Cast<JSReceiver | Null>(o: HeapObject): JSReceiver | Null
} }
} }
Cast<PromiseReaction>(o: HeapObject): PromiseReaction labels CastError {
if (IsPromiseReaction(o)) return %RawDownCast<PromiseReaction>(o);
goto CastError;
}
Cast<Smi | PromiseReaction>(o: Object): Smi |
PromiseReaction labels CastError {
typeswitch (o) {
case (o: Smi): {
return o;
}
case (o: PromiseReaction): {
return o;
}
case (Object): {
goto CastError;
}
}
}
extern macro AllocateHeapNumberWithValue(float64): HeapNumber; extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
extern macro ChangeInt32ToTagged(int32): Number; extern macro ChangeInt32ToTagged(int32): Number;
extern macro ChangeUint32ToTagged(uint32): Number; extern macro ChangeUint32ToTagged(uint32): Number;
...@@ -2857,6 +2914,10 @@ FromConstexpr<ContextSlot, constexpr ContextSlot>(c: constexpr ContextSlot): ...@@ -2857,6 +2914,10 @@ FromConstexpr<ContextSlot, constexpr ContextSlot>(c: constexpr ContextSlot):
ContextSlot { ContextSlot {
return IntPtrConstant(c); return IntPtrConstant(c);
} }
FromConstexpr<PromiseState, constexpr PromiseState>(s: constexpr PromiseState):
PromiseState {
return %FromConstexpr<PromiseState>(s);
}
macro Convert<To: type, From: type>(i: From): To { macro Convert<To: type, From: type>(i: From): To {
return i; return i;
...@@ -2991,6 +3052,9 @@ extern macro SmiToBInt(Smi): bint; ...@@ -2991,6 +3052,9 @@ extern macro SmiToBInt(Smi): bint;
Convert<bint, Smi>(v: Smi): bint { Convert<bint, Smi>(v: Smi): bint {
return SmiToBInt(v); return SmiToBInt(v);
} }
Convert<PromiseState, int32>(s: int32): PromiseState {
return %RawDownCast<PromiseState>(s);
}
macro Is<A: type, B: type>(implicit context: Context)(o: B): bool { macro Is<A: type, B: type>(implicit context: Context)(o: B): bool {
Cast<A>(o) otherwise return false; Cast<A>(o) otherwise return false;
...@@ -3491,6 +3555,7 @@ extern macro IsSymbol(HeapObject): bool; ...@@ -3491,6 +3555,7 @@ extern macro IsSymbol(HeapObject): bool;
extern macro IsJSArrayMap(Map): bool; extern macro IsJSArrayMap(Map): bool;
extern macro IsExtensibleMap(Map): bool; extern macro IsExtensibleMap(Map): bool;
extern macro IsJSPrimitiveWrapper(HeapObject): bool; extern macro IsJSPrimitiveWrapper(HeapObject): bool;
extern macro IsPromiseReaction(HeapObject): bool;
extern macro IsCustomElementsReceiverInstanceType(int32): bool; extern macro IsCustomElementsReceiverInstanceType(int32): bool;
extern macro Typeof(JSAny): String; extern macro Typeof(JSAny): String;
......
...@@ -762,8 +762,6 @@ namespace internal { ...@@ -762,8 +762,6 @@ namespace internal {
TFS(ForInFilter, kKey, kObject) \ TFS(ForInFilter, kKey, kObject) \
\ \
/* Promise */ \ /* Promise */ \
/* ES #sec-fulfillpromise */ \
TFS(FulfillPromise, kPromise, kValue) \
/* ES #sec-rejectpromise */ \ /* ES #sec-rejectpromise */ \
TFS(RejectPromise, kPromise, kReason, kDebugEvent) \ TFS(RejectPromise, kPromise, kReason, kDebugEvent) \
/* ES #sec-promise-resolve-functions */ \ /* ES #sec-promise-resolve-functions */ \
......
...@@ -564,7 +564,7 @@ PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask( ...@@ -564,7 +564,7 @@ PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask(
} }
// ES #sec-triggerpromisereactions // ES #sec-triggerpromisereactions
Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( void PromiseBuiltinsAssembler::TriggerPromiseReactions(
Node* context, Node* reactions, Node* argument, Node* context, Node* reactions, Node* argument,
PromiseReaction::Type type) { PromiseReaction::Type type) {
// We need to reverse the {reactions} here, since we record them on the // We need to reverse the {reactions} here, since we record them on the
...@@ -683,8 +683,6 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( ...@@ -683,8 +683,6 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions(
} }
BIND(&done_loop); BIND(&done_loop);
} }
return UndefinedConstant();
} }
template <typename... TArgs> template <typename... TArgs>
...@@ -1849,32 +1847,6 @@ TF_BUILTIN(PromisePrototypeFinally, PromiseBuiltinsAssembler) { ...@@ -1849,32 +1847,6 @@ TF_BUILTIN(PromisePrototypeFinally, PromiseBuiltinsAssembler) {
var_catch_finally.value())); var_catch_finally.value()));
} }
// ES #sec-fulfillpromise
TF_BUILTIN(FulfillPromise, PromiseBuiltinsAssembler) {
Node* const promise = Parameter(Descriptor::kPromise);
Node* const value = Parameter(Descriptor::kValue);
Node* const context = Parameter(Descriptor::kContext);
CSA_ASSERT(this, TaggedIsNotSmi(promise));
CSA_ASSERT(this, IsJSPromise(promise));
// 2. Let reactions be promise.[[PromiseFulfillReactions]].
TNode<Object> const reactions =
LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
// 3. Set promise.[[PromiseResult]] to value.
// 4. Set promise.[[PromiseFulfillReactions]] to undefined.
// 5. Set promise.[[PromiseRejectReactions]] to undefined.
StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, value);
// 6. Set promise.[[PromiseState]] to "fulfilled".
PromiseSetStatus(promise, Promise::kFulfilled);
// 7. Return TriggerPromiseReactions(reactions, value).
Return(TriggerPromiseReactions(context, reactions, value,
PromiseReaction::kFulfill));
}
// ES #sec-rejectpromise // ES #sec-rejectpromise
TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) { TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) {
Node* const promise = Parameter(Descriptor::kPromise); Node* const promise = Parameter(Descriptor::kPromise);
...@@ -1913,8 +1885,8 @@ TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) { ...@@ -1913,8 +1885,8 @@ TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) {
PromiseSetStatus(promise, Promise::kRejected); PromiseSetStatus(promise, Promise::kRejected);
// 7. Return TriggerPromiseReactions(reactions, reason). // 7. Return TriggerPromiseReactions(reactions, reason).
Return(TriggerPromiseReactions(context, reactions, reason, TriggerPromiseReactions(context, reactions, reason, PromiseReaction::kReject);
PromiseReaction::kReject)); Return(UndefinedConstant());
BIND(&if_runtime); BIND(&if_runtime);
TailCallRuntime(Runtime::kRejectPromise, context, promise, reason, TailCallRuntime(Runtime::kRejectPromise, context, promise, reason,
......
...@@ -74,6 +74,11 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { ...@@ -74,6 +74,11 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
Node* CreatePromiseGetCapabilitiesExecutorContext(Node* promise_capability, Node* CreatePromiseGetCapabilitiesExecutorContext(Node* promise_capability,
Node* native_context); Node* native_context);
// The below methods are only temporarily public until they are
// migrated to torque.
void TriggerPromiseReactions(Node* context, Node* promise, Node* result,
PromiseReaction::Type type);
protected: protected:
void PromiseInit(Node* promise); void PromiseInit(Node* promise);
...@@ -88,9 +93,6 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler { ...@@ -88,9 +93,6 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
TNode<Context> CreatePromiseContext(TNode<NativeContext> native_context, TNode<Context> CreatePromiseContext(TNode<NativeContext> native_context,
int slots); int slots);
Node* TriggerPromiseReactions(Node* context, Node* promise, Node* result,
PromiseReaction::Type type);
// We can skip the "resolve" lookup on {constructor} if it's the (initial) // We can skip the "resolve" lookup on {constructor} if it's the (initial)
// Promise constructor and the Promise.resolve() protector is intact, as // Promise constructor and the Promise.resolve() protector is intact, as
// that guards the lookup path for the "resolve" property on the %Promise% // that guards the lookup path for the "resolve" property on the %Promise%
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include 'src/builtins/builtins-promise-gen.h'
// https://tc39.es/ecma262/#sec-promise-abstract-operations
namespace promise {
extern macro PromiseBuiltinsAssembler::TriggerPromiseReactions(
implicit context: Context)(
Smi | PromiseReaction, JSAny, constexpr PromiseReactionType): void;
// https://tc39.es/ecma262/#sec-fulfillpromise
transitioning builtin
FulfillPromise(implicit context: Context)(promise: JSPromise, value: JSAny):
Undefined {
// Assert: The value of promise.[[PromiseState]] is "pending".
assert(promise.Status() == kPromisePending);
// 2. Let reactions be promise.[[PromiseFulfillReactions]].
const reactions =
UnsafeCast<(Smi | PromiseReaction)>(promise.reactions_or_result);
// 3. Set promise.[[PromiseResult]] to value.
// 4. Set promise.[[PromiseFulfillReactions]] to undefined.
// 5. Set promise.[[PromiseRejectReactions]] to undefined.
promise.reactions_or_result = value;
// 6. Set promise.[[PromiseState]] to "fulfilled".
promise.SetStatus(kPromiseFulfilled);
// 7. Return TriggerPromiseReactions(reactions, value).
TriggerPromiseReactions(reactions, value, kPromiseReactionFulfill);
return Undefined;
}
}
...@@ -6386,6 +6386,11 @@ TNode<BoolT> CodeStubAssembler::IsPropertyArray( ...@@ -6386,6 +6386,11 @@ TNode<BoolT> CodeStubAssembler::IsPropertyArray(
return HasInstanceType(object, PROPERTY_ARRAY_TYPE); return HasInstanceType(object, PROPERTY_ARRAY_TYPE);
} }
TNode<BoolT> CodeStubAssembler::IsPromiseReaction(
SloppyTNode<HeapObject> object) {
return HasInstanceType(object, PROMISE_REACTION_TYPE);
}
// This complicated check is due to elements oddities. If a smi array is empty // This complicated check is due to elements oddities. If a smi array is empty
// after Array.p.shift, it is replaced by the empty array constant. If it is // after Array.p.shift, it is replaced by the empty array constant. If it is
// later filled with a double element, we try to grow it but pass in a double // later filled with a double element, we try to grow it but pass in a double
......
...@@ -2483,6 +2483,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -2483,6 +2483,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> IsPromiseCapability(SloppyTNode<HeapObject> object); TNode<BoolT> IsPromiseCapability(SloppyTNode<HeapObject> object);
TNode<BoolT> IsPropertyArray(SloppyTNode<HeapObject> object); TNode<BoolT> IsPropertyArray(SloppyTNode<HeapObject> object);
TNode<BoolT> IsPropertyCell(SloppyTNode<HeapObject> object); TNode<BoolT> IsPropertyCell(SloppyTNode<HeapObject> object);
TNode<BoolT> IsPromiseReaction(SloppyTNode<HeapObject> object);
TNode<BoolT> IsPrototypeInitialArrayPrototype(SloppyTNode<Context> context, TNode<BoolT> IsPrototypeInitialArrayPrototype(SloppyTNode<Context> context,
SloppyTNode<Map> map); SloppyTNode<Map> map);
TNode<BoolT> IsPrototypeTypedArrayPrototype(SloppyTNode<Context> context, TNode<BoolT> IsPrototypeTypedArrayPrototype(SloppyTNode<Context> context,
......
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