LCOV - code coverage report
Current view: top level - src/ic - binary-op-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 264 265 99.6 %
Date: 2017-10-20 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/ic/binary-op-assembler.h"
       6             : 
       7             : #include "src/globals.h"
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : 
      12             : using compiler::Node;
      13             : 
      14         186 : Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
      15             :                                                   Node* rhs, Node* slot_id,
      16             :                                                   Node* feedback_vector,
      17             :                                                   bool rhs_is_smi) {
      18             :   // Shared entry for floating point addition.
      19         372 :   Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred),
      20         186 :       check_rhsisoddball(this, Label::kDeferred),
      21         186 :       call_with_oddball_feedback(this), call_with_any_feedback(this),
      22         186 :       call_add_stub(this), end(this), bigint(this, Label::kDeferred);
      23         372 :   VARIABLE(var_fadd_lhs, MachineRepresentation::kFloat64);
      24         372 :   VARIABLE(var_fadd_rhs, MachineRepresentation::kFloat64);
      25         372 :   VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
      26         372 :   VARIABLE(var_result, MachineRepresentation::kTagged);
      27             : 
      28             :   // Check if the {lhs} is a Smi or a HeapObject.
      29         186 :   Label if_lhsissmi(this);
      30             :   // If rhs is known to be an Smi we want to fast path Smi operation. This is
      31             :   // for AddSmi operation. For the normal Add operation, we want to fast path
      32             :   // both Smi and Number operations, so this path should not be marked as
      33             :   // Deferred.
      34             :   Label if_lhsisnotsmi(this,
      35         372 :                        rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
      36         372 :   Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
      37             : 
      38         186 :   BIND(&if_lhsissmi);
      39             :   {
      40         186 :     Comment("lhs is Smi");
      41         186 :     if (!rhs_is_smi) {
      42             :       // Check if the {rhs} is also a Smi.
      43          93 :       Label if_rhsissmi(this), if_rhsisnotsmi(this);
      44         186 :       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
      45             : 
      46          93 :       BIND(&if_rhsisnotsmi);
      47             :       {
      48             :         // Check if the {rhs} is a HeapNumber.
      49         186 :         GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
      50             : 
      51         186 :         var_fadd_lhs.Bind(SmiToFloat64(lhs));
      52         186 :         var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
      53          93 :         Goto(&do_fadd);
      54             :       }
      55             : 
      56         186 :       BIND(&if_rhsissmi);
      57             :     }
      58             : 
      59             :     {
      60         186 :       Comment("perform smi operation");
      61             :       // Try fast Smi addition first.
      62         186 :       Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(lhs),
      63         930 :                                          BitcastTaggedToWord(rhs));
      64         186 :       Node* overflow = Projection(1, pair);
      65             : 
      66             :       // Check if the Smi additon overflowed.
      67             :       // If rhs is known to be an Smi we want to fast path Smi operation. This
      68             :       // is for AddSmi operation. For the normal Add operation, we want to fast
      69             :       // path both Smi and Number operations, so this path should not be marked
      70             :       // as Deferred.
      71             :       Label if_overflow(this,
      72         186 :                         rhs_is_smi ? Label::kDeferred : Label::kNonDeferred),
      73         186 :           if_notoverflow(this);
      74         186 :       Branch(overflow, &if_overflow, &if_notoverflow);
      75             : 
      76         186 :       BIND(&if_overflow);
      77             :       {
      78         372 :         var_fadd_lhs.Bind(SmiToFloat64(lhs));
      79         372 :         var_fadd_rhs.Bind(SmiToFloat64(rhs));
      80         186 :         Goto(&do_fadd);
      81             :       }
      82             : 
      83         186 :       BIND(&if_notoverflow);
      84             :       {
      85             :         var_type_feedback.Bind(
      86         372 :             SmiConstant(BinaryOperationFeedback::kSignedSmall));
      87         558 :         var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
      88         186 :         Goto(&end);
      89         186 :       }
      90             :     }
      91             :   }
      92             : 
      93         186 :   BIND(&if_lhsisnotsmi);
      94             :   {
      95             :     // Check if {lhs} is a HeapNumber.
      96         372 :     GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
      97             : 
      98         186 :     if (!rhs_is_smi) {
      99             :       // Check if the {rhs} is Smi.
     100          93 :       Label if_rhsissmi(this), if_rhsisnotsmi(this);
     101         186 :       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
     102             : 
     103          93 :       BIND(&if_rhsisnotsmi);
     104             :       {
     105             :         // Check if the {rhs} is a HeapNumber.
     106         186 :         GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
     107             : 
     108         186 :         var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
     109         186 :         var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
     110          93 :         Goto(&do_fadd);
     111             :       }
     112             : 
     113         186 :       BIND(&if_rhsissmi);
     114             :     }
     115             :     {
     116         372 :       var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
     117         372 :       var_fadd_rhs.Bind(SmiToFloat64(rhs));
     118         186 :       Goto(&do_fadd);
     119             :     }
     120             :   }
     121             : 
     122         186 :   BIND(&do_fadd);
     123             :   {
     124         372 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     125         744 :     Node* value = Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
     126         372 :     Node* result = AllocateHeapNumberWithValue(value);
     127         186 :     var_result.Bind(result);
     128         186 :     Goto(&end);
     129             :   }
     130             : 
     131         186 :   BIND(&if_lhsisnotnumber);
     132             :   {
     133             :     // No checks on rhs are done yet. We just know lhs is not a number or Smi.
     134         186 :     Label if_lhsisoddball(this), if_lhsisnotoddball(this);
     135         372 :     Node* lhs_instance_type = LoadInstanceType(lhs);
     136         186 :     Node* lhs_is_oddball = InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE);
     137         186 :     Branch(lhs_is_oddball, &if_lhsisoddball, &if_lhsisnotoddball);
     138             : 
     139         186 :     BIND(&if_lhsisoddball);
     140             :     {
     141         372 :       GotoIf(TaggedIsSmi(rhs), &call_with_oddball_feedback);
     142             : 
     143             :       // Check if {rhs} is a HeapNumber.
     144             :       Branch(IsHeapNumber(rhs), &call_with_oddball_feedback,
     145         372 :              &check_rhsisoddball);
     146             :     }
     147             : 
     148         186 :     BIND(&if_lhsisnotoddball);
     149             :     {
     150         186 :       Label lhs_is_string(this), lhs_is_bigint(this);
     151         372 :       GotoIf(IsStringInstanceType(lhs_instance_type), &lhs_is_string);
     152         372 :       GotoIf(IsBigIntInstanceType(lhs_instance_type), &lhs_is_bigint);
     153         186 :       Goto(&call_with_any_feedback);
     154             : 
     155         186 :       BIND(&lhs_is_bigint);
     156             :       {
     157         372 :         GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
     158         372 :         Branch(IsBigInt(rhs), &bigint, &call_with_any_feedback);
     159             :       }
     160             : 
     161         186 :       BIND(&lhs_is_string);
     162             :       // Check if the {rhs} is a smi, and exit the string check early if it is.
     163         372 :       GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
     164             : 
     165         372 :       Node* rhs_instance_type = LoadInstanceType(rhs);
     166             : 
     167             :       // Exit unless {rhs} is a string. Since {lhs} is a string we no longer
     168             :       // need an Oddball check.
     169             :       GotoIfNot(IsStringInstanceType(rhs_instance_type),
     170         372 :                 &call_with_any_feedback);
     171             : 
     172         372 :       var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kString));
     173             :       Callable callable =
     174         186 :           CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
     175         186 :       var_result.Bind(CallStub(callable, context, lhs, rhs));
     176             : 
     177         372 :       Goto(&end);
     178         186 :     }
     179             :   }
     180             : 
     181         186 :   BIND(&check_rhsisoddball);
     182             :   {
     183             :     // Check if rhs is an oddball. At this point we know lhs is either a
     184             :     // Smi or number or oddball and rhs is not a number or Smi.
     185         372 :     Node* rhs_instance_type = LoadInstanceType(rhs);
     186         186 :     Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
     187         186 :     GotoIf(rhs_is_oddball, &call_with_oddball_feedback);
     188             :     Branch(IsBigIntInstanceType(rhs_instance_type), &bigint,
     189         372 :            &call_with_any_feedback);
     190             :   }
     191             : 
     192         186 :   BIND(&bigint);
     193             :   {
     194         372 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
     195             :     var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
     196         372 :                                 SmiConstant(Token::ADD)));
     197         186 :     Goto(&end);
     198             :   }
     199             : 
     200         186 :   BIND(&call_with_oddball_feedback);
     201             :   {
     202             :     var_type_feedback.Bind(
     203         372 :         SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     204         186 :     Goto(&call_add_stub);
     205             :   }
     206             : 
     207         186 :   BIND(&call_with_any_feedback);
     208             :   {
     209         372 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
     210         186 :     Goto(&call_add_stub);
     211             :   }
     212             : 
     213         186 :   BIND(&call_add_stub);
     214             :   {
     215         186 :     var_result.Bind(CallBuiltin(Builtins::kAdd, context, lhs, rhs));
     216         186 :     Goto(&end);
     217             :   }
     218             : 
     219         186 :   BIND(&end);
     220         186 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
     221         372 :   return var_result.value();
     222             : }
     223             : 
     224         744 : Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
     225             :     Node* context, Node* lhs, Node* rhs, Node* slot_id, Node* feedback_vector,
     226             :     const SmiOperation& smiOperation, const FloatOperation& floatOperation,
     227             :     Token::Value opcode, bool rhs_is_smi) {
     228        1488 :   Label do_float_operation(this), end(this), call_stub(this),
     229         744 :       check_rhsisoddball(this, Label::kDeferred), call_with_any_feedback(this),
     230         744 :       if_lhsisnotnumber(this, Label::kDeferred),
     231         744 :       if_bigint(this, Label::kDeferred);
     232        1488 :   VARIABLE(var_float_lhs, MachineRepresentation::kFloat64);
     233        1488 :   VARIABLE(var_float_rhs, MachineRepresentation::kFloat64);
     234        1488 :   VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
     235        1488 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     236             : 
     237         744 :   Label if_lhsissmi(this);
     238             :   // If rhs is known to be an Smi (in the SubSmi, MulSmi, DivSmi, ModSmi
     239             :   // bytecode handlers) we want to fast path Smi operation. For the normal
     240             :   // operation, we want to fast path both Smi and Number operations, so this
     241             :   // path should not be marked as Deferred.
     242             :   Label if_lhsisnotsmi(this,
     243        1488 :                        rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
     244        1488 :   Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
     245             : 
     246             :   // Check if the {lhs} is a Smi or a HeapObject.
     247         744 :   BIND(&if_lhsissmi);
     248             :   {
     249         744 :     Comment("lhs is Smi");
     250         744 :     if (!rhs_is_smi) {
     251             :       // Check if the {rhs} is also a Smi.
     252         372 :       Label if_rhsissmi(this), if_rhsisnotsmi(this);
     253         744 :       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
     254         372 :       BIND(&if_rhsisnotsmi);
     255             :       {
     256             :         // Check if {rhs} is a HeapNumber.
     257         744 :         GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
     258             : 
     259             :         // Perform a floating point operation.
     260         744 :         var_float_lhs.Bind(SmiToFloat64(lhs));
     261         744 :         var_float_rhs.Bind(LoadHeapNumberValue(rhs));
     262         372 :         Goto(&do_float_operation);
     263             :       }
     264             : 
     265         744 :       BIND(&if_rhsissmi);
     266             :     }
     267             : 
     268             :     {
     269         744 :       Comment("perform smi operation");
     270         744 :       var_result.Bind(smiOperation(lhs, rhs, &var_type_feedback));
     271         744 :       Goto(&end);
     272             :     }
     273             :   }
     274             : 
     275         744 :   BIND(&if_lhsisnotsmi);
     276             :   {
     277         744 :     Comment("lhs is not Smi");
     278             :     // Check if the {lhs} is a HeapNumber.
     279        1488 :     GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
     280             : 
     281         744 :     if (!rhs_is_smi) {
     282             :       // Check if the {rhs} is a Smi.
     283         372 :       Label if_rhsissmi(this), if_rhsisnotsmi(this);
     284         744 :       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
     285             : 
     286         372 :       BIND(&if_rhsisnotsmi);
     287             :       {
     288             :         // Check if the {rhs} is a HeapNumber.
     289         744 :         GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
     290             : 
     291             :         // Perform a floating point operation.
     292         744 :         var_float_lhs.Bind(LoadHeapNumberValue(lhs));
     293         744 :         var_float_rhs.Bind(LoadHeapNumberValue(rhs));
     294         372 :         Goto(&do_float_operation);
     295             :       }
     296             : 
     297         744 :       BIND(&if_rhsissmi);
     298             :     }
     299             : 
     300             :     {
     301             :       // Perform floating point operation.
     302        1488 :       var_float_lhs.Bind(LoadHeapNumberValue(lhs));
     303        1488 :       var_float_rhs.Bind(SmiToFloat64(rhs));
     304         744 :       Goto(&do_float_operation);
     305             :     }
     306             :   }
     307             : 
     308         744 :   BIND(&do_float_operation);
     309             :   {
     310        1488 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     311         744 :     Node* lhs_value = var_float_lhs.value();
     312         744 :     Node* rhs_value = var_float_rhs.value();
     313         744 :     Node* value = floatOperation(lhs_value, rhs_value);
     314        1488 :     var_result.Bind(AllocateHeapNumberWithValue(value));
     315         744 :     Goto(&end);
     316             :   }
     317             : 
     318         744 :   BIND(&if_lhsisnotnumber);
     319             :   {
     320             :     // No checks on rhs are done yet. We just know lhs is not a number or Smi.
     321         744 :     Label if_left_bigint(this), if_left_oddball(this);
     322        1488 :     Node* lhs_instance_type = LoadInstanceType(lhs);
     323        1488 :     GotoIf(IsBigIntInstanceType(lhs_instance_type), &if_left_bigint);
     324         744 :     Node* lhs_is_oddball = InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE);
     325         744 :     Branch(lhs_is_oddball, &if_left_oddball, &call_with_any_feedback);
     326             : 
     327         744 :     BIND(&if_left_oddball);
     328             :     {
     329         744 :       Label if_rhsissmi(this), if_rhsisnotsmi(this);
     330        1488 :       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
     331             : 
     332         744 :       BIND(&if_rhsissmi);
     333             :       {
     334             :         var_type_feedback.Bind(
     335        1488 :             SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     336         744 :         Goto(&call_stub);
     337             :       }
     338             : 
     339         744 :       BIND(&if_rhsisnotsmi);
     340             :       {
     341             :         // Check if {rhs} is a HeapNumber.
     342        1488 :         GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
     343             : 
     344             :         var_type_feedback.Bind(
     345        1488 :             SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     346         744 :         Goto(&call_stub);
     347         744 :       }
     348             :     }
     349             : 
     350         744 :     BIND(&if_left_bigint);
     351             :     {
     352        1488 :       GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
     353        1488 :       Branch(IsBigInt(rhs), &if_bigint, &call_with_any_feedback);
     354         744 :     }
     355             :   }
     356             : 
     357         744 :   BIND(&check_rhsisoddball);
     358             :   {
     359             :     // Check if rhs is an oddball. At this point we know lhs is either a
     360             :     // Smi or number or oddball and rhs is not a number or Smi.
     361        1488 :     Node* rhs_instance_type = LoadInstanceType(rhs);
     362        1488 :     GotoIf(IsBigIntInstanceType(rhs_instance_type), &if_bigint);
     363         744 :     Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
     364         744 :     GotoIfNot(rhs_is_oddball, &call_with_any_feedback);
     365             : 
     366             :     var_type_feedback.Bind(
     367        1488 :         SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     368         744 :     Goto(&call_stub);
     369             :   }
     370             : 
     371             :   // This handles the case where at least one input is a BigInt.
     372         744 :   BIND(&if_bigint);
     373             :   {
     374        1488 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
     375             :     var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
     376        1488 :                                 SmiConstant(opcode)));
     377         744 :     Goto(&end);
     378             :   }
     379             : 
     380         744 :   BIND(&call_with_any_feedback);
     381             :   {
     382        1488 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
     383         744 :     Goto(&call_stub);
     384             :   }
     385             : 
     386         744 :   BIND(&call_stub);
     387             :   {
     388             :     Node* result;
     389         744 :     switch (opcode) {
     390             :       case Token::SUB:
     391         186 :         result = CallBuiltin(Builtins::kSubtract, context, lhs, rhs);
     392         186 :         break;
     393             :       case Token::MUL:
     394         186 :         result = CallBuiltin(Builtins::kMultiply, context, lhs, rhs);
     395         186 :         break;
     396             :       case Token::DIV:
     397         186 :         result = CallBuiltin(Builtins::kDivide, context, lhs, rhs);
     398         186 :         break;
     399             :       case Token::MOD:
     400         186 :         result = CallBuiltin(Builtins::kModulus, context, lhs, rhs);
     401         186 :         break;
     402             :       default:
     403           0 :         UNREACHABLE();
     404             :     }
     405         744 :     var_result.Bind(result);
     406         744 :     Goto(&end);
     407             :   }
     408             : 
     409         744 :   BIND(&end);
     410         744 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
     411        1488 :   return var_result.value();
     412             : }
     413             : 
     414         186 : Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
     415             :                                                        Node* rhs, Node* slot_id,
     416             :                                                        Node* feedback_vector,
     417             :                                                        bool rhs_is_smi) {
     418         186 :   auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
     419         186 :     VARIABLE(var_result, MachineRepresentation::kTagged);
     420             :     // Try a fast Smi subtraction first.
     421         372 :     Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(lhs),
     422         930 :                                        BitcastTaggedToWord(rhs));
     423         186 :     Node* overflow = Projection(1, pair);
     424             : 
     425             :     // Check if the Smi subtraction overflowed.
     426         558 :     Label if_notoverflow(this), end(this);
     427             :     // If rhs is known to be an Smi (for SubSmi) we want to fast path Smi
     428             :     // operation. For the normal Sub operation, we want to fast path both
     429             :     // Smi and Number operations, so this path should not be marked as Deferred.
     430             :     Label if_overflow(this,
     431         372 :                       rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
     432         186 :     Branch(overflow, &if_overflow, &if_notoverflow);
     433             : 
     434         186 :     BIND(&if_notoverflow);
     435             :     {
     436             :       var_type_feedback->Bind(
     437         372 :           SmiConstant(BinaryOperationFeedback::kSignedSmall));
     438         558 :       var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
     439         186 :       Goto(&end);
     440             :     }
     441             : 
     442         186 :     BIND(&if_overflow);
     443             :     {
     444         372 :       var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     445         744 :       Node* value = Float64Sub(SmiToFloat64(lhs), SmiToFloat64(rhs));
     446         372 :       var_result.Bind(AllocateHeapNumberWithValue(value));
     447         186 :       Goto(&end);
     448             :     }
     449             : 
     450         186 :     BIND(&end);
     451         372 :     return var_result.value();
     452         372 :   };
     453             :   auto floatFunction = [=](Node* lhs, Node* rhs) {
     454         372 :     return Float64Sub(lhs, rhs);
     455         186 :   };
     456             :   return Generate_BinaryOperationWithFeedback(
     457             :       context, lhs, rhs, slot_id, feedback_vector, smiFunction, floatFunction,
     458         744 :       Token::SUB, rhs_is_smi);
     459             : }
     460             : 
     461         186 : Node* BinaryOpAssembler::Generate_MultiplyWithFeedback(Node* context, Node* lhs,
     462             :                                                        Node* rhs, Node* slot_id,
     463             :                                                        Node* feedback_vector,
     464             :                                                        bool rhs_is_smi) {
     465         186 :   auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
     466         186 :     Node* result = SmiMul(lhs, rhs);
     467             :     var_type_feedback->Bind(SelectSmiConstant(
     468         372 :         TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
     469         558 :         BinaryOperationFeedback::kNumber));
     470         186 :     return result;
     471             :   };
     472             :   auto floatFunction = [=](Node* lhs, Node* rhs) {
     473         372 :     return Float64Mul(lhs, rhs);
     474         186 :   };
     475             :   return Generate_BinaryOperationWithFeedback(
     476             :       context, lhs, rhs, slot_id, feedback_vector, smiFunction, floatFunction,
     477         744 :       Token::MUL, rhs_is_smi);
     478             : }
     479             : 
     480         186 : Node* BinaryOpAssembler::Generate_DivideWithFeedback(
     481             :     Node* context, Node* dividend, Node* divisor, Node* slot_id,
     482             :     Node* feedback_vector, bool rhs_is_smi) {
     483         186 :   auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
     484         186 :     VARIABLE(var_result, MachineRepresentation::kTagged);
     485             :     // If rhs is known to be an Smi (for DivSmi) we want to fast path Smi
     486             :     // operation. For the normal Div operation, we want to fast path both
     487             :     // Smi and Number operations, so this path should not be marked as Deferred.
     488         372 :     Label bailout(this, rhs_is_smi ? Label::kDeferred : Label::kNonDeferred),
     489         372 :         end(this);
     490         186 :     var_result.Bind(TrySmiDiv(lhs, rhs, &bailout));
     491         372 :     var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
     492         186 :     Goto(&end);
     493             : 
     494         186 :     BIND(&bailout);
     495             :     {
     496             :       var_type_feedback->Bind(
     497         372 :           SmiConstant(BinaryOperationFeedback::kSignedSmallInputs));
     498         744 :       Node* value = Float64Div(SmiToFloat64(lhs), SmiToFloat64(rhs));
     499         372 :       var_result.Bind(AllocateHeapNumberWithValue(value));
     500         186 :       Goto(&end);
     501             :     }
     502             : 
     503         186 :     BIND(&end);
     504         372 :     return var_result.value();
     505         372 :   };
     506             :   auto floatFunction = [=](Node* lhs, Node* rhs) {
     507         372 :     return Float64Div(lhs, rhs);
     508         186 :   };
     509             :   return Generate_BinaryOperationWithFeedback(
     510             :       context, dividend, divisor, slot_id, feedback_vector, smiFunction,
     511         744 :       floatFunction, Token::DIV, rhs_is_smi);
     512             : }
     513             : 
     514         186 : Node* BinaryOpAssembler::Generate_ModulusWithFeedback(
     515             :     Node* context, Node* dividend, Node* divisor, Node* slot_id,
     516             :     Node* feedback_vector, bool rhs_is_smi) {
     517         186 :   auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
     518         186 :     Node* result = SmiMod(lhs, rhs);
     519             :     var_type_feedback->Bind(SelectSmiConstant(
     520         372 :         TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
     521         558 :         BinaryOperationFeedback::kNumber));
     522         186 :     return result;
     523             :   };
     524             :   auto floatFunction = [=](Node* lhs, Node* rhs) {
     525         372 :     return Float64Mod(lhs, rhs);
     526         186 :   };
     527             :   return Generate_BinaryOperationWithFeedback(
     528             :       context, dividend, divisor, slot_id, feedback_vector, smiFunction,
     529         744 :       floatFunction, Token::MOD, rhs_is_smi);
     530             : }
     531             : 
     532             : }  // namespace internal
     533             : }  // namespace v8

Generated by: LCOV version 1.10