Commit c27c88b4 authored by epertoso's avatar epertoso Committed by Commit bot

[stubs] Introduce ModulusStub.

Adds a ModulusStub for the modulo operator and lets TurboFan and Ignition make use of it.

Review URL: https://codereview.chromium.org/1876793002

Cr-Commit-Position: refs/heads/master@{#35389}
parent e37e6fc7
......@@ -233,6 +233,12 @@ Callable CodeFactory::Divide(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::Modulus(Isolate* isolate) {
ModulusStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::BitwiseAnd(Isolate* isolate) {
BitwiseAndStub stub(isolate);
......
......@@ -86,6 +86,7 @@ class CodeFactory final {
static Callable Subtract(Isolate* isolate);
static Callable Multiply(Isolate* isolate);
static Callable Divide(Isolate* isolate);
static Callable Modulus(Isolate* isolate);
static Callable BitwiseAnd(Isolate* isolate);
static Callable BitwiseOr(Isolate* isolate);
static Callable BitwiseXor(Isolate* isolate);
......
......@@ -1324,8 +1324,8 @@ void DivideStub::GenerateAssembly(
assembler->Bind(&divisor_is_smi);
{
// Convert {divisor} to a double and divide it with the value of
// {dividend}.
// Convert {divisor} to a double and use it for a floating point
// division.
var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
assembler->Goto(&do_fdiv);
......@@ -1344,8 +1344,7 @@ void DivideStub::GenerateAssembly(
assembler->Bind(&divisor_is_number);
{
// Both {dividend} and {divisor} are HeapNumbers. Load their values
// and
// divide them.
// and divide them.
var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
assembler->Goto(&do_fdiv);
......@@ -1394,6 +1393,155 @@ void BitwiseAndStub::GenerateAssembly(
assembler->Return(result);
}
void ModulusStub::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 modulus.
Label do_fmod(assembler);
Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
var_divisor_float64(assembler, MachineRepresentation::kFloat64);
Node* number_map = assembler->HeapNumberMapConstant();
// We might need to loop one or two times due to ToNumber conversions.
Variable var_dividend(assembler, MachineRepresentation::kTagged),
var_divisor(assembler, MachineRepresentation::kTagged);
Variable* loop_variables[] = {&var_dividend, &var_divisor};
Label loop(assembler, 2, loop_variables);
var_dividend.Bind(assembler->Parameter(0));
var_divisor.Bind(assembler->Parameter(1));
assembler->Goto(&loop);
assembler->Bind(&loop);
{
Node* dividend = var_dividend.value();
Node* divisor = var_divisor.value();
Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
&dividend_is_not_smi);
assembler->Bind(&dividend_is_smi);
{
Label dividend_is_not_zero(assembler);
Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
&divisor_is_not_smi);
assembler->Bind(&divisor_is_smi);
{
var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
assembler->Goto(&do_fmod);
}
assembler->Bind(&divisor_is_not_smi);
{
Node* divisor_map = assembler->LoadMap(divisor);
// Check if {divisor} is a HeapNumber.
Label divisor_is_number(assembler),
divisor_is_not_number(assembler, Label::kDeferred);
assembler->Branch(assembler->WordEqual(divisor_map, number_map),
&divisor_is_number, &divisor_is_not_number);
assembler->Bind(&divisor_is_number);
{
// Convert {dividend} to a double and compute its modulus with the
// value of {dividend}.
var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
assembler->Goto(&do_fmod);
}
assembler->Bind(&divisor_is_not_number);
{
// Convert {divisor} to a number and loop.
Callable callable = CodeFactory::NonNumberToNumber(isolate());
var_divisor.Bind(assembler->CallStub(callable, context, divisor));
assembler->Goto(&loop);
}
}
}
assembler->Bind(&dividend_is_not_smi);
{
Node* dividend_map = assembler->LoadMap(dividend);
// Check if {dividend} is a HeapNumber.
Label dividend_is_number(assembler),
dividend_is_not_number(assembler, Label::kDeferred);
assembler->Branch(assembler->WordEqual(dividend_map, number_map),
&dividend_is_number, &dividend_is_not_number);
assembler->Bind(&dividend_is_number);
{
// Check if {divisor} is a Smi.
Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
&divisor_is_not_smi);
assembler->Bind(&divisor_is_smi);
{
// Convert {divisor} to a double and compute {dividend}'s modulus with
// it.
var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
assembler->Goto(&do_fmod);
}
assembler->Bind(&divisor_is_not_smi);
{
Node* divisor_map = assembler->LoadMap(divisor);
// Check if {divisor} is a HeapNumber.
Label divisor_is_number(assembler),
divisor_is_not_number(assembler, Label::kDeferred);
assembler->Branch(assembler->WordEqual(divisor_map, number_map),
&divisor_is_number, &divisor_is_not_number);
assembler->Bind(&divisor_is_number);
{
// Both {dividend} and {divisor} are HeapNumbers. Load their values
// and compute their modulus.
var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
assembler->Goto(&do_fmod);
}
assembler->Bind(&divisor_is_not_number);
{
// Convert {divisor} to a number and loop.
Callable callable = CodeFactory::NonNumberToNumber(isolate());
var_divisor.Bind(assembler->CallStub(callable, context, divisor));
assembler->Goto(&loop);
}
}
}
assembler->Bind(&dividend_is_not_number);
{
// Convert {dividend} to a Number and loop.
Callable callable = CodeFactory::NonNumberToNumber(isolate());
var_dividend.Bind(assembler->CallStub(callable, context, dividend));
assembler->Goto(&loop);
}
}
}
assembler->Bind(&do_fmod);
{
Node* value = assembler->Float64Mod(var_dividend_float64.value(),
var_divisor_float64.value());
Node* result = assembler->ChangeFloat64ToTagged(value);
assembler->Return(result);
}
}
void BitwiseOrStub::GenerateAssembly(
compiler::CodeStubAssembler* assembler) const {
using compiler::Node;
......
......@@ -114,6 +114,7 @@ namespace internal {
V(Subtract) \
V(Multiply) \
V(Divide) \
V(Modulus) \
V(BitwiseAnd) \
V(BitwiseOr) \
V(BitwiseXor) \
......@@ -704,6 +705,14 @@ class DivideStub final : public TurboFanCodeStub {
DEFINE_TURBOFAN_CODE_STUB(Divide, TurboFanCodeStub);
};
class ModulusStub final : public TurboFanCodeStub {
public:
explicit ModulusStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
DEFINE_TURBOFAN_CODE_STUB(Modulus, TurboFanCodeStub);
};
class BitwiseAndStub final : public TurboFanCodeStub {
public:
explicit BitwiseAndStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
......
......@@ -67,6 +67,7 @@ class Schedule;
V(Float64Sub) \
V(Float64Mul) \
V(Float64Div) \
V(Float64Mod) \
V(Float64InsertLowWord32) \
V(Float64InsertHighWord32) \
V(IntPtrAdd) \
......
......@@ -57,7 +57,6 @@ Reduction JSGenericLowering::Reduce(Node* node) {
REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL)
REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR)
REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR)
REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
#undef REPLACE_BINARY_OP_IC_CALL
#define REPLACE_RUNTIME_CALL(op, fun) \
......@@ -79,6 +78,7 @@ REPLACE_STUB_CALL(Add)
REPLACE_STUB_CALL(Subtract)
REPLACE_STUB_CALL(Multiply)
REPLACE_STUB_CALL(Divide)
REPLACE_STUB_CALL(Modulus)
REPLACE_STUB_CALL(BitwiseAnd)
REPLACE_STUB_CALL(BitwiseOr)
REPLACE_STUB_CALL(BitwiseXor)
......
......@@ -734,7 +734,7 @@ void Interpreter::DoDiv(InterpreterAssembler* assembler) {
//
// Modulo register <src> by accumulator.
void Interpreter::DoMod(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kModulus, assembler);
DoBinaryOp(CodeFactory::Modulus(isolate_), assembler);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment