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

Generated by: LCOV version 1.10