Commit 93a0b806 authored by lrn@chromium.org's avatar lrn@chromium.org

X64: Fix bug in DoBranch that miss detecting NaN as falsy.

Review URL: http://codereview.chromium.org/6369005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6399 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 56073b73
...@@ -977,25 +977,27 @@ void LCodeGen::DoBranch(LBranch* instr) { ...@@ -977,25 +977,27 @@ void LCodeGen::DoBranch(LBranch* instr) {
Label* true_label = chunk_->GetAssemblyLabel(true_block); Label* true_label = chunk_->GetAssemblyLabel(true_block);
Label* false_label = chunk_->GetAssemblyLabel(false_block); Label* false_label = chunk_->GetAssemblyLabel(false_block);
__ Cmp(reg, Factory::undefined_value()); __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
__ j(equal, false_label); __ j(equal, false_label);
__ Cmp(reg, Factory::true_value()); __ CompareRoot(reg, Heap::kTrueValueRootIndex);
__ j(equal, true_label); __ j(equal, true_label);
__ Cmp(reg, Factory::false_value()); __ CompareRoot(reg, Heap::kFalseValueRootIndex);
__ j(equal, false_label); __ j(equal, false_label);
__ SmiCompare(reg, Smi::FromInt(0)); __ SmiCompare(reg, Smi::FromInt(0));
__ j(equal, false_label); __ j(equal, false_label);
__ JumpIfSmi(reg, true_label); __ JumpIfSmi(reg, true_label);
// Test for double values. Plus/minus zero are false. NaN is handled // Test for double values. Plus/minus zero and NaN are false.
// in the stub.
NearLabel call_stub; NearLabel call_stub;
__ Cmp(FieldOperand(reg, HeapObject::kMapOffset), __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset),
Factory::heap_number_map()); Heap::kHeapNumberMapRootIndex);
__ j(not_equal, &call_stub); __ j(not_equal, &call_stub);
__ movq(kScratchRegister, FieldOperand(reg, HeapNumber::kValueOffset));
__ shl(kScratchRegister, Immediate(1)); // Shift out the sign bit. // HeapNumber => false iff +0, -0, or NaN. These three cases set the
__ j(zero, false_label); // Zero or negative zero. // zero flag when compared to zero using ucomisd.
__ xorpd(xmm0, xmm0);
__ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
__ j(zero, false_label);
__ jmp(true_label); __ jmp(true_label);
// The conversion stub doesn't cause garbage collections so it's // The conversion stub doesn't cause garbage collections so it's
......
...@@ -1326,10 +1326,10 @@ class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> { ...@@ -1326,10 +1326,10 @@ class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
}; };
class LCallKeyed: public LTemplateInstruction<1, 0, 1> { class LCallKeyed: public LTemplateInstruction<1, 1, 0> {
public: public:
explicit LCallKeyed(LOperand* temp) { explicit LCallKeyed(LOperand* key) {
temps_[0] = temp; inputs_[0] = key;
} }
DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed") DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
...@@ -1898,30 +1898,30 @@ class LChunkBuilder BASE_EMBEDDED { ...@@ -1898,30 +1898,30 @@ class LChunkBuilder BASE_EMBEDDED {
MUST_USE_RESULT LOperand* UseRegister(HValue* value); MUST_USE_RESULT LOperand* UseRegister(HValue* value);
MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value); MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
// A value in a register that may be trashed. // An input operand in a register that may be trashed.
MUST_USE_RESULT LOperand* UseTempRegister(HValue* value); MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
// An operand value in a register or stack slot. // An input operand in a register or stack slot.
MUST_USE_RESULT LOperand* Use(HValue* value); MUST_USE_RESULT LOperand* Use(HValue* value);
MUST_USE_RESULT LOperand* UseAtStart(HValue* value); MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
// An operand value in a register, stack slot or a constant operand. // An input operand in a register, stack slot or a constant operand.
MUST_USE_RESULT LOperand* UseOrConstant(HValue* value); MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value); MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
// An operand value in a register or a constant operand. // An input operand in a register or a constant operand.
MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value); MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value); MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
// An input operand in register, stack slot or a constant operand.
// Will not be moved to a register even if one is freely available.
MUST_USE_RESULT LOperand* UseAny(HValue* value);
// Temporary operand that must be in a register. // Temporary operand that must be in a register.
MUST_USE_RESULT LUnallocated* TempRegister(); MUST_USE_RESULT LUnallocated* TempRegister();
MUST_USE_RESULT LOperand* FixedTemp(Register reg); MUST_USE_RESULT LOperand* FixedTemp(Register reg);
MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg); MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg);
// An operand value in register, stack slot or a constant operand.
// Will not be moved to a register even if one is freely available.
LOperand* UseAny(HValue* value);
// Methods for setting up define-use relationships. // Methods for setting up define-use relationships.
// Return the same instruction that they are passed. // Return the same instruction that they are passed.
template<int I, int T> template<int I, int T>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment