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:
Till Schneidereit 2016-08-06 02:39:32 +02:00
Родитель d589429ecc
Коммит e2d055ae6b
5 изменённых файлов: 34 добавлений и 33 удалений

Просмотреть файл

@ -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;