| Index: src/code-stubs.cc
|
| diff --git a/src/code-stubs.cc b/src/code-stubs.cc
|
| index 60b350cd93b22c702053057d0cbfb0bdf572e844..7a6a6f0ac6180e0b8ce94b7172b0fe73c8a0c983 100644
|
| --- a/src/code-stubs.cc
|
| +++ b/src/code-stubs.cc
|
| @@ -1031,6 +1031,153 @@ void SubtractStub::GenerateAssembly(
|
| }
|
| }
|
|
|
| +void MultiplyStub::GenerateAssembly(
|
| + compiler::CodeStubAssembler* assembler) const {
|
| + using compiler::Node;
|
| + typedef compiler::CodeStubAssembler::Label Label;
|
| + typedef compiler::CodeStubAssembler::Variable Variable;
|
| +
|
| + Node* context = assembler->Parameter(2);
|
| +
|
| + // Shared entry point for floating point multiplication.
|
| + Label do_fmul(assembler);
|
| + Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64),
|
| + var_rhs_float64(assembler, MachineRepresentation::kFloat64);
|
| +
|
| + Node* number_map = assembler->HeapNumberMapConstant();
|
| +
|
| + // We might need to loop one or two times due to ToNumber conversions.
|
| + Variable var_lhs(assembler, MachineRepresentation::kTagged),
|
| + var_rhs(assembler, MachineRepresentation::kTagged);
|
| + Variable* loop_variables[] = {&var_lhs, &var_rhs};
|
| + Label loop(assembler, 2, loop_variables);
|
| + var_lhs.Bind(assembler->Parameter(0));
|
| + var_rhs.Bind(assembler->Parameter(1));
|
| + assembler->Goto(&loop);
|
| + assembler->Bind(&loop);
|
| + {
|
| + Node* lhs = var_lhs.value();
|
| + Node* rhs = var_rhs.value();
|
| +
|
| + Label lhs_is_smi(assembler), lhs_is_not_smi(assembler);
|
| + assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
|
| +
|
| + assembler->Bind(&lhs_is_smi);
|
| + {
|
| + Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
|
| + assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
|
| + &rhs_is_not_smi);
|
| +
|
| + assembler->Bind(&rhs_is_smi);
|
| + {
|
| + // Both {lhs} and {rhs} are Smis. Convert them to double and multiply.
|
| + // TODO(epertoso): use SmiMulWithOverflow once available.
|
| + var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
|
| + var_rhs_float64.Bind(assembler->SmiToFloat64(rhs));
|
| + assembler->Goto(&do_fmul);
|
| + }
|
| +
|
| + assembler->Bind(&rhs_is_not_smi);
|
| + {
|
| + Node* rhs_map = assembler->LoadMap(rhs);
|
| +
|
| + // Check if {rhs} is a HeapNumber.
|
| + Label rhs_is_number(assembler),
|
| + rhs_is_not_number(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->WordEqual(rhs_map, number_map),
|
| + &rhs_is_number, &rhs_is_not_number);
|
| +
|
| + assembler->Bind(&rhs_is_number);
|
| + {
|
| + // Convert {lhs} to a double and multiply it with the value of {rhs}.
|
| + var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
|
| + var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
|
| + assembler->Goto(&do_fmul);
|
| + }
|
| +
|
| + assembler->Bind(&rhs_is_not_number);
|
| + {
|
| + // Multiplication is commutative, swap {lhs} with {rhs} and loop.
|
| + var_lhs.Bind(rhs);
|
| + var_rhs.Bind(lhs);
|
| + assembler->Goto(&loop);
|
| + }
|
| + }
|
| + }
|
| +
|
| + assembler->Bind(&lhs_is_not_smi);
|
| + {
|
| + Node* lhs_map = assembler->LoadMap(lhs);
|
| +
|
| + // Check if {lhs} is a HeapNumber.
|
| + Label lhs_is_number(assembler),
|
| + lhs_is_not_number(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->WordEqual(lhs_map, number_map),
|
| + &lhs_is_number, &lhs_is_not_number);
|
| +
|
| + assembler->Bind(&lhs_is_number);
|
| + {
|
| + // Check if {rhs} is a Smi.
|
| + Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
|
| + assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
|
| + &rhs_is_not_smi);
|
| +
|
| + assembler->Bind(&rhs_is_smi);
|
| + {
|
| + // Convert {rhs} to a double and multiply it with the value of {lhs}.
|
| + var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
|
| + var_rhs_float64.Bind(assembler->SmiToFloat64(rhs));
|
| + assembler->Goto(&do_fmul);
|
| + }
|
| +
|
| + assembler->Bind(&rhs_is_not_smi);
|
| + {
|
| + Node* rhs_map = assembler->LoadMap(rhs);
|
| +
|
| + // Check if {rhs} is a HeapNumber.
|
| + Label rhs_is_number(assembler),
|
| + rhs_is_not_number(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->WordEqual(rhs_map, number_map),
|
| + &rhs_is_number, &rhs_is_not_number);
|
| +
|
| + assembler->Bind(&rhs_is_number);
|
| + {
|
| + // Both {lhs} and {rhs} are HeapNumbers. Load their values and
|
| + // multiply them.
|
| + var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
|
| + var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
|
| + assembler->Goto(&do_fmul);
|
| + }
|
| +
|
| + assembler->Bind(&rhs_is_not_number);
|
| + {
|
| + // Multiplication is commutative, swap {lhs} with {rhs} and loop.
|
| + var_lhs.Bind(rhs);
|
| + var_rhs.Bind(lhs);
|
| + assembler->Goto(&loop);
|
| + }
|
| + }
|
| + }
|
| +
|
| + assembler->Bind(&lhs_is_not_number);
|
| + {
|
| + // Convert {lhs} to a Number and loop.
|
| + Callable callable = CodeFactory::NonNumberToNumber(isolate());
|
| + var_lhs.Bind(assembler->CallStub(callable, context, lhs));
|
| + assembler->Goto(&loop);
|
| + }
|
| + }
|
| + }
|
| +
|
| + assembler->Bind(&do_fmul);
|
| + {
|
| + Node* value =
|
| + assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
|
| + Node* result = assembler->ChangeFloat64ToTagged(value);
|
| + assembler->Return(result);
|
| + }
|
| +}
|
| +
|
| void BitwiseAndStub::GenerateAssembly(
|
| compiler::CodeStubAssembler* assembler) const {
|
| using compiler::Node;
|
|
|