Chromium Code Reviews| Index: src/code-stubs.cc |
| diff --git a/src/code-stubs.cc b/src/code-stubs.cc |
| index 2c4445f59ddf22316137d67c95693bdd3bb1e411..c1c854b988143b079131ecbb5eda4bb6a9471c41 100644 |
| --- a/src/code-stubs.cc |
| +++ b/src/code-stubs.cc |
| @@ -473,6 +473,243 @@ void StringLengthStub::GenerateAssembly( |
| assembler->Return(result); |
| } |
| +void StrictEqualStub::GenerateAssembly( |
| + compiler::CodeStubAssembler* assembler) const { |
| + typedef compiler::CodeStubAssembler::Label Label; |
| + typedef compiler::Node Node; |
| + |
| + Node* lhs = assembler->Parameter(0); |
| + Node* rhs = assembler->Parameter(1); |
| + Node* context = assembler->Parameter(2); |
| + |
|
Yang
2016/03/02 10:29:16
This is really hard to read... :P
I'd have preferr
Benedikt Meurer
2016/03/02 11:27:04
Added the pseudo-code thanks. The short-cut unfort
|
| + Label if_true(assembler), if_false(assembler); |
| + |
| + // Check if {lhs} and {rhs} refer to the same object. |
| + Label if_same(assembler), if_notsame(assembler); |
| + assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); |
| + |
| + assembler->Bind(&if_same); |
| + { |
| + // The {lhs} and {rhs} reference the exact same value, yet we need special |
| + // treatment for HeapNumber, as NaN is not equal to NaN. |
| + // TODO(bmeurer): This seems to violate the SIMD.js specification, but it |
| + // seems to be what is tested in the current SIMD.js testsuite. |
| + |
| + // Check if {lhs} (and therefore {rhs}) is a Smi or a HeapObject. |
| + Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
| + assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
| + |
| + assembler->Bind(&if_lhsisnotsmi); |
| + { |
| + // Load the map of {lhs}. |
| + Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); |
| + |
| + // Check if {lhs} (and therefore {rhs}) is a HeapNumber. |
| + Node* number_map = assembler->HeapNumberMapConstant(); |
| + Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); |
| + assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
| + &if_lhsisnumber, &if_lhsisnotnumber); |
| + |
| + assembler->Bind(&if_lhsisnumber); |
| + { |
| + // Convert {lhs} (and therefore {rhs}) to floating point value. |
| + Node* lhs_value = assembler->LoadHeapNumberValue(lhs); |
| + |
| + // Check if the HeapNumber value is a NaN. |
| + assembler->BranchIfFloat64IsNaN(lhs_value, &if_false, &if_true); |
| + } |
| + |
| + assembler->Bind(&if_lhsisnotnumber); |
| + assembler->Goto(&if_true); |
| + } |
| + |
| + assembler->Bind(&if_lhsissmi); |
| + assembler->Goto(&if_true); |
| + } |
| + |
| + assembler->Bind(&if_notsame); |
| + { |
| + // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber, |
| + // String and Simd128Value they can still be considered equal. |
| + Node* number_map = assembler->HeapNumberMapConstant(); |
| + |
| + // Check if {lhs} is a Smi or a HeapObject. |
| + Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
| + assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
| + |
| + assembler->Bind(&if_lhsisnotsmi); |
| + { |
| + // Load the map of {lhs}. |
| + Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); |
| + |
| + // Check if {lhs} is a HeapNumber. |
| + Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); |
| + assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
| + &if_lhsisnumber, &if_lhsisnotnumber); |
| + |
| + assembler->Bind(&if_lhsisnumber); |
| + { |
| + // Check if {rhs} is a Smi or a HeapObject. |
| + Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| + assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| + &if_rhsisnotsmi); |
| + |
| + assembler->Bind(&if_rhsissmi); |
| + { |
| + // Convert {lhs} and {rhs} to floating point values. |
| + Node* lhs_value = assembler->LoadHeapNumberValue(lhs); |
| + Node* rhs_value = assembler->SmiToFloat64(rhs); |
| + |
| + // Perform a floating point comparison of {lhs} and {rhs}. |
| + assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, |
| + &if_false); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotsmi); |
| + { |
| + // Load the map of {rhs}. |
| + Node* rhs_map = |
| + assembler->LoadObjectField(rhs, HeapObject::kMapOffset); |
| + |
| + // Check if {rhs} is also a HeapNumber. |
| + Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); |
| + assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| + &if_rhsisnumber, &if_rhsisnotnumber); |
| + |
| + assembler->Bind(&if_rhsisnumber); |
| + { |
| + // Convert {lhs} and {rhs} to floating point values. |
| + Node* lhs_value = assembler->LoadHeapNumberValue(lhs); |
| + Node* rhs_value = assembler->LoadHeapNumberValue(rhs); |
| + |
| + // Perform a floating point comparison of {lhs} and {rhs}. |
| + assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, |
| + &if_false); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotnumber); |
| + assembler->Goto(&if_false); |
| + } |
| + } |
| + |
| + assembler->Bind(&if_lhsisnotnumber); |
| + { |
| + // Check if {rhs} is a Smi or a HeapObject. |
| + Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| + assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| + &if_rhsisnotsmi); |
| + |
| + assembler->Bind(&if_rhsissmi); |
| + assembler->Goto(&if_false); |
| + |
| + assembler->Bind(&if_rhsisnotsmi); |
| + { |
| + // Load the instance type of {lhs}. |
| + Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map); |
| + |
| + // Check if {lhs} is a String. |
| + Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); |
| + assembler->Branch(assembler->Int32LessThan( |
| + lhs_instance_type, |
| + assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| + &if_lhsisstring, &if_lhsisnotstring); |
| + |
| + assembler->Bind(&if_lhsisstring); |
| + { |
| + // Load the instance type of {rhs}. |
| + Node* rhs_instance_type = assembler->LoadInstanceType(rhs); |
| + |
| + // Check if {rhs} is also a String. |
| + Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); |
| + assembler->Branch(assembler->Int32LessThan( |
| + rhs_instance_type, assembler->Int32Constant( |
| + FIRST_NONSTRING_TYPE)), |
| + &if_rhsisstring, &if_rhsisnotstring); |
| + |
| + assembler->Bind(&if_rhsisstring); |
| + { |
| + // TODO(bmeurer): Optimize this further once the StringEqual |
| + // functionality is available in TurboFan land. |
| + assembler->TailCallRuntime(Runtime::kStringEqual, context, lhs, |
| + rhs); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotstring); |
| + assembler->Goto(&if_false); |
| + } |
| + |
| + assembler->Bind(&if_lhsisnotstring); |
| + { |
| + // Check if {lhs} is a Simd128Value. |
| + Label if_lhsissimd128value(assembler), |
| + if_lhsisnotsimd128value(assembler); |
| + assembler->Branch(assembler->Word32Equal( |
| + lhs_instance_type, |
| + assembler->Int32Constant(SIMD128_VALUE_TYPE)), |
| + &if_lhsissimd128value, &if_lhsisnotsimd128value); |
| + |
| + assembler->Bind(&if_lhsissimd128value); |
| + { |
| + // TODO(bmeurer): Inline the Simd128Value equality check. |
| + assembler->TailCallRuntime(Runtime::kStrictEqual, context, lhs, |
| + rhs); |
| + } |
| + |
| + assembler->Bind(&if_lhsisnotsimd128value); |
| + assembler->Goto(&if_false); |
| + } |
| + } |
| + } |
| + } |
| + |
| + assembler->Bind(&if_lhsissmi); |
| + { |
| + // We already know that {lhs} and {rhs} are not reference equal, and {lhs} |
| + // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a |
| + // HeapNumber with an equal floating point value. |
| + |
| + // Check if {rhs} is a Smi or a HeapObject. |
| + Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| + assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| + &if_rhsisnotsmi); |
| + |
| + assembler->Bind(&if_rhsissmi); |
| + assembler->Goto(&if_false); |
| + |
| + assembler->Bind(&if_rhsisnotsmi); |
| + { |
| + // Load the map of the {rhs}. |
| + Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); |
| + |
| + // The {rhs} could be a HeapNumber with the same value as {lhs}. |
| + Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); |
| + assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| + &if_rhsisnumber, &if_rhsisnotnumber); |
| + |
| + assembler->Bind(&if_rhsisnumber); |
| + { |
| + // Convert {lhs} and {rhs} to floating point values. |
| + Node* lhs_value = assembler->SmiToFloat64(lhs); |
| + Node* rhs_value = assembler->LoadHeapNumberValue(rhs); |
| + |
| + // Perform a floating point comparison of {lhs} and {rhs}. |
| + assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, |
| + &if_false); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotnumber); |
| + assembler->Goto(&if_false); |
| + } |
| + } |
| + } |
| + |
| + assembler->Bind(&if_true); |
| + assembler->Return(assembler->BooleanConstant(true)); |
| + |
| + assembler->Bind(&if_false); |
| + assembler->Return(assembler->BooleanConstant(false)); |
| +} |
| + |
| void ToBooleanStub::GenerateAssembly( |
| compiler::CodeStubAssembler* assembler) const { |
| typedef compiler::Node Node; |