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

[stubs] Introduce DivideStub.

Adds a DivideStub for the division operator and hooks it up with TurboFan and Ignition.

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

Cr-Commit-Position: refs/heads/master@{#35364}
parent 8aa6f871
......@@ -227,6 +227,12 @@ Callable CodeFactory::Multiply(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::Divide(Isolate* isolate) {
DivideStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::BitwiseAnd(Isolate* isolate) {
BitwiseAndStub stub(isolate);
......
......@@ -85,6 +85,7 @@ class CodeFactory final {
static Callable Add(Isolate* isolate);
static Callable Subtract(Isolate* isolate);
static Callable Multiply(Isolate* isolate);
static Callable Divide(Isolate* isolate);
static Callable BitwiseAnd(Isolate* isolate);
static Callable BitwiseOr(Isolate* isolate);
static Callable BitwiseXor(Isolate* isolate);
......
......@@ -1169,6 +1169,217 @@ void MultiplyStub::GenerateAssembly(
}
}
void DivideStub::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 division.
Label do_fdiv(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 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);
{
Label bailout(assembler);
// Do floating point division if {divisor} is zero.
assembler->GotoIf(
assembler->WordEqual(divisor, assembler->IntPtrConstant(0)),
&bailout);
// Do floating point division {dividend} is zero and {divisor} is
// negative.
Label dividend_is_zero(assembler), dividend_is_not_zero(assembler);
assembler->Branch(
assembler->WordEqual(dividend, assembler->IntPtrConstant(0)),
&dividend_is_zero, &dividend_is_not_zero);
assembler->Bind(&dividend_is_zero);
{
assembler->GotoIf(
assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)),
&bailout);
assembler->Goto(&dividend_is_not_zero);
}
assembler->Bind(&dividend_is_not_zero);
Node* untagged_divisor = assembler->SmiUntag(divisor);
Node* untagged_dividend = assembler->SmiUntag(dividend);
// Do floating point division if {dividend} is kMinInt (or kMinInt - 1
// if the Smi size is 31) and {divisor} is -1.
Label divisor_is_minus_one(assembler),
divisor_is_not_minus_one(assembler);
assembler->Branch(assembler->Word32Equal(untagged_divisor,
assembler->Int32Constant(-1)),
&divisor_is_minus_one, &divisor_is_not_minus_one);
assembler->Bind(&divisor_is_minus_one);
{
assembler->GotoIf(
assembler->Word32Equal(
untagged_dividend,
assembler->Int32Constant(
kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
&bailout);
assembler->Goto(&divisor_is_not_minus_one);
}
assembler->Bind(&divisor_is_not_minus_one);
// TODO(epertoso): consider adding a machine instruction that returns
// both the result and the remainder.
Node* untagged_result =
assembler->Int32Div(untagged_dividend, untagged_divisor);
Node* truncated =
assembler->IntPtrMul(untagged_result, untagged_divisor);
// Do floating point division if the remainder is not 0.
assembler->GotoIf(
assembler->Word32NotEqual(untagged_dividend, truncated), &bailout);
assembler->Return(assembler->SmiTag(untagged_result));
// Bailout: convert {dividend} and {divisor} to double and do double
// division.
assembler->Bind(&bailout);
{
var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
assembler->Goto(&do_fdiv);
}
}
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 divide it with the value of
// {divisor}.
var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
assembler->Goto(&do_fdiv);
}
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 divide it with the value of
// {dividend}.
var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
assembler->Goto(&do_fdiv);
}
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
// divide them.
var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
assembler->Goto(&do_fdiv);
}
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_fdiv);
{
Node* value = assembler->Float64Div(var_dividend_float64.value(),
var_divisor_float64.value());
Node* result = assembler->ChangeFloat64ToTagged(value);
assembler->Return(result);
}
}
void BitwiseAndStub::GenerateAssembly(
compiler::CodeStubAssembler* assembler) const {
using compiler::Node;
......
......@@ -113,6 +113,7 @@ namespace internal {
V(Add) \
V(Subtract) \
V(Multiply) \
V(Divide) \
V(BitwiseAnd) \
V(BitwiseOr) \
V(BitwiseXor) \
......@@ -695,6 +696,14 @@ class MultiplyStub final : public TurboFanCodeStub {
DEFINE_TURBOFAN_CODE_STUB(Multiply, TurboFanCodeStub);
};
class DivideStub final : public TurboFanCodeStub {
public:
explicit DivideStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
DEFINE_TURBOFAN_CODE_STUB(Divide, TurboFanCodeStub);
};
class BitwiseAndStub final : public TurboFanCodeStub {
public:
explicit BitwiseAndStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
......
......@@ -66,16 +66,19 @@ class Schedule;
V(Float64Add) \
V(Float64Sub) \
V(Float64Mul) \
V(Float64Div) \
V(Float64InsertLowWord32) \
V(Float64InsertHighWord32) \
V(IntPtrAdd) \
V(IntPtrAddWithOverflow) \
V(IntPtrSub) \
V(IntPtrSubWithOverflow) \
V(IntPtrMul) \
V(Int32Add) \
V(Int32AddWithOverflow) \
V(Int32Sub) \
V(Int32Mul) \
V(Int32Div) \
V(WordOr) \
V(WordAnd) \
V(WordXor) \
......
......@@ -73,7 +73,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(JSDivide, Token::DIV)
REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
#undef REPLACE_BINARY_OP_IC_CALL
......@@ -95,6 +94,7 @@ REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
REPLACE_STUB_CALL(Add)
REPLACE_STUB_CALL(Subtract)
REPLACE_STUB_CALL(Multiply)
REPLACE_STUB_CALL(Divide)
REPLACE_STUB_CALL(BitwiseAnd)
REPLACE_STUB_CALL(BitwiseOr)
REPLACE_STUB_CALL(BitwiseXor)
......
......@@ -353,6 +353,8 @@ class RawMachineAssembler {
INTPTR_BINOP(Int, AddWithOverflow);
INTPTR_BINOP(Int, Sub);
INTPTR_BINOP(Int, SubWithOverflow);
INTPTR_BINOP(Int, Mul);
INTPTR_BINOP(Int, Div);
INTPTR_BINOP(Int, LessThan);
INTPTR_BINOP(Int, LessThanOrEqual);
INTPTR_BINOP(Word, Equal);
......
......@@ -668,7 +668,7 @@ void Interpreter::DoMul(InterpreterAssembler* assembler) {
//
// Divide register <src> by accumulator.
void Interpreter::DoDiv(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kDivide, assembler);
DoBinaryOp(CodeFactory::Divide(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