LCOV - code coverage report
Current view: top level - src/ic - binary-op-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 396 396 100.0 %
Date: 2017-04-26 Functions: 5 5 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         172 : Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
      15             :                                                   Node* rhs, Node* slot_id,
      16             :                                                   Node* feedback_vector) {
      17             :   // Shared entry for floating point addition.
      18         344 :   Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred),
      19         172 :       check_rhsisoddball(this, Label::kDeferred),
      20         172 :       call_with_oddball_feedback(this), call_with_any_feedback(this),
      21         172 :       call_add_stub(this), end(this);
      22         344 :   VARIABLE(var_fadd_lhs, MachineRepresentation::kFloat64);
      23         344 :   VARIABLE(var_fadd_rhs, MachineRepresentation::kFloat64);
      24         344 :   VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
      25         344 :   VARIABLE(var_result, MachineRepresentation::kTagged);
      26             : 
      27             :   // Check if the {lhs} is a Smi or a HeapObject.
      28         172 :   Label if_lhsissmi(this), if_lhsisnotsmi(this);
      29         172 :   Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
      30             : 
      31         172 :   BIND(&if_lhsissmi);
      32             :   {
      33             :     // Check if the {rhs} is also a Smi.
      34         172 :     Label if_rhsissmi(this), if_rhsisnotsmi(this);
      35         172 :     Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
      36             : 
      37         172 :     BIND(&if_rhsissmi);
      38             :     {
      39             :       // Try fast Smi addition first.
      40             :       Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(lhs),
      41         172 :                                          BitcastTaggedToWord(rhs));
      42         172 :       Node* overflow = Projection(1, pair);
      43             : 
      44             :       // Check if the Smi additon overflowed.
      45         172 :       Label if_overflow(this), if_notoverflow(this);
      46         172 :       Branch(overflow, &if_overflow, &if_notoverflow);
      47             : 
      48         172 :       BIND(&if_overflow);
      49             :       {
      50         172 :         var_fadd_lhs.Bind(SmiToFloat64(lhs));
      51         172 :         var_fadd_rhs.Bind(SmiToFloat64(rhs));
      52         172 :         Goto(&do_fadd);
      53             :       }
      54             : 
      55         172 :       BIND(&if_notoverflow);
      56             :       {
      57             :         var_type_feedback.Bind(
      58         172 :             SmiConstant(BinaryOperationFeedback::kSignedSmall));
      59         172 :         var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
      60         172 :         Goto(&end);
      61         172 :       }
      62             :     }
      63             : 
      64         172 :     BIND(&if_rhsisnotsmi);
      65             :     {
      66             :       // Load the map of {rhs}.
      67         172 :       Node* rhs_map = LoadMap(rhs);
      68             : 
      69             :       // Check if the {rhs} is a HeapNumber.
      70         172 :       GotoIfNot(IsHeapNumberMap(rhs_map), &check_rhsisoddball);
      71             : 
      72         172 :       var_fadd_lhs.Bind(SmiToFloat64(lhs));
      73         172 :       var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
      74         172 :       Goto(&do_fadd);
      75         172 :     }
      76             :   }
      77             : 
      78         172 :   BIND(&if_lhsisnotsmi);
      79             :   {
      80             :     // Load the map of {lhs}.
      81         172 :     Node* lhs_map = LoadMap(lhs);
      82             : 
      83             :     // Check if {lhs} is a HeapNumber.
      84         172 :     GotoIfNot(IsHeapNumberMap(lhs_map), &if_lhsisnotnumber);
      85             : 
      86             :     // Check if the {rhs} is Smi.
      87         172 :     Label if_rhsissmi(this), if_rhsisnotsmi(this);
      88         172 :     Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
      89             : 
      90         172 :     BIND(&if_rhsissmi);
      91             :     {
      92         172 :       var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
      93         172 :       var_fadd_rhs.Bind(SmiToFloat64(rhs));
      94         172 :       Goto(&do_fadd);
      95             :     }
      96             : 
      97         172 :     BIND(&if_rhsisnotsmi);
      98             :     {
      99             :       // Load the map of {rhs}.
     100         172 :       Node* rhs_map = LoadMap(rhs);
     101             : 
     102             :       // Check if the {rhs} is a HeapNumber.
     103         172 :       GotoIfNot(IsHeapNumberMap(rhs_map), &check_rhsisoddball);
     104             : 
     105         172 :       var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
     106         172 :       var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
     107         172 :       Goto(&do_fadd);
     108         172 :     }
     109             :   }
     110             : 
     111         172 :   BIND(&do_fadd);
     112             :   {
     113         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     114         172 :     Node* value = Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
     115         172 :     Node* result = AllocateHeapNumberWithValue(value);
     116         172 :     var_result.Bind(result);
     117         172 :     Goto(&end);
     118             :   }
     119             : 
     120         172 :   BIND(&if_lhsisnotnumber);
     121             :   {
     122             :     // No checks on rhs are done yet. We just know lhs is not a number or Smi.
     123         172 :     Label if_lhsisoddball(this), if_lhsisnotoddball(this);
     124         172 :     Node* lhs_instance_type = LoadInstanceType(lhs);
     125             :     Node* lhs_is_oddball =
     126         172 :         Word32Equal(lhs_instance_type, Int32Constant(ODDBALL_TYPE));
     127         172 :     Branch(lhs_is_oddball, &if_lhsisoddball, &if_lhsisnotoddball);
     128             : 
     129         172 :     BIND(&if_lhsisoddball);
     130             :     {
     131         172 :       GotoIf(TaggedIsSmi(rhs), &call_with_oddball_feedback);
     132             : 
     133             :       // Load the map of the {rhs}.
     134         172 :       Node* rhs_map = LoadMap(rhs);
     135             : 
     136             :       // Check if {rhs} is a HeapNumber.
     137             :       Branch(IsHeapNumberMap(rhs_map), &call_with_oddball_feedback,
     138         172 :              &check_rhsisoddball);
     139             :     }
     140             : 
     141         172 :     BIND(&if_lhsisnotoddball);
     142             :     {
     143             :       // Exit unless {lhs} is a string
     144             :       GotoIfNot(IsStringInstanceType(lhs_instance_type),
     145         172 :                 &call_with_any_feedback);
     146             : 
     147             :       // Check if the {rhs} is a smi, and exit the string check early if it is.
     148         172 :       GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
     149             : 
     150         172 :       Node* rhs_instance_type = LoadInstanceType(rhs);
     151             : 
     152             :       // Exit unless {rhs} is a string. Since {lhs} is a string we no longer
     153             :       // need an Oddball check.
     154             :       GotoIfNot(IsStringInstanceType(rhs_instance_type),
     155         172 :                 &call_with_any_feedback);
     156             : 
     157         172 :       var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kString));
     158             :       Callable callable =
     159         172 :           CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
     160         172 :       var_result.Bind(CallStub(callable, context, lhs, rhs));
     161             : 
     162         172 :       Goto(&end);
     163         172 :     }
     164             :   }
     165             : 
     166         172 :   BIND(&check_rhsisoddball);
     167             :   {
     168             :     // Check if rhs is an oddball. At this point we know lhs is either a
     169             :     // Smi or number or oddball and rhs is not a number or Smi.
     170         172 :     Node* rhs_instance_type = LoadInstanceType(rhs);
     171             :     Node* rhs_is_oddball =
     172         172 :         Word32Equal(rhs_instance_type, Int32Constant(ODDBALL_TYPE));
     173             :     Branch(rhs_is_oddball, &call_with_oddball_feedback,
     174         172 :            &call_with_any_feedback);
     175             :   }
     176             : 
     177         172 :   BIND(&call_with_oddball_feedback);
     178             :   {
     179             :     var_type_feedback.Bind(
     180         172 :         SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     181         172 :     Goto(&call_add_stub);
     182             :   }
     183             : 
     184         172 :   BIND(&call_with_any_feedback);
     185             :   {
     186         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
     187         172 :     Goto(&call_add_stub);
     188             :   }
     189             : 
     190         172 :   BIND(&call_add_stub);
     191             :   {
     192         172 :     Callable callable = CodeFactory::Add(isolate());
     193         172 :     var_result.Bind(CallStub(callable, context, lhs, rhs));
     194         172 :     Goto(&end);
     195             :   }
     196             : 
     197         172 :   BIND(&end);
     198         172 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
     199         344 :   return var_result.value();
     200             : }
     201             : 
     202         172 : Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
     203             :                                                        Node* rhs, Node* slot_id,
     204             :                                                        Node* feedback_vector) {
     205             :   // Shared entry for floating point subtraction.
     206         344 :   Label do_fsub(this), end(this), call_subtract_stub(this),
     207         172 :       if_lhsisnotnumber(this), check_rhsisoddball(this),
     208         172 :       call_with_any_feedback(this);
     209         344 :   VARIABLE(var_fsub_lhs, MachineRepresentation::kFloat64);
     210         344 :   VARIABLE(var_fsub_rhs, MachineRepresentation::kFloat64);
     211         344 :   VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
     212         344 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     213             : 
     214             :   // Check if the {lhs} is a Smi or a HeapObject.
     215         172 :   Label if_lhsissmi(this), if_lhsisnotsmi(this);
     216         172 :   Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
     217             : 
     218         172 :   BIND(&if_lhsissmi);
     219             :   {
     220             :     // Check if the {rhs} is also a Smi.
     221         172 :     Label if_rhsissmi(this), if_rhsisnotsmi(this);
     222         172 :     Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
     223             : 
     224         172 :     BIND(&if_rhsissmi);
     225             :     {
     226             :       // Try a fast Smi subtraction first.
     227             :       Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(lhs),
     228         172 :                                          BitcastTaggedToWord(rhs));
     229         172 :       Node* overflow = Projection(1, pair);
     230             : 
     231             :       // Check if the Smi subtraction overflowed.
     232         172 :       Label if_overflow(this), if_notoverflow(this);
     233         172 :       Branch(overflow, &if_overflow, &if_notoverflow);
     234             : 
     235         172 :       BIND(&if_overflow);
     236             :       {
     237             :         // lhs, rhs - smi and result - number. combined - number.
     238             :         // The result doesn't fit into Smi range.
     239         172 :         var_fsub_lhs.Bind(SmiToFloat64(lhs));
     240         172 :         var_fsub_rhs.Bind(SmiToFloat64(rhs));
     241         172 :         Goto(&do_fsub);
     242             :       }
     243             : 
     244         172 :       BIND(&if_notoverflow);
     245             :       // lhs, rhs, result smi. combined - smi.
     246             :       var_type_feedback.Bind(
     247         172 :           SmiConstant(BinaryOperationFeedback::kSignedSmall));
     248         172 :       var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
     249         344 :       Goto(&end);
     250             :     }
     251             : 
     252         172 :     BIND(&if_rhsisnotsmi);
     253             :     {
     254             :       // Load the map of the {rhs}.
     255         172 :       Node* rhs_map = LoadMap(rhs);
     256             : 
     257             :       // Check if {rhs} is a HeapNumber.
     258         172 :       GotoIfNot(IsHeapNumberMap(rhs_map), &check_rhsisoddball);
     259             : 
     260             :       // Perform a floating point subtraction.
     261         172 :       var_fsub_lhs.Bind(SmiToFloat64(lhs));
     262         172 :       var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
     263         172 :       Goto(&do_fsub);
     264         172 :     }
     265             :   }
     266             : 
     267         172 :   BIND(&if_lhsisnotsmi);
     268             :   {
     269             :     // Load the map of the {lhs}.
     270         172 :     Node* lhs_map = LoadMap(lhs);
     271             : 
     272             :     // Check if the {lhs} is a HeapNumber.
     273         172 :     GotoIfNot(IsHeapNumberMap(lhs_map), &if_lhsisnotnumber);
     274             : 
     275             :     // Check if the {rhs} is a Smi.
     276         172 :     Label if_rhsissmi(this), if_rhsisnotsmi(this);
     277         172 :     Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
     278             : 
     279         172 :     BIND(&if_rhsissmi);
     280             :     {
     281             :       // Perform a floating point subtraction.
     282         172 :       var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
     283         172 :       var_fsub_rhs.Bind(SmiToFloat64(rhs));
     284         172 :       Goto(&do_fsub);
     285             :     }
     286             : 
     287         172 :     BIND(&if_rhsisnotsmi);
     288             :     {
     289             :       // Load the map of the {rhs}.
     290         172 :       Node* rhs_map = LoadMap(rhs);
     291             : 
     292             :       // Check if the {rhs} is a HeapNumber.
     293         172 :       GotoIfNot(IsHeapNumberMap(rhs_map), &check_rhsisoddball);
     294             : 
     295             :       // Perform a floating point subtraction.
     296         172 :       var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
     297         172 :       var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
     298         172 :       Goto(&do_fsub);
     299         172 :     }
     300             :   }
     301             : 
     302         172 :   BIND(&do_fsub);
     303             :   {
     304         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     305         172 :     Node* lhs_value = var_fsub_lhs.value();
     306         172 :     Node* rhs_value = var_fsub_rhs.value();
     307         172 :     Node* value = Float64Sub(lhs_value, rhs_value);
     308         172 :     var_result.Bind(AllocateHeapNumberWithValue(value));
     309         172 :     Goto(&end);
     310             :   }
     311             : 
     312         172 :   BIND(&if_lhsisnotnumber);
     313             :   {
     314             :     // No checks on rhs are done yet. We just know lhs is not a number or Smi.
     315             :     // Check if lhs is an oddball.
     316         172 :     Node* lhs_instance_type = LoadInstanceType(lhs);
     317             :     Node* lhs_is_oddball =
     318         172 :         Word32Equal(lhs_instance_type, Int32Constant(ODDBALL_TYPE));
     319         172 :     GotoIfNot(lhs_is_oddball, &call_with_any_feedback);
     320             : 
     321         172 :     Label if_rhsissmi(this), if_rhsisnotsmi(this);
     322         172 :     Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
     323             : 
     324         172 :     BIND(&if_rhsissmi);
     325             :     {
     326             :       var_type_feedback.Bind(
     327         172 :           SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     328         172 :       Goto(&call_subtract_stub);
     329             :     }
     330             : 
     331         172 :     BIND(&if_rhsisnotsmi);
     332             :     {
     333             :       // Load the map of the {rhs}.
     334         172 :       Node* rhs_map = LoadMap(rhs);
     335             : 
     336             :       // Check if {rhs} is a HeapNumber.
     337         172 :       GotoIfNot(IsHeapNumberMap(rhs_map), &check_rhsisoddball);
     338             : 
     339             :       var_type_feedback.Bind(
     340         172 :           SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     341         172 :       Goto(&call_subtract_stub);
     342         172 :     }
     343             :   }
     344             : 
     345         172 :   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         172 :     Node* rhs_instance_type = LoadInstanceType(rhs);
     350             :     Node* rhs_is_oddball =
     351         172 :         Word32Equal(rhs_instance_type, Int32Constant(ODDBALL_TYPE));
     352         172 :     GotoIfNot(rhs_is_oddball, &call_with_any_feedback);
     353             : 
     354             :     var_type_feedback.Bind(
     355         172 :         SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     356         172 :     Goto(&call_subtract_stub);
     357             :   }
     358             : 
     359         172 :   BIND(&call_with_any_feedback);
     360             :   {
     361         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
     362         172 :     Goto(&call_subtract_stub);
     363             :   }
     364             : 
     365         172 :   BIND(&call_subtract_stub);
     366             :   {
     367         172 :     Callable callable = CodeFactory::Subtract(isolate());
     368         172 :     var_result.Bind(CallStub(callable, context, lhs, rhs));
     369         172 :     Goto(&end);
     370             :   }
     371             : 
     372         172 :   BIND(&end);
     373         172 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
     374         344 :   return var_result.value();
     375             : }
     376             : 
     377         172 : Node* BinaryOpAssembler::Generate_MultiplyWithFeedback(Node* context, Node* lhs,
     378             :                                                        Node* rhs, Node* slot_id,
     379             :                                                        Node* feedback_vector) {
     380             :   // Shared entry point for floating point multiplication.
     381         344 :   Label do_fmul(this), if_lhsisnotnumber(this, Label::kDeferred),
     382         172 :       check_rhsisoddball(this, Label::kDeferred),
     383         172 :       call_with_oddball_feedback(this), call_with_any_feedback(this),
     384         172 :       call_multiply_stub(this), end(this);
     385         344 :   VARIABLE(var_lhs_float64, MachineRepresentation::kFloat64);
     386         344 :   VARIABLE(var_rhs_float64, MachineRepresentation::kFloat64);
     387         344 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     388         344 :   VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
     389             : 
     390         172 :   Label lhs_is_smi(this), lhs_is_not_smi(this);
     391         172 :   Branch(TaggedIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
     392             : 
     393         172 :   BIND(&lhs_is_smi);
     394             :   {
     395         172 :     Label rhs_is_smi(this), rhs_is_not_smi(this);
     396         172 :     Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
     397             : 
     398         172 :     BIND(&rhs_is_smi);
     399             :     {
     400             :       // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
     401             :       // in case of overflow.
     402         172 :       var_result.Bind(SmiMul(lhs, rhs));
     403             :       var_type_feedback.Bind(
     404             :           SelectSmiConstant(TaggedIsSmi(var_result.value()),
     405             :                             BinaryOperationFeedback::kSignedSmall,
     406         344 :                             BinaryOperationFeedback::kNumber));
     407         172 :       Goto(&end);
     408             :     }
     409             : 
     410         172 :     BIND(&rhs_is_not_smi);
     411             :     {
     412         172 :       Node* rhs_map = LoadMap(rhs);
     413             : 
     414             :       // Check if {rhs} is a HeapNumber.
     415         172 :       GotoIfNot(IsHeapNumberMap(rhs_map), &check_rhsisoddball);
     416             : 
     417             :       // Convert {lhs} to a double and multiply it with the value of {rhs}.
     418         172 :       var_lhs_float64.Bind(SmiToFloat64(lhs));
     419         172 :       var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
     420         172 :       Goto(&do_fmul);
     421         172 :     }
     422             :   }
     423             : 
     424         172 :   BIND(&lhs_is_not_smi);
     425             :   {
     426         172 :     Node* lhs_map = LoadMap(lhs);
     427             : 
     428             :     // Check if {lhs} is a HeapNumber.
     429         172 :     GotoIfNot(IsHeapNumberMap(lhs_map), &if_lhsisnotnumber);
     430             : 
     431             :     // Check if {rhs} is a Smi.
     432         172 :     Label rhs_is_smi(this), rhs_is_not_smi(this);
     433         172 :     Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
     434             : 
     435         172 :     BIND(&rhs_is_smi);
     436             :     {
     437             :       // Convert {rhs} to a double and multiply it with the value of {lhs}.
     438         172 :       var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
     439         172 :       var_rhs_float64.Bind(SmiToFloat64(rhs));
     440         172 :       Goto(&do_fmul);
     441             :     }
     442             : 
     443         172 :     BIND(&rhs_is_not_smi);
     444             :     {
     445         172 :       Node* rhs_map = LoadMap(rhs);
     446             : 
     447             :       // Check if {rhs} is a HeapNumber.
     448         172 :       GotoIfNot(IsHeapNumberMap(rhs_map), &check_rhsisoddball);
     449             : 
     450             :       // Both {lhs} and {rhs} are HeapNumbers. Load their values and
     451             :       // multiply them.
     452         172 :       var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
     453         172 :       var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
     454         172 :       Goto(&do_fmul);
     455         172 :     }
     456             :   }
     457             : 
     458         172 :   BIND(&do_fmul);
     459             :   {
     460         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     461         172 :     Node* value = Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
     462         172 :     Node* result = AllocateHeapNumberWithValue(value);
     463         172 :     var_result.Bind(result);
     464         172 :     Goto(&end);
     465             :   }
     466             : 
     467         172 :   BIND(&if_lhsisnotnumber);
     468             :   {
     469             :     // No checks on rhs are done yet. We just know lhs is not a number or Smi.
     470             :     // Check if lhs is an oddball.
     471         172 :     Node* lhs_instance_type = LoadInstanceType(lhs);
     472             :     Node* lhs_is_oddball =
     473         172 :         Word32Equal(lhs_instance_type, Int32Constant(ODDBALL_TYPE));
     474         172 :     GotoIfNot(lhs_is_oddball, &call_with_any_feedback);
     475             : 
     476         172 :     GotoIf(TaggedIsSmi(rhs), &call_with_oddball_feedback);
     477             : 
     478             :     // Load the map of the {rhs}.
     479         172 :     Node* rhs_map = LoadMap(rhs);
     480             : 
     481             :     // Check if {rhs} is a HeapNumber.
     482             :     Branch(IsHeapNumberMap(rhs_map), &call_with_oddball_feedback,
     483         172 :            &check_rhsisoddball);
     484             :   }
     485             : 
     486         172 :   BIND(&check_rhsisoddball);
     487             :   {
     488             :     // Check if rhs is an oddball. At this point we know lhs is either a
     489             :     // Smi or number or oddball and rhs is not a number or Smi.
     490         172 :     Node* rhs_instance_type = LoadInstanceType(rhs);
     491             :     Node* rhs_is_oddball =
     492         172 :         Word32Equal(rhs_instance_type, Int32Constant(ODDBALL_TYPE));
     493             :     Branch(rhs_is_oddball, &call_with_oddball_feedback,
     494         172 :            &call_with_any_feedback);
     495             :   }
     496             : 
     497         172 :   BIND(&call_with_oddball_feedback);
     498             :   {
     499             :     var_type_feedback.Bind(
     500         172 :         SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     501         172 :     Goto(&call_multiply_stub);
     502             :   }
     503             : 
     504         172 :   BIND(&call_with_any_feedback);
     505             :   {
     506         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
     507         172 :     Goto(&call_multiply_stub);
     508             :   }
     509             : 
     510         172 :   BIND(&call_multiply_stub);
     511             :   {
     512         172 :     Callable callable = CodeFactory::Multiply(isolate());
     513         172 :     var_result.Bind(CallStub(callable, context, lhs, rhs));
     514         172 :     Goto(&end);
     515             :   }
     516             : 
     517         172 :   BIND(&end);
     518         172 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
     519         344 :   return var_result.value();
     520             : }
     521             : 
     522         172 : Node* BinaryOpAssembler::Generate_DivideWithFeedback(Node* context,
     523             :                                                      Node* dividend,
     524             :                                                      Node* divisor,
     525             :                                                      Node* slot_id,
     526             :                                                      Node* feedback_vector) {
     527             :   // Shared entry point for floating point division.
     528         344 :   Label do_fdiv(this), dividend_is_not_number(this, Label::kDeferred),
     529         172 :       check_divisor_for_oddball(this, Label::kDeferred),
     530         172 :       call_with_oddball_feedback(this), call_with_any_feedback(this),
     531         172 :       call_divide_stub(this), end(this);
     532         344 :   VARIABLE(var_dividend_float64, MachineRepresentation::kFloat64);
     533         344 :   VARIABLE(var_divisor_float64, MachineRepresentation::kFloat64);
     534         344 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     535         344 :   VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
     536             : 
     537         172 :   Label dividend_is_smi(this), dividend_is_not_smi(this);
     538         172 :   Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
     539             : 
     540         172 :   BIND(&dividend_is_smi);
     541             :   {
     542         172 :     Label divisor_is_smi(this), divisor_is_not_smi(this);
     543         172 :     Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
     544             : 
     545         172 :     BIND(&divisor_is_smi);
     546             :     {
     547             :       Label bailout(this);
     548             : 
     549             :       // Try to perform Smi division if possible.
     550         172 :       var_result.Bind(TrySmiDiv(dividend, divisor, &bailout));
     551             :       var_type_feedback.Bind(
     552         172 :           SmiConstant(BinaryOperationFeedback::kSignedSmall));
     553         172 :       Goto(&end);
     554             : 
     555             :       // Bailout: convert {dividend} and {divisor} to double and do double
     556             :       // division.
     557         172 :       BIND(&bailout);
     558             :       {
     559         172 :         var_dividend_float64.Bind(SmiToFloat64(dividend));
     560         172 :         var_divisor_float64.Bind(SmiToFloat64(divisor));
     561         172 :         Goto(&do_fdiv);
     562         172 :       }
     563             :     }
     564             : 
     565         172 :     BIND(&divisor_is_not_smi);
     566             :     {
     567         172 :       Node* divisor_map = LoadMap(divisor);
     568             : 
     569             :       // Check if {divisor} is a HeapNumber.
     570         172 :       GotoIfNot(IsHeapNumberMap(divisor_map), &check_divisor_for_oddball);
     571             : 
     572             :       // Convert {dividend} to a double and divide it with the value of
     573             :       // {divisor}.
     574         172 :       var_dividend_float64.Bind(SmiToFloat64(dividend));
     575         172 :       var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
     576         172 :       Goto(&do_fdiv);
     577             :     }
     578             : 
     579         172 :     BIND(&dividend_is_not_smi);
     580             :     {
     581         172 :       Node* dividend_map = LoadMap(dividend);
     582             : 
     583             :       // Check if {dividend} is a HeapNumber.
     584         172 :       GotoIfNot(IsHeapNumberMap(dividend_map), &dividend_is_not_number);
     585             : 
     586             :       // Check if {divisor} is a Smi.
     587         172 :       Label divisor_is_smi(this), divisor_is_not_smi(this);
     588         172 :       Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
     589             : 
     590         172 :       BIND(&divisor_is_smi);
     591             :       {
     592             :         // Convert {divisor} to a double and use it for a floating point
     593             :         // division.
     594         172 :         var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
     595         172 :         var_divisor_float64.Bind(SmiToFloat64(divisor));
     596         172 :         Goto(&do_fdiv);
     597             :       }
     598             : 
     599         172 :       BIND(&divisor_is_not_smi);
     600             :       {
     601         172 :         Node* divisor_map = LoadMap(divisor);
     602             : 
     603             :         // Check if {divisor} is a HeapNumber.
     604         172 :         GotoIfNot(IsHeapNumberMap(divisor_map), &check_divisor_for_oddball);
     605             : 
     606             :         // Both {dividend} and {divisor} are HeapNumbers. Load their values
     607             :         // and divide them.
     608         172 :         var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
     609         172 :         var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
     610         172 :         Goto(&do_fdiv);
     611         172 :       }
     612         172 :     }
     613             :   }
     614             : 
     615         172 :   BIND(&do_fdiv);
     616             :   {
     617         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     618             :     Node* value =
     619         172 :         Float64Div(var_dividend_float64.value(), var_divisor_float64.value());
     620         172 :     var_result.Bind(AllocateHeapNumberWithValue(value));
     621         172 :     Goto(&end);
     622             :   }
     623             : 
     624         172 :   BIND(&dividend_is_not_number);
     625             :   {
     626             :     // We just know dividend is not a number or Smi. No checks on divisor yet.
     627             :     // Check if dividend is an oddball.
     628         172 :     Node* dividend_instance_type = LoadInstanceType(dividend);
     629             :     Node* dividend_is_oddball =
     630         172 :         Word32Equal(dividend_instance_type, Int32Constant(ODDBALL_TYPE));
     631         172 :     GotoIfNot(dividend_is_oddball, &call_with_any_feedback);
     632             : 
     633         172 :     GotoIf(TaggedIsSmi(divisor), &call_with_oddball_feedback);
     634             : 
     635             :     // Load the map of the {divisor}.
     636         172 :     Node* divisor_map = LoadMap(divisor);
     637             : 
     638             :     // Check if {divisor} is a HeapNumber.
     639             :     Branch(IsHeapNumberMap(divisor_map), &call_with_oddball_feedback,
     640         172 :            &check_divisor_for_oddball);
     641             :   }
     642             : 
     643         172 :   BIND(&check_divisor_for_oddball);
     644             :   {
     645             :     // Check if divisor is an oddball. At this point we know dividend is either
     646             :     // a Smi or number or oddball and divisor is not a number or Smi.
     647         172 :     Node* divisor_instance_type = LoadInstanceType(divisor);
     648             :     Node* divisor_is_oddball =
     649         172 :         Word32Equal(divisor_instance_type, Int32Constant(ODDBALL_TYPE));
     650             :     Branch(divisor_is_oddball, &call_with_oddball_feedback,
     651         172 :            &call_with_any_feedback);
     652             :   }
     653             : 
     654         172 :   BIND(&call_with_oddball_feedback);
     655             :   {
     656             :     var_type_feedback.Bind(
     657         172 :         SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     658         172 :     Goto(&call_divide_stub);
     659             :   }
     660             : 
     661         172 :   BIND(&call_with_any_feedback);
     662             :   {
     663         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
     664         172 :     Goto(&call_divide_stub);
     665             :   }
     666             : 
     667         172 :   BIND(&call_divide_stub);
     668             :   {
     669         172 :     Callable callable = CodeFactory::Divide(isolate());
     670         172 :     var_result.Bind(CallStub(callable, context, dividend, divisor));
     671         172 :     Goto(&end);
     672             :   }
     673             : 
     674         172 :   BIND(&end);
     675         172 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
     676         344 :   return var_result.value();
     677             : }
     678             : 
     679         172 : Node* BinaryOpAssembler::Generate_ModulusWithFeedback(Node* context,
     680             :                                                       Node* dividend,
     681             :                                                       Node* divisor,
     682             :                                                       Node* slot_id,
     683             :                                                       Node* feedback_vector) {
     684             :   // Shared entry point for floating point division.
     685         344 :   Label do_fmod(this), dividend_is_not_number(this, Label::kDeferred),
     686         172 :       check_divisor_for_oddball(this, Label::kDeferred),
     687         172 :       call_with_oddball_feedback(this), call_with_any_feedback(this),
     688         172 :       call_modulus_stub(this), end(this);
     689         344 :   VARIABLE(var_dividend_float64, MachineRepresentation::kFloat64);
     690         344 :   VARIABLE(var_divisor_float64, MachineRepresentation::kFloat64);
     691         344 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     692         344 :   VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
     693             : 
     694         172 :   Label dividend_is_smi(this), dividend_is_not_smi(this);
     695         172 :   Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
     696             : 
     697         172 :   BIND(&dividend_is_smi);
     698             :   {
     699         172 :     Label divisor_is_smi(this), divisor_is_not_smi(this);
     700         172 :     Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
     701             : 
     702         172 :     BIND(&divisor_is_smi);
     703             :     {
     704         172 :       var_result.Bind(SmiMod(dividend, divisor));
     705             :       var_type_feedback.Bind(
     706             :           SelectSmiConstant(TaggedIsSmi(var_result.value()),
     707             :                             BinaryOperationFeedback::kSignedSmall,
     708         344 :                             BinaryOperationFeedback::kNumber));
     709         172 :       Goto(&end);
     710             :     }
     711             : 
     712         172 :     BIND(&divisor_is_not_smi);
     713             :     {
     714         172 :       Node* divisor_map = LoadMap(divisor);
     715             : 
     716             :       // Check if {divisor} is a HeapNumber.
     717         172 :       GotoIfNot(IsHeapNumberMap(divisor_map), &check_divisor_for_oddball);
     718             : 
     719             :       // Convert {dividend} to a double and divide it with the value of
     720             :       // {divisor}.
     721         172 :       var_dividend_float64.Bind(SmiToFloat64(dividend));
     722         172 :       var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
     723         172 :       Goto(&do_fmod);
     724         172 :     }
     725             :   }
     726             : 
     727         172 :   BIND(&dividend_is_not_smi);
     728             :   {
     729         172 :     Node* dividend_map = LoadMap(dividend);
     730             : 
     731             :     // Check if {dividend} is a HeapNumber.
     732         172 :     GotoIfNot(IsHeapNumberMap(dividend_map), &dividend_is_not_number);
     733             : 
     734             :     // Check if {divisor} is a Smi.
     735         172 :     Label divisor_is_smi(this), divisor_is_not_smi(this);
     736         172 :     Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
     737             : 
     738         172 :     BIND(&divisor_is_smi);
     739             :     {
     740             :       // Convert {divisor} to a double and use it for a floating point
     741             :       // division.
     742         172 :       var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
     743         172 :       var_divisor_float64.Bind(SmiToFloat64(divisor));
     744         172 :       Goto(&do_fmod);
     745             :     }
     746             : 
     747         172 :     BIND(&divisor_is_not_smi);
     748             :     {
     749         172 :       Node* divisor_map = LoadMap(divisor);
     750             : 
     751             :       // Check if {divisor} is a HeapNumber.
     752         172 :       GotoIfNot(IsHeapNumberMap(divisor_map), &check_divisor_for_oddball);
     753             : 
     754             :       // Both {dividend} and {divisor} are HeapNumbers. Load their values
     755             :       // and divide them.
     756         172 :       var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
     757         172 :       var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
     758         172 :       Goto(&do_fmod);
     759         172 :     }
     760             :   }
     761             : 
     762         172 :   BIND(&do_fmod);
     763             :   {
     764         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
     765             :     Node* value =
     766         172 :         Float64Mod(var_dividend_float64.value(), var_divisor_float64.value());
     767         172 :     var_result.Bind(AllocateHeapNumberWithValue(value));
     768         172 :     Goto(&end);
     769             :   }
     770             : 
     771         172 :   BIND(&dividend_is_not_number);
     772             :   {
     773             :     // No checks on divisor yet. We just know dividend is not a number or Smi.
     774             :     // Check if dividend is an oddball.
     775         172 :     Node* dividend_instance_type = LoadInstanceType(dividend);
     776             :     Node* dividend_is_oddball =
     777         172 :         Word32Equal(dividend_instance_type, Int32Constant(ODDBALL_TYPE));
     778         172 :     GotoIfNot(dividend_is_oddball, &call_with_any_feedback);
     779             : 
     780         172 :     GotoIf(TaggedIsSmi(divisor), &call_with_oddball_feedback);
     781             : 
     782             :     // Load the map of the {divisor}.
     783         172 :     Node* divisor_map = LoadMap(divisor);
     784             : 
     785             :     // Check if {divisor} is a HeapNumber.
     786             :     Branch(IsHeapNumberMap(divisor_map), &call_with_oddball_feedback,
     787         172 :            &check_divisor_for_oddball);
     788             :   }
     789             : 
     790         172 :   BIND(&check_divisor_for_oddball);
     791             :   {
     792             :     // Check if divisor is an oddball. At this point we know dividend is either
     793             :     // a Smi or number or oddball and divisor is not a number or Smi.
     794         172 :     Node* divisor_instance_type = LoadInstanceType(divisor);
     795             :     Node* divisor_is_oddball =
     796         172 :         Word32Equal(divisor_instance_type, Int32Constant(ODDBALL_TYPE));
     797             :     Branch(divisor_is_oddball, &call_with_oddball_feedback,
     798         172 :            &call_with_any_feedback);
     799             :   }
     800             : 
     801         172 :   BIND(&call_with_oddball_feedback);
     802             :   {
     803             :     var_type_feedback.Bind(
     804         172 :         SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
     805         172 :     Goto(&call_modulus_stub);
     806             :   }
     807             : 
     808         172 :   BIND(&call_with_any_feedback);
     809             :   {
     810         172 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
     811         172 :     Goto(&call_modulus_stub);
     812             :   }
     813             : 
     814         172 :   BIND(&call_modulus_stub);
     815             :   {
     816         172 :     Callable callable = CodeFactory::Modulus(isolate());
     817         172 :     var_result.Bind(CallStub(callable, context, dividend, divisor));
     818         172 :     Goto(&end);
     819             :   }
     820             : 
     821         172 :   BIND(&end);
     822         172 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
     823         344 :   return var_result.value();
     824             : }
     825             : 
     826             : }  // namespace internal
     827             : }  // namespace v8

Generated by: LCOV version 1.10