11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/ic/binary-op-assembler.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/common/globals.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cinamespace v8 {
101cb0ef41Sopenharmony_cinamespace internal {
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
131cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<Object> lhs, TNode<Object> rhs,
141cb0ef41Sopenharmony_ci    TNode<UintPtrT> slot_id, const LazyNode<HeapObject>& maybe_feedback_vector,
151cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
161cb0ef41Sopenharmony_ci  // Shared entry for floating point addition.
171cb0ef41Sopenharmony_ci  Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred),
181cb0ef41Sopenharmony_ci      check_rhsisoddball(this, Label::kDeferred),
191cb0ef41Sopenharmony_ci      call_with_oddball_feedback(this), call_with_any_feedback(this),
201cb0ef41Sopenharmony_ci      call_add_stub(this), end(this), bigint(this, Label::kDeferred);
211cb0ef41Sopenharmony_ci  TVARIABLE(Float64T, var_fadd_lhs);
221cb0ef41Sopenharmony_ci  TVARIABLE(Float64T, var_fadd_rhs);
231cb0ef41Sopenharmony_ci  TVARIABLE(Smi, var_type_feedback);
241cb0ef41Sopenharmony_ci  TVARIABLE(Object, var_result);
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  // Check if the {lhs} is a Smi or a HeapObject.
271cb0ef41Sopenharmony_ci  Label if_lhsissmi(this);
281cb0ef41Sopenharmony_ci  // If rhs is known to be an Smi we want to fast path Smi operation. This is
291cb0ef41Sopenharmony_ci  // for AddSmi operation. For the normal Add operation, we want to fast path
301cb0ef41Sopenharmony_ci  // both Smi and Number operations, so this path should not be marked as
311cb0ef41Sopenharmony_ci  // Deferred.
321cb0ef41Sopenharmony_ci  Label if_lhsisnotsmi(this,
331cb0ef41Sopenharmony_ci                       rhs_known_smi ? Label::kDeferred : Label::kNonDeferred);
341cb0ef41Sopenharmony_ci  Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  BIND(&if_lhsissmi);
371cb0ef41Sopenharmony_ci  {
381cb0ef41Sopenharmony_ci    Comment("lhs is Smi");
391cb0ef41Sopenharmony_ci    TNode<Smi> lhs_smi = CAST(lhs);
401cb0ef41Sopenharmony_ci    if (!rhs_known_smi) {
411cb0ef41Sopenharmony_ci      // Check if the {rhs} is also a Smi.
421cb0ef41Sopenharmony_ci      Label if_rhsissmi(this), if_rhsisnotsmi(this);
431cb0ef41Sopenharmony_ci      Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci      BIND(&if_rhsisnotsmi);
461cb0ef41Sopenharmony_ci      {
471cb0ef41Sopenharmony_ci        // Check if the {rhs} is a HeapNumber.
481cb0ef41Sopenharmony_ci        TNode<HeapObject> rhs_heap_object = CAST(rhs);
491cb0ef41Sopenharmony_ci        GotoIfNot(IsHeapNumber(rhs_heap_object), &check_rhsisoddball);
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci        var_fadd_lhs = SmiToFloat64(lhs_smi);
521cb0ef41Sopenharmony_ci        var_fadd_rhs = LoadHeapNumberValue(rhs_heap_object);
531cb0ef41Sopenharmony_ci        Goto(&do_fadd);
541cb0ef41Sopenharmony_ci      }
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci      BIND(&if_rhsissmi);
571cb0ef41Sopenharmony_ci    }
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci    {
601cb0ef41Sopenharmony_ci      Comment("perform smi operation");
611cb0ef41Sopenharmony_ci      // If rhs is known to be an Smi we want to fast path Smi operation. This
621cb0ef41Sopenharmony_ci      // is for AddSmi operation. For the normal Add operation, we want to fast
631cb0ef41Sopenharmony_ci      // path both Smi and Number operations, so this path should not be marked
641cb0ef41Sopenharmony_ci      // as Deferred.
651cb0ef41Sopenharmony_ci      TNode<Smi> rhs_smi = CAST(rhs);
661cb0ef41Sopenharmony_ci      Label if_overflow(this,
671cb0ef41Sopenharmony_ci                        rhs_known_smi ? Label::kDeferred : Label::kNonDeferred);
681cb0ef41Sopenharmony_ci      TNode<Smi> smi_result = TrySmiAdd(lhs_smi, rhs_smi, &if_overflow);
691cb0ef41Sopenharmony_ci      // Not overflowed.
701cb0ef41Sopenharmony_ci      {
711cb0ef41Sopenharmony_ci        var_type_feedback = SmiConstant(BinaryOperationFeedback::kSignedSmall);
721cb0ef41Sopenharmony_ci        UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(),
731cb0ef41Sopenharmony_ci                       slot_id, update_feedback_mode);
741cb0ef41Sopenharmony_ci        var_result = smi_result;
751cb0ef41Sopenharmony_ci        Goto(&end);
761cb0ef41Sopenharmony_ci      }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci      BIND(&if_overflow);
791cb0ef41Sopenharmony_ci      {
801cb0ef41Sopenharmony_ci        var_fadd_lhs = SmiToFloat64(lhs_smi);
811cb0ef41Sopenharmony_ci        var_fadd_rhs = SmiToFloat64(rhs_smi);
821cb0ef41Sopenharmony_ci        Goto(&do_fadd);
831cb0ef41Sopenharmony_ci      }
841cb0ef41Sopenharmony_ci    }
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  BIND(&if_lhsisnotsmi);
881cb0ef41Sopenharmony_ci  {
891cb0ef41Sopenharmony_ci    // Check if {lhs} is a HeapNumber.
901cb0ef41Sopenharmony_ci    TNode<HeapObject> lhs_heap_object = CAST(lhs);
911cb0ef41Sopenharmony_ci    GotoIfNot(IsHeapNumber(lhs_heap_object), &if_lhsisnotnumber);
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    if (!rhs_known_smi) {
941cb0ef41Sopenharmony_ci      // Check if the {rhs} is Smi.
951cb0ef41Sopenharmony_ci      Label if_rhsissmi(this), if_rhsisnotsmi(this);
961cb0ef41Sopenharmony_ci      Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci      BIND(&if_rhsisnotsmi);
991cb0ef41Sopenharmony_ci      {
1001cb0ef41Sopenharmony_ci        // Check if the {rhs} is a HeapNumber.
1011cb0ef41Sopenharmony_ci        TNode<HeapObject> rhs_heap_object = CAST(rhs);
1021cb0ef41Sopenharmony_ci        GotoIfNot(IsHeapNumber(rhs_heap_object), &check_rhsisoddball);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci        var_fadd_lhs = LoadHeapNumberValue(lhs_heap_object);
1051cb0ef41Sopenharmony_ci        var_fadd_rhs = LoadHeapNumberValue(rhs_heap_object);
1061cb0ef41Sopenharmony_ci        Goto(&do_fadd);
1071cb0ef41Sopenharmony_ci      }
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci      BIND(&if_rhsissmi);
1101cb0ef41Sopenharmony_ci    }
1111cb0ef41Sopenharmony_ci    {
1121cb0ef41Sopenharmony_ci      var_fadd_lhs = LoadHeapNumberValue(lhs_heap_object);
1131cb0ef41Sopenharmony_ci      var_fadd_rhs = SmiToFloat64(CAST(rhs));
1141cb0ef41Sopenharmony_ci      Goto(&do_fadd);
1151cb0ef41Sopenharmony_ci    }
1161cb0ef41Sopenharmony_ci  }
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  BIND(&do_fadd);
1191cb0ef41Sopenharmony_ci  {
1201cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
1211cb0ef41Sopenharmony_ci    UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(), slot_id,
1221cb0ef41Sopenharmony_ci                   update_feedback_mode);
1231cb0ef41Sopenharmony_ci    TNode<Float64T> value =
1241cb0ef41Sopenharmony_ci        Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
1251cb0ef41Sopenharmony_ci    TNode<HeapNumber> result = AllocateHeapNumberWithValue(value);
1261cb0ef41Sopenharmony_ci    var_result = result;
1271cb0ef41Sopenharmony_ci    Goto(&end);
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  BIND(&if_lhsisnotnumber);
1311cb0ef41Sopenharmony_ci  {
1321cb0ef41Sopenharmony_ci    // No checks on rhs are done yet. We just know lhs is not a number or Smi.
1331cb0ef41Sopenharmony_ci    Label if_lhsisoddball(this), if_lhsisnotoddball(this);
1341cb0ef41Sopenharmony_ci    TNode<Uint16T> lhs_instance_type = LoadInstanceType(CAST(lhs));
1351cb0ef41Sopenharmony_ci    TNode<BoolT> lhs_is_oddball =
1361cb0ef41Sopenharmony_ci        InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE);
1371cb0ef41Sopenharmony_ci    Branch(lhs_is_oddball, &if_lhsisoddball, &if_lhsisnotoddball);
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci    BIND(&if_lhsisoddball);
1401cb0ef41Sopenharmony_ci    {
1411cb0ef41Sopenharmony_ci      GotoIf(TaggedIsSmi(rhs), &call_with_oddball_feedback);
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci      // Check if {rhs} is a HeapNumber.
1441cb0ef41Sopenharmony_ci      Branch(IsHeapNumber(CAST(rhs)), &call_with_oddball_feedback,
1451cb0ef41Sopenharmony_ci             &check_rhsisoddball);
1461cb0ef41Sopenharmony_ci    }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci    BIND(&if_lhsisnotoddball);
1491cb0ef41Sopenharmony_ci    {
1501cb0ef41Sopenharmony_ci      // Check if the {rhs} is a smi, and exit the string and bigint check early
1511cb0ef41Sopenharmony_ci      // if it is.
1521cb0ef41Sopenharmony_ci      GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
1531cb0ef41Sopenharmony_ci      TNode<HeapObject> rhs_heap_object = CAST(rhs);
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci      Label lhs_is_string(this), lhs_is_bigint(this);
1561cb0ef41Sopenharmony_ci      GotoIf(IsStringInstanceType(lhs_instance_type), &lhs_is_string);
1571cb0ef41Sopenharmony_ci      GotoIf(IsBigIntInstanceType(lhs_instance_type), &lhs_is_bigint);
1581cb0ef41Sopenharmony_ci      Goto(&call_with_any_feedback);
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci      BIND(&lhs_is_bigint);
1611cb0ef41Sopenharmony_ci      Branch(IsBigInt(rhs_heap_object), &bigint, &call_with_any_feedback);
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci      BIND(&lhs_is_string);
1641cb0ef41Sopenharmony_ci      {
1651cb0ef41Sopenharmony_ci        TNode<Uint16T> rhs_instance_type = LoadInstanceType(rhs_heap_object);
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci        // Exit unless {rhs} is a string. Since {lhs} is a string we no longer
1681cb0ef41Sopenharmony_ci        // need an Oddball check.
1691cb0ef41Sopenharmony_ci        GotoIfNot(IsStringInstanceType(rhs_instance_type),
1701cb0ef41Sopenharmony_ci                  &call_with_any_feedback);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci        var_type_feedback = SmiConstant(BinaryOperationFeedback::kString);
1731cb0ef41Sopenharmony_ci        UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(),
1741cb0ef41Sopenharmony_ci                       slot_id, update_feedback_mode);
1751cb0ef41Sopenharmony_ci        var_result =
1761cb0ef41Sopenharmony_ci            CallBuiltin(Builtin::kStringAdd_CheckNone, context(), lhs, rhs);
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci        Goto(&end);
1791cb0ef41Sopenharmony_ci      }
1801cb0ef41Sopenharmony_ci    }
1811cb0ef41Sopenharmony_ci  }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  BIND(&check_rhsisoddball);
1841cb0ef41Sopenharmony_ci  {
1851cb0ef41Sopenharmony_ci    // Check if rhs is an oddball. At this point we know lhs is either a
1861cb0ef41Sopenharmony_ci    // Smi or number or oddball and rhs is not a number or Smi.
1871cb0ef41Sopenharmony_ci    TNode<Uint16T> rhs_instance_type = LoadInstanceType(CAST(rhs));
1881cb0ef41Sopenharmony_ci    TNode<BoolT> rhs_is_oddball =
1891cb0ef41Sopenharmony_ci        InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
1901cb0ef41Sopenharmony_ci    GotoIf(rhs_is_oddball, &call_with_oddball_feedback);
1911cb0ef41Sopenharmony_ci    Goto(&call_with_any_feedback);
1921cb0ef41Sopenharmony_ci  }
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  BIND(&bigint);
1951cb0ef41Sopenharmony_ci  {
1961cb0ef41Sopenharmony_ci    // Both {lhs} and {rhs} are of BigInt type.
1971cb0ef41Sopenharmony_ci    Label bigint_too_big(this);
1981cb0ef41Sopenharmony_ci    var_result = CallBuiltin(Builtin::kBigIntAddNoThrow, context(), lhs, rhs);
1991cb0ef41Sopenharmony_ci    // Check for sentinel that signals BigIntTooBig exception.
2001cb0ef41Sopenharmony_ci    GotoIf(TaggedIsSmi(var_result.value()), &bigint_too_big);
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt);
2031cb0ef41Sopenharmony_ci    UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(), slot_id,
2041cb0ef41Sopenharmony_ci                   update_feedback_mode);
2051cb0ef41Sopenharmony_ci    Goto(&end);
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci    BIND(&bigint_too_big);
2081cb0ef41Sopenharmony_ci    {
2091cb0ef41Sopenharmony_ci      // Update feedback to prevent deopt loop.
2101cb0ef41Sopenharmony_ci      UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
2111cb0ef41Sopenharmony_ci                     maybe_feedback_vector(), slot_id, update_feedback_mode);
2121cb0ef41Sopenharmony_ci      ThrowRangeError(context(), MessageTemplate::kBigIntTooBig);
2131cb0ef41Sopenharmony_ci    }
2141cb0ef41Sopenharmony_ci  }
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  BIND(&call_with_oddball_feedback);
2171cb0ef41Sopenharmony_ci  {
2181cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumberOrOddball);
2191cb0ef41Sopenharmony_ci    Goto(&call_add_stub);
2201cb0ef41Sopenharmony_ci  }
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  BIND(&call_with_any_feedback);
2231cb0ef41Sopenharmony_ci  {
2241cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kAny);
2251cb0ef41Sopenharmony_ci    Goto(&call_add_stub);
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  BIND(&call_add_stub);
2291cb0ef41Sopenharmony_ci  {
2301cb0ef41Sopenharmony_ci    UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(), slot_id,
2311cb0ef41Sopenharmony_ci                   update_feedback_mode);
2321cb0ef41Sopenharmony_ci    var_result = CallBuiltin(Builtin::kAdd, context(), lhs, rhs);
2331cb0ef41Sopenharmony_ci    Goto(&end);
2341cb0ef41Sopenharmony_ci  }
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  BIND(&end);
2371cb0ef41Sopenharmony_ci  return var_result.value();
2381cb0ef41Sopenharmony_ci}
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
2411cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<Object> lhs, TNode<Object> rhs,
2421cb0ef41Sopenharmony_ci    TNode<UintPtrT> slot_id, const LazyNode<HeapObject>& maybe_feedback_vector,
2431cb0ef41Sopenharmony_ci    const SmiOperation& smiOperation, const FloatOperation& floatOperation,
2441cb0ef41Sopenharmony_ci    Operation op, UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
2451cb0ef41Sopenharmony_ci  Label do_float_operation(this), end(this), call_stub(this),
2461cb0ef41Sopenharmony_ci      check_rhsisoddball(this, Label::kDeferred), call_with_any_feedback(this),
2471cb0ef41Sopenharmony_ci      if_lhsisnotnumber(this, Label::kDeferred),
2481cb0ef41Sopenharmony_ci      if_both_bigint(this, Label::kDeferred);
2491cb0ef41Sopenharmony_ci  TVARIABLE(Float64T, var_float_lhs);
2501cb0ef41Sopenharmony_ci  TVARIABLE(Float64T, var_float_rhs);
2511cb0ef41Sopenharmony_ci  TVARIABLE(Smi, var_type_feedback);
2521cb0ef41Sopenharmony_ci  TVARIABLE(Object, var_result);
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  Label if_lhsissmi(this);
2551cb0ef41Sopenharmony_ci  // If rhs is known to be an Smi (in the SubSmi, MulSmi, DivSmi, ModSmi
2561cb0ef41Sopenharmony_ci  // bytecode handlers) we want to fast path Smi operation. For the normal
2571cb0ef41Sopenharmony_ci  // operation, we want to fast path both Smi and Number operations, so this
2581cb0ef41Sopenharmony_ci  // path should not be marked as Deferred.
2591cb0ef41Sopenharmony_ci  Label if_lhsisnotsmi(this,
2601cb0ef41Sopenharmony_ci                       rhs_known_smi ? Label::kDeferred : Label::kNonDeferred);
2611cb0ef41Sopenharmony_ci  Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  // Check if the {lhs} is a Smi or a HeapObject.
2641cb0ef41Sopenharmony_ci  BIND(&if_lhsissmi);
2651cb0ef41Sopenharmony_ci  {
2661cb0ef41Sopenharmony_ci    Comment("lhs is Smi");
2671cb0ef41Sopenharmony_ci    TNode<Smi> lhs_smi = CAST(lhs);
2681cb0ef41Sopenharmony_ci    if (!rhs_known_smi) {
2691cb0ef41Sopenharmony_ci      // Check if the {rhs} is also a Smi.
2701cb0ef41Sopenharmony_ci      Label if_rhsissmi(this), if_rhsisnotsmi(this);
2711cb0ef41Sopenharmony_ci      Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci      BIND(&if_rhsisnotsmi);
2741cb0ef41Sopenharmony_ci      {
2751cb0ef41Sopenharmony_ci        // Check if {rhs} is a HeapNumber.
2761cb0ef41Sopenharmony_ci        TNode<HeapObject> rhs_heap_object = CAST(rhs);
2771cb0ef41Sopenharmony_ci        GotoIfNot(IsHeapNumber(rhs_heap_object), &check_rhsisoddball);
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci        // Perform a floating point operation.
2801cb0ef41Sopenharmony_ci        var_float_lhs = SmiToFloat64(lhs_smi);
2811cb0ef41Sopenharmony_ci        var_float_rhs = LoadHeapNumberValue(rhs_heap_object);
2821cb0ef41Sopenharmony_ci        Goto(&do_float_operation);
2831cb0ef41Sopenharmony_ci      }
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci      BIND(&if_rhsissmi);
2861cb0ef41Sopenharmony_ci    }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci    {
2891cb0ef41Sopenharmony_ci      Comment("perform smi operation");
2901cb0ef41Sopenharmony_ci      var_result = smiOperation(lhs_smi, CAST(rhs), &var_type_feedback);
2911cb0ef41Sopenharmony_ci      UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(),
2921cb0ef41Sopenharmony_ci                     slot_id, update_feedback_mode);
2931cb0ef41Sopenharmony_ci      Goto(&end);
2941cb0ef41Sopenharmony_ci    }
2951cb0ef41Sopenharmony_ci  }
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci  BIND(&if_lhsisnotsmi);
2981cb0ef41Sopenharmony_ci  {
2991cb0ef41Sopenharmony_ci    Comment("lhs is not Smi");
3001cb0ef41Sopenharmony_ci    // Check if the {lhs} is a HeapNumber.
3011cb0ef41Sopenharmony_ci    TNode<HeapObject> lhs_heap_object = CAST(lhs);
3021cb0ef41Sopenharmony_ci    GotoIfNot(IsHeapNumber(lhs_heap_object), &if_lhsisnotnumber);
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci    if (!rhs_known_smi) {
3051cb0ef41Sopenharmony_ci      // Check if the {rhs} is a Smi.
3061cb0ef41Sopenharmony_ci      Label if_rhsissmi(this), if_rhsisnotsmi(this);
3071cb0ef41Sopenharmony_ci      Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci      BIND(&if_rhsisnotsmi);
3101cb0ef41Sopenharmony_ci      {
3111cb0ef41Sopenharmony_ci        // Check if the {rhs} is a HeapNumber.
3121cb0ef41Sopenharmony_ci        TNode<HeapObject> rhs_heap_object = CAST(rhs);
3131cb0ef41Sopenharmony_ci        GotoIfNot(IsHeapNumber(rhs_heap_object), &check_rhsisoddball);
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci        // Perform a floating point operation.
3161cb0ef41Sopenharmony_ci        var_float_lhs = LoadHeapNumberValue(lhs_heap_object);
3171cb0ef41Sopenharmony_ci        var_float_rhs = LoadHeapNumberValue(rhs_heap_object);
3181cb0ef41Sopenharmony_ci        Goto(&do_float_operation);
3191cb0ef41Sopenharmony_ci      }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci      BIND(&if_rhsissmi);
3221cb0ef41Sopenharmony_ci    }
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci    {
3251cb0ef41Sopenharmony_ci      // Perform floating point operation.
3261cb0ef41Sopenharmony_ci      var_float_lhs = LoadHeapNumberValue(lhs_heap_object);
3271cb0ef41Sopenharmony_ci      var_float_rhs = SmiToFloat64(CAST(rhs));
3281cb0ef41Sopenharmony_ci      Goto(&do_float_operation);
3291cb0ef41Sopenharmony_ci    }
3301cb0ef41Sopenharmony_ci  }
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci  BIND(&do_float_operation);
3331cb0ef41Sopenharmony_ci  {
3341cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
3351cb0ef41Sopenharmony_ci    UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(), slot_id,
3361cb0ef41Sopenharmony_ci                   update_feedback_mode);
3371cb0ef41Sopenharmony_ci    TNode<Float64T> lhs_value = var_float_lhs.value();
3381cb0ef41Sopenharmony_ci    TNode<Float64T> rhs_value = var_float_rhs.value();
3391cb0ef41Sopenharmony_ci    TNode<Float64T> value = floatOperation(lhs_value, rhs_value);
3401cb0ef41Sopenharmony_ci    var_result = AllocateHeapNumberWithValue(value);
3411cb0ef41Sopenharmony_ci    Goto(&end);
3421cb0ef41Sopenharmony_ci  }
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  BIND(&if_lhsisnotnumber);
3451cb0ef41Sopenharmony_ci  {
3461cb0ef41Sopenharmony_ci    // No checks on rhs are done yet. We just know lhs is not a number or Smi.
3471cb0ef41Sopenharmony_ci    Label if_left_bigint(this), if_left_oddball(this);
3481cb0ef41Sopenharmony_ci    TNode<Uint16T> lhs_instance_type = LoadInstanceType(CAST(lhs));
3491cb0ef41Sopenharmony_ci    GotoIf(IsBigIntInstanceType(lhs_instance_type), &if_left_bigint);
3501cb0ef41Sopenharmony_ci    TNode<BoolT> lhs_is_oddball =
3511cb0ef41Sopenharmony_ci        InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE);
3521cb0ef41Sopenharmony_ci    Branch(lhs_is_oddball, &if_left_oddball, &call_with_any_feedback);
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci    BIND(&if_left_oddball);
3551cb0ef41Sopenharmony_ci    {
3561cb0ef41Sopenharmony_ci      Label if_rhsissmi(this), if_rhsisnotsmi(this);
3571cb0ef41Sopenharmony_ci      Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci      BIND(&if_rhsissmi);
3601cb0ef41Sopenharmony_ci      {
3611cb0ef41Sopenharmony_ci        var_type_feedback =
3621cb0ef41Sopenharmony_ci            SmiConstant(BinaryOperationFeedback::kNumberOrOddball);
3631cb0ef41Sopenharmony_ci        Goto(&call_stub);
3641cb0ef41Sopenharmony_ci      }
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci      BIND(&if_rhsisnotsmi);
3671cb0ef41Sopenharmony_ci      {
3681cb0ef41Sopenharmony_ci        // Check if {rhs} is a HeapNumber.
3691cb0ef41Sopenharmony_ci        GotoIfNot(IsHeapNumber(CAST(rhs)), &check_rhsisoddball);
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci        var_type_feedback =
3721cb0ef41Sopenharmony_ci            SmiConstant(BinaryOperationFeedback::kNumberOrOddball);
3731cb0ef41Sopenharmony_ci        Goto(&call_stub);
3741cb0ef41Sopenharmony_ci      }
3751cb0ef41Sopenharmony_ci    }
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci    BIND(&if_left_bigint);
3781cb0ef41Sopenharmony_ci    {
3791cb0ef41Sopenharmony_ci      GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
3801cb0ef41Sopenharmony_ci      Branch(IsBigInt(CAST(rhs)), &if_both_bigint, &call_with_any_feedback);
3811cb0ef41Sopenharmony_ci    }
3821cb0ef41Sopenharmony_ci  }
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  BIND(&check_rhsisoddball);
3851cb0ef41Sopenharmony_ci  {
3861cb0ef41Sopenharmony_ci    // Check if rhs is an oddball. At this point we know lhs is either a
3871cb0ef41Sopenharmony_ci    // Smi or number or oddball and rhs is not a number or Smi.
3881cb0ef41Sopenharmony_ci    TNode<Uint16T> rhs_instance_type = LoadInstanceType(CAST(rhs));
3891cb0ef41Sopenharmony_ci    TNode<BoolT> rhs_is_oddball =
3901cb0ef41Sopenharmony_ci        InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
3911cb0ef41Sopenharmony_ci    GotoIfNot(rhs_is_oddball, &call_with_any_feedback);
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumberOrOddball);
3941cb0ef41Sopenharmony_ci    Goto(&call_stub);
3951cb0ef41Sopenharmony_ci  }
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci  BIND(&if_both_bigint);
3981cb0ef41Sopenharmony_ci  {
3991cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt);
4001cb0ef41Sopenharmony_ci    UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(), slot_id,
4011cb0ef41Sopenharmony_ci                   update_feedback_mode);
4021cb0ef41Sopenharmony_ci    if (op == Operation::kSubtract) {
4031cb0ef41Sopenharmony_ci      Label bigint_too_big(this);
4041cb0ef41Sopenharmony_ci      var_result =
4051cb0ef41Sopenharmony_ci          CallBuiltin(Builtin::kBigIntSubtractNoThrow, context(), lhs, rhs);
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci      // Check for sentinel that signals BigIntTooBig exception.
4081cb0ef41Sopenharmony_ci      GotoIf(TaggedIsSmi(var_result.value()), &bigint_too_big);
4091cb0ef41Sopenharmony_ci      Goto(&end);
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci      BIND(&bigint_too_big);
4121cb0ef41Sopenharmony_ci      {
4131cb0ef41Sopenharmony_ci        // Update feedback to prevent deopt loop.
4141cb0ef41Sopenharmony_ci        UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
4151cb0ef41Sopenharmony_ci                       maybe_feedback_vector(), slot_id, update_feedback_mode);
4161cb0ef41Sopenharmony_ci        ThrowRangeError(context(), MessageTemplate::kBigIntTooBig);
4171cb0ef41Sopenharmony_ci      }
4181cb0ef41Sopenharmony_ci    } else {
4191cb0ef41Sopenharmony_ci      var_result = CallRuntime(Runtime::kBigIntBinaryOp, context(), lhs, rhs,
4201cb0ef41Sopenharmony_ci                               SmiConstant(op));
4211cb0ef41Sopenharmony_ci      Goto(&end);
4221cb0ef41Sopenharmony_ci    }
4231cb0ef41Sopenharmony_ci  }
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_ci  BIND(&call_with_any_feedback);
4261cb0ef41Sopenharmony_ci  {
4271cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kAny);
4281cb0ef41Sopenharmony_ci    Goto(&call_stub);
4291cb0ef41Sopenharmony_ci  }
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci  BIND(&call_stub);
4321cb0ef41Sopenharmony_ci  {
4331cb0ef41Sopenharmony_ci    UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(), slot_id,
4341cb0ef41Sopenharmony_ci                   update_feedback_mode);
4351cb0ef41Sopenharmony_ci    TNode<Object> result;
4361cb0ef41Sopenharmony_ci    switch (op) {
4371cb0ef41Sopenharmony_ci      case Operation::kSubtract:
4381cb0ef41Sopenharmony_ci        result = CallBuiltin(Builtin::kSubtract, context(), lhs, rhs);
4391cb0ef41Sopenharmony_ci        break;
4401cb0ef41Sopenharmony_ci      case Operation::kMultiply:
4411cb0ef41Sopenharmony_ci        result = CallBuiltin(Builtin::kMultiply, context(), lhs, rhs);
4421cb0ef41Sopenharmony_ci        break;
4431cb0ef41Sopenharmony_ci      case Operation::kDivide:
4441cb0ef41Sopenharmony_ci        result = CallBuiltin(Builtin::kDivide, context(), lhs, rhs);
4451cb0ef41Sopenharmony_ci        break;
4461cb0ef41Sopenharmony_ci      case Operation::kModulus:
4471cb0ef41Sopenharmony_ci        result = CallBuiltin(Builtin::kModulus, context(), lhs, rhs);
4481cb0ef41Sopenharmony_ci        break;
4491cb0ef41Sopenharmony_ci      case Operation::kExponentiate:
4501cb0ef41Sopenharmony_ci        result = CallBuiltin(Builtin::kExponentiate, context(), lhs, rhs);
4511cb0ef41Sopenharmony_ci        break;
4521cb0ef41Sopenharmony_ci      default:
4531cb0ef41Sopenharmony_ci        UNREACHABLE();
4541cb0ef41Sopenharmony_ci    }
4551cb0ef41Sopenharmony_ci    var_result = result;
4561cb0ef41Sopenharmony_ci    Goto(&end);
4571cb0ef41Sopenharmony_ci  }
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  BIND(&end);
4601cb0ef41Sopenharmony_ci  return var_result.value();
4611cb0ef41Sopenharmony_ci}
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_SubtractWithFeedback(
4641cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<Object> lhs, TNode<Object> rhs,
4651cb0ef41Sopenharmony_ci    TNode<UintPtrT> slot_id, const LazyNode<HeapObject>& maybe_feedback_vector,
4661cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
4671cb0ef41Sopenharmony_ci  auto smiFunction = [=](TNode<Smi> lhs, TNode<Smi> rhs,
4681cb0ef41Sopenharmony_ci                         TVariable<Smi>* var_type_feedback) {
4691cb0ef41Sopenharmony_ci    Label end(this);
4701cb0ef41Sopenharmony_ci    TVARIABLE(Number, var_result);
4711cb0ef41Sopenharmony_ci    // If rhs is known to be an Smi (for SubSmi) we want to fast path Smi
4721cb0ef41Sopenharmony_ci    // operation. For the normal Sub operation, we want to fast path both
4731cb0ef41Sopenharmony_ci    // Smi and Number operations, so this path should not be marked as Deferred.
4741cb0ef41Sopenharmony_ci    Label if_overflow(this,
4751cb0ef41Sopenharmony_ci                      rhs_known_smi ? Label::kDeferred : Label::kNonDeferred);
4761cb0ef41Sopenharmony_ci    var_result = TrySmiSub(lhs, rhs, &if_overflow);
4771cb0ef41Sopenharmony_ci    *var_type_feedback = SmiConstant(BinaryOperationFeedback::kSignedSmall);
4781cb0ef41Sopenharmony_ci    Goto(&end);
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci    BIND(&if_overflow);
4811cb0ef41Sopenharmony_ci    {
4821cb0ef41Sopenharmony_ci      *var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
4831cb0ef41Sopenharmony_ci      TNode<Float64T> value = Float64Sub(SmiToFloat64(lhs), SmiToFloat64(rhs));
4841cb0ef41Sopenharmony_ci      var_result = AllocateHeapNumberWithValue(value);
4851cb0ef41Sopenharmony_ci      Goto(&end);
4861cb0ef41Sopenharmony_ci    }
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci    BIND(&end);
4891cb0ef41Sopenharmony_ci    return var_result.value();
4901cb0ef41Sopenharmony_ci  };
4911cb0ef41Sopenharmony_ci  auto floatFunction = [=](TNode<Float64T> lhs, TNode<Float64T> rhs) {
4921cb0ef41Sopenharmony_ci    return Float64Sub(lhs, rhs);
4931cb0ef41Sopenharmony_ci  };
4941cb0ef41Sopenharmony_ci  return Generate_BinaryOperationWithFeedback(
4951cb0ef41Sopenharmony_ci      context, lhs, rhs, slot_id, maybe_feedback_vector, smiFunction,
4961cb0ef41Sopenharmony_ci      floatFunction, Operation::kSubtract, update_feedback_mode, rhs_known_smi);
4971cb0ef41Sopenharmony_ci}
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_MultiplyWithFeedback(
5001cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<Object> lhs, TNode<Object> rhs,
5011cb0ef41Sopenharmony_ci    TNode<UintPtrT> slot_id, const LazyNode<HeapObject>& maybe_feedback_vector,
5021cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
5031cb0ef41Sopenharmony_ci  auto smiFunction = [=](TNode<Smi> lhs, TNode<Smi> rhs,
5041cb0ef41Sopenharmony_ci                         TVariable<Smi>* var_type_feedback) {
5051cb0ef41Sopenharmony_ci    TNode<Number> result = SmiMul(lhs, rhs);
5061cb0ef41Sopenharmony_ci    *var_type_feedback = SelectSmiConstant(
5071cb0ef41Sopenharmony_ci        TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
5081cb0ef41Sopenharmony_ci        BinaryOperationFeedback::kNumber);
5091cb0ef41Sopenharmony_ci    return result;
5101cb0ef41Sopenharmony_ci  };
5111cb0ef41Sopenharmony_ci  auto floatFunction = [=](TNode<Float64T> lhs, TNode<Float64T> rhs) {
5121cb0ef41Sopenharmony_ci    return Float64Mul(lhs, rhs);
5131cb0ef41Sopenharmony_ci  };
5141cb0ef41Sopenharmony_ci  return Generate_BinaryOperationWithFeedback(
5151cb0ef41Sopenharmony_ci      context, lhs, rhs, slot_id, maybe_feedback_vector, smiFunction,
5161cb0ef41Sopenharmony_ci      floatFunction, Operation::kMultiply, update_feedback_mode, rhs_known_smi);
5171cb0ef41Sopenharmony_ci}
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_DivideWithFeedback(
5201cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<Object> dividend,
5211cb0ef41Sopenharmony_ci    TNode<Object> divisor, TNode<UintPtrT> slot_id,
5221cb0ef41Sopenharmony_ci    const LazyNode<HeapObject>& maybe_feedback_vector,
5231cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
5241cb0ef41Sopenharmony_ci  auto smiFunction = [=](TNode<Smi> lhs, TNode<Smi> rhs,
5251cb0ef41Sopenharmony_ci                         TVariable<Smi>* var_type_feedback) {
5261cb0ef41Sopenharmony_ci    TVARIABLE(Object, var_result);
5271cb0ef41Sopenharmony_ci    // If rhs is known to be an Smi (for DivSmi) we want to fast path Smi
5281cb0ef41Sopenharmony_ci    // operation. For the normal Div operation, we want to fast path both
5291cb0ef41Sopenharmony_ci    // Smi and Number operations, so this path should not be marked as Deferred.
5301cb0ef41Sopenharmony_ci    Label bailout(this, rhs_known_smi ? Label::kDeferred : Label::kNonDeferred),
5311cb0ef41Sopenharmony_ci        end(this);
5321cb0ef41Sopenharmony_ci    var_result = TrySmiDiv(lhs, rhs, &bailout);
5331cb0ef41Sopenharmony_ci    *var_type_feedback = SmiConstant(BinaryOperationFeedback::kSignedSmall);
5341cb0ef41Sopenharmony_ci    Goto(&end);
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci    BIND(&bailout);
5371cb0ef41Sopenharmony_ci    {
5381cb0ef41Sopenharmony_ci      *var_type_feedback =
5391cb0ef41Sopenharmony_ci          SmiConstant(BinaryOperationFeedback::kSignedSmallInputs);
5401cb0ef41Sopenharmony_ci      TNode<Float64T> value = Float64Div(SmiToFloat64(lhs), SmiToFloat64(rhs));
5411cb0ef41Sopenharmony_ci      var_result = AllocateHeapNumberWithValue(value);
5421cb0ef41Sopenharmony_ci      Goto(&end);
5431cb0ef41Sopenharmony_ci    }
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ci    BIND(&end);
5461cb0ef41Sopenharmony_ci    return var_result.value();
5471cb0ef41Sopenharmony_ci  };
5481cb0ef41Sopenharmony_ci  auto floatFunction = [=](TNode<Float64T> lhs, TNode<Float64T> rhs) {
5491cb0ef41Sopenharmony_ci    return Float64Div(lhs, rhs);
5501cb0ef41Sopenharmony_ci  };
5511cb0ef41Sopenharmony_ci  return Generate_BinaryOperationWithFeedback(
5521cb0ef41Sopenharmony_ci      context, dividend, divisor, slot_id, maybe_feedback_vector, smiFunction,
5531cb0ef41Sopenharmony_ci      floatFunction, Operation::kDivide, update_feedback_mode, rhs_known_smi);
5541cb0ef41Sopenharmony_ci}
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_ModulusWithFeedback(
5571cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<Object> dividend,
5581cb0ef41Sopenharmony_ci    TNode<Object> divisor, TNode<UintPtrT> slot_id,
5591cb0ef41Sopenharmony_ci    const LazyNode<HeapObject>& maybe_feedback_vector,
5601cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
5611cb0ef41Sopenharmony_ci  auto smiFunction = [=](TNode<Smi> lhs, TNode<Smi> rhs,
5621cb0ef41Sopenharmony_ci                         TVariable<Smi>* var_type_feedback) {
5631cb0ef41Sopenharmony_ci    TNode<Number> result = SmiMod(lhs, rhs);
5641cb0ef41Sopenharmony_ci    *var_type_feedback = SelectSmiConstant(
5651cb0ef41Sopenharmony_ci        TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
5661cb0ef41Sopenharmony_ci        BinaryOperationFeedback::kNumber);
5671cb0ef41Sopenharmony_ci    return result;
5681cb0ef41Sopenharmony_ci  };
5691cb0ef41Sopenharmony_ci  auto floatFunction = [=](TNode<Float64T> lhs, TNode<Float64T> rhs) {
5701cb0ef41Sopenharmony_ci    return Float64Mod(lhs, rhs);
5711cb0ef41Sopenharmony_ci  };
5721cb0ef41Sopenharmony_ci  return Generate_BinaryOperationWithFeedback(
5731cb0ef41Sopenharmony_ci      context, dividend, divisor, slot_id, maybe_feedback_vector, smiFunction,
5741cb0ef41Sopenharmony_ci      floatFunction, Operation::kModulus, update_feedback_mode, rhs_known_smi);
5751cb0ef41Sopenharmony_ci}
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_ExponentiateWithFeedback(
5781cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<Object> base,
5791cb0ef41Sopenharmony_ci    TNode<Object> exponent, TNode<UintPtrT> slot_id,
5801cb0ef41Sopenharmony_ci    const LazyNode<HeapObject>& maybe_feedback_vector,
5811cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
5821cb0ef41Sopenharmony_ci  auto smiFunction = [=](TNode<Smi> base, TNode<Smi> exponent,
5831cb0ef41Sopenharmony_ci                         TVariable<Smi>* var_type_feedback) {
5841cb0ef41Sopenharmony_ci    *var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
5851cb0ef41Sopenharmony_ci    return AllocateHeapNumberWithValue(
5861cb0ef41Sopenharmony_ci        Float64Pow(SmiToFloat64(base), SmiToFloat64(exponent)));
5871cb0ef41Sopenharmony_ci  };
5881cb0ef41Sopenharmony_ci  auto floatFunction = [=](TNode<Float64T> base, TNode<Float64T> exponent) {
5891cb0ef41Sopenharmony_ci    return Float64Pow(base, exponent);
5901cb0ef41Sopenharmony_ci  };
5911cb0ef41Sopenharmony_ci  return Generate_BinaryOperationWithFeedback(
5921cb0ef41Sopenharmony_ci      context, base, exponent, slot_id, maybe_feedback_vector, smiFunction,
5931cb0ef41Sopenharmony_ci      floatFunction, Operation::kExponentiate, update_feedback_mode,
5941cb0ef41Sopenharmony_ci      rhs_known_smi);
5951cb0ef41Sopenharmony_ci}
5961cb0ef41Sopenharmony_ci
5971cb0ef41Sopenharmony_ciTNode<Object> BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback(
5981cb0ef41Sopenharmony_ci    Operation bitwise_op, TNode<Object> left, TNode<Object> right,
5991cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<UintPtrT>* slot,
6001cb0ef41Sopenharmony_ci    const LazyNode<HeapObject>* maybe_feedback_vector,
6011cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode) {
6021cb0ef41Sopenharmony_ci  TVARIABLE(Object, result);
6031cb0ef41Sopenharmony_ci  TVARIABLE(Smi, var_left_feedback);
6041cb0ef41Sopenharmony_ci  TVARIABLE(Smi, var_right_feedback);
6051cb0ef41Sopenharmony_ci  TVARIABLE(Word32T, var_left_word32);
6061cb0ef41Sopenharmony_ci  TVARIABLE(Word32T, var_right_word32);
6071cb0ef41Sopenharmony_ci  TVARIABLE(BigInt, var_left_bigint);
6081cb0ef41Sopenharmony_ci  TVARIABLE(BigInt, var_right_bigint);
6091cb0ef41Sopenharmony_ci  // These are the variables that are passed to BigIntBinaryOp. They are not
6101cb0ef41Sopenharmony_ci  // guaranteed to be BigInts because the Runtime call handles throwing
6111cb0ef41Sopenharmony_ci  // exceptions when only one side is a BigInt.
6121cb0ef41Sopenharmony_ci  TVARIABLE(Object, var_left_maybe_bigint, left);
6131cb0ef41Sopenharmony_ci  TVARIABLE(Numeric, var_right_maybe_bigint);
6141cb0ef41Sopenharmony_ci  Label done(this);
6151cb0ef41Sopenharmony_ci  Label if_left_number(this), do_number_op(this);
6161cb0ef41Sopenharmony_ci  Label if_left_bigint(this), do_bigint_op(this);
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci  TaggedToWord32OrBigIntWithFeedback(
6191cb0ef41Sopenharmony_ci      context(), left, &if_left_number, &var_left_word32, &if_left_bigint,
6201cb0ef41Sopenharmony_ci      &var_left_bigint, slot ? &var_left_feedback : nullptr);
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci  Label right_is_bigint(this);
6231cb0ef41Sopenharmony_ci  BIND(&if_left_number);
6241cb0ef41Sopenharmony_ci  {
6251cb0ef41Sopenharmony_ci    TaggedToWord32OrBigIntWithFeedback(
6261cb0ef41Sopenharmony_ci        context(), right, &do_number_op, &var_right_word32, &right_is_bigint,
6271cb0ef41Sopenharmony_ci        &var_right_bigint, slot ? &var_right_feedback : nullptr);
6281cb0ef41Sopenharmony_ci  }
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  BIND(&right_is_bigint);
6311cb0ef41Sopenharmony_ci  {
6321cb0ef41Sopenharmony_ci    // At this point it's guaranteed that the op will fail because the RHS is a
6331cb0ef41Sopenharmony_ci    // BigInt while the LHS is not, but that's ok because the Runtime call will
6341cb0ef41Sopenharmony_ci    // throw the exception.
6351cb0ef41Sopenharmony_ci    var_right_maybe_bigint = var_right_bigint.value();
6361cb0ef41Sopenharmony_ci    Goto(&do_bigint_op);
6371cb0ef41Sopenharmony_ci  }
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci  BIND(&do_number_op);
6401cb0ef41Sopenharmony_ci  {
6411cb0ef41Sopenharmony_ci    result = BitwiseOp(var_left_word32.value(), var_right_word32.value(),
6421cb0ef41Sopenharmony_ci                       bitwise_op);
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ci    if (slot) {
6451cb0ef41Sopenharmony_ci      TNode<Smi> result_type = SelectSmiConstant(
6461cb0ef41Sopenharmony_ci          TaggedIsSmi(result.value()), BinaryOperationFeedback::kSignedSmall,
6471cb0ef41Sopenharmony_ci          BinaryOperationFeedback::kNumber);
6481cb0ef41Sopenharmony_ci      TNode<Smi> input_feedback =
6491cb0ef41Sopenharmony_ci          SmiOr(var_left_feedback.value(), var_right_feedback.value());
6501cb0ef41Sopenharmony_ci      TNode<Smi> feedback = SmiOr(result_type, input_feedback);
6511cb0ef41Sopenharmony_ci      UpdateFeedback(feedback, (*maybe_feedback_vector)(), *slot,
6521cb0ef41Sopenharmony_ci                     update_feedback_mode);
6531cb0ef41Sopenharmony_ci    }
6541cb0ef41Sopenharmony_ci    Goto(&done);
6551cb0ef41Sopenharmony_ci  }
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_ci  // BigInt cases.
6581cb0ef41Sopenharmony_ci  BIND(&if_left_bigint);
6591cb0ef41Sopenharmony_ci  {
6601cb0ef41Sopenharmony_ci    TaggedToNumericWithFeedback(context(), right, &var_right_maybe_bigint,
6611cb0ef41Sopenharmony_ci                                &var_right_feedback);
6621cb0ef41Sopenharmony_ci    var_left_maybe_bigint = var_left_bigint.value();
6631cb0ef41Sopenharmony_ci    Goto(&do_bigint_op);
6641cb0ef41Sopenharmony_ci  }
6651cb0ef41Sopenharmony_ci
6661cb0ef41Sopenharmony_ci  BIND(&do_bigint_op);
6671cb0ef41Sopenharmony_ci  {
6681cb0ef41Sopenharmony_ci    if (slot) {
6691cb0ef41Sopenharmony_ci      // Ensure that the feedback is updated even if the runtime call below
6701cb0ef41Sopenharmony_ci      // would throw.
6711cb0ef41Sopenharmony_ci      TNode<Smi> feedback =
6721cb0ef41Sopenharmony_ci          SmiOr(var_left_feedback.value(), var_right_feedback.value());
6731cb0ef41Sopenharmony_ci      UpdateFeedback(feedback, (*maybe_feedback_vector)(), *slot,
6741cb0ef41Sopenharmony_ci                     update_feedback_mode);
6751cb0ef41Sopenharmony_ci    }
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_ci    result = CallRuntime(
6781cb0ef41Sopenharmony_ci        Runtime::kBigIntBinaryOp, context(), var_left_maybe_bigint.value(),
6791cb0ef41Sopenharmony_ci        var_right_maybe_bigint.value(), SmiConstant(bitwise_op));
6801cb0ef41Sopenharmony_ci    Goto(&done);
6811cb0ef41Sopenharmony_ci  }
6821cb0ef41Sopenharmony_ci
6831cb0ef41Sopenharmony_ci  BIND(&done);
6841cb0ef41Sopenharmony_ci  return result.value();
6851cb0ef41Sopenharmony_ci}
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ciTNode<Object>
6881cb0ef41Sopenharmony_ciBinaryOpAssembler::Generate_BitwiseBinaryOpWithSmiOperandAndOptionalFeedback(
6891cb0ef41Sopenharmony_ci    Operation bitwise_op, TNode<Object> left, TNode<Object> right,
6901cb0ef41Sopenharmony_ci    const LazyNode<Context>& context, TNode<UintPtrT>* slot,
6911cb0ef41Sopenharmony_ci    const LazyNode<HeapObject>* maybe_feedback_vector,
6921cb0ef41Sopenharmony_ci    UpdateFeedbackMode update_feedback_mode) {
6931cb0ef41Sopenharmony_ci  TNode<Smi> right_smi = CAST(right);
6941cb0ef41Sopenharmony_ci  TVARIABLE(Object, result);
6951cb0ef41Sopenharmony_ci  TVARIABLE(Smi, var_left_feedback);
6961cb0ef41Sopenharmony_ci  TVARIABLE(Word32T, var_left_word32);
6971cb0ef41Sopenharmony_ci  TVARIABLE(BigInt, var_left_bigint);
6981cb0ef41Sopenharmony_ci  TVARIABLE(Smi, feedback);
6991cb0ef41Sopenharmony_ci  // Check if the {lhs} is a Smi or a HeapObject.
7001cb0ef41Sopenharmony_ci  Label if_lhsissmi(this), if_lhsisnotsmi(this, Label::kDeferred);
7011cb0ef41Sopenharmony_ci  Label do_number_op(this), if_bigint_mix(this), done(this);
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_ci  Branch(TaggedIsSmi(left), &if_lhsissmi, &if_lhsisnotsmi);
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ci  BIND(&if_lhsissmi);
7061cb0ef41Sopenharmony_ci  {
7071cb0ef41Sopenharmony_ci    TNode<Smi> left_smi = CAST(left);
7081cb0ef41Sopenharmony_ci    result = BitwiseSmiOp(left_smi, right_smi, bitwise_op);
7091cb0ef41Sopenharmony_ci    if (slot) {
7101cb0ef41Sopenharmony_ci      if (IsBitwiseOutputKnownSmi(bitwise_op)) {
7111cb0ef41Sopenharmony_ci        feedback = SmiConstant(BinaryOperationFeedback::kSignedSmall);
7121cb0ef41Sopenharmony_ci      } else {
7131cb0ef41Sopenharmony_ci        feedback = SelectSmiConstant(TaggedIsSmi(result.value()),
7141cb0ef41Sopenharmony_ci                                     BinaryOperationFeedback::kSignedSmall,
7151cb0ef41Sopenharmony_ci                                     BinaryOperationFeedback::kNumber);
7161cb0ef41Sopenharmony_ci      }
7171cb0ef41Sopenharmony_ci    }
7181cb0ef41Sopenharmony_ci    Goto(&done);
7191cb0ef41Sopenharmony_ci  }
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  BIND(&if_lhsisnotsmi);
7221cb0ef41Sopenharmony_ci  {
7231cb0ef41Sopenharmony_ci    TNode<HeapObject> left_pointer = CAST(left);
7241cb0ef41Sopenharmony_ci    TaggedPointerToWord32OrBigIntWithFeedback(
7251cb0ef41Sopenharmony_ci        context(), left_pointer, &do_number_op, &var_left_word32,
7261cb0ef41Sopenharmony_ci        &if_bigint_mix, &var_left_bigint, &var_left_feedback);
7271cb0ef41Sopenharmony_ci    BIND(&do_number_op);
7281cb0ef41Sopenharmony_ci    {
7291cb0ef41Sopenharmony_ci      result =
7301cb0ef41Sopenharmony_ci          BitwiseOp(var_left_word32.value(), SmiToInt32(right_smi), bitwise_op);
7311cb0ef41Sopenharmony_ci      if (slot) {
7321cb0ef41Sopenharmony_ci        TNode<Smi> result_type = SelectSmiConstant(
7331cb0ef41Sopenharmony_ci            TaggedIsSmi(result.value()), BinaryOperationFeedback::kSignedSmall,
7341cb0ef41Sopenharmony_ci            BinaryOperationFeedback::kNumber);
7351cb0ef41Sopenharmony_ci        feedback = SmiOr(result_type, var_left_feedback.value());
7361cb0ef41Sopenharmony_ci      }
7371cb0ef41Sopenharmony_ci      Goto(&done);
7381cb0ef41Sopenharmony_ci    }
7391cb0ef41Sopenharmony_ci
7401cb0ef41Sopenharmony_ci    BIND(&if_bigint_mix);
7411cb0ef41Sopenharmony_ci    {
7421cb0ef41Sopenharmony_ci      if (slot) {
7431cb0ef41Sopenharmony_ci        // Ensure that the feedback is updated before we throw.
7441cb0ef41Sopenharmony_ci        feedback = var_left_feedback.value();
7451cb0ef41Sopenharmony_ci        UpdateFeedback(feedback.value(), (*maybe_feedback_vector)(), *slot,
7461cb0ef41Sopenharmony_ci                       update_feedback_mode);
7471cb0ef41Sopenharmony_ci      }
7481cb0ef41Sopenharmony_ci      ThrowTypeError(context(), MessageTemplate::kBigIntMixedTypes);
7491cb0ef41Sopenharmony_ci    }
7501cb0ef41Sopenharmony_ci  }
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_ci  BIND(&done);
7531cb0ef41Sopenharmony_ci  UpdateFeedback(feedback.value(), (*maybe_feedback_vector)(), *slot,
7541cb0ef41Sopenharmony_ci                 update_feedback_mode);
7551cb0ef41Sopenharmony_ci  return result.value();
7561cb0ef41Sopenharmony_ci}
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci}  // namespace internal
7591cb0ef41Sopenharmony_ci}  // namespace v8
760