Commit 18d05c87 authored by Mythri's avatar Mythri Committed by Commit Bot

[Interpreter] Refactor arithmetic bytecode handlers.

The Smi versions of arithmetic bytecodes (AddSmi, SubSmi, MulSmi,
DivSmi, ModSmi) have a fast path for Smi case and call to a builtin
on the slow path. However, this builtin is only used by these bytecode
handlers. This cl removes the builtins and inlines them into
bytecode handlers. This will also save few checks in the slow-path.

Subtract, multiply, divide and modulus also share the same checks to 
collect type feedback on several cases. This cl also refactors them
to share the same code.

Also removed a couple of TODOs that are no longer relevant.

Bug: v8:4280, v8:6474
Change-Id: Id23bd61c2074564a1beacb0632165f52370ff226
Reviewed-on: https://chromium-review.googlesource.com/530845
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45982}
parent c2c4de29
......@@ -696,11 +696,6 @@ namespace internal {
TFC(GreaterThanOrEqual, Compare, 1) \
TFC(Equal, Compare, 1) \
TFC(StrictEqual, Compare, 1) \
TFC(AddWithFeedback, BinaryOpWithVector, 1) \
TFC(SubtractWithFeedback, BinaryOpWithVector, 1) \
TFC(MultiplyWithFeedback, BinaryOpWithVector, 1) \
TFC(DivideWithFeedback, BinaryOpWithVector, 1) \
TFC(ModulusWithFeedback, BinaryOpWithVector, 1) \
\
/* Object */ \
CPP(ObjectAssign) \
......
......@@ -838,65 +838,5 @@ TF_BUILTIN(StrictEqual, CodeStubAssembler) {
Return(StrictEqual(lhs, rhs));
}
TF_BUILTIN(AddWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* function = Parameter(Descriptor::kFunction);
Return(Generate_AddWithFeedback(context, left, right,
ChangeUint32ToWord(slot), vector, function));
}
TF_BUILTIN(SubtractWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* function = Parameter(Descriptor::kFunction);
Return(Generate_SubtractWithFeedback(
context, left, right, ChangeUint32ToWord(slot), vector, function));
}
TF_BUILTIN(MultiplyWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* function = Parameter(Descriptor::kFunction);
Return(Generate_MultiplyWithFeedback(
context, left, right, ChangeUint32ToWord(slot), vector, function));
}
TF_BUILTIN(DivideWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* function = Parameter(Descriptor::kFunction);
Return(Generate_DivideWithFeedback(
context, left, right, ChangeUint32ToWord(slot), vector, function));
}
TF_BUILTIN(ModulusWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* function = Parameter(Descriptor::kFunction);
Return(Generate_ModulusWithFeedback(
context, left, right, ChangeUint32ToWord(slot), vector, function));
}
} // namespace internal
} // namespace v8
......@@ -14,7 +14,8 @@ using compiler::Node;
Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
Node* rhs, Node* slot_id,
Node* feedback_vector,
Node* function) {
Node* function,
bool rhs_is_smi) {
// Shared entry for floating point addition.
Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred),
check_rhsisoddball(this, Label::kDeferred),
......@@ -26,24 +27,51 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
VARIABLE(var_result, MachineRepresentation::kTagged);
// Check if the {lhs} is a Smi or a HeapObject.
Label if_lhsissmi(this), if_lhsisnotsmi(this);
Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
Label if_lhsissmi(this);
// If rhs is known to be an Smi we want to fast path Smi operation. This is
// for AddSmi operation. For the normal Add operation, we want to fast path
// both Smi and Number operations, so this path should not be marked as
// Deferred.
Label if_lhsisnotsmi(this,
rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
BIND(&if_lhsissmi);
{
// Check if the {rhs} is also a Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
Comment("lhs is Smi");
if (!rhs_is_smi) {
// Check if the {rhs} is also a Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
BIND(&if_rhsisnotsmi);
{
// Check if the {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
var_fadd_lhs.Bind(SmiToFloat64(lhs));
var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fadd);
}
BIND(&if_rhsissmi);
}
BIND(&if_rhsissmi);
{
Comment("perform smi operation");
// Try fast Smi addition first.
Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(lhs),
BitcastTaggedToWord(rhs));
Node* overflow = Projection(1, pair);
// Check if the Smi additon overflowed.
Label if_overflow(this), if_notoverflow(this);
// If rhs is known to be an Smi we want to fast path Smi operation. This
// is for AddSmi operation. For the normal Add operation, we want to fast
// path both Smi and Number operations, so this path should not be marked
// as Deferred.
Label if_overflow(this,
rhs_is_smi ? Label::kDeferred : Label::kNonDeferred),
if_notoverflow(this);
Branch(overflow, &if_overflow, &if_notoverflow);
BIND(&if_overflow);
......@@ -61,16 +89,6 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
Goto(&end);
}
}
BIND(&if_rhsisnotsmi);
{
// Check if the {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
var_fadd_lhs.Bind(SmiToFloat64(lhs));
var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fadd);
}
}
BIND(&if_lhsisnotsmi);
......@@ -78,24 +96,26 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
// Check if {lhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
// Check if the {rhs} is Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
if (!rhs_is_smi) {
// Check if the {rhs} is Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
BIND(&if_rhsissmi);
{
var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
var_fadd_rhs.Bind(SmiToFloat64(rhs));
Goto(&do_fadd);
}
BIND(&if_rhsisnotsmi);
{
// Check if the {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
BIND(&if_rhsisnotsmi);
{
// Check if the {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fadd);
}
BIND(&if_rhsissmi);
}
{
var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
var_fadd_rhs.Bind(SmiToFloat64(rhs));
Goto(&do_fadd);
}
}
......@@ -121,6 +141,7 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
BIND(&if_lhsisoddball);
{
GotoIf(TaggedIsSmi(rhs), &call_with_oddball_feedback);
// Check if {rhs} is a HeapNumber.
Branch(IsHeapNumber(rhs), &call_with_oddball_feedback,
&check_rhsisoddball);
......@@ -186,104 +207,96 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
return var_result.value();
}
Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
Node* rhs, Node* slot_id,
Node* feedback_vector,
Node* function) {
// Shared entry for floating point subtraction.
Label do_fsub(this), end(this), call_subtract_stub(this),
if_lhsisnotnumber(this), check_rhsisoddball(this),
call_with_any_feedback(this);
VARIABLE(var_fsub_lhs, MachineRepresentation::kFloat64);
VARIABLE(var_fsub_rhs, MachineRepresentation::kFloat64);
Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
Node* context, Node* lhs, Node* rhs, Node* slot_id, Node* feedback_vector,
Node* function, const SmiOperation& smiOperation,
const FloatOperation& floatOperation, Token::Value opcode,
bool rhs_is_smi) {
Label do_float_operation(this), end(this), call_stub(this),
check_rhsisoddball(this, Label::kDeferred), call_with_any_feedback(this),
if_lhsisnotnumber(this, Label::kDeferred);
VARIABLE(var_float_lhs, MachineRepresentation::kFloat64);
VARIABLE(var_float_rhs, MachineRepresentation::kFloat64);
VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
VARIABLE(var_result, MachineRepresentation::kTagged);
// Check if the {lhs} is a Smi or a HeapObject.
Label if_lhsissmi(this), if_lhsisnotsmi(this);
Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
Label if_lhsissmi(this);
// If rhs is known to be an Smi (in the SubSmi, MulSmi, DivSmi, ModSmi
// bytecode handlers) we want to fast path Smi operation. For the normal
// operation, we want to fast path both Smi and Number operations, so this
// path should not be marked as Deferred.
Label if_lhsisnotsmi(this,
rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
// Check if the {lhs} is a Smi or a HeapObject.
BIND(&if_lhsissmi);
{
// Check if the {rhs} is also a Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
BIND(&if_rhsissmi);
{
// Try a fast Smi subtraction first.
Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(lhs),
BitcastTaggedToWord(rhs));
Node* overflow = Projection(1, pair);
// Check if the Smi subtraction overflowed.
Label if_overflow(this), if_notoverflow(this);
Branch(overflow, &if_overflow, &if_notoverflow);
BIND(&if_overflow);
Comment("lhs is Smi");
if (!rhs_is_smi) {
// Check if the {rhs} is also a Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
BIND(&if_rhsisnotsmi);
{
// lhs, rhs - smi and result - number. combined - number.
// The result doesn't fit into Smi range.
var_fsub_lhs.Bind(SmiToFloat64(lhs));
var_fsub_rhs.Bind(SmiToFloat64(rhs));
Goto(&do_fsub);
// Check if {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
// Perform a floating point operation.
var_float_lhs.Bind(SmiToFloat64(lhs));
var_float_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_float_operation);
}
BIND(&if_notoverflow);
// lhs, rhs, result smi. combined - smi.
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kSignedSmall));
var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
Goto(&end);
BIND(&if_rhsissmi);
}
BIND(&if_rhsisnotsmi);
{
// Check if {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
// Perform a floating point subtraction.
var_fsub_lhs.Bind(SmiToFloat64(lhs));
var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fsub);
Comment("perform smi operation");
var_result.Bind(smiOperation(lhs, rhs, &var_type_feedback));
Goto(&end);
}
}
BIND(&if_lhsisnotsmi);
{
Comment("lhs is not Smi");
// Check if the {lhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
// Check if the {rhs} is a Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
if (!rhs_is_smi) {
// Check if the {rhs} is a Smi.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
BIND(&if_rhsissmi);
{
// Perform a floating point subtraction.
var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
var_fsub_rhs.Bind(SmiToFloat64(rhs));
Goto(&do_fsub);
BIND(&if_rhsisnotsmi);
{
// Check if the {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
// Perform a floating point operation.
var_float_lhs.Bind(LoadHeapNumberValue(lhs));
var_float_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_float_operation);
}
BIND(&if_rhsissmi);
}
BIND(&if_rhsisnotsmi);
{
// Check if the {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
// Perform a floating point subtraction.
var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fsub);
var_float_lhs.Bind(LoadHeapNumberValue(lhs));
var_float_rhs.Bind(SmiToFloat64(rhs));
Goto(&do_float_operation);
}
}
BIND(&do_fsub);
BIND(&do_float_operation);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
Node* lhs_value = var_fsub_lhs.value();
Node* rhs_value = var_fsub_rhs.value();
Node* value = Float64Sub(lhs_value, rhs_value);
Node* lhs_value = var_float_lhs.value();
Node* rhs_value = var_float_rhs.value();
Node* value = floatOperation(lhs_value, rhs_value);
var_result.Bind(AllocateHeapNumberWithValue(value));
Goto(&end);
}
......@@ -304,7 +317,7 @@ Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
{
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
Goto(&call_subtract_stub);
Goto(&call_stub);
}
BIND(&if_rhsisnotsmi);
......@@ -314,7 +327,7 @@ Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
Goto(&call_subtract_stub);
Goto(&call_stub);
}
}
......@@ -329,18 +342,35 @@ Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
Goto(&call_subtract_stub);
Goto(&call_stub);
}
BIND(&call_with_any_feedback);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
Goto(&call_subtract_stub);
}
BIND(&call_subtract_stub);
{
var_result.Bind(CallBuiltin(Builtins::kSubtract, context, lhs, rhs));
Goto(&call_stub);
}
BIND(&call_stub);
{
Node* result;
switch (opcode) {
case Token::SUB:
result = CallBuiltin(Builtins::kSubtract, context, lhs, rhs);
break;
case Token::MUL:
result = CallBuiltin(Builtins::kMultiply, context, lhs, rhs);
break;
case Token::DIV:
result = CallBuiltin(Builtins::kDivide, context, lhs, rhs);
break;
case Token::MOD:
result = CallBuiltin(Builtins::kModulus, context, lhs, rhs);
break;
default:
UNREACHABLE();
}
var_result.Bind(result);
Goto(&end);
}
......@@ -349,418 +379,123 @@ Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
return var_result.value();
}
Node* BinaryOpAssembler::Generate_MultiplyWithFeedback(Node* context, Node* lhs,
Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
Node* rhs, Node* slot_id,
Node* feedback_vector,
Node* function) {
// Shared entry point for floating point multiplication.
Label do_fmul(this), if_lhsisnotnumber(this, Label::kDeferred),
check_rhsisoddball(this, Label::kDeferred),
call_with_oddball_feedback(this), call_with_any_feedback(this),
call_multiply_stub(this), end(this);
VARIABLE(var_lhs_float64, MachineRepresentation::kFloat64);
VARIABLE(var_rhs_float64, MachineRepresentation::kFloat64);
VARIABLE(var_result, MachineRepresentation::kTagged);
VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
Label lhs_is_smi(this), lhs_is_not_smi(this);
Branch(TaggedIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
BIND(&lhs_is_smi);
{
Label rhs_is_smi(this), rhs_is_not_smi(this);
Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
BIND(&rhs_is_smi);
Node* function,
bool rhs_is_smi) {
auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
VARIABLE(var_result, MachineRepresentation::kTagged);
// Try a fast Smi subtraction first.
Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(lhs),
BitcastTaggedToWord(rhs));
Node* overflow = Projection(1, pair);
// Check if the Smi subtraction overflowed.
Label if_notoverflow(this), end(this);
// If rhs is known to be an Smi (for SubSmi) we want to fast path Smi
// operation. For the normal Sub operation, we want to fast path both
// Smi and Number operations, so this path should not be marked as Deferred.
Label if_overflow(this,
rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
Branch(overflow, &if_overflow, &if_notoverflow);
BIND(&if_notoverflow);
{
// Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
// in case of overflow.
var_result.Bind(SmiMul(lhs, rhs));
var_type_feedback.Bind(
SelectSmiConstant(TaggedIsSmi(var_result.value()),
BinaryOperationFeedback::kSignedSmall,
BinaryOperationFeedback::kNumber));
var_type_feedback->Bind(
SmiConstant(BinaryOperationFeedback::kSignedSmall));
var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
Goto(&end);
}
BIND(&rhs_is_not_smi);
{
// Check if {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
// Convert {lhs} to a double and multiply it with the value of {rhs}.
var_lhs_float64.Bind(SmiToFloat64(lhs));
var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fmul);
}
}
BIND(&lhs_is_not_smi);
{
// Check if {lhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
// Check if {rhs} is a Smi.
Label rhs_is_smi(this), rhs_is_not_smi(this);
Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
BIND(&rhs_is_smi);
{
// Convert {rhs} to a double and multiply it with the value of {lhs}.
var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
var_rhs_float64.Bind(SmiToFloat64(rhs));
Goto(&do_fmul);
}
BIND(&rhs_is_not_smi);
BIND(&if_overflow);
{
// Check if {rhs} is a HeapNumber.
GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
// Both {lhs} and {rhs} are HeapNumbers. Load their values and
// multiply them.
var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fmul);
var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber));
Node* value = Float64Sub(SmiToFloat64(lhs), SmiToFloat64(rhs));
var_result.Bind(AllocateHeapNumberWithValue(value));
Goto(&end);
}
}
BIND(&do_fmul);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
Node* value = Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
Node* result = AllocateHeapNumberWithValue(value);
var_result.Bind(result);
Goto(&end);
}
BIND(&if_lhsisnotnumber);
{
// No checks on rhs are done yet. We just know lhs is not a number or Smi.
// Check if lhs is an oddball.
Node* lhs_instance_type = LoadInstanceType(lhs);
Node* lhs_is_oddball =
Word32Equal(lhs_instance_type, Int32Constant(ODDBALL_TYPE));
GotoIfNot(lhs_is_oddball, &call_with_any_feedback);
GotoIf(TaggedIsSmi(rhs), &call_with_oddball_feedback);
// Check if {rhs} is a HeapNumber.
Branch(IsHeapNumber(rhs), &call_with_oddball_feedback, &check_rhsisoddball);
}
BIND(&check_rhsisoddball);
{
// Check if rhs is an oddball. At this point we know lhs is either a
// Smi or number or oddball and rhs is not a number or Smi.
Node* rhs_instance_type = LoadInstanceType(rhs);
Node* rhs_is_oddball =
Word32Equal(rhs_instance_type, Int32Constant(ODDBALL_TYPE));
Branch(rhs_is_oddball, &call_with_oddball_feedback,
&call_with_any_feedback);
}
BIND(&call_with_oddball_feedback);
{
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
Goto(&call_multiply_stub);
}
BIND(&call_with_any_feedback);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
Goto(&call_multiply_stub);
}
BIND(&call_multiply_stub);
{
var_result.Bind(CallBuiltin(Builtins::kMultiply, context, lhs, rhs));
Goto(&end);
}
BIND(&end);
return var_result.value();
};
auto floatFunction = [=](Node* lhs, Node* rhs) {
return Float64Sub(lhs, rhs);
};
return Generate_BinaryOperationWithFeedback(
context, lhs, rhs, slot_id, feedback_vector, function, smiFunction,
floatFunction, Token::SUB, rhs_is_smi);
}
BIND(&end);
UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id, function);
return var_result.value();
Node* BinaryOpAssembler::Generate_MultiplyWithFeedback(Node* context, Node* lhs,
Node* rhs, Node* slot_id,
Node* feedback_vector,
Node* function,
bool rhs_is_smi) {
auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
Node* result = SmiMul(lhs, rhs);
var_type_feedback->Bind(SelectSmiConstant(
TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
BinaryOperationFeedback::kNumber));
return result;
};
auto floatFunction = [=](Node* lhs, Node* rhs) {
return Float64Mul(lhs, rhs);
};
return Generate_BinaryOperationWithFeedback(
context, lhs, rhs, slot_id, feedback_vector, function, smiFunction,
floatFunction, Token::MUL, rhs_is_smi);
}
Node* BinaryOpAssembler::Generate_DivideWithFeedback(
Node* context, Node* dividend, Node* divisor, Node* slot_id,
Node* feedback_vector, Node* function) {
// Shared entry point for floating point division.
Label do_fdiv(this), dividend_is_not_number(this, Label::kDeferred),
check_divisor_for_oddball(this, Label::kDeferred),
call_with_oddball_feedback(this), call_with_any_feedback(this),
call_divide_stub(this), end(this);
VARIABLE(var_dividend_float64, MachineRepresentation::kFloat64);
VARIABLE(var_divisor_float64, MachineRepresentation::kFloat64);
VARIABLE(var_result, MachineRepresentation::kTagged);
VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
Label dividend_is_smi(this), dividend_is_not_smi(this);
Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
BIND(&dividend_is_smi);
{
Label divisor_is_smi(this), divisor_is_not_smi(this);
Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
Node* feedback_vector, Node* function, bool rhs_is_smi) {
auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
VARIABLE(var_result, MachineRepresentation::kTagged);
// If rhs is known to be an Smi (for DivSmi) we want to fast path Smi
// operation. For the normal Div operation, we want to fast path both
// Smi and Number operations, so this path should not be marked as Deferred.
Label bailout(this, rhs_is_smi ? Label::kDeferred : Label::kNonDeferred),
end(this);
var_result.Bind(TrySmiDiv(lhs, rhs, &bailout));
var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
Goto(&end);
BIND(&divisor_is_smi);
BIND(&bailout);
{
Label bailout(this);
// Try to perform Smi division if possible.
var_result.Bind(TrySmiDiv(dividend, divisor, &bailout));
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kSignedSmall));
var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber));
Node* value = Float64Div(SmiToFloat64(lhs), SmiToFloat64(rhs));
var_result.Bind(AllocateHeapNumberWithValue(value));
Goto(&end);
// Bailout: convert {dividend} and {divisor} to double and do double
// division.
BIND(&bailout);
{
var_dividend_float64.Bind(SmiToFloat64(dividend));
var_divisor_float64.Bind(SmiToFloat64(divisor));
Goto(&do_fdiv);
}
}
BIND(&divisor_is_not_smi);
{
// Check if {divisor} is a HeapNumber.
GotoIfNot(IsHeapNumber(divisor), &check_divisor_for_oddball);
// Convert {dividend} to a double and divide it with the value of
// {divisor}.
var_dividend_float64.Bind(SmiToFloat64(dividend));
var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
Goto(&do_fdiv);
}
BIND(&dividend_is_not_smi);
{
// Check if {dividend} is a HeapNumber.
GotoIfNot(IsHeapNumber(dividend), &dividend_is_not_number);
// Check if {divisor} is a Smi.
Label divisor_is_smi(this), divisor_is_not_smi(this);
Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
BIND(&divisor_is_smi);
{
// Convert {divisor} to a double and use it for a floating point
// division.
var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(SmiToFloat64(divisor));
Goto(&do_fdiv);
}
BIND(&divisor_is_not_smi);
{
// Check if {divisor} is a HeapNumber.
GotoIfNot(IsHeapNumber(divisor), &check_divisor_for_oddball);
// Both {dividend} and {divisor} are HeapNumbers. Load their values
// and divide them.
var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
Goto(&do_fdiv);
}
}
}
BIND(&do_fdiv);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
Node* value =
Float64Div(var_dividend_float64.value(), var_divisor_float64.value());
var_result.Bind(AllocateHeapNumberWithValue(value));
Goto(&end);
}
BIND(&dividend_is_not_number);
{
// We just know dividend is not a number or Smi. No checks on divisor yet.
// Check if dividend is an oddball.
Node* dividend_instance_type = LoadInstanceType(dividend);
Node* dividend_is_oddball =
Word32Equal(dividend_instance_type, Int32Constant(ODDBALL_TYPE));
GotoIfNot(dividend_is_oddball, &call_with_any_feedback);
GotoIf(TaggedIsSmi(divisor), &call_with_oddball_feedback);
// Check if {divisor} is a HeapNumber.
Branch(IsHeapNumber(divisor), &call_with_oddball_feedback,
&check_divisor_for_oddball);
}
BIND(&check_divisor_for_oddball);
{
// Check if divisor is an oddball. At this point we know dividend is either
// a Smi or number or oddball and divisor is not a number or Smi.
Node* divisor_instance_type = LoadInstanceType(divisor);
Node* divisor_is_oddball =
Word32Equal(divisor_instance_type, Int32Constant(ODDBALL_TYPE));
Branch(divisor_is_oddball, &call_with_oddball_feedback,
&call_with_any_feedback);
}
BIND(&call_with_oddball_feedback);
{
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
Goto(&call_divide_stub);
}
BIND(&call_with_any_feedback);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
Goto(&call_divide_stub);
}
BIND(&call_divide_stub);
{
var_result.Bind(CallBuiltin(Builtins::kDivide, context, dividend, divisor));
Goto(&end);
}
BIND(&end);
UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id, function);
return var_result.value();
BIND(&end);
return var_result.value();
};
auto floatFunction = [=](Node* lhs, Node* rhs) {
return Float64Div(lhs, rhs);
};
return Generate_BinaryOperationWithFeedback(
context, dividend, divisor, slot_id, feedback_vector, function,
smiFunction, floatFunction, Token::DIV, rhs_is_smi);
}
Node* BinaryOpAssembler::Generate_ModulusWithFeedback(
Node* context, Node* dividend, Node* divisor, Node* slot_id,
Node* feedback_vector, Node* function) {
// Shared entry point for floating point division.
Label do_fmod(this), dividend_is_not_number(this, Label::kDeferred),
check_divisor_for_oddball(this, Label::kDeferred),
call_with_oddball_feedback(this), call_with_any_feedback(this),
call_modulus_stub(this), end(this);
VARIABLE(var_dividend_float64, MachineRepresentation::kFloat64);
VARIABLE(var_divisor_float64, MachineRepresentation::kFloat64);
VARIABLE(var_result, MachineRepresentation::kTagged);
VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
Label dividend_is_smi(this), dividend_is_not_smi(this);
Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
BIND(&dividend_is_smi);
{
Label divisor_is_smi(this), divisor_is_not_smi(this);
Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
BIND(&divisor_is_smi);
{
var_result.Bind(SmiMod(dividend, divisor));
var_type_feedback.Bind(
SelectSmiConstant(TaggedIsSmi(var_result.value()),
BinaryOperationFeedback::kSignedSmall,
BinaryOperationFeedback::kNumber));
Goto(&end);
}
BIND(&divisor_is_not_smi);
{
// Check if {divisor} is a HeapNumber.
GotoIfNot(IsHeapNumber(divisor), &check_divisor_for_oddball);
// Convert {dividend} to a double and divide it with the value of
// {divisor}.
var_dividend_float64.Bind(SmiToFloat64(dividend));
var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
Goto(&do_fmod);
}
}
BIND(&dividend_is_not_smi);
{
// Check if {dividend} is a HeapNumber.
GotoIfNot(IsHeapNumber(dividend), &dividend_is_not_number);
// Check if {divisor} is a Smi.
Label divisor_is_smi(this), divisor_is_not_smi(this);
Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
BIND(&divisor_is_smi);
{
// Convert {divisor} to a double and use it for a floating point
// division.
var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(SmiToFloat64(divisor));
Goto(&do_fmod);
}
BIND(&divisor_is_not_smi);
{
// Check if {divisor} is a HeapNumber.
GotoIfNot(IsHeapNumber(divisor), &check_divisor_for_oddball);
// Both {dividend} and {divisor} are HeapNumbers. Load their values
// and divide them.
var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
Goto(&do_fmod);
}
}
BIND(&do_fmod);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
Node* value =
Float64Mod(var_dividend_float64.value(), var_divisor_float64.value());
var_result.Bind(AllocateHeapNumberWithValue(value));
Goto(&end);
}
BIND(&dividend_is_not_number);
{
// No checks on divisor yet. We just know dividend is not a number or Smi.
// Check if dividend is an oddball.
Node* dividend_instance_type = LoadInstanceType(dividend);
Node* dividend_is_oddball =
Word32Equal(dividend_instance_type, Int32Constant(ODDBALL_TYPE));
GotoIfNot(dividend_is_oddball, &call_with_any_feedback);
GotoIf(TaggedIsSmi(divisor), &call_with_oddball_feedback);
// Check if {divisor} is a HeapNumber.
Branch(IsHeapNumber(divisor), &call_with_oddball_feedback,
&check_divisor_for_oddball);
}
BIND(&check_divisor_for_oddball);
{
// Check if divisor is an oddball. At this point we know dividend is either
// a Smi or number or oddball and divisor is not a number or Smi.
Node* divisor_instance_type = LoadInstanceType(divisor);
Node* divisor_is_oddball =
Word32Equal(divisor_instance_type, Int32Constant(ODDBALL_TYPE));
Branch(divisor_is_oddball, &call_with_oddball_feedback,
&call_with_any_feedback);
}
BIND(&call_with_oddball_feedback);
{
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
Goto(&call_modulus_stub);
}
BIND(&call_with_any_feedback);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
Goto(&call_modulus_stub);
}
BIND(&call_modulus_stub);
{
var_result.Bind(
CallBuiltin(Builtins::kModulus, context, dividend, divisor));
Goto(&end);
}
BIND(&end);
UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id, function);
return var_result.value();
Node* feedback_vector, Node* function, bool rhs_is_smi) {
auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
Node* result = SmiMod(lhs, rhs);
var_type_feedback->Bind(SelectSmiConstant(
TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
BinaryOperationFeedback::kNumber));
return result;
};
auto floatFunction = [=](Node* lhs, Node* rhs) {
return Float64Mod(lhs, rhs);
};
return Generate_BinaryOperationWithFeedback(
context, dividend, divisor, slot_id, feedback_vector, function,
smiFunction, floatFunction, Token::MOD, rhs_is_smi);
}
} // namespace internal
......
......@@ -5,6 +5,7 @@
#ifndef V8_SRC_IC_BINARY_OP_ASSEMBLER_H_
#define V8_SRC_IC_BINARY_OP_ASSEMBLER_H_
#include <functional>
#include "src/code-stub-assembler.h"
namespace v8 {
......@@ -23,23 +24,35 @@ class BinaryOpAssembler : public CodeStubAssembler {
Node* Generate_AddWithFeedback(Node* context, Node* lhs, Node* rhs,
Node* slot_id, Node* feedback_vector,
Node* function);
Node* function, bool rhs_is_smi);
Node* Generate_SubtractWithFeedback(Node* context, Node* lhs, Node* rhs,
Node* slot_id, Node* feedback_vector,
Node* function);
Node* function, bool rhs_is_smi);
Node* Generate_MultiplyWithFeedback(Node* context, Node* lhs, Node* rhs,
Node* slot_id, Node* feedback_vector,
Node* function);
Node* function, bool rhs_is_smi);
Node* Generate_DivideWithFeedback(Node* context, Node* dividend,
Node* divisor, Node* slot_id,
Node* feedback_vector, Node* function);
Node* feedback_vector, Node* function,
bool rhs_is_smi);
Node* Generate_ModulusWithFeedback(Node* context, Node* dividend,
Node* divisor, Node* slot_id,
Node* feedback_vector, Node* function);
Node* feedback_vector, Node* function,
bool rhs_is_smi);
private:
typedef std::function<Node*(Node*, Node*, Variable*)> SmiOperation;
typedef std::function<Node*(Node*, Node*)> FloatOperation;
Node* Generate_BinaryOperationWithFeedback(
Node* context, Node* lhs, Node* rhs, Node* slot_id, Node* feedback_vector,
Node* function, const SmiOperation& smiOperation,
const FloatOperation& floatOperation, Token::Value opcode,
bool rhs_is_smi);
};
} // namespace internal
......
......@@ -830,11 +830,9 @@ class InterpreterBinaryOpAssembler : public InterpreterAssembler {
OperandScale operand_scale)
: InterpreterAssembler(state, bytecode, operand_scale) {}
typedef Node* (BinaryOpAssembler::*BinaryOpGenerator)(Node* context,
Node* left, Node* right,
Node* slot,
Node* vector,
Node* function);
typedef Node* (BinaryOpAssembler::*BinaryOpGenerator)(
Node* context, Node* left, Node* right, Node* slot, Node* vector,
Node* function, bool lhs_is_smi);
void BinaryOpWithFeedback(BinaryOpGenerator generator) {
Node* reg_index = BytecodeOperandReg(0);
......@@ -847,7 +845,22 @@ class InterpreterBinaryOpAssembler : public InterpreterAssembler {
BinaryOpAssembler binop_asm(state());
Node* result = (binop_asm.*generator)(context, lhs, rhs, slot_index,
feedback_vector, function);
feedback_vector, function, false);
SetAccumulator(result);
Dispatch();
}
void BinaryOpSmiWithFeedback(BinaryOpGenerator generator) {
Node* lhs = GetAccumulator();
Node* rhs = BytecodeOperandImmSmi(0);
Node* context = GetContext();
Node* slot_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
Node* function = LoadRegister(Register::function_closure());
BinaryOpAssembler binop_asm(state());
Node* result = (binop_asm.*generator)(context, lhs, rhs, slot_index,
feedback_vector, function, true);
SetAccumulator(result);
Dispatch();
}
......@@ -891,228 +904,36 @@ IGNITION_HANDLER(Mod, InterpreterBinaryOpAssembler) {
// AddSmi <imm>
//
// Adds an immediate value <imm> to the value in the accumulator.
IGNITION_HANDLER(AddSmi, InterpreterAssembler) {
Variable var_result(this, MachineRepresentation::kTagged);
Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
Node* left = GetAccumulator();
Node* right = BytecodeOperandImmSmi(0);
Node* slot_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
Node* function = LoadRegister(Register::function_closure());
// {right} is known to be a Smi.
// Check if the {left} is a Smi take the fast path.
Branch(TaggedIsSmi(left), &fastpath, &slowpath);
BIND(&fastpath);
{
// Try fast Smi addition first.
Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(left),
BitcastTaggedToWord(right));
Node* overflow = Projection(1, pair);
// Check if the Smi additon overflowed.
Label if_notoverflow(this);
Branch(overflow, &slowpath, &if_notoverflow);
BIND(&if_notoverflow);
{
UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall),
feedback_vector, slot_index, function);
var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
Goto(&end);
}
}
BIND(&slowpath);
{
Node* context = GetContext();
// TODO(ishell): pass slot as word-size value.
var_result.Bind(CallBuiltin(Builtins::kAddWithFeedback, context, left,
right, TruncateWordToWord32(slot_index),
feedback_vector, function));
Goto(&end);
}
BIND(&end);
{
SetAccumulator(var_result.value());
Dispatch();
}
IGNITION_HANDLER(AddSmi, InterpreterBinaryOpAssembler) {
BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_AddWithFeedback);
}
// SubSmi <imm>
//
// Subtracts an immediate value <imm> from the value in the accumulator.
IGNITION_HANDLER(SubSmi, InterpreterAssembler) {
Variable var_result(this, MachineRepresentation::kTagged);
Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
Node* left = GetAccumulator();
Node* right = BytecodeOperandImmSmi(0);
Node* slot_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
Node* function = LoadRegister(Register::function_closure());
// {right} is known to be a Smi.
// Check if the {left} is a Smi take the fast path.
Branch(TaggedIsSmi(left), &fastpath, &slowpath);
BIND(&fastpath);
{
// Try fast Smi subtraction first.
Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(left),
BitcastTaggedToWord(right));
Node* overflow = Projection(1, pair);
// Check if the Smi subtraction overflowed.
Label if_notoverflow(this);
Branch(overflow, &slowpath, &if_notoverflow);
BIND(&if_notoverflow);
{
UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall),
feedback_vector, slot_index, function);
var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
Goto(&end);
}
}
BIND(&slowpath);
{
Node* context = GetContext();
// TODO(ishell): pass slot as word-size value.
var_result.Bind(CallBuiltin(Builtins::kSubtractWithFeedback, context, left,
right, TruncateWordToWord32(slot_index),
feedback_vector, function));
Goto(&end);
}
BIND(&end);
{
SetAccumulator(var_result.value());
Dispatch();
}
IGNITION_HANDLER(SubSmi, InterpreterBinaryOpAssembler) {
BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_SubtractWithFeedback);
}
// MulSmi <imm>
//
// Multiplies an immediate value <imm> to the value in the accumulator.
IGNITION_HANDLER(MulSmi, InterpreterAssembler) {
Variable var_result(this, MachineRepresentation::kTagged);
Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
Node* left = GetAccumulator();
Node* right = BytecodeOperandImmSmi(0);
Node* slot_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
Node* function = LoadRegister(Register::function_closure());
// {right} is known to be a Smi.
// Check if the {left} is a Smi take the fast path.
Branch(TaggedIsSmi(left), &fastpath, &slowpath);
BIND(&fastpath);
{
// Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
// in case of overflow.
var_result.Bind(SmiMul(left, right));
Node* feedback = SelectSmiConstant(TaggedIsSmi(var_result.value()),
BinaryOperationFeedback::kSignedSmall,
BinaryOperationFeedback::kNumber);
UpdateFeedback(feedback, feedback_vector, slot_index, function);
Goto(&end);
}
BIND(&slowpath);
{
Node* context = GetContext();
// TODO(ishell): pass slot as word-size value.
var_result.Bind(CallBuiltin(Builtins::kMultiplyWithFeedback, context, left,
right, TruncateWordToWord32(slot_index),
feedback_vector, function));
Goto(&end);
}
BIND(&end);
{
SetAccumulator(var_result.value());
Dispatch();
}
IGNITION_HANDLER(MulSmi, InterpreterBinaryOpAssembler) {
BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_MultiplyWithFeedback);
}
// DivSmi <imm>
//
// Divides the value in the accumulator by immediate value <imm>.
IGNITION_HANDLER(DivSmi, InterpreterAssembler) {
Variable var_result(this, MachineRepresentation::kTagged);
Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
Node* left = GetAccumulator();
Node* right = BytecodeOperandImmSmi(0);
Node* slot_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
Node* function = LoadRegister(Register::function_closure());
// {right} is known to be a Smi.
// Check if the {left} is a Smi take the fast path.
Branch(TaggedIsSmi(left), &fastpath, &slowpath);
BIND(&fastpath);
{
var_result.Bind(TrySmiDiv(left, right, &slowpath));
UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall),
feedback_vector, slot_index, function);
Goto(&end);
}
BIND(&slowpath);
{
Node* context = GetContext();
// TODO(ishell): pass slot as word-size value.
var_result.Bind(CallBuiltin(Builtins::kDivideWithFeedback, context, left,
right, TruncateWordToWord32(slot_index),
feedback_vector, function));
Goto(&end);
}
BIND(&end);
{
SetAccumulator(var_result.value());
Dispatch();
}
IGNITION_HANDLER(DivSmi, InterpreterBinaryOpAssembler) {
BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_DivideWithFeedback);
}
// ModSmi <imm>
//
// Modulo accumulator by immediate value <imm>.
IGNITION_HANDLER(ModSmi, InterpreterAssembler) {
Variable var_result(this, MachineRepresentation::kTagged);
Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
Node* left = GetAccumulator();
Node* right = BytecodeOperandImmSmi(0);
Node* slot_index = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
Node* function = LoadRegister(Register::function_closure());
// {right} is known to be a Smi.
// Check if the {left} is a Smi take the fast path.
Branch(TaggedIsSmi(left), &fastpath, &slowpath);
BIND(&fastpath);
{
// Both {lhs} and {rhs} are Smis. The result is not necessarily a smi.
var_result.Bind(SmiMod(left, right));
Node* feedback = SelectSmiConstant(TaggedIsSmi(var_result.value()),
BinaryOperationFeedback::kSignedSmall,
BinaryOperationFeedback::kNumber);
UpdateFeedback(feedback, feedback_vector, slot_index, function);
Goto(&end);
}
BIND(&slowpath);
{
Node* context = GetContext();
// TODO(ishell): pass slot as word-size value.
var_result.Bind(CallBuiltin(Builtins::kModulusWithFeedback, context, left,
right, TruncateWordToWord32(slot_index),
feedback_vector, function));
Goto(&end);
}
BIND(&end);
{
SetAccumulator(var_result.value());
Dispatch();
}
IGNITION_HANDLER(ModSmi, InterpreterBinaryOpAssembler) {
BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
}
class InterpreterBitwiseBinaryOpAssembler : public InterpreterAssembler {
......
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