Index: src/code-stub-assembler.cc |
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
index 6d1c4ca1a7297cff79f468daaf77529033e9907f..7c15dea612e6510b7e6ce4ab669947db91d60844 100644 |
--- a/src/code-stub-assembler.cc |
+++ b/src/code-stub-assembler.cc |
@@ -2271,6 +2271,40 @@ void CodeStubAssembler::InitializeAllocationMemento( |
} |
} |
+Node* CodeStubAssembler::TryTaggedToFloat64(Node* value, |
+ Label* if_valueisnotnumber) { |
+ Label out(this); |
+ Variable var_result(this, MachineRepresentation::kFloat64); |
+ |
+ // Check if the {value} is a Smi or a HeapObject. |
+ Label if_valueissmi(this), if_valueisnotsmi(this); |
+ Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); |
+ |
+ Bind(&if_valueissmi); |
+ { |
+ // Convert the Smi {value}. |
+ var_result.Bind(SmiToFloat64(value)); |
+ Goto(&out); |
+ } |
+ |
+ Bind(&if_valueisnotsmi); |
+ { |
+ // Check if {value} is a HeapNumber. |
+ Label if_valueisheapnumber(this); |
+ Branch(IsHeapNumberMap(LoadMap(value)), &if_valueisheapnumber, |
+ if_valueisnotnumber); |
+ |
+ Bind(&if_valueisheapnumber); |
+ { |
+ // Load the floating point value. |
+ var_result.Bind(LoadHeapNumberValue(value)); |
+ Goto(&out); |
+ } |
+ } |
+ Bind(&out); |
+ return var_result.value(); |
+} |
+ |
Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { |
// We might need to loop once due to ToNumber conversion. |
Variable var_value(this, MachineRepresentation::kTagged), |
@@ -2280,42 +2314,23 @@ Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { |
Goto(&loop); |
Bind(&loop); |
{ |
+ Label if_valueisnotnumber(this, Label::kDeferred); |
+ |
// Load the current {value}. |
value = var_value.value(); |
- // Check if the {value} is a Smi or a HeapObject. |
- Label if_valueissmi(this), if_valueisnotsmi(this); |
- Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); |
- |
- Bind(&if_valueissmi); |
- { |
- // Convert the Smi {value}. |
- var_result.Bind(SmiToFloat64(value)); |
- Goto(&done_loop); |
- } |
+ // Convert {value} to Float64 if it is a number and convert it to a number |
+ // otherwise. |
+ Node* const result = TryTaggedToFloat64(value, &if_valueisnotnumber); |
+ var_result.Bind(result); |
+ Goto(&done_loop); |
- Bind(&if_valueisnotsmi); |
+ Bind(&if_valueisnotnumber); |
{ |
- // Check if {value} is a HeapNumber. |
- Label if_valueisheapnumber(this), |
- if_valueisnotheapnumber(this, Label::kDeferred); |
- Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()), |
- &if_valueisheapnumber, &if_valueisnotheapnumber); |
- |
- Bind(&if_valueisheapnumber); |
- { |
- // Load the floating point value. |
- var_result.Bind(LoadHeapNumberValue(value)); |
- Goto(&done_loop); |
- } |
- |
- Bind(&if_valueisnotheapnumber); |
- { |
- // Convert the {value} to a Number first. |
- Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
- var_value.Bind(CallStub(callable, context, value)); |
- Goto(&loop); |
- } |
+ // Convert the {value} to a Number first. |
+ Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
+ var_value.Bind(CallStub(callable, context, value)); |
+ Goto(&loop); |
} |
} |
Bind(&done_loop); |
@@ -6574,24 +6589,7 @@ Node* CodeStubAssembler::PrepareValueForWrite(Node* value, |
Representation representation, |
Label* bailout) { |
if (representation.IsDouble()) { |
- Variable var_value(this, MachineRepresentation::kFloat64); |
- Label if_smi(this), if_heap_object(this), done(this); |
- Branch(TaggedIsSmi(value), &if_smi, &if_heap_object); |
- Bind(&if_smi); |
- { |
- var_value.Bind(SmiToFloat64(value)); |
- Goto(&done); |
- } |
- Bind(&if_heap_object); |
- { |
- GotoUnless( |
- Word32Equal(LoadInstanceType(value), Int32Constant(HEAP_NUMBER_TYPE)), |
- bailout); |
- var_value.Bind(LoadHeapNumberValue(value)); |
- Goto(&done); |
- } |
- Bind(&done); |
- value = var_value.value(); |
+ value = TryTaggedToFloat64(value, bailout); |
} else if (representation.IsHeapObject()) { |
// Field type is checked by the handler, here we only check if the value |
// is a heap object. |
@@ -8576,6 +8574,95 @@ compiler::Node* CodeStubAssembler::StrictEqual(ResultMode mode, |
return result.value(); |
} |
+// ECMA#sec-samevalue |
+// This algorithm differs from the Strict Equality Comparison Algorithm in its |
+// treatment of signed zeroes and NaNs. |
+compiler::Node* CodeStubAssembler::SameValue(compiler::Node* lhs, |
+ compiler::Node* rhs, |
+ compiler::Node* context) { |
+ Variable var_result(this, MachineType::PointerRepresentation()); |
+ Label strict_equal(this), out(this); |
+ |
+ Node* const int_false = IntPtrConstant(0); |
+ Node* const int_true = IntPtrConstant(1); |
+ |
+ Label if_equal(this), if_notequal(this); |
+ Branch(WordEqual(lhs, rhs), &if_equal, &if_notequal); |
+ |
+ Bind(&if_equal); |
+ { |
+ // This covers the case when {lhs} == {rhs}. We can simply return true |
+ // because SameValue considers two NaNs to be equal. |
+ |
+ var_result.Bind(int_true); |
+ Goto(&out); |
+ } |
+ |
+ Bind(&if_notequal); |
+ { |
+ // This covers the case when {lhs} != {rhs}. We only handle numbers here |
+ // and defer to StrictEqual for the rest. |
+ |
+ Node* const lhs_float = TryTaggedToFloat64(lhs, &strict_equal); |
+ Node* const rhs_float = TryTaggedToFloat64(rhs, &strict_equal); |
+ |
+ Label if_lhsisnan(this), if_lhsnotnan(this); |
+ BranchIfFloat64IsNaN(lhs_float, &if_lhsisnan, &if_lhsnotnan); |
+ |
+ Bind(&if_lhsisnan); |
+ { |
+ // Return true iff {rhs} is NaN. |
+ |
+ Node* const result = |
+ Select(Float64Equal(rhs_float, rhs_float), int_false, int_true, |
+ MachineType::PointerRepresentation()); |
+ var_result.Bind(result); |
+ Goto(&out); |
+ } |
+ |
+ Bind(&if_lhsnotnan); |
+ { |
+ Label if_floatisequal(this), if_floatnotequal(this); |
+ Branch(Float64Equal(lhs_float, rhs_float), &if_floatisequal, |
+ &if_floatnotequal); |
+ |
+ Bind(&if_floatisequal); |
+ { |
+ // We still need to handle the case when {lhs} and {rhs} are -0.0 and |
+ // 0.0 (or vice versa). Compare the high word to |
+ // distinguish between the two. |
+ |
+ Node* const lhs_hi_word = Float64ExtractHighWord32(lhs_float); |
+ Node* const rhs_hi_word = Float64ExtractHighWord32(rhs_float); |
+ |
+ // If x is +0 and y is -0, return false. |
+ // If x is -0 and y is +0, return false. |
+ |
+ Node* const result = Word32Equal(lhs_hi_word, rhs_hi_word); |
+ var_result.Bind(result); |
+ Goto(&out); |
+ } |
+ |
+ Bind(&if_floatnotequal); |
+ { |
+ var_result.Bind(int_false); |
+ Goto(&out); |
+ } |
+ } |
+ } |
+ |
+ Bind(&strict_equal); |
+ { |
+ Node* const is_equal = StrictEqual(kDontNegateResult, lhs, rhs, context); |
+ Node* const result = WordEqual(is_equal, TrueConstant()); |
+ var_result.Bind(result); |
+ Goto(&out); |
+ } |
+ |
+ Bind(&out); |
+ return var_result.value(); |
+} |
+ |
compiler::Node* CodeStubAssembler::ForInFilter(compiler::Node* key, |
compiler::Node* object, |
compiler::Node* context) { |