Chromium Code Reviews| Index: src/code-stubs.cc |
| diff --git a/src/code-stubs.cc b/src/code-stubs.cc |
| index 2646787e3b8551ca008640fa9b686b421846168f..67438e5ac28932b0ade564aa2a78959dee0a4a19 100644 |
| --- a/src/code-stubs.cc |
| +++ b/src/code-stubs.cc |
| @@ -1035,6 +1035,182 @@ void SubtractStub::GenerateAssembly( |
| namespace { |
| +void GenerateBitwiseOperation( |
| + compiler::CodeStubAssembler* assembler, |
| + compiler::Node* (compiler::CodeStubAssembler::*bitop)(compiler::Node*, |
| + compiler::Node*)) { |
| + typedef compiler::CodeStubAssembler::Label Label; |
| + typedef compiler::Node Node; |
| + typedef compiler::CodeStubAssembler::Variable Variable; |
| + |
| + Node* context = assembler->Parameter(2); |
| + |
| + // Shared entry for word32 bitwise operation. |
| + Label do_bitop(assembler); |
| + Variable var_bitop_lhs(assembler, MachineRepresentation::kWord32), |
| + var_bitop_rhs(assembler, MachineRepresentation::kWord32); |
| + |
| + // We might need to loop several times due to ToNumber conversions. |
| + Variable var_lhs(assembler, MachineRepresentation::kTagged), |
| + var_rhs(assembler, MachineRepresentation::kTagged); |
| + Variable* loop_vars[2] = {&var_lhs, &var_rhs}; |
| + Label loop(assembler, 2, loop_vars); |
| + var_lhs.Bind(assembler->Parameter(0)); |
| + var_rhs.Bind(assembler->Parameter(1)); |
| + assembler->Goto(&loop); |
|
epertoso
2016/03/23 13:15:39
Wouldn't an 'ObjectToInt32' or similar-named metho
Benedikt Meurer
2016/03/23 13:23:03
Well, you'd still need to distinguish HeapNumber a
epertoso
2016/03/23 13:41:39
As discussed offline, let's leave it like this for
|
| + assembler->Bind(&loop); |
| + { |
| + // Load the current {lhs} and {rhs} values. |
| + Node* lhs = var_lhs.value(); |
| + Node* rhs = var_rhs.value(); |
| + |
| + // Check if the {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_lhsissmi); |
| + { |
| + // Check if the {rhs} is also a Smi. |
| + Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| + assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| + &if_rhsisnotsmi); |
| + |
| + assembler->Bind(&if_rhsissmi); |
| + { |
| + // Perform the word32 bitwise operation. |
| + var_bitop_lhs.Bind(assembler->SmiToInt32(lhs)); |
| + var_bitop_rhs.Bind(assembler->SmiToInt32(rhs)); |
| + assembler->Goto(&do_bitop); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotsmi); |
| + { |
| + // Load the map of the {rhs}. |
| + Node* rhs_map = assembler->LoadMap(rhs); |
| + |
| + // Check if {rhs} is a HeapNumber. |
| + Label if_rhsisnumber(assembler), |
| + if_rhsisnotnumber(assembler, Label::kDeferred); |
| + Node* number_map = assembler->HeapNumberMapConstant(); |
| + assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| + &if_rhsisnumber, &if_rhsisnotnumber); |
| + |
| + assembler->Bind(&if_rhsisnumber); |
| + { |
| + // Perform the word32 bitwise operation. |
| + var_bitop_lhs.Bind(assembler->SmiToInt32(lhs)); |
| + var_bitop_rhs.Bind(assembler->TruncateHeapNumberValueToInt32(rhs)); |
| + assembler->Goto(&do_bitop); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotnumber); |
| + { |
| + // Convert the {rhs} to a Number first. |
| + Callable callable = |
| + CodeFactory::NonNumberToNumber(assembler->isolate()); |
| + var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| + assembler->Goto(&loop); |
| + } |
| + } |
| + } |
| + |
| + assembler->Bind(&if_lhsisnotsmi); |
| + { |
| + // Load the map of the {lhs}. |
| + Node* lhs_map = assembler->LoadMap(lhs); |
| + |
| + // Check if the {lhs} is a HeapNumber. |
| + Label if_lhsisnumber(assembler), |
| + if_lhsisnotnumber(assembler, Label::kDeferred); |
| + Node* number_map = assembler->HeapNumberMapConstant(); |
| + assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
| + &if_lhsisnumber, &if_lhsisnotnumber); |
| + |
| + assembler->Bind(&if_lhsisnumber); |
| + { |
| + // Check if the {rhs} is a Smi. |
| + Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| + assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| + &if_rhsisnotsmi); |
| + |
| + assembler->Bind(&if_rhsissmi); |
| + { |
| + // Perform the word32 bitwise operation. |
| + var_bitop_lhs.Bind(assembler->TruncateHeapNumberValueToInt32(lhs)); |
| + var_bitop_rhs.Bind(assembler->SmiToInt32(rhs)); |
| + assembler->Goto(&do_bitop); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotsmi); |
| + { |
| + // Load the map of the {rhs}. |
| + Node* rhs_map = assembler->LoadMap(rhs); |
| + |
| + // Check if the {rhs} is a HeapNumber. |
| + Label if_rhsisnumber(assembler), |
| + if_rhsisnotnumber(assembler, Label::kDeferred); |
| + assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| + &if_rhsisnumber, &if_rhsisnotnumber); |
| + |
| + assembler->Bind(&if_rhsisnumber); |
| + { |
| + // Perform the word32 bitwise operation. |
| + var_bitop_lhs.Bind(assembler->TruncateHeapNumberValueToInt32(lhs)); |
| + var_bitop_rhs.Bind(assembler->TruncateHeapNumberValueToInt32(rhs)); |
| + assembler->Goto(&do_bitop); |
| + } |
| + |
| + assembler->Bind(&if_rhsisnotnumber); |
| + { |
| + // Convert the {rhs} to a Number first. |
| + Callable callable = |
| + CodeFactory::NonNumberToNumber(assembler->isolate()); |
| + var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| + assembler->Goto(&loop); |
| + } |
| + } |
| + } |
| + |
| + assembler->Bind(&if_lhsisnotnumber); |
| + { |
| + // Convert the {lhs} to a Number first. |
| + Callable callable = |
| + CodeFactory::NonNumberToNumber(assembler->isolate()); |
| + var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| + assembler->Goto(&loop); |
| + } |
| + } |
| + } |
| + |
| + assembler->Bind(&do_bitop); |
| + { |
| + Node* lhs_value = var_bitop_lhs.value(); |
| + Node* rhs_value = var_bitop_rhs.value(); |
| + Node* value = (assembler->*bitop)(lhs_value, rhs_value); |
| + Node* result = assembler->ChangeInt32ToTagged(value); |
| + assembler->Return(result); |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +void BitwiseAndStub::GenerateAssembly( |
| + compiler::CodeStubAssembler* assembler) const { |
| + GenerateBitwiseOperation(assembler, &compiler::CodeStubAssembler::Word32And); |
| +} |
| + |
| +void BitwiseOrStub::GenerateAssembly( |
| + compiler::CodeStubAssembler* assembler) const { |
| + GenerateBitwiseOperation(assembler, &compiler::CodeStubAssembler::Word32Or); |
| +} |
| + |
| +void BitwiseXorStub::GenerateAssembly( |
| + compiler::CodeStubAssembler* assembler) const { |
| + GenerateBitwiseOperation(assembler, &compiler::CodeStubAssembler::Word32Xor); |
| +} |
| + |
| +namespace { |
| + |
| enum RelationalComparisonMode { |
| kLessThan, |
| kLessThanOrEqual, |