[stubs] Introduce AddStub and SubtractStub.

This adds two new stubs, AddStub and SubtractStub, for the plus and the
minus operators, and hooks them up with TurboFan and Ignition.
Especially the addition case is very heavy and we might want to look
into splitting that up further into specialized stubs (similar to what
we did with ToNumberStub recently).

R=epertoso@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34994}
This commit is contained in:
bmeurer 2016-03-22 08:42:24 -07:00 committed by Commit bot
parent 890f3dd7c5
commit 0bedf6f061
9 changed files with 589 additions and 4 deletions

View File

@ -206,6 +206,18 @@ Callable CodeFactory::RegExpExec(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor()); return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
} }
// static
Callable CodeFactory::Add(Isolate* isolate) {
AddStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::Subtract(Isolate* isolate) {
SubtractStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static // static
Callable CodeFactory::LessThan(Isolate* isolate) { Callable CodeFactory::LessThan(Isolate* isolate) {
LessThanStub stub(isolate); LessThanStub stub(isolate);

View File

@ -79,6 +79,8 @@ class CodeFactory final {
static Callable RegExpConstructResult(Isolate* isolate); static Callable RegExpConstructResult(Isolate* isolate);
static Callable RegExpExec(Isolate* isolate); static Callable RegExpExec(Isolate* isolate);
static Callable Add(Isolate* isolate);
static Callable Subtract(Isolate* isolate);
static Callable LessThan(Isolate* isolate); static Callable LessThan(Isolate* isolate);
static Callable LessThanOrEqual(Isolate* isolate); static Callable LessThanOrEqual(Isolate* isolate);
static Callable GreaterThan(Isolate* isolate); static Callable GreaterThan(Isolate* isolate);

View File

@ -515,6 +515,540 @@ void StringLengthStub::GenerateAssembly(
assembler->Return(result); assembler->Return(result);
} }
void AddStub::GenerateAssembly(compiler::CodeStubAssembler* assembler) const {
typedef compiler::CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef compiler::CodeStubAssembler::Variable Variable;
Node* context = assembler->Parameter(2);
// Shared entry for floating point addition.
Label do_fadd(assembler);
Variable var_fadd_lhs(assembler, MachineRepresentation::kFloat64),
var_fadd_rhs(assembler, MachineRepresentation::kFloat64);
// We might need to loop several times due to ToPrimitive, ToString and/or
// 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);
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);
{
// TODO(bmeurer): Properly fuse Int64AddWithOverflow on x64
Node* pair = assembler->SmiAddWithOverflow(lhs, rhs);
Node* result = assembler->Projection(0, pair);
Node* overflow = assembler->Projection(1, pair);
Label if_overflow(assembler), if_notoverflow(assembler);
assembler->Branch(overflow, &if_overflow, &if_notoverflow);
assembler->Bind(&if_overflow);
{
var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs));
assembler->Goto(&do_fadd);
}
assembler->Bind(&if_notoverflow);
assembler->Return(result);
}
assembler->Bind(&if_rhsisnotsmi);
{
// Load the map of {rhs}.
Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset);
// Check if the {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);
{
var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
assembler->Goto(&do_fadd);
}
assembler->Bind(&if_rhsisnotnumber);
{
// Load the instance type of {rhs}.
Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map);
// Check if the {rhs} is a String.
Label if_rhsisstring(assembler, Label::kDeferred),
if_rhsisnotstring(assembler, Label::kDeferred);
assembler->Branch(assembler->Int32LessThan(
rhs_instance_type,
assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
&if_rhsisstring, &if_rhsisnotstring);
assembler->Bind(&if_rhsisstring);
{
// Convert {lhs}, which is a Smi, to a String and concatenate the
// resulting string with the String {rhs}.
Callable callable = CodeFactory::StringAdd(
assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
assembler->TailCallStub(callable, context, lhs, rhs);
}
assembler->Bind(&if_rhsisnotstring);
{
// Check if {rhs} is a JSReceiver.
Label if_rhsisreceiver(assembler, Label::kDeferred),
if_rhsisnotreceiver(assembler, Label::kDeferred);
assembler->Branch(
assembler->Int32LessThanOrEqual(
assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
rhs_instance_type),
&if_rhsisreceiver, &if_rhsisnotreceiver);
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_rhs.Bind(
assembler->CallRuntime(Runtime::kToPrimitive, context, rhs));
assembler->Goto(&loop);
}
assembler->Bind(&if_rhsisnotreceiver);
{
// Convert {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 and instance type of {lhs}.
Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
// 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);
{
// Convert {rhs} to a String (using the sequence of ToPrimitive with
// no hint followed by ToString) and concatenate the strings.
Callable callable = CodeFactory::StringAdd(
assembler->isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
assembler->TailCallStub(callable, context, lhs, rhs);
}
assembler->Bind(&if_lhsisnotstring);
{
// Check if {rhs} is a Smi.
Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
&if_rhsisnotsmi);
assembler->Bind(&if_rhsissmi);
{
// Check if {lhs} is a Number.
Label if_lhsisnumber(assembler),
if_lhsisnotnumber(assembler, Label::kDeferred);
assembler->Branch(assembler->Word32Equal(
lhs_instance_type,
assembler->Int32Constant(HEAP_NUMBER_TYPE)),
&if_lhsisnumber, &if_lhsisnotnumber);
assembler->Bind(&if_lhsisnumber);
{
// The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them.
var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs));
assembler->Goto(&do_fadd);
}
assembler->Bind(&if_lhsisnotnumber);
{
// The {lhs} is neither a Number nor a String, and the {rhs} is a
// Smi.
Label if_lhsisreceiver(assembler, Label::kDeferred),
if_lhsisnotreceiver(assembler, Label::kDeferred);
assembler->Branch(
assembler->Int32LessThanOrEqual(
assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
lhs_instance_type),
&if_lhsisreceiver, &if_lhsisnotreceiver);
assembler->Bind(&if_lhsisreceiver);
{
// Convert {lhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_lhs.Bind(
assembler->CallRuntime(Runtime::kToPrimitive, context, lhs));
assembler->Goto(&loop);
}
assembler->Bind(&if_lhsisnotreceiver);
{
// Convert {lhs} to a Number first.
Callable callable =
CodeFactory::NonNumberToNumber(assembler->isolate());
var_lhs.Bind(assembler->CallStub(callable, context, lhs));
assembler->Goto(&loop);
}
}
}
assembler->Bind(&if_rhsisnotsmi);
{
// Load the instance type of {rhs}.
Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
// Check if {rhs} is 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);
{
// Convert {lhs} to a String (using the sequence of ToPrimitive with
// no hint followed by ToString) and concatenate the strings.
Callable callable = CodeFactory::StringAdd(
assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
assembler->TailCallStub(callable, context, lhs, rhs);
}
assembler->Bind(&if_rhsisnotstring);
{
// Check if {lhs} is a HeapNumber.
Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
assembler->Branch(assembler->Word32Equal(
lhs_instance_type,
assembler->Int32Constant(HEAP_NUMBER_TYPE)),
&if_lhsisnumber, &if_lhsisnotnumber);
assembler->Bind(&if_lhsisnumber);
{
// Check if {rhs} is also a HeapNumber.
Label if_rhsisnumber(assembler),
if_rhsisnotnumber(assembler, Label::kDeferred);
assembler->Branch(assembler->Word32Equal(
rhs_instance_type,
assembler->Int32Constant(HEAP_NUMBER_TYPE)),
&if_rhsisnumber, &if_rhsisnotnumber);
assembler->Bind(&if_rhsisnumber);
{
// Perform a floating point addition.
var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
assembler->Goto(&do_fadd);
}
assembler->Bind(&if_rhsisnotnumber);
{
// Check if {rhs} is a JSReceiver.
Label if_rhsisreceiver(assembler, Label::kDeferred),
if_rhsisnotreceiver(assembler, Label::kDeferred);
assembler->Branch(
assembler->Int32LessThanOrEqual(
assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
rhs_instance_type),
&if_rhsisreceiver, &if_rhsisnotreceiver);
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here too.
var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, rhs));
assembler->Goto(&loop);
}
assembler->Bind(&if_rhsisnotreceiver);
{
// Convert {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);
{
// Check if {lhs} is a JSReceiver.
Label if_lhsisreceiver(assembler, Label::kDeferred),
if_lhsisnotreceiver(assembler);
assembler->Branch(
assembler->Int32LessThanOrEqual(
assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
lhs_instance_type),
&if_lhsisreceiver, &if_lhsisnotreceiver);
assembler->Bind(&if_lhsisreceiver);
{
// Convert {lhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, lhs));
assembler->Goto(&loop);
}
assembler->Bind(&if_lhsisnotreceiver);
{
// Check if {rhs} is a JSReceiver.
Label if_rhsisreceiver(assembler, Label::kDeferred),
if_rhsisnotreceiver(assembler, Label::kDeferred);
assembler->Branch(
assembler->Int32LessThanOrEqual(
assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
rhs_instance_type),
&if_rhsisreceiver, &if_rhsisnotreceiver);
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here too.
var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, rhs));
assembler->Goto(&loop);
}
assembler->Bind(&if_rhsisnotreceiver);
{
// Convert {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_fadd);
{
Node* lhs_value = var_fadd_lhs.value();
Node* rhs_value = var_fadd_rhs.value();
Node* value = assembler->Float64Add(lhs_value, rhs_value);
// TODO(bmeurer): Introduce a ChangeFloat64ToTagged.
Node* result = assembler->Allocate(HeapNumber::kSize,
compiler::CodeStubAssembler::kNone);
assembler->StoreMapNoWriteBarrier(result,
assembler->HeapNumberMapConstant());
assembler->StoreHeapNumberValue(result, value);
assembler->Return(result);
}
}
void SubtractStub::GenerateAssembly(
compiler::CodeStubAssembler* assembler) const {
typedef compiler::CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef compiler::CodeStubAssembler::Variable Variable;
Node* context = assembler->Parameter(2);
// Shared entry for floating point subtraction.
Label do_fsub(assembler);
Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64),
var_fsub_rhs(assembler, MachineRepresentation::kFloat64);
// We might need to loop several times due to ToPrimitive and/or 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);
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);
{
// Try a fast Smi subtraction first.
Node* pair = assembler->SmiSubWithOverflow(lhs, rhs);
Node* result = assembler->Projection(0, pair);
Node* overflow = assembler->Projection(1, pair);
// Check if the Smi subtraction overflowed.
Label if_overflow(assembler), if_notoverflow(assembler);
assembler->Branch(overflow, &if_overflow, &if_notoverflow);
assembler->Bind(&if_overflow);
{
// The result doesn't fit into Smi range.
var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs));
var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs));
assembler->Goto(&do_fsub);
}
assembler->Bind(&if_notoverflow);
assembler->Return(result);
}
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 a floating point subtraction.
var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs));
var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
assembler->Goto(&do_fsub);
}
assembler->Bind(&if_rhsisnotnumber);
{
// Convert the {rhs} to a Number first.
Callable callable = CodeFactory::NonNumberToNumber(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 a floating point subtraction.
var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs));
assembler->Goto(&do_fsub);
}
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 a floating point subtraction.
var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
assembler->Goto(&do_fsub);
}
assembler->Bind(&if_rhsisnotnumber);
{
// Convert the {rhs} to a Number first.
Callable callable = CodeFactory::NonNumberToNumber(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(isolate());
var_lhs.Bind(assembler->CallStub(callable, context, lhs));
assembler->Goto(&loop);
}
}
}
assembler->Bind(&do_fsub);
{
Node* lhs_value = var_fsub_lhs.value();
Node* rhs_value = var_fsub_rhs.value();
Node* value = assembler->Float64Sub(lhs_value, rhs_value);
// TODO(bmeurer): Introduce a ChangeFloat64ToTagged.
Node* result = assembler->Allocate(HeapNumber::kSize,
compiler::CodeStubAssembler::kNone);
assembler->StoreMapNoWriteBarrier(result,
assembler->HeapNumberMapConstant());
assembler->StoreHeapNumberValue(result, value);
assembler->Return(result);
}
}
namespace { namespace {
enum RelationalComparisonMode { enum RelationalComparisonMode {

View File

@ -111,6 +111,8 @@ namespace internal {
V(AllocateUint8x16) \ V(AllocateUint8x16) \
V(AllocateBool8x16) \ V(AllocateBool8x16) \
V(StringLength) \ V(StringLength) \
V(Add) \
V(Subtract) \
V(LessThan) \ V(LessThan) \
V(LessThanOrEqual) \ V(LessThanOrEqual) \
V(GreaterThan) \ V(GreaterThan) \
@ -667,6 +669,22 @@ class StringLengthStub : public TurboFanCodeStub {
DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub);
}; };
class AddStub final : public TurboFanCodeStub {
public:
explicit AddStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
DEFINE_TURBOFAN_CODE_STUB(Add, TurboFanCodeStub);
};
class SubtractStub final : public TurboFanCodeStub {
public:
explicit SubtractStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
DEFINE_TURBOFAN_CODE_STUB(Subtract, TurboFanCodeStub);
};
class LessThanStub final : public TurboFanCodeStub { class LessThanStub final : public TurboFanCodeStub {
public: public:
explicit LessThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit LessThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}

View File

@ -175,6 +175,16 @@ Node* CodeStubAssembler::SmiToFloat64(Node* value) {
Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); } Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); }
Node* CodeStubAssembler::SmiAddWithOverflow(Node* a, Node* b) {
return IntPtrAddWithOverflow(a, b);
}
Node* CodeStubAssembler::SmiSub(Node* a, Node* b) { return IntPtrSub(a, b); }
Node* CodeStubAssembler::SmiSubWithOverflow(Node* a, Node* b) {
return IntPtrSubWithOverflow(a, b);
}
Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); } Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); }
Node* CodeStubAssembler::SmiLessThan(Node* a, Node* b) { Node* CodeStubAssembler::SmiLessThan(Node* a, Node* b) {

View File

@ -63,8 +63,12 @@ class Schedule;
#define CODE_STUB_ASSEMBLER_BINARY_OP_LIST(V) \ #define CODE_STUB_ASSEMBLER_BINARY_OP_LIST(V) \
CODE_STUB_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \ CODE_STUB_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
V(Float64Add) \
V(Float64Sub) \
V(IntPtrAdd) \ V(IntPtrAdd) \
V(IntPtrAddWithOverflow) \
V(IntPtrSub) \ V(IntPtrSub) \
V(IntPtrSubWithOverflow) \
V(Int32Add) \ V(Int32Add) \
V(Int32Sub) \ V(Int32Sub) \
V(Int32Mul) \ V(Int32Mul) \
@ -263,6 +267,9 @@ class CodeStubAssembler {
// Smi operations. // Smi operations.
Node* SmiAdd(Node* a, Node* b); Node* SmiAdd(Node* a, Node* b);
Node* SmiAddWithOverflow(Node* a, Node* b);
Node* SmiSub(Node* a, Node* b);
Node* SmiSubWithOverflow(Node* a, Node* b);
Node* SmiEqual(Node* a, Node* b); Node* SmiEqual(Node* a, Node* b);
Node* SmiLessThan(Node* a, Node* b); Node* SmiLessThan(Node* a, Node* b);
Node* SmiLessThanOrEqual(Node* a, Node* b); Node* SmiLessThanOrEqual(Node* a, Node* b);

View File

@ -76,8 +76,6 @@ REPLACE_BINARY_OP_IC_CALL(JSBitwiseAnd, Token::BIT_AND)
REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL) REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL)
REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR) REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR)
REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR) REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR)
REPLACE_BINARY_OP_IC_CALL(JSAdd, Token::ADD)
REPLACE_BINARY_OP_IC_CALL(JSSubtract, Token::SUB)
REPLACE_BINARY_OP_IC_CALL(JSMultiply, Token::MUL) REPLACE_BINARY_OP_IC_CALL(JSMultiply, Token::MUL)
REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV) REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV)
REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD) REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
@ -98,6 +96,8 @@ REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
Callable callable = CodeFactory::Name(isolate()); \ Callable callable = CodeFactory::Name(isolate()); \
ReplaceWithStubCall(node, callable, flags); \ ReplaceWithStubCall(node, callable, flags); \
} }
REPLACE_STUB_CALL(Add)
REPLACE_STUB_CALL(Subtract)
REPLACE_STUB_CALL(LessThan) REPLACE_STUB_CALL(LessThan)
REPLACE_STUB_CALL(LessThanOrEqual) REPLACE_STUB_CALL(LessThanOrEqual)
REPLACE_STUB_CALL(GreaterThan) REPLACE_STUB_CALL(GreaterThan)

View File

@ -347,7 +347,9 @@ class RawMachineAssembler {
} }
INTPTR_BINOP(Int, Add); INTPTR_BINOP(Int, Add);
INTPTR_BINOP(Int, AddWithOverflow);
INTPTR_BINOP(Int, Sub); INTPTR_BINOP(Int, Sub);
INTPTR_BINOP(Int, SubWithOverflow);
INTPTR_BINOP(Int, LessThan); INTPTR_BINOP(Int, LessThan);
INTPTR_BINOP(Int, LessThanOrEqual); INTPTR_BINOP(Int, LessThanOrEqual);
INTPTR_BINOP(Word, Equal); INTPTR_BINOP(Word, Equal);

View File

@ -650,7 +650,7 @@ void Interpreter::DoBinaryOp(Runtime::FunctionId function_id,
// //
// Add register <src> to accumulator. // Add register <src> to accumulator.
void Interpreter::DoAdd(InterpreterAssembler* assembler) { void Interpreter::DoAdd(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kAdd, assembler); DoBinaryOp(CodeFactory::Add(isolate_), assembler);
} }
@ -658,7 +658,7 @@ void Interpreter::DoAdd(InterpreterAssembler* assembler) {
// //
// Subtract register <src> from accumulator. // Subtract register <src> from accumulator.
void Interpreter::DoSub(InterpreterAssembler* assembler) { void Interpreter::DoSub(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kSubtract, assembler); DoBinaryOp(CodeFactory::Subtract(isolate_), assembler);
} }