X64: Fix bug in DoBranch that miss detecting NaN as falsy.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Jan 2011 13:52:08 +0000 (13:52 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Jan 2011 13:52:08 +0000 (13:52 +0000)
Review URL: http://codereview.chromium.org/6369005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6399 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.h

index 9938ff0..dc988b1 100644 (file)
@@ -977,25 +977,27 @@ void LCodeGen::DoBranch(LBranch* instr) {
       Label* true_label = chunk_->GetAssemblyLabel(true_block);
       Label* false_label = chunk_->GetAssemblyLabel(false_block);
 
-      __ Cmp(reg, Factory::undefined_value());
+      __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
       __ j(equal, false_label);
-      __ Cmp(reg, Factory::true_value());
+      __ CompareRoot(reg, Heap::kTrueValueRootIndex);
       __ j(equal, true_label);
-      __ Cmp(reg, Factory::false_value());
+      __ CompareRoot(reg, Heap::kFalseValueRootIndex);
       __ j(equal, false_label);
       __ SmiCompare(reg, Smi::FromInt(0));
       __ j(equal, false_label);
       __ JumpIfSmi(reg, true_label);
 
-      // Test for double values. Plus/minus zero are false. NaN is handled
-      // in the stub.
+      // Test for double values. Plus/minus zero and NaN are false.
       NearLabel call_stub;
-      __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
-             Factory::heap_number_map());
+      __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset),
+                     Heap::kHeapNumberMapRootIndex);
       __ j(not_equal, &call_stub);
-      __ movq(kScratchRegister, FieldOperand(reg, HeapNumber::kValueOffset));
-      __ shl(kScratchRegister, Immediate(1));  // Shift out the sign bit.
-      __ j(zero, false_label);  // Zero or negative zero.
+
+      // HeapNumber => false iff +0, -0, or NaN. These three cases set the
+      // zero flag when compared to zero using ucomisd.
+      __ xorpd(xmm0, xmm0);
+      __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
+      __ j(zero, false_label);
       __ jmp(true_label);
 
       // The conversion stub doesn't cause garbage collections so it's
index f80e53c..787a426 100644 (file)
@@ -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:
-  explicit LCallKeyed(LOperand* temp) {
-    temps_[0] = temp;
+  explicit LCallKeyed(LOperand* key) {
+    inputs_[0] = key;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
@@ -1898,30 +1898,30 @@ class LChunkBuilder BASE_EMBEDDED {
   MUST_USE_RESULT LOperand* UseRegister(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);
 
-  // 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* 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* 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* 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.
   MUST_USE_RESULT LUnallocated* TempRegister();
   MUST_USE_RESULT LOperand* FixedTemp(Register 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.
   // Return the same instruction that they are passed.
   template<int I, int T>