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