Bug 991720 part 3 - Enforce recovery of stores before reading object values. r=h4writer

This commit is contained in:
Nicolas B. Pierron 2014-12-19 15:28:31 +01:00
parent 669929b8ef
commit b2cbcdb3ff
6 changed files with 47 additions and 2 deletions

View File

@ -393,6 +393,9 @@ class SnapshotIterator
bool hasInstructionResult(uint32_t index) const {
return instructionResults_;
}
bool hasInstructionResults() const {
return instructionResults_;
}
Value fromInstructionResult(uint32_t index) const;
Value allocationValue(const RValueAllocation &a, ReadMethod rm = RM_Normal);

View File

@ -1751,6 +1751,14 @@ FromTypedPayload(JSValueType type, uintptr_t payload)
bool
SnapshotIterator::allocationReadable(const RValueAllocation &alloc, ReadMethod rm)
{
// If we have to recover stores, and if we are not interested in the
// default value of the instruction, then we have to check if the recover
// instruction results are available.
if (alloc.needSideEffect() && !(rm & RM_AlwaysDefault)) {
if (!hasInstructionResults())
return false;
}
switch (alloc.mode()) {
case RValueAllocation::DOUBLE_REG:
return hasRegister(alloc.fpuReg());

View File

@ -101,6 +101,15 @@ MIRType MIRTypeFromValue(const js::Value &vp)
*/ \
_(RecoveredOnBailout) \
\
/* Some instructions might represent an object, but the memory of these
* objects might be incomplete if we have not recovered all the stores which
* were supposed to happen before. This flag is used to annotate
* instructions which might return a pointer to a memory area which is not
* yet fully initialized. This flag is used to ensure that stores are
* executed before returning the value.
*/ \
_(IncompleteObject) \
\
/* The current instruction got discarded from the MIR Graph. This is useful
* when we want to iterate over resume points and instructions, while
* handling instructions which are discarded without reporting to the

View File

@ -313,7 +313,7 @@ RValueAllocation
RValueAllocation::read(CompactBufferReader &reader)
{
uint8_t mode = reader.readByte();
const Layout &layout = layoutFromMode(Mode(mode));
const Layout &layout = layoutFromMode(Mode(mode & MODE_MASK));
Payload arg1, arg2;
readPayload(reader, layout.type1, &mode, &arg1);

View File

@ -69,6 +69,17 @@ class RValueAllocation
TYPED_STACK_MAX = 0x2f,
TYPED_STACK = TYPED_STACK_MIN,
// This mask can be used with any other valid mode. When this flag is
// set on the mode, this inform the snapshot iterator that even if the
// allocation is readable, the content of if might be incomplete unless
// all side-effects are executed.
RECOVER_SIDE_EFFECT_MASK = 0x80,
// This mask represents the set of bits which can be used to encode a
// value in a snapshot. The mode is used to determine how to interpret
// the union of values and how to pack the value in memory.
MODE_MASK = 0x17f,
INVALID = 0x100,
};
@ -269,6 +280,11 @@ class RValueAllocation
payloadOfIndex(cstIndex));
}
void setNeedSideEffect() {
MOZ_ASSERT(!needSideEffect() && mode_ != INVALID);
mode_ = Mode(mode_ | RECOVER_SIDE_EFFECT_MASK);
}
void writeHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const;
public:
static RValueAllocation read(CompactBufferReader &reader);
@ -276,7 +292,10 @@ class RValueAllocation
public:
Mode mode() const {
return mode_;
return Mode(mode_ & MODE_MASK);
}
bool needSideEffect() const {
return mode_ & RECOVER_SIDE_EFFECT_MASK;
}
uint32_t index() const {

View File

@ -399,6 +399,12 @@ CodeGeneratorShared::encodeAllocation(LSnapshot *snapshot, MDefinition *mir,
}
}
// This set an extra bit as part of the RValueAllocation, such that we know
// that recover instruction have to be executed without wrapping the
// instruction in a no-op recover instruction.
if (mir->isIncompleteObject())
alloc.setNeedSideEffect();
snapshots_.add(alloc);
*allocIndex += mir->isRecoveredOnBailout() ? 0 : 1;
}