Bug 1322093 part 5 - Factor out restoreInputState from emitFailurePath. r=h4writer
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -334,16 +334,101 @@ CacheRegisterAllocator::knownType(ValOpe
case OperandLocation::Uninitialized:
break;
}
MOZ_CRASH("Invalid kind");
}
+void
+CacheRegisterAllocator::restoreInputState(MacroAssembler& masm)
+{
+ size_t numInputOperands = origInputLocations_.length();
+ MOZ_ASSERT(writer_.numInputOperands() == numInputOperands);
+
+ for (size_t j = 0; j < numInputOperands; j++) {
+ OperandLocation orig = origInputLocation(j);
+ OperandLocation cur = operandLocation(j);
+
+ MOZ_ASSERT(orig.kind() == OperandLocation::ValueReg);
+
+ // We have a cycle if a destination register will be used later
+ // as source register. If that happens, just push the current value
+ // on the stack and later get it from there.
+ for (size_t k = j + 1; k < numInputOperands; k++) {
+ OperandLocation laterSource = operandLocation(k);
+ switch (laterSource.kind()) {
+ case OperandLocation::ValueReg:
+ if (orig.aliasesReg(laterSource.valueReg())) {
+ stackPushed_ += sizeof(js::Value);
+ masm.pushValue(laterSource.valueReg());
+ laterSource.setValueStack(stackPushed_);
+ }
+ continue;
+ case OperandLocation::PayloadReg:
+ if (orig.aliasesReg(laterSource.payloadReg())) {
+ stackPushed_ += sizeof(uintptr_t);
+ masm.push(laterSource.payloadReg());
+ laterSource.setPayloadStack(stackPushed_, laterSource.payloadType());
+ }
+ continue;
+ case OperandLocation::PayloadStack:
+ case OperandLocation::ValueStack:
+ case OperandLocation::Constant:
+ continue;
+ case OperandLocation::Uninitialized:
+ break;
+ }
+ MOZ_CRASH("Invalid kind");
+ }
+
+ switch (cur.kind()) {
+ case OperandLocation::ValueReg:
+ masm.moveValue(cur.valueReg(), orig.valueReg());
+ continue;
+ case OperandLocation::PayloadReg:
+ masm.tagValue(cur.payloadType(), cur.payloadReg(), orig.valueReg());
+ continue;
+ case OperandLocation::PayloadStack: {
+ MOZ_ASSERT(stackPushed_ >= sizeof(uintptr_t));
+ Register scratch = orig.valueReg().scratchReg();
+ if (cur.payloadStack() == stackPushed_) {
+ masm.pop(scratch);
+ stackPushed_ -= sizeof(uintptr_t);
+ } else {
+ MOZ_ASSERT(cur.payloadStack() < stackPushed_);
+ masm.loadPtr(Address(masm.getStackPointer(), stackPushed_ - cur.payloadStack()),
+ scratch);
+ }
+ masm.tagValue(cur.payloadType(), scratch, orig.valueReg());
+ continue;
+ }
+ case OperandLocation::ValueStack:
+ MOZ_ASSERT(stackPushed_ >= sizeof(js::Value));
+ if (cur.valueStack() == stackPushed_) {
+ masm.popValue(orig.valueReg());
+ stackPushed_ -= sizeof(js::Value);
+ } else {
+ MOZ_ASSERT(cur.valueStack() < stackPushed_);
+ masm.loadValue(Address(masm.getStackPointer(), stackPushed_ - cur.valueStack()),
+ orig.valueReg());
+ }
+ continue;
+ case OperandLocation::Constant:
+ continue;
+ case OperandLocation::Uninitialized:
+ break;
+ }
+ MOZ_CRASH("Invalid kind");
+ }
+
+ discardStack(masm);
+}
+
size_t
CacheIRStubInfo::stubDataSize() const
{
size_t field = 0;
size_t size = 0;
while (true) {
StubField::Type type = fieldType(field++);
if (type == StubField::Type::Limit)
@@ -613,102 +698,27 @@ CacheIRCompiler::addFailurePath(FailureP
if (!failurePaths.append(Move(newFailure)))
return false;
*failure = &failurePaths.back();
return true;
}
void
-CacheIRCompiler::emitFailurePath(size_t i)
+CacheIRCompiler::emitFailurePath(size_t index)
{
- FailurePath& failure = failurePaths[i];
+ FailurePath& failure = failurePaths[index];
+
+ allocator.setStackPushed(failure.stackPushed());
+
+ for (size_t i = 0; i < writer_.numInputOperands(); i++)
+ allocator.setOperandLocation(i, failure.input(i));
masm.bind(failure.label());
-
- uint32_t stackPushed = failure.stackPushed();
- size_t numInputOperands = writer_.numInputOperands();
-
- for (size_t j = 0; j < numInputOperands; j++) {
- OperandLocation orig = allocator.origInputLocation(j);
- OperandLocation cur = failure.input(j);
-
- MOZ_ASSERT(orig.kind() == OperandLocation::ValueReg);
-
- // We have a cycle if a destination register will be used later
- // as source register. If that happens, just push the current value
- // on the stack and later get it from there.
- for (size_t k = j + 1; k < numInputOperands; k++) {
- OperandLocation laterSource = failure.input(k);
- switch (laterSource.kind()) {
- case OperandLocation::ValueReg:
- if (orig.aliasesReg(laterSource.valueReg())) {
- stackPushed += sizeof(js::Value);
- masm.pushValue(laterSource.valueReg());
- laterSource.setValueStack(stackPushed);
- }
- continue;
- case OperandLocation::PayloadReg:
- if (orig.aliasesReg(laterSource.payloadReg())) {
- stackPushed += sizeof(uintptr_t);
- masm.push(laterSource.payloadReg());
- laterSource.setPayloadStack(stackPushed, laterSource.payloadType());
- }
- continue;
- case OperandLocation::PayloadStack:
- case OperandLocation::ValueStack:
- case OperandLocation::Constant:
- continue;
- case OperandLocation::Uninitialized:
- break;
- }
- MOZ_CRASH("Invalid kind");
- }
-
- switch (cur.kind()) {
- case OperandLocation::ValueReg:
- masm.moveValue(cur.valueReg(), orig.valueReg());
- continue;
- case OperandLocation::PayloadReg:
- masm.tagValue(cur.payloadType(), cur.payloadReg(), orig.valueReg());
- continue;
- case OperandLocation::PayloadStack: {
- MOZ_ASSERT(stackPushed >= sizeof(uintptr_t));
- Register scratch = orig.valueReg().scratchReg();
- if (cur.payloadStack() == stackPushed) {
- masm.pop(scratch);
- stackPushed -= sizeof(uintptr_t);
- } else {
- MOZ_ASSERT(cur.payloadStack() < stackPushed);
- masm.loadPtr(Address(masm.getStackPointer(), stackPushed - cur.payloadStack()),
- scratch);
- }
- masm.tagValue(cur.payloadType(), scratch, orig.valueReg());
- continue;
- }
- case OperandLocation::ValueStack:
- MOZ_ASSERT(stackPushed >= sizeof(js::Value));
- if (cur.valueStack() == stackPushed) {
- masm.popValue(orig.valueReg());
- stackPushed -= sizeof(js::Value);
- } else {
- MOZ_ASSERT(cur.valueStack() < stackPushed);
- masm.loadValue(Address(masm.getStackPointer(), stackPushed - cur.valueStack()),
- orig.valueReg());
- }
- continue;
- case OperandLocation::Constant:
- continue;
- case OperandLocation::Uninitialized:
- break;
- }
- MOZ_CRASH("Invalid kind");
- }
-
- allocator.discardStack(masm);
+ allocator.restoreInputState(masm);
}
bool
CacheIRCompiler::emitGuardIsObject()
{
ValOperandId inputId = reader.valOperandId();
if (allocator.knownType(inputId) == JSVAL_TYPE_OBJECT)
return true;
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -174,32 +174,39 @@ class MOZ_RAII CacheRegisterAllocator
writer_(writer)
{}
MOZ_MUST_USE bool init(const AllocatableGeneralRegisterSet& available);
OperandLocation operandLocation(size_t i) const {
return operandLocations_[i];
}
+ void setOperandLocation(size_t i, const OperandLocation& loc) {
+ operandLocations_[i] = loc;
+ }
+
OperandLocation origInputLocation(size_t i) const {
return origInputLocations_[i];
}
void initInputLocation(size_t i, ValueOperand reg) {
origInputLocations_[i].setValueReg(reg);
operandLocations_[i] = origInputLocations_[i];
}
void nextOp() {
currentOpRegs_.clear();
currentInstruction_++;
}
uint32_t stackPushed() const {
return stackPushed_;
}
+ void setStackPushed(uint32_t pushed) {
+ stackPushed_ = pushed;
+ }
bool isAllocatable(Register reg) const {
return allocatableRegs_.has(reg);
}
// Allocates a new register.
Register allocateRegister(MacroAssembler& masm);
ValueOperand allocateValueRegister(MacroAssembler& masm);
@@ -221,16 +228,20 @@ class MOZ_RAII CacheRegisterAllocator
Register useRegister(MacroAssembler& masm, TypedOperandId typedId);
// Allocates an output register for the given operand.
Register defineRegister(MacroAssembler& masm, TypedOperandId typedId);
ValueOperand defineValueRegister(MacroAssembler& masm, ValOperandId val);
// Returns |val|'s JSValueType or JSVAL_TYPE_UNKNOWN.
JSValueType knownType(ValOperandId val) const;
+
+ // Emits code to restore registers and stack to the state at the start of
+ // the stub.
+ void restoreInputState(MacroAssembler& masm);
};
// RAII class to allocate a scratch register and release it when we're done
// with it.
class MOZ_RAII AutoScratchRegister
{
CacheRegisterAllocator& alloc_;
Register reg_;
@@ -336,17 +347,17 @@ class MOZ_RAII CacheIRCompiler
: cx_(cx),
reader(writer),
writer_(writer),
allocator(writer_)
{}
MOZ_MUST_USE bool addFailurePath(FailurePath** failure);
- void emitFailurePath(size_t i);
+ void emitFailurePath(size_t index);
#define DEFINE_SHARED_OP(op) MOZ_MUST_USE bool emit##op();
CACHE_IR_SHARED_OPS(DEFINE_SHARED_OP)
#undef DEFINE_SHARED_OP
};
// See the 'Sharing Baseline stub code' comment in CacheIR.h for a description
// of this class.