Bug 1073033 part 2.0 - Snapshot: Add Recover instruction with default value. r=bbouvier

This commit is contained in:
Nicolas B. Pierron 2014-12-19 15:28:28 +01:00
Родитель ad80860b57
Коммит a820b1f0ec
4 изменённых файлов: 71 добавлений и 8 удалений

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

@ -356,6 +356,18 @@ class SnapshotIterator
IonScript *ionScript_;
RInstructionResults *instructionResults_;
enum ReadMethod {
// Read the normal value.
RM_Normal = 1 << 0,
// Read the default value, or the normal value if there is no default.
RM_AlwaysDefault = 1 << 1,
// Try to read the normal value if it is readable, otherwise default to
// the Default value.
RM_NormalOrDefault = RM_Normal | RM_AlwaysDefault,
};
private:
// Read a spilled register from the machine state.
bool hasRegister(Register reg) const {
@ -383,8 +395,8 @@ class SnapshotIterator
}
Value fromInstructionResult(uint32_t index) const;
Value allocationValue(const RValueAllocation &a);
bool allocationReadable(const RValueAllocation &a);
Value allocationValue(const RValueAllocation &a, ReadMethod rm = RM_Normal);
bool allocationReadable(const RValueAllocation &a, ReadMethod rm = RM_Normal);
void writeAllocationValuePayload(const RValueAllocation &a, Value v);
void warnUnreadableAllocation();
@ -482,6 +494,14 @@ class SnapshotIterator
return allocationValue(readAllocation());
}
// Read the |Normal| value unless it is not available and that the snapshot
// provides a |Default| value. This is useful to avoid invalidations of the
// frame while we are only interested in a few properties which are provided
// by the |Default| value.
Value readWithDefault() {
return allocationValue(readAllocation(), RM_NormalOrDefault);
}
Value maybeRead(MaybeReadFallback &fallback) {
RValueAllocation a = readAllocation();
if (allocationReadable(a))

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

@ -1749,7 +1749,7 @@ FromTypedPayload(JSValueType type, uintptr_t payload)
}
bool
SnapshotIterator::allocationReadable(const RValueAllocation &alloc)
SnapshotIterator::allocationReadable(const RValueAllocation &alloc, ReadMethod rm)
{
switch (alloc.mode()) {
case RValueAllocation::DOUBLE_REG:
@ -1776,6 +1776,8 @@ SnapshotIterator::allocationReadable(const RValueAllocation &alloc)
case RValueAllocation::RECOVER_INSTRUCTION:
return hasInstructionResult(alloc.index());
case RValueAllocation::RI_WITH_DEFAULT_CST:
return rm & RM_AlwaysDefault || hasInstructionResult(alloc.index());
default:
return true;
@ -1783,7 +1785,7 @@ SnapshotIterator::allocationReadable(const RValueAllocation &alloc)
}
Value
SnapshotIterator::allocationValue(const RValueAllocation &alloc)
SnapshotIterator::allocationValue(const RValueAllocation &alloc, ReadMethod rm)
{
switch (alloc.mode()) {
case RValueAllocation::CONSTANT:
@ -1887,6 +1889,12 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc)
case RValueAllocation::RECOVER_INSTRUCTION:
return fromInstructionResult(alloc.index());
case RValueAllocation::RI_WITH_DEFAULT_CST:
if (rm & RM_Normal && hasInstructionResult(alloc.index()))
return fromInstructionResult(alloc.index());
MOZ_ASSERT(rm & RM_AlwaysDefault);
return ionScript_->getConstant(alloc.index2());
default:
MOZ_CRASH("huh?");
}
@ -1956,6 +1964,12 @@ SnapshotIterator::writeAllocationValuePayload(const RValueAllocation &alloc, Val
MOZ_CRASH("Recover instructions are handled by the JitActivation.");
break;
case RValueAllocation::RI_WITH_DEFAULT_CST:
// Assume that we are always going to be writing on the default value
// while tracing.
ionScript_->getConstant(alloc.index2()) = v;
break;
default:
MOZ_CRASH("huh?");
}
@ -1965,10 +1979,10 @@ void
SnapshotIterator::traceAllocation(JSTracer *trc)
{
RValueAllocation alloc = readAllocation();
if (!allocationReadable(alloc))
if (!allocationReadable(alloc, RM_AlwaysDefault))
return;
Value v = allocationValue(alloc);
Value v = allocationValue(alloc, RM_AlwaysDefault);
if (!v.isMarkable())
return;
@ -2313,8 +2327,12 @@ InlineFrameIterator::findNextFrame()
for (unsigned j = 0; j < skipCount; j++)
si_.skip();
// The JSFunction is a constant, otherwise we would not have inlined it.
Value funval = si_.read();
// This value should correspond to the function which is being inlined.
// The value must be readable to iterate over the inline frame. Most of
// the time, these functions are stored as JSFunction constants,
// register which are holding the JSFunction pointer, or recover
// instruction with Default value.
Value funval = si_.readWithDefault();
// Skip extra value allocations.
while (si_.moreAllocations())

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

@ -79,6 +79,11 @@ using namespace js::jit;
// RECOVER_INSTRUCTION [INDEX]
// Index into the list of recovered instruction results.
//
// RI_WITH_DEFAULT_CST [INDEX] [INDEX]
// The first payload is the index into the list of recovered
// instruction results. The second payload is the index in the
// constant pool.
//
// TYPED_REG [PACKED_TAG, GPR_REG]:
// Value with statically known type, which payload is stored in a
// register.
@ -231,6 +236,14 @@ RValueAllocation::layoutFromMode(Mode mode)
};
return layout;
}
case RI_WITH_DEFAULT_CST: {
static const RValueAllocation::Layout layout = {
PAYLOAD_INDEX,
PAYLOAD_INDEX,
"instruction with default"
};
return layout;
}
default: {
static const RValueAllocation::Layout regLayout = {

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

@ -54,7 +54,10 @@ class RValueAllocation
UNTYPED_REG = 0x06,
UNTYPED_STACK = 0x07,
#endif
// Recover instructions.
RECOVER_INSTRUCTION = 0x0a,
RI_WITH_DEFAULT_CST = 0x0b,
// The JSValueType is packed in the Mode.
TYPED_REG_MIN = 0x10,
@ -260,6 +263,11 @@ class RValueAllocation
static RValueAllocation RecoverInstruction(uint32_t index) {
return RValueAllocation(RECOVER_INSTRUCTION, payloadOfIndex(index));
}
static RValueAllocation RecoverInstruction(uint32_t riIndex, uint32_t cstIndex) {
return RValueAllocation(RI_WITH_DEFAULT_CST,
payloadOfIndex(riIndex),
payloadOfIndex(cstIndex));
}
void writeHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const;
public:
@ -293,6 +301,10 @@ class RValueAllocation
return arg1_.type;
}
uint32_t index2() const {
MOZ_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_INDEX);
return arg2_.index;
}
int32_t stackOffset2() const {
MOZ_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_STACK_OFFSET);
return arg2_.stackOffset;