Fix phis for non-sse2 double values
Since hydrogen will try to merge phi-inputs using registers, even if the values are spilled, we cannot mark LGoto as double clobbering instruction. BUG= R=verwaest@chromium.org Review URL: https://codereview.chromium.org/23068038 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16671 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8dbd822855
commit
553d73a289
@ -382,9 +382,13 @@ bool LCodeGen::GenerateBody() {
|
||||
|
||||
instr->CompileToNative(this);
|
||||
|
||||
if (!CpuFeatures::IsSupported(SSE2) &&
|
||||
FLAG_debug_code && FLAG_enable_slow_asserts) {
|
||||
if (!CpuFeatures::IsSupported(SSE2)) {
|
||||
if (instr->IsGoto()) {
|
||||
x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr));
|
||||
} else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
|
||||
!instr->IsGap() && !instr->IsReturn()) {
|
||||
__ VerifyX87StackDepth(x87_stack_.depth());
|
||||
}
|
||||
}
|
||||
}
|
||||
EnsureSpaceForLazyDeopt();
|
||||
@ -682,6 +686,21 @@ void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
|
||||
__ fstp(0);
|
||||
stack_depth_--;
|
||||
}
|
||||
__ VerifyX87StackDepth(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr) {
|
||||
ASSERT(stack_depth_ <= 1);
|
||||
// If ever used for new stubs producing two pairs of doubles joined into two
|
||||
// phis this assert hits. That situation is not handled, since the two stacks
|
||||
// might have st0 and st1 swapped.
|
||||
if (current_block_id + 1 != goto_instr->block_id()) {
|
||||
// If we have a value on the x87 stack on leaving a block, it must be a
|
||||
// phi input. If the next block we compile is not the join block, we have
|
||||
// to discard the stack state.
|
||||
stack_depth_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2486,6 +2505,10 @@ void LCodeGen::EmitGoto(int block) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoClobberDoubles(LClobberDoubles* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoGoto(LGoto* instr) {
|
||||
EmitGoto(instr->block_id());
|
||||
}
|
||||
|
@ -471,6 +471,7 @@ class LCodeGen V8_FINAL BASE_EMBEDDED {
|
||||
void PrepareToWrite(X87Register reg);
|
||||
void CommitWrite(X87Register reg);
|
||||
void FlushIfNecessary(LInstruction* instr, LCodeGen* cgen);
|
||||
void LeavingBlock(int current_block_id, LGoto* goto_instr);
|
||||
int depth() const { return stack_depth_; }
|
||||
void pop() {
|
||||
ASSERT(is_mutable_);
|
||||
|
@ -954,6 +954,16 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
|
||||
if (FLAG_stress_environments && !instr->HasEnvironment()) {
|
||||
instr = AssignEnvironment(instr);
|
||||
}
|
||||
if (!CpuFeatures::IsSafeForSnapshot(SSE2) && instr->IsGoto() &&
|
||||
LGoto::cast(instr)->jumps_to_join()) {
|
||||
// TODO(olivf) Since phis of spilled values are joined as registers
|
||||
// (not in the stack slot), we need to allow the goto gaps to keep one
|
||||
// x87 register alive. To ensure all other values are still spilled, we
|
||||
// insert a fpu register barrier right before.
|
||||
LClobberDoubles* clobber = new(zone()) LClobberDoubles();
|
||||
clobber->set_hydrogen_value(current);
|
||||
chunk_->AddInstruction(clobber, current_block_);
|
||||
}
|
||||
instr->set_hydrogen_value(current);
|
||||
chunk_->AddInstruction(instr, current_block_);
|
||||
}
|
||||
@ -1046,7 +1056,7 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
|
||||
return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
|
||||
return new(zone()) LGoto(instr->FirstSuccessor());
|
||||
}
|
||||
|
||||
|
||||
@ -1058,7 +1068,7 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
|
||||
HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
|
||||
? instr->FirstSuccessor()
|
||||
: instr->SecondSuccessor();
|
||||
return new(zone()) LGoto(successor->block_id());
|
||||
return new(zone()) LGoto(successor);
|
||||
}
|
||||
|
||||
ToBooleanStub::Types expected = instr->expected_input_types();
|
||||
|
@ -73,6 +73,7 @@ class LCodeGen;
|
||||
V(ClampTToUint8) \
|
||||
V(ClampTToUint8NoSSE2) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(ClobberDoubles) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -406,19 +407,32 @@ class LInstructionGap V8_FINAL : public LGap {
|
||||
};
|
||||
|
||||
|
||||
class LClobberDoubles V8_FINAL : public LTemplateInstruction<0, 0, 0> {
|
||||
public:
|
||||
LClobberDoubles() { ASSERT(!CpuFeatures::IsSafeForSnapshot(SSE2)); }
|
||||
|
||||
virtual bool ClobbersDoubleRegisters() const { return true; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(ClobberDoubles, "clobber-d")
|
||||
};
|
||||
|
||||
|
||||
class LGoto V8_FINAL : public LTemplateInstruction<0, 0, 0> {
|
||||
public:
|
||||
explicit LGoto(int block_id) : block_id_(block_id) { }
|
||||
explicit LGoto(HBasicBlock* block) : block_(block) { }
|
||||
|
||||
virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE;
|
||||
DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
|
||||
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
|
||||
virtual bool IsControl() const V8_OVERRIDE { return true; }
|
||||
|
||||
int block_id() const { return block_id_; }
|
||||
int block_id() const { return block_->block_id(); }
|
||||
virtual bool ClobbersDoubleRegisters() const { return false; }
|
||||
|
||||
bool jumps_to_join() const { return block_->predecessors()->length() > 1; }
|
||||
|
||||
private:
|
||||
int block_id_;
|
||||
HBasicBlock* block_;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user