Bug 1083866 - Mark bailout frames. r=jandem

This commit is contained in:
Nicolas B. Pierron 2014-10-22 18:37:35 +02:00
Родитель 252da901b5
Коммит 5225ef8c26
2 изменённых файлов: 136 добавлений и 0 удалений

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

@ -56,6 +56,12 @@ ReadFrameSlot(IonJSFrameLayout *fp, int32_t slot)
return *(uintptr_t *)((char *)fp + OffsetOfFrameSlot(slot));
}
static inline void
WriteFrameSlot(IonJSFrameLayout *fp, int32_t slot, uintptr_t value)
{
*(uintptr_t *)((char *)fp + OffsetOfFrameSlot(slot)) = value;
}
static inline double
ReadFrameDoubleSlot(IonJSFrameLayout *fp, int32_t slot)
{
@ -972,6 +978,42 @@ MarkIonJSFrame(JSTracer *trc, const JitFrameIterator &frame)
#endif
}
static void
MarkBailoutFrame(JSTracer *trc, const JitFrameIterator &frame)
{
IonJSFrameLayout *layout = (IonJSFrameLayout *)frame.fp();
layout->replaceCalleeToken(MarkCalleeToken(trc, layout->calleeToken()));
// We have to mark the list of actual arguments, as only formal arguments
// are represented in the Snapshot.
MarkFrameAndActualArguments(trc, frame);
// Under a bailout, do not have a Safepoint to only iterate over GC-things.
// Thus we use a SnapshotIterator to trace all the locations which would be
// used to reconstruct the Baseline frame.
//
// Note that at the time where this function is called, we have not yet
// started to reconstruct baseline frames.
// The vector of recover instructions is already traced as part of the
// JitActivation.
SnapshotIterator snapIter(frame);
// For each instruction, we read the allocations without evaluating the
// recover instruction, nor reconstructing the frame. We are only looking at
// tracing readable allocations.
while (true) {
while (snapIter.moreAllocations())
snapIter.traceAllocation(trc);
if (!snapIter.moreInstructions())
break;
snapIter.nextInstruction();
};
}
#ifdef JSGC_GENERATIONAL
template <typename T>
void
@ -1306,6 +1348,9 @@ MarkJitActivation(JSTracer *trc, const JitActivationIterator &activations)
case JitFrame_IonJS:
MarkIonJSFrame(trc, frames);
break;
case JitFrame_Bailout:
MarkBailoutFrame(trc, frames);
break;
case JitFrame_Unwound_IonJS:
MOZ_CRASH("invalid");
case JitFrame_Rectifier:
@ -1752,6 +1797,94 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc)
}
}
void
SnapshotIterator::writeAllocationValuePayload(const RValueAllocation &alloc, Value v)
{
uintptr_t payload = *v.payloadUIntPtr();
#if defined(JS_PUNBOX64)
// Do not write back the tag, as this will trigger an assertion when we will
// reconstruct the JS Value while marking again or when bailing out.
payload &= JSVAL_PAYLOAD_MASK;
#endif
switch (alloc.mode()) {
case RValueAllocation::CONSTANT:
ionScript_->getConstant(alloc.index()) = v;
break;
case RValueAllocation::CST_UNDEFINED:
case RValueAllocation::CST_NULL:
case RValueAllocation::DOUBLE_REG:
case RValueAllocation::FLOAT32_REG:
case RValueAllocation::FLOAT32_STACK:
MOZ_CRASH("Not a GC thing: Unexpected write");
break;
case RValueAllocation::TYPED_REG:
machine_.write(alloc.reg2(), payload);
break;
case RValueAllocation::TYPED_STACK:
switch (alloc.knownType()) {
default:
MOZ_CRASH("Not a GC thing: Unexpected write");
break;
case JSVAL_TYPE_STRING:
case JSVAL_TYPE_SYMBOL:
case JSVAL_TYPE_OBJECT:
WriteFrameSlot(fp_, alloc.stackOffset2(), payload);
break;
}
break;
#if defined(JS_NUNBOX32)
case RValueAllocation::UNTYPED_REG_REG:
case RValueAllocation::UNTYPED_STACK_REG:
machine_.write(alloc.reg2(), payload);
break;
case RValueAllocation::UNTYPED_REG_STACK:
case RValueAllocation::UNTYPED_STACK_STACK:
WriteFrameSlot(fp_, alloc.stackOffset2(), payload);
break;
#elif defined(JS_PUNBOX64)
case RValueAllocation::UNTYPED_REG:
machine_.write(alloc.reg(), v.asRawBits());
break;
case RValueAllocation::UNTYPED_STACK:
WriteFrameSlot(fp_, alloc.stackOffset(), v.asRawBits());
break;
#endif
case RValueAllocation::RECOVER_INSTRUCTION:
MOZ_CRASH("Recover instructions are handled by the JitActivation.");
break;
default:
MOZ_CRASH("huh?");
}
}
void
SnapshotIterator::traceAllocation(JSTracer *trc)
{
RValueAllocation alloc = readAllocation();
if (!allocationReadable(alloc))
return;
Value v = allocationValue(alloc);
if (!v.isMarkable())
return;
Value copy = v;
gc::MarkValueRoot(trc, &v, "ion-typed-reg");
if (v != copy) {
MOZ_ASSERT(SameType(v, copy));
writeAllocationValuePayload(alloc, v);
}
}
const RResumePoint *
SnapshotIterator::resumePoint() const
{

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

@ -388,6 +388,7 @@ class SnapshotIterator
Value allocationValue(const RValueAllocation &a);
bool allocationReadable(const RValueAllocation &a);
void writeAllocationValuePayload(const RValueAllocation &a, Value v);
void warnUnreadableAllocation();
public:
@ -502,6 +503,8 @@ class SnapshotIterator
return fallback.unreadablePlaceholder();
}
void traceAllocation(JSTracer *trc);
void readCommonFrameSlots(Value *scopeChain, Value *rval) {
if (scopeChain)
*scopeChain = read();