| Index: src/code-stubs.cc
|
| diff --git a/src/code-stubs.cc b/src/code-stubs.cc
|
| index 87cbf091b0ea65404077c1aa97c45e0b5da17788..e8b527053478eba475acc21912c78ecc1a5d2472 100644
|
| --- a/src/code-stubs.cc
|
| +++ b/src/code-stubs.cc
|
| @@ -671,8 +671,10 @@ compiler::Node* AddWithFeedbackStub::Generate(
|
| typedef CodeStubAssembler::Variable Variable;
|
|
|
| // Shared entry for floating point addition.
|
| - Label do_fadd(assembler), end(assembler),
|
| - call_add_stub(assembler, Label::kDeferred);
|
| + Label do_fadd(assembler), if_lhsisnotnumber(assembler, Label::kDeferred),
|
| + check_rhsisoddball(assembler, Label::kDeferred),
|
| + call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
|
| + call_add_stub(assembler), end(assembler);
|
| Variable var_fadd_lhs(assembler, MachineRepresentation::kFloat64),
|
| var_fadd_rhs(assembler, MachineRepresentation::kFloat64),
|
| var_type_feedback(assembler, MachineRepresentation::kWord32),
|
| @@ -725,7 +727,7 @@ compiler::Node* AddWithFeedbackStub::Generate(
|
|
|
| // Check if the {rhs} is a HeapNumber.
|
| assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map),
|
| - &call_add_stub);
|
| + &check_rhsisoddball);
|
|
|
| var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs));
|
| var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
|
| @@ -735,14 +737,12 @@ compiler::Node* AddWithFeedbackStub::Generate(
|
|
|
| assembler->Bind(&if_lhsisnotsmi);
|
| {
|
| - Label check_string(assembler);
|
| -
|
| // Load the map of {lhs}.
|
| Node* lhs_map = assembler->LoadMap(lhs);
|
|
|
| // Check if {lhs} is a HeapNumber.
|
| - Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
|
| - assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map), &check_string);
|
| + assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map),
|
| + &if_lhsisnotnumber);
|
|
|
| // Check if the {rhs} is Smi.
|
| Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
|
| @@ -763,29 +763,62 @@ compiler::Node* AddWithFeedbackStub::Generate(
|
|
|
| // Check if the {rhs} is a HeapNumber.
|
| assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map),
|
| - &call_add_stub);
|
| + &check_rhsisoddball);
|
|
|
| var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs));
|
| var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs));
|
| assembler->Goto(&do_fadd);
|
| }
|
| + }
|
| +
|
| + assembler->Bind(&do_fadd);
|
| + {
|
| + var_type_feedback.Bind(
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNumber));
|
| + Node* value =
|
| + assembler->Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
|
| + Node* result = assembler->ChangeFloat64ToTagged(value);
|
| + var_result.Bind(result);
|
| + assembler->Goto(&end);
|
| + }
|
|
|
| - assembler->Bind(&check_string);
|
| + assembler->Bind(&if_lhsisnotnumber);
|
| + {
|
| + // No checks on rhs are done yet. We just know lhs is not a number or Smi.
|
| + Label if_lhsisoddball(assembler), if_lhsisnotoddball(assembler);
|
| + Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
|
| + Node* lhs_is_oddball = assembler->Word32Equal(
|
| + lhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->Branch(lhs_is_oddball, &if_lhsisoddball, &if_lhsisnotoddball);
|
| +
|
| + assembler->Bind(&if_lhsisoddball);
|
| {
|
| - // Check if the {rhs} is a smi, and exit the string check early if it is.
|
| - assembler->GotoIf(assembler->TaggedIsSmi(rhs), &call_add_stub);
|
| + assembler->GotoIf(assembler->TaggedIsSmi(rhs),
|
| + &call_with_oddball_feedback);
|
|
|
| - Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map);
|
| + // Load the map of the {rhs}.
|
| + Node* rhs_map = assembler->LoadMap(rhs);
|
| +
|
| + // Check if {rhs} is a HeapNumber.
|
| + assembler->Branch(assembler->IsHeapNumberMap(rhs_map),
|
| + &call_with_oddball_feedback, &check_rhsisoddball);
|
| + }
|
|
|
| + assembler->Bind(&if_lhsisnotoddball);
|
| + {
|
| // Exit unless {lhs} is a string
|
| assembler->GotoUnless(assembler->IsStringInstanceType(lhs_instance_type),
|
| - &call_add_stub);
|
| + &call_with_any_feedback);
|
| +
|
| + // Check if the {rhs} is a smi, and exit the string check early if it is.
|
| + assembler->GotoIf(assembler->TaggedIsSmi(rhs), &call_with_any_feedback);
|
|
|
| Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
|
|
|
| - // Exit unless {rhs} is a string
|
| + // Exit unless {rhs} is a string. Since {lhs} is a string we no longer
|
| + // need an Oddball check.
|
| assembler->GotoUnless(assembler->IsStringInstanceType(rhs_instance_type),
|
| - &call_add_stub);
|
| + &call_with_any_feedback);
|
|
|
| var_type_feedback.Bind(
|
| assembler->Int32Constant(BinaryOperationFeedback::kString));
|
| @@ -797,21 +830,33 @@ compiler::Node* AddWithFeedbackStub::Generate(
|
| }
|
| }
|
|
|
| - assembler->Bind(&do_fadd);
|
| + assembler->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 = assembler->LoadInstanceType(rhs);
|
| + Node* rhs_is_oddball = assembler->Word32Equal(
|
| + rhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->Branch(rhs_is_oddball, &call_with_oddball_feedback,
|
| + &call_with_any_feedback);
|
| + }
|
| +
|
| + assembler->Bind(&call_with_oddball_feedback);
|
| {
|
| var_type_feedback.Bind(
|
| - assembler->Int32Constant(BinaryOperationFeedback::kNumber));
|
| - Node* value =
|
| - assembler->Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
|
| - Node* result = assembler->ChangeFloat64ToTagged(value);
|
| - var_result.Bind(result);
|
| - assembler->Goto(&end);
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
|
| + assembler->Goto(&call_add_stub);
|
| }
|
|
|
| - assembler->Bind(&call_add_stub);
|
| + assembler->Bind(&call_with_any_feedback);
|
| {
|
| var_type_feedback.Bind(
|
| assembler->Int32Constant(BinaryOperationFeedback::kAny));
|
| + assembler->Goto(&call_add_stub);
|
| + }
|
| +
|
| + assembler->Bind(&call_add_stub);
|
| + {
|
| Callable callable = CodeFactory::Add(assembler->isolate());
|
| var_result.Bind(assembler->CallStub(callable, context, lhs, rhs));
|
| assembler->Goto(&end);
|
| @@ -1027,8 +1072,10 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
|
| typedef CodeStubAssembler::Variable Variable;
|
|
|
| // Shared entry point for floating point multiplication.
|
| - Label do_fmul(assembler), end(assembler),
|
| - call_multiply_stub(assembler, Label::kDeferred);
|
| + Label do_fmul(assembler), if_lhsisnotnumber(assembler, Label::kDeferred),
|
| + check_rhsisoddball(assembler, Label::kDeferred),
|
| + call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
|
| + call_multiply_stub(assembler), end(assembler);
|
| Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64),
|
| var_rhs_float64(assembler, MachineRepresentation::kFloat64),
|
| var_result(assembler, MachineRepresentation::kTagged),
|
| @@ -1064,7 +1111,7 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
|
|
|
| // Check if {rhs} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(rhs_map, number_map),
|
| - &call_multiply_stub);
|
| + &check_rhsisoddball);
|
|
|
| // Convert {lhs} to a double and multiply it with the value of {rhs}.
|
| var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
|
| @@ -1079,7 +1126,7 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
|
|
|
| // Check if {lhs} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(lhs_map, number_map),
|
| - &call_multiply_stub);
|
| + &if_lhsisnotnumber);
|
|
|
| // Check if {rhs} is a Smi.
|
| Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
|
| @@ -1100,7 +1147,7 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
|
|
|
| // Check if {rhs} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(rhs_map, number_map),
|
| - &call_multiply_stub);
|
| + &check_rhsisoddball);
|
|
|
| // Both {lhs} and {rhs} are HeapNumbers. Load their values and
|
| // multiply them.
|
| @@ -1121,10 +1168,52 @@ compiler::Node* MultiplyWithFeedbackStub::Generate(
|
| assembler->Goto(&end);
|
| }
|
|
|
| - assembler->Bind(&call_multiply_stub);
|
| + assembler->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 = assembler->LoadInstanceType(lhs);
|
| + Node* lhs_is_oddball = assembler->Word32Equal(
|
| + lhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->GotoUnless(lhs_is_oddball, &call_with_any_feedback);
|
| +
|
| + assembler->GotoIf(assembler->TaggedIsSmi(rhs), &call_with_oddball_feedback);
|
| +
|
| + // Load the map of the {rhs}.
|
| + Node* rhs_map = assembler->LoadMap(rhs);
|
| +
|
| + // Check if {rhs} is a HeapNumber.
|
| + assembler->Branch(assembler->IsHeapNumberMap(rhs_map),
|
| + &call_with_oddball_feedback, &check_rhsisoddball);
|
| + }
|
| +
|
| + assembler->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 = assembler->LoadInstanceType(rhs);
|
| + Node* rhs_is_oddball = assembler->Word32Equal(
|
| + rhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->Branch(rhs_is_oddball, &call_with_oddball_feedback,
|
| + &call_with_any_feedback);
|
| + }
|
| +
|
| + assembler->Bind(&call_with_oddball_feedback);
|
| + {
|
| + var_type_feedback.Bind(
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
|
| + assembler->Goto(&call_multiply_stub);
|
| + }
|
| +
|
| + assembler->Bind(&call_with_any_feedback);
|
| {
|
| var_type_feedback.Bind(
|
| assembler->Int32Constant(BinaryOperationFeedback::kAny));
|
| + assembler->Goto(&call_multiply_stub);
|
| + }
|
| +
|
| + assembler->Bind(&call_multiply_stub);
|
| + {
|
| Callable callable = CodeFactory::Multiply(assembler->isolate());
|
| var_result.Bind(assembler->CallStub(callable, context, lhs, rhs));
|
| assembler->Goto(&end);
|
| @@ -1147,7 +1236,10 @@ compiler::Node* DivideWithFeedbackStub::Generate(
|
| typedef CodeStubAssembler::Variable Variable;
|
|
|
| // Shared entry point for floating point division.
|
| - Label do_fdiv(assembler), end(assembler), call_divide_stub(assembler);
|
| + Label do_fdiv(assembler), dividend_is_not_number(assembler, Label::kDeferred),
|
| + check_divisor_for_oddball(assembler, Label::kDeferred),
|
| + call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
|
| + call_divide_stub(assembler), end(assembler);
|
| Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
|
| var_divisor_float64(assembler, MachineRepresentation::kFloat64),
|
| var_result(assembler, MachineRepresentation::kTagged),
|
| @@ -1240,7 +1332,7 @@ compiler::Node* DivideWithFeedbackStub::Generate(
|
|
|
| // Check if {divisor} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
|
| - &call_divide_stub);
|
| + &check_divisor_for_oddball);
|
|
|
| // Convert {dividend} to a double and divide it with the value of
|
| // {divisor}.
|
| @@ -1255,7 +1347,7 @@ compiler::Node* DivideWithFeedbackStub::Generate(
|
|
|
| // Check if {dividend} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(dividend_map, number_map),
|
| - &call_divide_stub);
|
| + ÷nd_is_not_number);
|
|
|
| // Check if {divisor} is a Smi.
|
| Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
|
| @@ -1277,7 +1369,7 @@ compiler::Node* DivideWithFeedbackStub::Generate(
|
|
|
| // Check if {divisor} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
|
| - &call_divide_stub);
|
| + &check_divisor_for_oddball);
|
|
|
| // Both {dividend} and {divisor} are HeapNumbers. Load their values
|
| // and divide them.
|
| @@ -1298,10 +1390,53 @@ compiler::Node* DivideWithFeedbackStub::Generate(
|
| assembler->Goto(&end);
|
| }
|
|
|
| - assembler->Bind(&call_divide_stub);
|
| + assembler->Bind(÷nd_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 = assembler->LoadInstanceType(dividend);
|
| + Node* dividend_is_oddball = assembler->Word32Equal(
|
| + dividend_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->GotoUnless(dividend_is_oddball, &call_with_any_feedback);
|
| +
|
| + assembler->GotoIf(assembler->TaggedIsSmi(divisor),
|
| + &call_with_oddball_feedback);
|
| +
|
| + // Load the map of the {divisor}.
|
| + Node* divisor_map = assembler->LoadMap(divisor);
|
| +
|
| + // Check if {divisor} is a HeapNumber.
|
| + assembler->Branch(assembler->IsHeapNumberMap(divisor_map),
|
| + &call_with_oddball_feedback, &check_divisor_for_oddball);
|
| + }
|
| +
|
| + assembler->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 = assembler->LoadInstanceType(divisor);
|
| + Node* divisor_is_oddball = assembler->Word32Equal(
|
| + divisor_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->Branch(divisor_is_oddball, &call_with_oddball_feedback,
|
| + &call_with_any_feedback);
|
| + }
|
| +
|
| + assembler->Bind(&call_with_oddball_feedback);
|
| + {
|
| + var_type_feedback.Bind(
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
|
| + assembler->Goto(&call_divide_stub);
|
| + }
|
| +
|
| + assembler->Bind(&call_with_any_feedback);
|
| {
|
| var_type_feedback.Bind(
|
| assembler->Int32Constant(BinaryOperationFeedback::kAny));
|
| + assembler->Goto(&call_divide_stub);
|
| + }
|
| +
|
| + assembler->Bind(&call_divide_stub);
|
| + {
|
| Callable callable = CodeFactory::Divide(assembler->isolate());
|
| var_result.Bind(assembler->CallStub(callable, context, dividend, divisor));
|
| assembler->Goto(&end);
|
| @@ -1323,7 +1458,10 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
|
| typedef CodeStubAssembler::Variable Variable;
|
|
|
| // Shared entry point for floating point division.
|
| - Label do_fmod(assembler), end(assembler), call_modulus_stub(assembler);
|
| + Label do_fmod(assembler), dividend_is_not_number(assembler, Label::kDeferred),
|
| + check_divisor_for_oddball(assembler, Label::kDeferred),
|
| + call_with_oddball_feedback(assembler), call_with_any_feedback(assembler),
|
| + call_modulus_stub(assembler), end(assembler);
|
| Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
|
| var_divisor_float64(assembler, MachineRepresentation::kFloat64),
|
| var_result(assembler, MachineRepresentation::kTagged),
|
| @@ -1357,7 +1495,7 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
|
|
|
| // Check if {divisor} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
|
| - &call_modulus_stub);
|
| + &check_divisor_for_oddball);
|
|
|
| // Convert {dividend} to a double and divide it with the value of
|
| // {divisor}.
|
| @@ -1373,7 +1511,7 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
|
|
|
| // Check if {dividend} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(dividend_map, number_map),
|
| - &call_modulus_stub);
|
| + ÷nd_is_not_number);
|
|
|
| // Check if {divisor} is a Smi.
|
| Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
|
| @@ -1395,7 +1533,7 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
|
|
|
| // Check if {divisor} is a HeapNumber.
|
| assembler->GotoUnless(assembler->WordEqual(divisor_map, number_map),
|
| - &call_modulus_stub);
|
| + &check_divisor_for_oddball);
|
|
|
| // Both {dividend} and {divisor} are HeapNumbers. Load their values
|
| // and divide them.
|
| @@ -1415,10 +1553,53 @@ compiler::Node* ModulusWithFeedbackStub::Generate(
|
| assembler->Goto(&end);
|
| }
|
|
|
| - assembler->Bind(&call_modulus_stub);
|
| + assembler->Bind(÷nd_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 = assembler->LoadInstanceType(dividend);
|
| + Node* dividend_is_oddball = assembler->Word32Equal(
|
| + dividend_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->GotoUnless(dividend_is_oddball, &call_with_any_feedback);
|
| +
|
| + assembler->GotoIf(assembler->TaggedIsSmi(divisor),
|
| + &call_with_oddball_feedback);
|
| +
|
| + // Load the map of the {divisor}.
|
| + Node* divisor_map = assembler->LoadMap(divisor);
|
| +
|
| + // Check if {divisor} is a HeapNumber.
|
| + assembler->Branch(assembler->IsHeapNumberMap(divisor_map),
|
| + &call_with_oddball_feedback, &check_divisor_for_oddball);
|
| + }
|
| +
|
| + assembler->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 = assembler->LoadInstanceType(divisor);
|
| + Node* divisor_is_oddball = assembler->Word32Equal(
|
| + divisor_instance_type, assembler->Int32Constant(ODDBALL_TYPE));
|
| + assembler->Branch(divisor_is_oddball, &call_with_oddball_feedback,
|
| + &call_with_any_feedback);
|
| + }
|
| +
|
| + assembler->Bind(&call_with_oddball_feedback);
|
| + {
|
| + var_type_feedback.Bind(
|
| + assembler->Int32Constant(BinaryOperationFeedback::kNumberOrOddball));
|
| + assembler->Goto(&call_modulus_stub);
|
| + }
|
| +
|
| + assembler->Bind(&call_with_any_feedback);
|
| {
|
| var_type_feedback.Bind(
|
| assembler->Int32Constant(BinaryOperationFeedback::kAny));
|
| + assembler->Goto(&call_modulus_stub);
|
| + }
|
| +
|
| + assembler->Bind(&call_modulus_stub);
|
| + {
|
| Callable callable = CodeFactory::Modulus(assembler->isolate());
|
| var_result.Bind(assembler->CallStub(callable, context, dividend, divisor));
|
| assembler->Goto(&end);
|
|
|