зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1289318 - Part 7: Store the Promise reactions list in the same slot as the result. r=efaust
A Promise can only have either a list of reactions, if it's pending, or a result/reason, if it's resolved. This gets us down to 3 non-debug-info slots. If we now move the debug info into its own object and only allocate that when the debugger is open, Promise instances only need 4 slots. MozReview-Commit-ID: FuLAwhmFTBe
This commit is contained in:
Родитель
d589429ecc
Коммит
e2d055ae6b
|
@ -152,13 +152,12 @@ ResolvePromise(JSContext* cx, Handle<PromiseObject*> promise, HandleValue valueO
|
|||
// instead of getting the right list of reactions, we determine the
|
||||
// resolution type to retrieve the right information from the
|
||||
// reaction records.
|
||||
RootedValue reactionsVal(cx, promise->getFixedSlot(PROMISE_REACTIONS_SLOT));
|
||||
RootedValue reactionsVal(cx, promise->getFixedSlot(PROMISE_REACTIONS_OR_RESULT_SLOT));
|
||||
|
||||
// Step 3.
|
||||
promise->setFixedSlot(PROMISE_RESULT_SLOT, valueOrReason);
|
||||
|
||||
// Steps 4-5.
|
||||
promise->setFixedSlot(PROMISE_REACTIONS_SLOT, UndefinedValue());
|
||||
// Step 3-5.
|
||||
// The same slot is used for the reactions list and the result, so setting
|
||||
// the result also removes the reactions list.
|
||||
promise->setFixedSlot(PROMISE_REACTIONS_OR_RESULT_SLOT, valueOrReason);
|
||||
|
||||
// Step 6.
|
||||
promise->setFixedSlot(PROMISE_STATE_SLOT, Int32Value(int32_t(state)));
|
||||
|
@ -554,7 +553,10 @@ PromiseObject::getID()
|
|||
bool
|
||||
PromiseObject::dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> values)
|
||||
{
|
||||
RootedValue reactionsVal(cx, getReservedSlot(PROMISE_REACTIONS_SLOT));
|
||||
if (state() != JS::PromiseState::Pending)
|
||||
return true;
|
||||
|
||||
RootedValue reactionsVal(cx, getReservedSlot(PROMISE_REACTIONS_OR_RESULT_SLOT));
|
||||
if (reactionsVal.isNullOrUndefined())
|
||||
return true;
|
||||
RootedObject reactions(cx, &reactionsVal.toObject());
|
||||
|
|
|
@ -30,11 +30,11 @@ class PromiseObject : public NativeObject
|
|||
}
|
||||
Value value() {
|
||||
MOZ_ASSERT(state() == JS::PromiseState::Fulfilled);
|
||||
return getFixedSlot(PROMISE_RESULT_SLOT);
|
||||
return getFixedSlot(PROMISE_REACTIONS_OR_RESULT_SLOT);
|
||||
}
|
||||
Value reason() {
|
||||
MOZ_ASSERT(state() == JS::PromiseState::Rejected);
|
||||
return getFixedSlot(PROMISE_RESULT_SLOT);
|
||||
return getFixedSlot(PROMISE_REACTIONS_OR_RESULT_SLOT);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool resolve(JSContext* cx, HandleValue resolutionValue);
|
||||
|
|
|
@ -480,19 +480,19 @@ function BlockOnPromise(promise, blockedPromise, onResolve, onReject) {
|
|||
function AddDependentPromise(dependentPromise) {
|
||||
assert(IsPromise(this), "AddDependentPromise expects an unwrapped Promise as the receiver");
|
||||
|
||||
if (GetPromiseState(this) !== PROMISE_STATE_PENDING)
|
||||
return;
|
||||
|
||||
let reaction = new PromiseReactionRecord(dependentPromise, NullFunction, NullFunction,
|
||||
NullFunction, NullFunction, null);
|
||||
|
||||
let reactions = UnsafeGetReservedSlot(this, PROMISE_REACTIONS_SLOT);
|
||||
let reactions = UnsafeGetReservedSlot(this, PROMISE_REACTIONS_OR_RESULT_SLOT);
|
||||
|
||||
// The reactions list might not have been allocated yet or been reset
|
||||
// because the Promise was resolved.
|
||||
if (!reactions) {
|
||||
if (GetPromiseState(this) === PROMISE_STATE_PENDING)
|
||||
UnsafeSetReservedSlot(promise, PROMISE_REACTIONS_SLOT, [reaction]);
|
||||
return;
|
||||
}
|
||||
_DefineDataProperty(reactions, reactions.length, reaction);
|
||||
// The reactions list might not have been allocated yet.
|
||||
if (!reactions)
|
||||
UnsafeSetReservedSlot(dependentPromise, PROMISE_REACTIONS_OR_RESULT_SLOT, [reaction]);
|
||||
else
|
||||
_DefineDataProperty(reactions, reactions.length, reaction);
|
||||
}
|
||||
|
||||
// ES6, 25.4.4.4.
|
||||
|
@ -739,9 +739,9 @@ function PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)
|
|||
if (state === PROMISE_STATE_PENDING) {
|
||||
// Steps 7.a,b.
|
||||
// We only have a single list for fulfill and reject reactions.
|
||||
let reactions = UnsafeGetReservedSlot(promise, PROMISE_REACTIONS_SLOT);
|
||||
let reactions = UnsafeGetReservedSlot(promise, PROMISE_REACTIONS_OR_RESULT_SLOT);
|
||||
if (!reactions)
|
||||
UnsafeSetReservedSlot(promise, PROMISE_REACTIONS_SLOT, [reaction]);
|
||||
UnsafeSetReservedSlot(promise, PROMISE_REACTIONS_OR_RESULT_SLOT, [reaction]);
|
||||
else
|
||||
_DefineDataProperty(reactions, reactions.length, reaction);
|
||||
}
|
||||
|
@ -749,7 +749,7 @@ function PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)
|
|||
// Step 8.
|
||||
else if (state === PROMISE_STATE_FULFILLED) {
|
||||
// Step 8.a.
|
||||
let value = UnsafeGetReservedSlot(promise, PROMISE_RESULT_SLOT);
|
||||
let value = UnsafeGetReservedSlot(promise, PROMISE_REACTIONS_OR_RESULT_SLOT);
|
||||
|
||||
// Step 8.b.
|
||||
EnqueuePromiseReactionJob(reaction, PROMISE_JOB_TYPE_FULFILL, value);
|
||||
|
@ -761,7 +761,7 @@ function PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)
|
|||
assert(state === PROMISE_STATE_REJECTED, "Invalid Promise state " + state);
|
||||
|
||||
// Step 9.b.
|
||||
let reason = UnsafeGetReservedSlot(promise, PROMISE_RESULT_SLOT);
|
||||
let reason = UnsafeGetReservedSlot(promise, PROMISE_REACTIONS_OR_RESULT_SLOT);
|
||||
|
||||
// Step 9.c.
|
||||
if (UnsafeGetInt32FromReservedSlot(promise, PROMISE_IS_HANDLED_SLOT) !==
|
||||
|
|
|
@ -57,16 +57,15 @@
|
|||
#define ITEM_KIND_VALUE 1
|
||||
#define ITEM_KIND_KEY_AND_VALUE 2
|
||||
|
||||
#define PROMISE_STATE_SLOT 0
|
||||
#define PROMISE_RESULT_SLOT 1
|
||||
#define PROMISE_REACTIONS_SLOT 2
|
||||
#define PROMISE_RESOLVE_FUNCTION_SLOT 3
|
||||
#define PROMISE_ALLOCATION_SITE_SLOT 4
|
||||
#define PROMISE_RESOLUTION_SITE_SLOT 5
|
||||
#define PROMISE_ALLOCATION_TIME_SLOT 6
|
||||
#define PROMISE_RESOLUTION_TIME_SLOT 7
|
||||
#define PROMISE_ID_SLOT 8
|
||||
#define PROMISE_IS_HANDLED_SLOT 9
|
||||
#define PROMISE_STATE_SLOT 0
|
||||
#define PROMISE_REACTIONS_OR_RESULT_SLOT 1
|
||||
#define PROMISE_RESOLVE_FUNCTION_SLOT 2
|
||||
#define PROMISE_ALLOCATION_SITE_SLOT 3
|
||||
#define PROMISE_RESOLUTION_SITE_SLOT 4
|
||||
#define PROMISE_ALLOCATION_TIME_SLOT 5
|
||||
#define PROMISE_RESOLUTION_TIME_SLOT 6
|
||||
#define PROMISE_ID_SLOT 7
|
||||
#define PROMISE_IS_HANDLED_SLOT 8
|
||||
|
||||
#define PROMISE_STATE_PENDING 0
|
||||
#define PROMISE_STATE_FULFILLED 1
|
||||
|
|
|
@ -1445,7 +1445,7 @@ SettlePromiseNow(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
RootedNativeObject promise(cx, &args[0].toObject().as<NativeObject>());
|
||||
promise->setReservedSlot(PROMISE_STATE_SLOT, Int32Value(PROMISE_STATE_FULFILLED));
|
||||
promise->setReservedSlot(PROMISE_RESULT_SLOT, UndefinedValue());
|
||||
promise->setReservedSlot(PROMISE_REACTIONS_OR_RESULT_SLOT, UndefinedValue());
|
||||
|
||||
JS::dbg::onPromiseSettled(cx, promise);
|
||||
return true;
|
||||
|
|
Загрузка…
Ссылка в новой задаче