11cb0ef41Sopenharmony_ci// Copyright 2015 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/compiler/effect-control-linearizer.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "include/v8-fast-api-calls.h" 81cb0ef41Sopenharmony_ci#include "src/base/bits.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors-inl.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 121cb0ef41Sopenharmony_ci#include "src/common/ptr-compr-inl.h" 131cb0ef41Sopenharmony_ci#include "src/compiler/access-builder.h" 141cb0ef41Sopenharmony_ci#include "src/compiler/compiler-source-position-table.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/fast-api-calls.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/feedback-source.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/graph-assembler.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h" 191cb0ef41Sopenharmony_ci#include "src/compiler/js-heap-broker.h" 201cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 211cb0ef41Sopenharmony_ci#include "src/compiler/memory-lowering.h" 221cb0ef41Sopenharmony_ci#include "src/compiler/node-matchers.h" 231cb0ef41Sopenharmony_ci#include "src/compiler/node-origin-table.h" 241cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h" 251cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 261cb0ef41Sopenharmony_ci#include "src/compiler/schedule.h" 271cb0ef41Sopenharmony_ci#include "src/compiler/select-lowering.h" 281cb0ef41Sopenharmony_ci#include "src/execution/frames.h" 291cb0ef41Sopenharmony_ci#include "src/heap/factory-inl.h" 301cb0ef41Sopenharmony_ci#include "src/objects/heap-number.h" 311cb0ef41Sopenharmony_ci#include "src/objects/oddball.h" 321cb0ef41Sopenharmony_ci#include "src/objects/ordered-hash-table.h" 331cb0ef41Sopenharmony_ci#include "src/objects/turbofan-types.h" 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_cinamespace v8 { 361cb0ef41Sopenharmony_cinamespace internal { 371cb0ef41Sopenharmony_cinamespace compiler { 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_cienum class MaintainSchedule { kMaintain, kDiscard }; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciclass EffectControlLinearizer { 421cb0ef41Sopenharmony_ci public: 431cb0ef41Sopenharmony_ci EffectControlLinearizer(JSGraph* js_graph, Schedule* schedule, 441cb0ef41Sopenharmony_ci JSGraphAssembler* graph_assembler, Zone* temp_zone, 451cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, 461cb0ef41Sopenharmony_ci NodeOriginTable* node_origins, 471cb0ef41Sopenharmony_ci MaintainSchedule maintain_schedule, 481cb0ef41Sopenharmony_ci JSHeapBroker* broker) 491cb0ef41Sopenharmony_ci : js_graph_(js_graph), 501cb0ef41Sopenharmony_ci schedule_(schedule), 511cb0ef41Sopenharmony_ci temp_zone_(temp_zone), 521cb0ef41Sopenharmony_ci maintain_schedule_(maintain_schedule), 531cb0ef41Sopenharmony_ci source_positions_(source_positions), 541cb0ef41Sopenharmony_ci node_origins_(node_origins), 551cb0ef41Sopenharmony_ci broker_(broker), 561cb0ef41Sopenharmony_ci graph_assembler_(graph_assembler), 571cb0ef41Sopenharmony_ci frame_state_zapper_(nullptr) {} 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci void Run(); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci private: 621cb0ef41Sopenharmony_ci void UpdateEffectControlForNode(Node* node); 631cb0ef41Sopenharmony_ci void ProcessNode(Node* node, Node** frame_state); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci bool TryWireInStateEffect(Node* node, Node* frame_state); 661cb0ef41Sopenharmony_ci Node* LowerChangeBitToTagged(Node* node); 671cb0ef41Sopenharmony_ci Node* LowerChangeInt31ToTaggedSigned(Node* node); 681cb0ef41Sopenharmony_ci Node* LowerChangeInt32ToTagged(Node* node); 691cb0ef41Sopenharmony_ci Node* LowerChangeInt64ToTagged(Node* node); 701cb0ef41Sopenharmony_ci Node* LowerChangeUint32ToTagged(Node* node); 711cb0ef41Sopenharmony_ci Node* LowerChangeUint64ToTagged(Node* node); 721cb0ef41Sopenharmony_ci Node* LowerChangeFloat64ToTagged(Node* node); 731cb0ef41Sopenharmony_ci Node* LowerChangeFloat64ToTaggedPointer(Node* node); 741cb0ef41Sopenharmony_ci Node* LowerChangeTaggedSignedToInt32(Node* node); 751cb0ef41Sopenharmony_ci Node* LowerChangeTaggedSignedToInt64(Node* node); 761cb0ef41Sopenharmony_ci Node* LowerChangeTaggedToBit(Node* node); 771cb0ef41Sopenharmony_ci Node* LowerChangeTaggedToInt32(Node* node); 781cb0ef41Sopenharmony_ci Node* LowerChangeTaggedToUint32(Node* node); 791cb0ef41Sopenharmony_ci Node* LowerChangeTaggedToInt64(Node* node); 801cb0ef41Sopenharmony_ci Node* LowerChangeTaggedToTaggedSigned(Node* node); 811cb0ef41Sopenharmony_ci Node* LowerCheckInternalizedString(Node* node, Node* frame_state); 821cb0ef41Sopenharmony_ci void LowerCheckMaps(Node* node, Node* frame_state); 831cb0ef41Sopenharmony_ci Node* LowerCompareMaps(Node* node); 841cb0ef41Sopenharmony_ci Node* LowerCheckNumber(Node* node, Node* frame_state); 851cb0ef41Sopenharmony_ci Node* LowerCheckClosure(Node* node, Node* frame_state); 861cb0ef41Sopenharmony_ci Node* LowerCheckReceiver(Node* node, Node* frame_state); 871cb0ef41Sopenharmony_ci Node* LowerCheckReceiverOrNullOrUndefined(Node* node, Node* frame_state); 881cb0ef41Sopenharmony_ci Node* LowerCheckString(Node* node, Node* frame_state); 891cb0ef41Sopenharmony_ci Node* LowerCheckBigInt(Node* node, Node* frame_state); 901cb0ef41Sopenharmony_ci Node* LowerCheckSymbol(Node* node, Node* frame_state); 911cb0ef41Sopenharmony_ci void LowerCheckIf(Node* node, Node* frame_state); 921cb0ef41Sopenharmony_ci Node* LowerCheckedInt32Add(Node* node, Node* frame_state); 931cb0ef41Sopenharmony_ci Node* LowerCheckedInt32Sub(Node* node, Node* frame_state); 941cb0ef41Sopenharmony_ci Node* LowerCheckedInt32Div(Node* node, Node* frame_state); 951cb0ef41Sopenharmony_ci Node* LowerCheckedInt32Mod(Node* node, Node* frame_state); 961cb0ef41Sopenharmony_ci Node* LowerCheckedUint32Div(Node* node, Node* frame_state); 971cb0ef41Sopenharmony_ci Node* LowerCheckedUint32Mod(Node* node, Node* frame_state); 981cb0ef41Sopenharmony_ci Node* LowerCheckedInt32Mul(Node* node, Node* frame_state); 991cb0ef41Sopenharmony_ci Node* LowerCheckedInt32ToTaggedSigned(Node* node, Node* frame_state); 1001cb0ef41Sopenharmony_ci Node* LowerCheckedInt64ToInt32(Node* node, Node* frame_state); 1011cb0ef41Sopenharmony_ci Node* LowerCheckedInt64ToTaggedSigned(Node* node, Node* frame_state); 1021cb0ef41Sopenharmony_ci Node* LowerCheckedUint32Bounds(Node* node, Node* frame_state); 1031cb0ef41Sopenharmony_ci Node* LowerCheckedUint32ToInt32(Node* node, Node* frame_state); 1041cb0ef41Sopenharmony_ci Node* LowerCheckedUint32ToTaggedSigned(Node* node, Node* frame_state); 1051cb0ef41Sopenharmony_ci Node* LowerCheckedUint64Bounds(Node* node, Node* frame_state); 1061cb0ef41Sopenharmony_ci Node* LowerCheckedUint64ToInt32(Node* node, Node* frame_state); 1071cb0ef41Sopenharmony_ci Node* LowerCheckedUint64ToTaggedSigned(Node* node, Node* frame_state); 1081cb0ef41Sopenharmony_ci Node* LowerCheckedFloat64ToInt32(Node* node, Node* frame_state); 1091cb0ef41Sopenharmony_ci Node* LowerCheckedFloat64ToInt64(Node* node, Node* frame_state); 1101cb0ef41Sopenharmony_ci Node* LowerCheckedTaggedSignedToInt32(Node* node, Node* frame_state); 1111cb0ef41Sopenharmony_ci Node* LowerCheckedTaggedToArrayIndex(Node* node, Node* frame_state); 1121cb0ef41Sopenharmony_ci Node* LowerCheckedTaggedToInt32(Node* node, Node* frame_state); 1131cb0ef41Sopenharmony_ci Node* LowerCheckedTaggedToInt64(Node* node, Node* frame_state); 1141cb0ef41Sopenharmony_ci Node* LowerCheckedTaggedToFloat64(Node* node, Node* frame_state); 1151cb0ef41Sopenharmony_ci Node* LowerCheckedTaggedToTaggedSigned(Node* node, Node* frame_state); 1161cb0ef41Sopenharmony_ci Node* LowerCheckedTaggedToTaggedPointer(Node* node, Node* frame_state); 1171cb0ef41Sopenharmony_ci Node* LowerChangeInt64ToBigInt(Node* node); 1181cb0ef41Sopenharmony_ci Node* LowerChangeUint64ToBigInt(Node* node); 1191cb0ef41Sopenharmony_ci Node* LowerTruncateBigIntToWord64(Node* node); 1201cb0ef41Sopenharmony_ci Node* LowerChangeTaggedToFloat64(Node* node); 1211cb0ef41Sopenharmony_ci void TruncateTaggedPointerToBit(Node* node, GraphAssemblerLabel<1>* done); 1221cb0ef41Sopenharmony_ci Node* LowerTruncateTaggedToBit(Node* node); 1231cb0ef41Sopenharmony_ci Node* LowerTruncateTaggedPointerToBit(Node* node); 1241cb0ef41Sopenharmony_ci Node* LowerTruncateTaggedToFloat64(Node* node); 1251cb0ef41Sopenharmony_ci Node* LowerTruncateTaggedToWord32(Node* node); 1261cb0ef41Sopenharmony_ci Node* LowerCheckedTruncateTaggedToWord32(Node* node, Node* frame_state); 1271cb0ef41Sopenharmony_ci Node* LowerAllocate(Node* node); 1281cb0ef41Sopenharmony_ci Node* LowerNumberToString(Node* node); 1291cb0ef41Sopenharmony_ci Node* LowerObjectIsArrayBufferView(Node* node); 1301cb0ef41Sopenharmony_ci Node* LowerObjectIsBigInt(Node* node); 1311cb0ef41Sopenharmony_ci Node* LowerObjectIsCallable(Node* node); 1321cb0ef41Sopenharmony_ci Node* LowerObjectIsConstructor(Node* node); 1331cb0ef41Sopenharmony_ci Node* LowerObjectIsDetectableCallable(Node* node); 1341cb0ef41Sopenharmony_ci Node* LowerObjectIsMinusZero(Node* node); 1351cb0ef41Sopenharmony_ci Node* LowerNumberIsMinusZero(Node* node); 1361cb0ef41Sopenharmony_ci Node* LowerObjectIsNaN(Node* node); 1371cb0ef41Sopenharmony_ci Node* LowerNumberIsNaN(Node* node); 1381cb0ef41Sopenharmony_ci Node* LowerObjectIsNonCallable(Node* node); 1391cb0ef41Sopenharmony_ci Node* LowerObjectIsNumber(Node* node); 1401cb0ef41Sopenharmony_ci Node* LowerObjectIsReceiver(Node* node); 1411cb0ef41Sopenharmony_ci Node* LowerObjectIsSmi(Node* node); 1421cb0ef41Sopenharmony_ci Node* LowerObjectIsString(Node* node); 1431cb0ef41Sopenharmony_ci Node* LowerObjectIsSymbol(Node* node); 1441cb0ef41Sopenharmony_ci Node* LowerObjectIsUndetectable(Node* node); 1451cb0ef41Sopenharmony_ci Node* LowerNumberIsFloat64Hole(Node* node); 1461cb0ef41Sopenharmony_ci Node* LowerNumberIsFinite(Node* node); 1471cb0ef41Sopenharmony_ci Node* LowerObjectIsFiniteNumber(Node* node); 1481cb0ef41Sopenharmony_ci Node* LowerNumberIsInteger(Node* node); 1491cb0ef41Sopenharmony_ci Node* LowerObjectIsInteger(Node* node); 1501cb0ef41Sopenharmony_ci Node* LowerNumberIsSafeInteger(Node* node); 1511cb0ef41Sopenharmony_ci Node* LowerObjectIsSafeInteger(Node* node); 1521cb0ef41Sopenharmony_ci Node* LowerArgumentsLength(Node* node); 1531cb0ef41Sopenharmony_ci Node* LowerRestLength(Node* node); 1541cb0ef41Sopenharmony_ci Node* LowerNewDoubleElements(Node* node); 1551cb0ef41Sopenharmony_ci Node* LowerNewSmiOrObjectElements(Node* node); 1561cb0ef41Sopenharmony_ci Node* LowerNewArgumentsElements(Node* node); 1571cb0ef41Sopenharmony_ci Node* LowerNewConsString(Node* node); 1581cb0ef41Sopenharmony_ci Node* LowerSameValue(Node* node); 1591cb0ef41Sopenharmony_ci Node* LowerSameValueNumbersOnly(Node* node); 1601cb0ef41Sopenharmony_ci Node* LowerNumberSameValue(Node* node); 1611cb0ef41Sopenharmony_ci Node* LowerDeadValue(Node* node); 1621cb0ef41Sopenharmony_ci Node* LowerStringConcat(Node* node); 1631cb0ef41Sopenharmony_ci Node* LowerStringToNumber(Node* node); 1641cb0ef41Sopenharmony_ci Node* LowerStringCharCodeAt(Node* node); 1651cb0ef41Sopenharmony_ci Node* StringCharCodeAt(Node* receiver, Node* position); 1661cb0ef41Sopenharmony_ci Node* LowerStringCodePointAt(Node* node); 1671cb0ef41Sopenharmony_ci Node* LowerStringToLowerCaseIntl(Node* node); 1681cb0ef41Sopenharmony_ci Node* LowerStringToUpperCaseIntl(Node* node); 1691cb0ef41Sopenharmony_ci Node* LowerStringFromSingleCharCode(Node* node); 1701cb0ef41Sopenharmony_ci Node* LowerStringFromSingleCodePoint(Node* node); 1711cb0ef41Sopenharmony_ci Node* LowerStringIndexOf(Node* node); 1721cb0ef41Sopenharmony_ci Node* LowerStringSubstring(Node* node); 1731cb0ef41Sopenharmony_ci Node* LowerStringFromCodePointAt(Node* node); 1741cb0ef41Sopenharmony_ci Node* LowerStringLength(Node* node); 1751cb0ef41Sopenharmony_ci Node* LowerStringEqual(Node* node); 1761cb0ef41Sopenharmony_ci Node* LowerStringLessThan(Node* node); 1771cb0ef41Sopenharmony_ci Node* LowerStringLessThanOrEqual(Node* node); 1781cb0ef41Sopenharmony_ci Node* LowerBigIntAdd(Node* node, Node* frame_state); 1791cb0ef41Sopenharmony_ci Node* LowerBigIntSubtract(Node* node, Node* frame_state); 1801cb0ef41Sopenharmony_ci Node* LowerBigIntNegate(Node* node); 1811cb0ef41Sopenharmony_ci Node* LowerCheckFloat64Hole(Node* node, Node* frame_state); 1821cb0ef41Sopenharmony_ci Node* LowerCheckNotTaggedHole(Node* node, Node* frame_state); 1831cb0ef41Sopenharmony_ci Node* LowerConvertTaggedHoleToUndefined(Node* node); 1841cb0ef41Sopenharmony_ci void LowerCheckEqualsInternalizedString(Node* node, Node* frame_state); 1851cb0ef41Sopenharmony_ci void LowerCheckEqualsSymbol(Node* node, Node* frame_state); 1861cb0ef41Sopenharmony_ci Node* LowerTypeOf(Node* node); 1871cb0ef41Sopenharmony_ci Node* LowerToBoolean(Node* node); 1881cb0ef41Sopenharmony_ci Node* LowerPlainPrimitiveToNumber(Node* node); 1891cb0ef41Sopenharmony_ci Node* LowerPlainPrimitiveToWord32(Node* node); 1901cb0ef41Sopenharmony_ci Node* LowerPlainPrimitiveToFloat64(Node* node); 1911cb0ef41Sopenharmony_ci Node* LowerEnsureWritableFastElements(Node* node); 1921cb0ef41Sopenharmony_ci Node* LowerMaybeGrowFastElements(Node* node, Node* frame_state); 1931cb0ef41Sopenharmony_ci void LowerTransitionElementsKind(Node* node); 1941cb0ef41Sopenharmony_ci Node* LowerLoadFieldByIndex(Node* node); 1951cb0ef41Sopenharmony_ci Node* LowerLoadMessage(Node* node); 1961cb0ef41Sopenharmony_ci Node* AdaptFastCallTypedArrayArgument(Node* node, 1971cb0ef41Sopenharmony_ci ElementsKind expected_elements_kind, 1981cb0ef41Sopenharmony_ci GraphAssemblerLabel<0>* bailout); 1991cb0ef41Sopenharmony_ci Node* AdaptFastCallArgument(Node* node, CTypeInfo arg_type, 2001cb0ef41Sopenharmony_ci GraphAssemblerLabel<0>* if_error); 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci struct AdaptOverloadedFastCallResult { 2031cb0ef41Sopenharmony_ci Node* target_address; 2041cb0ef41Sopenharmony_ci Node* argument; 2051cb0ef41Sopenharmony_ci }; 2061cb0ef41Sopenharmony_ci AdaptOverloadedFastCallResult AdaptOverloadedFastCallArgument( 2071cb0ef41Sopenharmony_ci Node* node, const FastApiCallFunctionVector& c_functions, 2081cb0ef41Sopenharmony_ci const fast_api_call::OverloadsResolutionResult& 2091cb0ef41Sopenharmony_ci overloads_resolution_result, 2101cb0ef41Sopenharmony_ci GraphAssemblerLabel<0>* if_error); 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci Node* WrapFastCall(const CallDescriptor* call_descriptor, int inputs_size, 2131cb0ef41Sopenharmony_ci Node** inputs, Node* target, 2141cb0ef41Sopenharmony_ci const CFunctionInfo* c_signature, int c_arg_count, 2151cb0ef41Sopenharmony_ci Node* stack_slot); 2161cb0ef41Sopenharmony_ci Node* GenerateSlowApiCall(Node* node); 2171cb0ef41Sopenharmony_ci Node* LowerFastApiCall(Node* node); 2181cb0ef41Sopenharmony_ci Node* LowerLoadTypedElement(Node* node); 2191cb0ef41Sopenharmony_ci Node* LowerLoadDataViewElement(Node* node); 2201cb0ef41Sopenharmony_ci Node* LowerLoadStackArgument(Node* node); 2211cb0ef41Sopenharmony_ci void LowerStoreMessage(Node* node); 2221cb0ef41Sopenharmony_ci void LowerStoreTypedElement(Node* node); 2231cb0ef41Sopenharmony_ci void LowerStoreDataViewElement(Node* node); 2241cb0ef41Sopenharmony_ci void LowerStoreSignedSmallElement(Node* node); 2251cb0ef41Sopenharmony_ci Node* LowerFindOrderedHashMapEntry(Node* node); 2261cb0ef41Sopenharmony_ci Node* LowerFindOrderedHashMapEntryForInt32Key(Node* node); 2271cb0ef41Sopenharmony_ci void LowerTransitionAndStoreElement(Node* node); 2281cb0ef41Sopenharmony_ci void LowerTransitionAndStoreNumberElement(Node* node); 2291cb0ef41Sopenharmony_ci void LowerTransitionAndStoreNonNumberElement(Node* node); 2301cb0ef41Sopenharmony_ci void LowerRuntimeAbort(Node* node); 2311cb0ef41Sopenharmony_ci Node* LowerAssertType(Node* node); 2321cb0ef41Sopenharmony_ci Node* LowerFoldConstant(Node* node); 2331cb0ef41Sopenharmony_ci Node* LowerConvertReceiver(Node* node); 2341cb0ef41Sopenharmony_ci Node* LowerDateNow(Node* node); 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci // Lowering of optional operators. 2371cb0ef41Sopenharmony_ci Maybe<Node*> LowerFloat64RoundUp(Node* node); 2381cb0ef41Sopenharmony_ci Maybe<Node*> LowerFloat64RoundDown(Node* node); 2391cb0ef41Sopenharmony_ci Maybe<Node*> LowerFloat64RoundTiesEven(Node* node); 2401cb0ef41Sopenharmony_ci Maybe<Node*> LowerFloat64RoundTruncate(Node* node); 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci Node* AllocateHeapNumberWithValue(Node* node); 2431cb0ef41Sopenharmony_ci Node* BuildCheckedFloat64ToInt32(CheckForMinusZeroMode mode, 2441cb0ef41Sopenharmony_ci const FeedbackSource& feedback, Node* value, 2451cb0ef41Sopenharmony_ci Node* frame_state); 2461cb0ef41Sopenharmony_ci Node* BuildCheckedFloat64ToInt64(CheckForMinusZeroMode mode, 2471cb0ef41Sopenharmony_ci const FeedbackSource& feedback, Node* value, 2481cb0ef41Sopenharmony_ci Node* frame_state); 2491cb0ef41Sopenharmony_ci Node* BuildCheckedFloat64ToIndex(const FeedbackSource& feedback, Node* value, 2501cb0ef41Sopenharmony_ci Node* frame_state); 2511cb0ef41Sopenharmony_ci Node* BuildCheckedHeapNumberOrOddballToFloat64(CheckTaggedInputMode mode, 2521cb0ef41Sopenharmony_ci const FeedbackSource& feedback, 2531cb0ef41Sopenharmony_ci Node* value, 2541cb0ef41Sopenharmony_ci Node* frame_state); 2551cb0ef41Sopenharmony_ci Node* BuildReverseBytes(ExternalArrayType type, Node* value); 2561cb0ef41Sopenharmony_ci Node* BuildFloat64RoundDown(Node* value); 2571cb0ef41Sopenharmony_ci Node* BuildFloat64RoundTruncate(Node* input); 2581cb0ef41Sopenharmony_ci template <size_t VarCount, size_t VarCount2> 2591cb0ef41Sopenharmony_ci void SmiTagOrOverflow(Node* value, GraphAssemblerLabel<VarCount>* if_overflow, 2601cb0ef41Sopenharmony_ci GraphAssemblerLabel<VarCount2>* done); 2611cb0ef41Sopenharmony_ci Node* SmiTagOrDeopt(Node* value, const CheckParameters& params, 2621cb0ef41Sopenharmony_ci Node* frame_state); 2631cb0ef41Sopenharmony_ci Node* BuildUint32Mod(Node* lhs, Node* rhs); 2641cb0ef41Sopenharmony_ci Node* ComputeUnseededHash(Node* value); 2651cb0ef41Sopenharmony_ci Node* LowerStringComparison(Callable const& callable, Node* node); 2661cb0ef41Sopenharmony_ci Node* IsElementsKindGreaterThan(Node* kind, ElementsKind reference_kind); 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci Node* BuildTypedArrayDataPointer(Node* base, Node* external); 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci template <typename... Args> 2711cb0ef41Sopenharmony_ci Node* CallBuiltin(Builtin builtin, Operator::Properties properties, Args...); 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci Node* ChangeBitToTagged(Node* value); 2741cb0ef41Sopenharmony_ci Node* ChangeFloat64ToTagged(Node* value, CheckForMinusZeroMode mode); 2751cb0ef41Sopenharmony_ci Node* ChangeInt32ToSmi(Node* value); 2761cb0ef41Sopenharmony_ci // In pointer compression, we smi-corrupt. This means the upper bits of a Smi 2771cb0ef41Sopenharmony_ci // are not important. ChangeTaggedInt32ToSmi has a known tagged int32 as input 2781cb0ef41Sopenharmony_ci // and takes advantage of the smi corruption by emitting a Bitcast node 2791cb0ef41Sopenharmony_ci // instead of a Change node in order to save instructions. 2801cb0ef41Sopenharmony_ci // In non pointer compression, it behaves like ChangeInt32ToSmi. 2811cb0ef41Sopenharmony_ci Node* ChangeTaggedInt32ToSmi(Node* value); 2821cb0ef41Sopenharmony_ci Node* ChangeInt32ToIntPtr(Node* value); 2831cb0ef41Sopenharmony_ci Node* ChangeInt32ToTagged(Node* value); 2841cb0ef41Sopenharmony_ci Node* ChangeInt64ToSmi(Node* value); 2851cb0ef41Sopenharmony_ci Node* ChangeIntPtrToInt32(Node* value); 2861cb0ef41Sopenharmony_ci Node* ChangeIntPtrToSmi(Node* value); 2871cb0ef41Sopenharmony_ci Node* ChangeUint32ToUintPtr(Node* value); 2881cb0ef41Sopenharmony_ci Node* ChangeUint32ToSmi(Node* value); 2891cb0ef41Sopenharmony_ci Node* ChangeUint32ToTagged(Node* value); 2901cb0ef41Sopenharmony_ci Node* ChangeSmiToIntPtr(Node* value); 2911cb0ef41Sopenharmony_ci Node* ChangeSmiToInt32(Node* value); 2921cb0ef41Sopenharmony_ci Node* ChangeSmiToInt64(Node* value); 2931cb0ef41Sopenharmony_ci Node* ObjectIsSmi(Node* value); 2941cb0ef41Sopenharmony_ci Node* LoadFromSeqString(Node* receiver, Node* position, Node* is_one_byte); 2951cb0ef41Sopenharmony_ci Node* TruncateWordToInt32(Node* value); 2961cb0ef41Sopenharmony_ci Node* MakeWeakForComparison(Node* heap_object); 2971cb0ef41Sopenharmony_ci Node* BuildIsWeakReferenceTo(Node* maybe_object, Node* value); 2981cb0ef41Sopenharmony_ci Node* BuildIsClearedWeakReference(Node* maybe_object); 2991cb0ef41Sopenharmony_ci Node* BuildIsStrongReference(Node* value); 3001cb0ef41Sopenharmony_ci Node* BuildStrongReferenceFromWeakReference(Node* value); 3011cb0ef41Sopenharmony_ci Node* SmiMaxValueConstant(); 3021cb0ef41Sopenharmony_ci Node* SmiShiftBitsConstant(); 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci // Pass {bitfield} = {digit} = nullptr to construct the canoncial 0n BigInt. 3051cb0ef41Sopenharmony_ci Node* BuildAllocateBigInt(Node* bitfield, Node* digit); 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci void TransitionElementsTo(Node* node, Node* array, ElementsKind from, 3081cb0ef41Sopenharmony_ci ElementsKind to); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci // This function tries to migrate |value| if its map |value_map| is 3111cb0ef41Sopenharmony_ci // deprecated. It deopts, if either |value_map| isn't deprecated or migration 3121cb0ef41Sopenharmony_ci // fails. 3131cb0ef41Sopenharmony_ci void MigrateInstanceOrDeopt(Node* value, Node* value_map, Node* frame_state, 3141cb0ef41Sopenharmony_ci FeedbackSource const& feedback_source, 3151cb0ef41Sopenharmony_ci DeoptimizeReason reason); 3161cb0ef41Sopenharmony_ci // Tries to migrate |value| if its map |value_map| is deprecated, but doesn't 3171cb0ef41Sopenharmony_ci // deopt on failure. 3181cb0ef41Sopenharmony_ci void TryMigrateInstance(Node* value, Node* value_map); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci bool should_maintain_schedule() const { 3211cb0ef41Sopenharmony_ci return maintain_schedule_ == MaintainSchedule::kMaintain; 3221cb0ef41Sopenharmony_ci } 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci Factory* factory() const { return isolate()->factory(); } 3251cb0ef41Sopenharmony_ci Isolate* isolate() const { return jsgraph()->isolate(); } 3261cb0ef41Sopenharmony_ci JSGraph* jsgraph() const { return js_graph_; } 3271cb0ef41Sopenharmony_ci Graph* graph() const { return js_graph_->graph(); } 3281cb0ef41Sopenharmony_ci Schedule* schedule() const { return schedule_; } 3291cb0ef41Sopenharmony_ci Zone* temp_zone() const { return temp_zone_; } 3301cb0ef41Sopenharmony_ci CommonOperatorBuilder* common() const { return js_graph_->common(); } 3311cb0ef41Sopenharmony_ci SimplifiedOperatorBuilder* simplified() const { 3321cb0ef41Sopenharmony_ci return js_graph_->simplified(); 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci MachineOperatorBuilder* machine() const { return js_graph_->machine(); } 3351cb0ef41Sopenharmony_ci JSGraphAssembler* gasm() const { return graph_assembler_; } 3361cb0ef41Sopenharmony_ci JSHeapBroker* broker() const { return broker_; } 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci JSGraph* js_graph_; 3391cb0ef41Sopenharmony_ci Schedule* schedule_; 3401cb0ef41Sopenharmony_ci Zone* temp_zone_; 3411cb0ef41Sopenharmony_ci MaintainSchedule maintain_schedule_; 3421cb0ef41Sopenharmony_ci RegionObservability region_observability_ = RegionObservability::kObservable; 3431cb0ef41Sopenharmony_ci bool inside_region_ = false; 3441cb0ef41Sopenharmony_ci SourcePositionTable* source_positions_; 3451cb0ef41Sopenharmony_ci NodeOriginTable* node_origins_; 3461cb0ef41Sopenharmony_ci JSHeapBroker* broker_; 3471cb0ef41Sopenharmony_ci JSGraphAssembler* graph_assembler_; 3481cb0ef41Sopenharmony_ci Node* frame_state_zapper_; // For tracking down compiler::Node::New crashes. 3491cb0ef41Sopenharmony_ci}; 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_cinamespace { 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_cistruct BlockEffectControlData { 3541cb0ef41Sopenharmony_ci Node* current_effect = nullptr; // New effect. 3551cb0ef41Sopenharmony_ci Node* current_control = nullptr; // New control. 3561cb0ef41Sopenharmony_ci Node* current_frame_state = nullptr; // New frame state. 3571cb0ef41Sopenharmony_ci}; 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ciclass BlockEffectControlMap { 3601cb0ef41Sopenharmony_ci public: 3611cb0ef41Sopenharmony_ci explicit BlockEffectControlMap(Zone* temp_zone) : map_(temp_zone) {} 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ci BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) { 3641cb0ef41Sopenharmony_ci return map_[std::make_pair(from->id().ToInt(), to->id().ToInt())]; 3651cb0ef41Sopenharmony_ci } 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci const BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) const { 3681cb0ef41Sopenharmony_ci return map_.at(std::make_pair(from->id().ToInt(), to->id().ToInt())); 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci private: 3721cb0ef41Sopenharmony_ci using Key = std::pair<int32_t, int32_t>; 3731cb0ef41Sopenharmony_ci using Map = ZoneMap<Key, BlockEffectControlData>; 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci Map map_; 3761cb0ef41Sopenharmony_ci}; 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci// Effect phis that need to be updated after the first pass. 3791cb0ef41Sopenharmony_cistruct PendingEffectPhi { 3801cb0ef41Sopenharmony_ci Node* effect_phi; 3811cb0ef41Sopenharmony_ci BasicBlock* block; 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci PendingEffectPhi(Node* effect_phi, BasicBlock* block) 3841cb0ef41Sopenharmony_ci : effect_phi(effect_phi), block(block) {} 3851cb0ef41Sopenharmony_ci}; 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_civoid UpdateEffectPhi(Node* node, BasicBlock* block, 3881cb0ef41Sopenharmony_ci BlockEffectControlMap* block_effects) { 3891cb0ef41Sopenharmony_ci // Update all inputs to an effect phi with the effects from the given 3901cb0ef41Sopenharmony_ci // block->effect map. 3911cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); 3921cb0ef41Sopenharmony_ci DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()), 3931cb0ef41Sopenharmony_ci block->PredecessorCount()); 3941cb0ef41Sopenharmony_ci for (int i = 0; i < node->op()->EffectInputCount(); i++) { 3951cb0ef41Sopenharmony_ci Node* input = node->InputAt(i); 3961cb0ef41Sopenharmony_ci BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); 3971cb0ef41Sopenharmony_ci const BlockEffectControlData& block_effect = 3981cb0ef41Sopenharmony_ci block_effects->For(predecessor, block); 3991cb0ef41Sopenharmony_ci Node* effect = block_effect.current_effect; 4001cb0ef41Sopenharmony_ci if (input != effect) { 4011cb0ef41Sopenharmony_ci node->ReplaceInput(i, effect); 4021cb0ef41Sopenharmony_ci } 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci} 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_civoid UpdateBlockControl(BasicBlock* block, 4071cb0ef41Sopenharmony_ci BlockEffectControlMap* block_effects) { 4081cb0ef41Sopenharmony_ci Node* control = block->NodeAt(0); 4091cb0ef41Sopenharmony_ci DCHECK(NodeProperties::IsControl(control)); 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci // Do not rewire the end node. 4121cb0ef41Sopenharmony_ci if (control->opcode() == IrOpcode::kEnd) return; 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci // Update all inputs to the given control node with the correct control. 4151cb0ef41Sopenharmony_ci DCHECK(control->opcode() == IrOpcode::kMerge || 4161cb0ef41Sopenharmony_ci static_cast<size_t>(control->op()->ControlInputCount()) == 4171cb0ef41Sopenharmony_ci block->PredecessorCount()); 4181cb0ef41Sopenharmony_ci if (static_cast<size_t>(control->op()->ControlInputCount()) != 4191cb0ef41Sopenharmony_ci block->PredecessorCount()) { 4201cb0ef41Sopenharmony_ci return; // We already re-wired the control inputs of this node. 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci for (int i = 0; i < control->op()->ControlInputCount(); i++) { 4231cb0ef41Sopenharmony_ci Node* input = NodeProperties::GetControlInput(control, i); 4241cb0ef41Sopenharmony_ci BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i)); 4251cb0ef41Sopenharmony_ci const BlockEffectControlData& block_effect = 4261cb0ef41Sopenharmony_ci block_effects->For(predecessor, block); 4271cb0ef41Sopenharmony_ci if (input != block_effect.current_control) { 4281cb0ef41Sopenharmony_ci NodeProperties::ReplaceControlInput(control, block_effect.current_control, 4291cb0ef41Sopenharmony_ci i); 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci} 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_civoid RemoveRenameNode(Node* node) { 4351cb0ef41Sopenharmony_ci DCHECK(IrOpcode::kFinishRegion == node->opcode() || 4361cb0ef41Sopenharmony_ci IrOpcode::kBeginRegion == node->opcode() || 4371cb0ef41Sopenharmony_ci IrOpcode::kTypeGuard == node->opcode()); 4381cb0ef41Sopenharmony_ci // Update the value/context uses to the value input of the finish node and 4391cb0ef41Sopenharmony_ci // the effect uses to the effect input. 4401cb0ef41Sopenharmony_ci for (Edge edge : node->use_edges()) { 4411cb0ef41Sopenharmony_ci DCHECK(!edge.from()->IsDead()); 4421cb0ef41Sopenharmony_ci if (NodeProperties::IsEffectEdge(edge)) { 4431cb0ef41Sopenharmony_ci edge.UpdateTo(NodeProperties::GetEffectInput(node)); 4441cb0ef41Sopenharmony_ci } else { 4451cb0ef41Sopenharmony_ci DCHECK(!NodeProperties::IsControlEdge(edge)); 4461cb0ef41Sopenharmony_ci DCHECK(!NodeProperties::IsFrameStateEdge(edge)); 4471cb0ef41Sopenharmony_ci edge.UpdateTo(node->InputAt(0)); 4481cb0ef41Sopenharmony_ci } 4491cb0ef41Sopenharmony_ci } 4501cb0ef41Sopenharmony_ci node->Kill(); 4511cb0ef41Sopenharmony_ci} 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_civoid TryCloneBranch(Node* node, BasicBlock* block, Zone* temp_zone, 4541cb0ef41Sopenharmony_ci Graph* graph, CommonOperatorBuilder* common, 4551cb0ef41Sopenharmony_ci BlockEffectControlMap* block_effects, 4561cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, 4571cb0ef41Sopenharmony_ci NodeOriginTable* node_origins) { 4581cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kBranch, node->opcode()); 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_ci // This optimization is a special case of (super)block cloning. It takes an 4611cb0ef41Sopenharmony_ci // input graph as shown below and clones the Branch node for every predecessor 4621cb0ef41Sopenharmony_ci // to the Merge, essentially removing the Merge completely. This avoids 4631cb0ef41Sopenharmony_ci // materializing the bit for the Phi and may offer potential for further 4641cb0ef41Sopenharmony_ci // branch folding optimizations (i.e. because one or more inputs to the Phi is 4651cb0ef41Sopenharmony_ci // a constant). Note that there may be more Phi nodes hanging off the Merge, 4661cb0ef41Sopenharmony_ci // but we can only a certain subset of them currently (actually only Phi and 4671cb0ef41Sopenharmony_ci // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control 4681cb0ef41Sopenharmony_ci // input). 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci // Control1 ... ControlN 4711cb0ef41Sopenharmony_ci // ^ ^ 4721cb0ef41Sopenharmony_ci // | | Cond1 ... CondN 4731cb0ef41Sopenharmony_ci // +----+ +----+ ^ ^ 4741cb0ef41Sopenharmony_ci // | | | | 4751cb0ef41Sopenharmony_ci // | | +----+ | 4761cb0ef41Sopenharmony_ci // Merge<--+ | +------------+ 4771cb0ef41Sopenharmony_ci // ^ \|/ 4781cb0ef41Sopenharmony_ci // | Phi 4791cb0ef41Sopenharmony_ci // | | 4801cb0ef41Sopenharmony_ci // Branch----+ 4811cb0ef41Sopenharmony_ci // ^ 4821cb0ef41Sopenharmony_ci // | 4831cb0ef41Sopenharmony_ci // +-----+-----+ 4841cb0ef41Sopenharmony_ci // | | 4851cb0ef41Sopenharmony_ci // IfTrue IfFalse 4861cb0ef41Sopenharmony_ci // ^ ^ 4871cb0ef41Sopenharmony_ci // | | 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this: 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci // Control1 Cond1 ... ControlN CondN 4921cb0ef41Sopenharmony_ci // ^ ^ ^ ^ 4931cb0ef41Sopenharmony_ci // \ / \ / 4941cb0ef41Sopenharmony_ci // Branch ... Branch 4951cb0ef41Sopenharmony_ci // ^ ^ 4961cb0ef41Sopenharmony_ci // | | 4971cb0ef41Sopenharmony_ci // +---+---+ +---+----+ 4981cb0ef41Sopenharmony_ci // | | | | 4991cb0ef41Sopenharmony_ci // IfTrue IfFalse ... IfTrue IfFalse 5001cb0ef41Sopenharmony_ci // ^ ^ ^ ^ 5011cb0ef41Sopenharmony_ci // | | | | 5021cb0ef41Sopenharmony_ci // +--+ +-------------+ | 5031cb0ef41Sopenharmony_ci // | | +--------------+ +--+ 5041cb0ef41Sopenharmony_ci // | | | | 5051cb0ef41Sopenharmony_ci // Merge Merge 5061cb0ef41Sopenharmony_ci // ^ ^ 5071cb0ef41Sopenharmony_ci // | | 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci SourcePositionTable::Scope scope(source_positions, 5101cb0ef41Sopenharmony_ci source_positions->GetSourcePosition(node)); 5111cb0ef41Sopenharmony_ci NodeOriginTable::Scope origin_scope(node_origins, "clone branch", node); 5121cb0ef41Sopenharmony_ci Node* branch = node; 5131cb0ef41Sopenharmony_ci Node* cond = NodeProperties::GetValueInput(branch, 0); 5141cb0ef41Sopenharmony_ci if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return; 5151cb0ef41Sopenharmony_ci Node* merge = NodeProperties::GetControlInput(branch); 5161cb0ef41Sopenharmony_ci if (merge->opcode() != IrOpcode::kMerge || 5171cb0ef41Sopenharmony_ci NodeProperties::GetControlInput(cond) != merge) { 5181cb0ef41Sopenharmony_ci return; 5191cb0ef41Sopenharmony_ci } 5201cb0ef41Sopenharmony_ci // Grab the IfTrue/IfFalse projections of the Branch. 5211cb0ef41Sopenharmony_ci BranchMatcher matcher(branch); 5221cb0ef41Sopenharmony_ci // Check/collect other Phi/EffectPhi nodes hanging off the Merge. 5231cb0ef41Sopenharmony_ci NodeVector phis(temp_zone); 5241cb0ef41Sopenharmony_ci for (Node* const use : merge->uses()) { 5251cb0ef41Sopenharmony_ci if (use == branch || use == cond) continue; 5261cb0ef41Sopenharmony_ci // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the 5271cb0ef41Sopenharmony_ci // Merge. Ideally, we would just clone the nodes (and everything that 5281cb0ef41Sopenharmony_ci // depends on it to some distant join point), but that requires knowledge 5291cb0ef41Sopenharmony_ci // about dominance/post-dominance. 5301cb0ef41Sopenharmony_ci if (!NodeProperties::IsPhi(use)) return; 5311cb0ef41Sopenharmony_ci for (Edge edge : use->use_edges()) { 5321cb0ef41Sopenharmony_ci // Right now we can only handle Phi/EffectPhi nodes whose uses are 5331cb0ef41Sopenharmony_ci // directly control-dependend on either the IfTrue or the IfFalse 5341cb0ef41Sopenharmony_ci // successor, because we know exactly how to update those uses. 5351cb0ef41Sopenharmony_ci if (edge.from()->op()->ControlInputCount() != 1) return; 5361cb0ef41Sopenharmony_ci Node* control = NodeProperties::GetControlInput(edge.from()); 5371cb0ef41Sopenharmony_ci if (NodeProperties::IsPhi(edge.from())) { 5381cb0ef41Sopenharmony_ci control = NodeProperties::GetControlInput(control, edge.index()); 5391cb0ef41Sopenharmony_ci } 5401cb0ef41Sopenharmony_ci if (control != matcher.IfTrue() && control != matcher.IfFalse()) return; 5411cb0ef41Sopenharmony_ci } 5421cb0ef41Sopenharmony_ci phis.push_back(use); 5431cb0ef41Sopenharmony_ci } 5441cb0ef41Sopenharmony_ci BranchHint const hint = BranchHintOf(branch->op()); 5451cb0ef41Sopenharmony_ci int const input_count = merge->op()->ControlInputCount(); 5461cb0ef41Sopenharmony_ci DCHECK_LE(1, input_count); 5471cb0ef41Sopenharmony_ci Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count); 5481cb0ef41Sopenharmony_ci Node** const merge_true_inputs = &inputs[0]; 5491cb0ef41Sopenharmony_ci Node** const merge_false_inputs = &inputs[input_count]; 5501cb0ef41Sopenharmony_ci for (int index = 0; index < input_count; ++index) { 5511cb0ef41Sopenharmony_ci Node* cond1 = NodeProperties::GetValueInput(cond, index); 5521cb0ef41Sopenharmony_ci Node* control1 = NodeProperties::GetControlInput(merge, index); 5531cb0ef41Sopenharmony_ci Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1); 5541cb0ef41Sopenharmony_ci merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1); 5551cb0ef41Sopenharmony_ci merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1); 5561cb0ef41Sopenharmony_ci } 5571cb0ef41Sopenharmony_ci Node* const merge_true = matcher.IfTrue(); 5581cb0ef41Sopenharmony_ci Node* const merge_false = matcher.IfFalse(); 5591cb0ef41Sopenharmony_ci merge_true->TrimInputCount(0); 5601cb0ef41Sopenharmony_ci merge_false->TrimInputCount(0); 5611cb0ef41Sopenharmony_ci for (int i = 0; i < input_count; ++i) { 5621cb0ef41Sopenharmony_ci merge_true->AppendInput(graph->zone(), merge_true_inputs[i]); 5631cb0ef41Sopenharmony_ci merge_false->AppendInput(graph->zone(), merge_false_inputs[i]); 5641cb0ef41Sopenharmony_ci } 5651cb0ef41Sopenharmony_ci DCHECK_EQ(2u, block->SuccessorCount()); 5661cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count)); 5671cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count)); 5681cb0ef41Sopenharmony_ci int const true_index = 5691cb0ef41Sopenharmony_ci block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1; 5701cb0ef41Sopenharmony_ci BlockEffectControlData* true_block_data = 5711cb0ef41Sopenharmony_ci &block_effects->For(block, block->SuccessorAt(true_index)); 5721cb0ef41Sopenharmony_ci BlockEffectControlData* false_block_data = 5731cb0ef41Sopenharmony_ci &block_effects->For(block, block->SuccessorAt(true_index ^ 1)); 5741cb0ef41Sopenharmony_ci for (Node* const phi : phis) { 5751cb0ef41Sopenharmony_ci for (int index = 0; index < input_count; ++index) { 5761cb0ef41Sopenharmony_ci inputs[index] = phi->InputAt(index); 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci inputs[input_count] = merge_true; 5791cb0ef41Sopenharmony_ci Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs); 5801cb0ef41Sopenharmony_ci inputs[input_count] = merge_false; 5811cb0ef41Sopenharmony_ci Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs); 5821cb0ef41Sopenharmony_ci if (phi->UseCount() == 0) { 5831cb0ef41Sopenharmony_ci DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi); 5841cb0ef41Sopenharmony_ci } else { 5851cb0ef41Sopenharmony_ci for (Edge edge : phi->use_edges()) { 5861cb0ef41Sopenharmony_ci Node* control = NodeProperties::GetControlInput(edge.from()); 5871cb0ef41Sopenharmony_ci if (NodeProperties::IsPhi(edge.from())) { 5881cb0ef41Sopenharmony_ci control = NodeProperties::GetControlInput(control, edge.index()); 5891cb0ef41Sopenharmony_ci } 5901cb0ef41Sopenharmony_ci DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse()); 5911cb0ef41Sopenharmony_ci edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false); 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci } 5941cb0ef41Sopenharmony_ci if (phi->opcode() == IrOpcode::kEffectPhi) { 5951cb0ef41Sopenharmony_ci true_block_data->current_effect = phi_true; 5961cb0ef41Sopenharmony_ci false_block_data->current_effect = phi_false; 5971cb0ef41Sopenharmony_ci } 5981cb0ef41Sopenharmony_ci phi->Kill(); 5991cb0ef41Sopenharmony_ci } 6001cb0ef41Sopenharmony_ci // Fix up IfTrue and IfFalse and kill all dead nodes. 6011cb0ef41Sopenharmony_ci if (branch == block->control_input()) { 6021cb0ef41Sopenharmony_ci true_block_data->current_control = merge_true; 6031cb0ef41Sopenharmony_ci false_block_data->current_control = merge_false; 6041cb0ef41Sopenharmony_ci } 6051cb0ef41Sopenharmony_ci branch->Kill(); 6061cb0ef41Sopenharmony_ci cond->Kill(); 6071cb0ef41Sopenharmony_ci merge->Kill(); 6081cb0ef41Sopenharmony_ci} 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_ci} // namespace 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_civoid EffectControlLinearizer::Run() { 6131cb0ef41Sopenharmony_ci BlockEffectControlMap block_effects(temp_zone()); 6141cb0ef41Sopenharmony_ci ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone()); 6151cb0ef41Sopenharmony_ci ZoneVector<BasicBlock*> pending_block_controls(temp_zone()); 6161cb0ef41Sopenharmony_ci NodeVector inputs_buffer(temp_zone()); 6171cb0ef41Sopenharmony_ci 6181cb0ef41Sopenharmony_ci // TODO(rmcilroy) We should not depend on having rpo_order on schedule, and 6191cb0ef41Sopenharmony_ci // instead just do our own RPO walk here. 6201cb0ef41Sopenharmony_ci for (BasicBlock* block : *(schedule()->rpo_order())) { 6211cb0ef41Sopenharmony_ci if (block != schedule()->start() && block->PredecessorCount() == 0) { 6221cb0ef41Sopenharmony_ci // Block has been removed from the schedule by a preceeding unreachable 6231cb0ef41Sopenharmony_ci // node, just skip it. 6241cb0ef41Sopenharmony_ci continue; 6251cb0ef41Sopenharmony_ci } 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci gasm()->Reset(); 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ci BasicBlock::iterator instr = block->begin(); 6301cb0ef41Sopenharmony_ci BasicBlock::iterator end_instr = block->end(); 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ci // The control node should be the first. 6331cb0ef41Sopenharmony_ci Node* control = *instr; 6341cb0ef41Sopenharmony_ci gasm()->AddNode(control); 6351cb0ef41Sopenharmony_ci 6361cb0ef41Sopenharmony_ci DCHECK(NodeProperties::IsControl(control)); 6371cb0ef41Sopenharmony_ci bool has_incoming_backedge = IrOpcode::kLoop == control->opcode(); 6381cb0ef41Sopenharmony_ci // Update the control inputs. 6391cb0ef41Sopenharmony_ci if (has_incoming_backedge) { 6401cb0ef41Sopenharmony_ci // If there are back edges, we need to update later because we have not 6411cb0ef41Sopenharmony_ci // computed the control yet. 6421cb0ef41Sopenharmony_ci pending_block_controls.push_back(block); 6431cb0ef41Sopenharmony_ci } else { 6441cb0ef41Sopenharmony_ci // If there are no back edges, we can update now. 6451cb0ef41Sopenharmony_ci UpdateBlockControl(block, &block_effects); 6461cb0ef41Sopenharmony_ci } 6471cb0ef41Sopenharmony_ci instr++; 6481cb0ef41Sopenharmony_ci 6491cb0ef41Sopenharmony_ci // Iterate over the phis and update the effect phis. 6501cb0ef41Sopenharmony_ci Node* effect_phi = nullptr; 6511cb0ef41Sopenharmony_ci Node* terminate = nullptr; 6521cb0ef41Sopenharmony_ci for (; instr != end_instr; instr++) { 6531cb0ef41Sopenharmony_ci Node* node = *instr; 6541cb0ef41Sopenharmony_ci // Only go through the phis and effect phis. 6551cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kEffectPhi) { 6561cb0ef41Sopenharmony_ci // There should be at most one effect phi in a block. 6571cb0ef41Sopenharmony_ci DCHECK_NULL(effect_phi); 6581cb0ef41Sopenharmony_ci // IfException blocks should not have effect phis. 6591cb0ef41Sopenharmony_ci DCHECK_NE(IrOpcode::kIfException, control->opcode()); 6601cb0ef41Sopenharmony_ci effect_phi = node; 6611cb0ef41Sopenharmony_ci } else if (node->opcode() == IrOpcode::kPhi) { 6621cb0ef41Sopenharmony_ci // Just skip phis. 6631cb0ef41Sopenharmony_ci } else if (node->opcode() == IrOpcode::kTerminate) { 6641cb0ef41Sopenharmony_ci DCHECK_NULL(terminate); 6651cb0ef41Sopenharmony_ci terminate = node; 6661cb0ef41Sopenharmony_ci } else { 6671cb0ef41Sopenharmony_ci break; 6681cb0ef41Sopenharmony_ci } 6691cb0ef41Sopenharmony_ci gasm()->AddNode(node); 6701cb0ef41Sopenharmony_ci } 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci if (effect_phi) { 6731cb0ef41Sopenharmony_ci // Make sure we update the inputs to the incoming blocks' effects. 6741cb0ef41Sopenharmony_ci if (has_incoming_backedge) { 6751cb0ef41Sopenharmony_ci // In case of loops, we do not update the effect phi immediately 6761cb0ef41Sopenharmony_ci // because the back predecessor has not been handled yet. We just 6771cb0ef41Sopenharmony_ci // record the effect phi for later processing. 6781cb0ef41Sopenharmony_ci pending_effect_phis.push_back(PendingEffectPhi(effect_phi, block)); 6791cb0ef41Sopenharmony_ci } else { 6801cb0ef41Sopenharmony_ci UpdateEffectPhi(effect_phi, block, &block_effects); 6811cb0ef41Sopenharmony_ci } 6821cb0ef41Sopenharmony_ci } 6831cb0ef41Sopenharmony_ci 6841cb0ef41Sopenharmony_ci Node* effect = effect_phi; 6851cb0ef41Sopenharmony_ci if (effect == nullptr) { 6861cb0ef41Sopenharmony_ci // There was no effect phi. 6871cb0ef41Sopenharmony_ci if (block == schedule()->start()) { 6881cb0ef41Sopenharmony_ci // Start block => effect is start. 6891cb0ef41Sopenharmony_ci DCHECK_EQ(graph()->start(), control); 6901cb0ef41Sopenharmony_ci effect = graph()->start(); 6911cb0ef41Sopenharmony_ci } else if (control->opcode() == IrOpcode::kEnd) { 6921cb0ef41Sopenharmony_ci // End block is just a dummy, no effect needed. 6931cb0ef41Sopenharmony_ci DCHECK_EQ(BasicBlock::kNone, block->control()); 6941cb0ef41Sopenharmony_ci DCHECK_EQ(1u, block->size()); 6951cb0ef41Sopenharmony_ci effect = nullptr; 6961cb0ef41Sopenharmony_ci } else { 6971cb0ef41Sopenharmony_ci // If all the predecessors have the same effect, we can use it as our 6981cb0ef41Sopenharmony_ci // current effect. 6991cb0ef41Sopenharmony_ci for (size_t i = 0; i < block->PredecessorCount(); ++i) { 7001cb0ef41Sopenharmony_ci const BlockEffectControlData& data = 7011cb0ef41Sopenharmony_ci block_effects.For(block->PredecessorAt(i), block); 7021cb0ef41Sopenharmony_ci if (!effect) effect = data.current_effect; 7031cb0ef41Sopenharmony_ci if (data.current_effect != effect) { 7041cb0ef41Sopenharmony_ci effect = nullptr; 7051cb0ef41Sopenharmony_ci break; 7061cb0ef41Sopenharmony_ci } 7071cb0ef41Sopenharmony_ci } 7081cb0ef41Sopenharmony_ci if (effect == nullptr) { 7091cb0ef41Sopenharmony_ci DCHECK_NE(IrOpcode::kIfException, control->opcode()); 7101cb0ef41Sopenharmony_ci // The input blocks do not have the same effect. We have 7111cb0ef41Sopenharmony_ci // to create an effect phi node. 7121cb0ef41Sopenharmony_ci inputs_buffer.clear(); 7131cb0ef41Sopenharmony_ci inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead()); 7141cb0ef41Sopenharmony_ci inputs_buffer.push_back(control); 7151cb0ef41Sopenharmony_ci effect = graph()->NewNode( 7161cb0ef41Sopenharmony_ci common()->EffectPhi(static_cast<int>(block->PredecessorCount())), 7171cb0ef41Sopenharmony_ci static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front())); 7181cb0ef41Sopenharmony_ci gasm()->AddNode(effect); 7191cb0ef41Sopenharmony_ci // For loops, we update the effect phi node later to break cycles. 7201cb0ef41Sopenharmony_ci if (control->opcode() == IrOpcode::kLoop) { 7211cb0ef41Sopenharmony_ci pending_effect_phis.push_back(PendingEffectPhi(effect, block)); 7221cb0ef41Sopenharmony_ci } else { 7231cb0ef41Sopenharmony_ci UpdateEffectPhi(effect, block, &block_effects); 7241cb0ef41Sopenharmony_ci } 7251cb0ef41Sopenharmony_ci } else if (control->opcode() == IrOpcode::kIfException) { 7261cb0ef41Sopenharmony_ci // The IfException is connected into the effect chain, so we need 7271cb0ef41Sopenharmony_ci // to update the effect here. 7281cb0ef41Sopenharmony_ci NodeProperties::ReplaceEffectInput(control, effect); 7291cb0ef41Sopenharmony_ci effect = control; 7301cb0ef41Sopenharmony_ci } 7311cb0ef41Sopenharmony_ci } 7321cb0ef41Sopenharmony_ci } 7331cb0ef41Sopenharmony_ci 7341cb0ef41Sopenharmony_ci // Fixup the Terminate node. 7351cb0ef41Sopenharmony_ci if (terminate != nullptr) { 7361cb0ef41Sopenharmony_ci NodeProperties::ReplaceEffectInput(terminate, effect); 7371cb0ef41Sopenharmony_ci } 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_ci // The frame state at block entry is determined by the frame states leaving 7401cb0ef41Sopenharmony_ci // all predecessors. In case there is no frame state dominating this block, 7411cb0ef41Sopenharmony_ci // we can rely on a checkpoint being present before the next deoptimization. 7421cb0ef41Sopenharmony_ci Node* frame_state = nullptr; 7431cb0ef41Sopenharmony_ci if (block != schedule()->start()) { 7441cb0ef41Sopenharmony_ci // If all the predecessors have the same effect, we can use it 7451cb0ef41Sopenharmony_ci // as our current effect. 7461cb0ef41Sopenharmony_ci frame_state = 7471cb0ef41Sopenharmony_ci block_effects.For(block->PredecessorAt(0), block).current_frame_state; 7481cb0ef41Sopenharmony_ci for (size_t i = 1; i < block->PredecessorCount(); i++) { 7491cb0ef41Sopenharmony_ci if (block_effects.For(block->PredecessorAt(i), block) 7501cb0ef41Sopenharmony_ci .current_frame_state != frame_state) { 7511cb0ef41Sopenharmony_ci frame_state = nullptr; 7521cb0ef41Sopenharmony_ci frame_state_zapper_ = graph()->end(); 7531cb0ef41Sopenharmony_ci break; 7541cb0ef41Sopenharmony_ci } 7551cb0ef41Sopenharmony_ci } 7561cb0ef41Sopenharmony_ci } 7571cb0ef41Sopenharmony_ci 7581cb0ef41Sopenharmony_ci gasm()->InitializeEffectControl(effect, control); 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ci // Process the ordinary instructions. 7611cb0ef41Sopenharmony_ci for (; instr != end_instr; instr++) { 7621cb0ef41Sopenharmony_ci Node* node = *instr; 7631cb0ef41Sopenharmony_ci ProcessNode(node, &frame_state); 7641cb0ef41Sopenharmony_ci } 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci switch (block->control()) { 7671cb0ef41Sopenharmony_ci case BasicBlock::kGoto: 7681cb0ef41Sopenharmony_ci case BasicBlock::kNone: 7691cb0ef41Sopenharmony_ci break; 7701cb0ef41Sopenharmony_ci case BasicBlock::kCall: 7711cb0ef41Sopenharmony_ci case BasicBlock::kTailCall: 7721cb0ef41Sopenharmony_ci case BasicBlock::kSwitch: 7731cb0ef41Sopenharmony_ci case BasicBlock::kReturn: 7741cb0ef41Sopenharmony_ci case BasicBlock::kDeoptimize: 7751cb0ef41Sopenharmony_ci case BasicBlock::kThrow: 7761cb0ef41Sopenharmony_ci case BasicBlock::kBranch: 7771cb0ef41Sopenharmony_ci UpdateEffectControlForNode(block->control_input()); 7781cb0ef41Sopenharmony_ci gasm()->UpdateEffectControlWith(block->control_input()); 7791cb0ef41Sopenharmony_ci break; 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci 7821cb0ef41Sopenharmony_ci if (!should_maintain_schedule() && 7831cb0ef41Sopenharmony_ci block->control() == BasicBlock::kBranch) { 7841cb0ef41Sopenharmony_ci TryCloneBranch(block->control_input(), block, temp_zone(), graph(), 7851cb0ef41Sopenharmony_ci common(), &block_effects, source_positions_, 7861cb0ef41Sopenharmony_ci node_origins_); 7871cb0ef41Sopenharmony_ci } 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ci // Store the effect, control and frame state for later use. 7901cb0ef41Sopenharmony_ci for (BasicBlock* successor : block->successors()) { 7911cb0ef41Sopenharmony_ci BlockEffectControlData* data = &block_effects.For(block, successor); 7921cb0ef41Sopenharmony_ci if (data->current_effect == nullptr) { 7931cb0ef41Sopenharmony_ci data->current_effect = gasm()->effect(); 7941cb0ef41Sopenharmony_ci } 7951cb0ef41Sopenharmony_ci if (data->current_control == nullptr) { 7961cb0ef41Sopenharmony_ci data->current_control = gasm()->control(); 7971cb0ef41Sopenharmony_ci } 7981cb0ef41Sopenharmony_ci data->current_frame_state = frame_state; 7991cb0ef41Sopenharmony_ci } 8001cb0ef41Sopenharmony_ci } 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci for (BasicBlock* pending_block_control : pending_block_controls) { 8031cb0ef41Sopenharmony_ci UpdateBlockControl(pending_block_control, &block_effects); 8041cb0ef41Sopenharmony_ci } 8051cb0ef41Sopenharmony_ci // Update the incoming edges of the effect phis that could not be processed 8061cb0ef41Sopenharmony_ci // during the first pass (because they could have incoming back edges). 8071cb0ef41Sopenharmony_ci for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) { 8081cb0ef41Sopenharmony_ci UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block, 8091cb0ef41Sopenharmony_ci &block_effects); 8101cb0ef41Sopenharmony_ci } 8111cb0ef41Sopenharmony_ci 8121cb0ef41Sopenharmony_ci schedule_->rpo_order()->clear(); 8131cb0ef41Sopenharmony_ci} 8141cb0ef41Sopenharmony_ci 8151cb0ef41Sopenharmony_civoid EffectControlLinearizer::UpdateEffectControlForNode(Node* node) { 8161cb0ef41Sopenharmony_ci // If the node takes an effect, replace with the current one. 8171cb0ef41Sopenharmony_ci if (node->op()->EffectInputCount() > 0) { 8181cb0ef41Sopenharmony_ci DCHECK_EQ(1, node->op()->EffectInputCount()); 8191cb0ef41Sopenharmony_ci NodeProperties::ReplaceEffectInput(node, gasm()->effect()); 8201cb0ef41Sopenharmony_ci } else { 8211cb0ef41Sopenharmony_ci // New effect chain is only started with a Start or ValueEffect node. 8221cb0ef41Sopenharmony_ci DCHECK(node->op()->EffectOutputCount() == 0 || 8231cb0ef41Sopenharmony_ci node->opcode() == IrOpcode::kStart); 8241cb0ef41Sopenharmony_ci } 8251cb0ef41Sopenharmony_ci 8261cb0ef41Sopenharmony_ci // Rewire control inputs. 8271cb0ef41Sopenharmony_ci for (int i = 0; i < node->op()->ControlInputCount(); i++) { 8281cb0ef41Sopenharmony_ci NodeProperties::ReplaceControlInput(node, gasm()->control(), i); 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci} 8311cb0ef41Sopenharmony_ci 8321cb0ef41Sopenharmony_civoid EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state) { 8331cb0ef41Sopenharmony_ci SourcePositionTable::Scope scope(source_positions_, 8341cb0ef41Sopenharmony_ci source_positions_->GetSourcePosition(node)); 8351cb0ef41Sopenharmony_ci NodeOriginTable::Scope origin_scope(node_origins_, "process node", node); 8361cb0ef41Sopenharmony_ci 8371cb0ef41Sopenharmony_ci // If basic block is unreachable after this point, update the node's effect 8381cb0ef41Sopenharmony_ci // and control inputs to mark it as dead, but don't process further. 8391cb0ef41Sopenharmony_ci if (gasm()->effect() == jsgraph()->Dead()) { 8401cb0ef41Sopenharmony_ci UpdateEffectControlForNode(node); 8411cb0ef41Sopenharmony_ci return; 8421cb0ef41Sopenharmony_ci } 8431cb0ef41Sopenharmony_ci 8441cb0ef41Sopenharmony_ci // If the node needs to be wired into the effect/control chain, do this 8451cb0ef41Sopenharmony_ci // here. Pass current frame state for lowering to eager deoptimization. 8461cb0ef41Sopenharmony_ci if (TryWireInStateEffect(node, *frame_state)) { 8471cb0ef41Sopenharmony_ci return; 8481cb0ef41Sopenharmony_ci } 8491cb0ef41Sopenharmony_ci 8501cb0ef41Sopenharmony_ci // If the node has a visible effect, then there must be a checkpoint in the 8511cb0ef41Sopenharmony_ci // effect chain before we are allowed to place another eager deoptimization 8521cb0ef41Sopenharmony_ci // point. We zap the frame state to ensure this invariant is maintained. 8531cb0ef41Sopenharmony_ci if (region_observability_ == RegionObservability::kObservable && 8541cb0ef41Sopenharmony_ci !node->op()->HasProperty(Operator::kNoWrite)) { 8551cb0ef41Sopenharmony_ci *frame_state = nullptr; 8561cb0ef41Sopenharmony_ci frame_state_zapper_ = node; 8571cb0ef41Sopenharmony_ci } 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_ci // Remove the end markers of 'atomic' allocation region because the 8601cb0ef41Sopenharmony_ci // region should be wired-in now. 8611cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kFinishRegion) { 8621cb0ef41Sopenharmony_ci // Reset the current region observability. 8631cb0ef41Sopenharmony_ci region_observability_ = RegionObservability::kObservable; 8641cb0ef41Sopenharmony_ci inside_region_ = false; 8651cb0ef41Sopenharmony_ci // Update the value uses to the value input of the finish node and 8661cb0ef41Sopenharmony_ci // the effect uses to the effect input. 8671cb0ef41Sopenharmony_ci return RemoveRenameNode(node); 8681cb0ef41Sopenharmony_ci } 8691cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kBeginRegion) { 8701cb0ef41Sopenharmony_ci // Determine the observability for this region and use that for all 8711cb0ef41Sopenharmony_ci // nodes inside the region (i.e. ignore the absence of kNoWrite on 8721cb0ef41Sopenharmony_ci // StoreField and other operators). 8731cb0ef41Sopenharmony_ci DCHECK_NE(RegionObservability::kNotObservable, region_observability_); 8741cb0ef41Sopenharmony_ci region_observability_ = RegionObservabilityOf(node->op()); 8751cb0ef41Sopenharmony_ci inside_region_ = true; 8761cb0ef41Sopenharmony_ci // Update the value uses to the value input of the finish node and 8771cb0ef41Sopenharmony_ci // the effect uses to the effect input. 8781cb0ef41Sopenharmony_ci return RemoveRenameNode(node); 8791cb0ef41Sopenharmony_ci } 8801cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kTypeGuard) { 8811cb0ef41Sopenharmony_ci return RemoveRenameNode(node); 8821cb0ef41Sopenharmony_ci } 8831cb0ef41Sopenharmony_ci 8841cb0ef41Sopenharmony_ci // Special treatment for checkpoint nodes. 8851cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kCheckpoint) { 8861cb0ef41Sopenharmony_ci // Unlink the check point; effect uses will be updated to the incoming 8871cb0ef41Sopenharmony_ci // effect that is passed. The frame state is preserved for lowering. 8881cb0ef41Sopenharmony_ci DCHECK_EQ(RegionObservability::kObservable, region_observability_); 8891cb0ef41Sopenharmony_ci *frame_state = NodeProperties::GetFrameStateInput(node); 8901cb0ef41Sopenharmony_ci return; 8911cb0ef41Sopenharmony_ci } 8921cb0ef41Sopenharmony_ci 8931cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kStoreField) { 8941cb0ef41Sopenharmony_ci // Mark stores outside a region as non-initializing and non-transitioning. 8951cb0ef41Sopenharmony_ci if (!inside_region_) { 8961cb0ef41Sopenharmony_ci const FieldAccess access = FieldAccessOf(node->op()); 8971cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(node, simplified()->StoreField(access, false)); 8981cb0ef41Sopenharmony_ci } 8991cb0ef41Sopenharmony_ci } 9001cb0ef41Sopenharmony_ci 9011cb0ef41Sopenharmony_ci // The IfSuccess nodes should always start a basic block (and basic block 9021cb0ef41Sopenharmony_ci // start nodes are not handled in the ProcessNode method). 9031cb0ef41Sopenharmony_ci DCHECK_NE(IrOpcode::kIfSuccess, node->opcode()); 9041cb0ef41Sopenharmony_ci 9051cb0ef41Sopenharmony_ci UpdateEffectControlForNode(node); 9061cb0ef41Sopenharmony_ci 9071cb0ef41Sopenharmony_ci gasm()->AddNode(node); 9081cb0ef41Sopenharmony_ci 9091cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kUnreachable) { 9101cb0ef41Sopenharmony_ci // Break the effect chain on {Unreachable} and reconnect to the graph end. 9111cb0ef41Sopenharmony_ci // Mark the following code for deletion by connecting to the {Dead} node. 9121cb0ef41Sopenharmony_ci gasm()->ConnectUnreachableToEnd(); 9131cb0ef41Sopenharmony_ci } 9141cb0ef41Sopenharmony_ci} 9151cb0ef41Sopenharmony_ci 9161cb0ef41Sopenharmony_cibool EffectControlLinearizer::TryWireInStateEffect(Node* node, 9171cb0ef41Sopenharmony_ci Node* frame_state) { 9181cb0ef41Sopenharmony_ci Node* result = nullptr; 9191cb0ef41Sopenharmony_ci switch (node->opcode()) { 9201cb0ef41Sopenharmony_ci case IrOpcode::kChangeBitToTagged: 9211cb0ef41Sopenharmony_ci result = LowerChangeBitToTagged(node); 9221cb0ef41Sopenharmony_ci break; 9231cb0ef41Sopenharmony_ci case IrOpcode::kChangeInt31ToTaggedSigned: 9241cb0ef41Sopenharmony_ci result = LowerChangeInt31ToTaggedSigned(node); 9251cb0ef41Sopenharmony_ci break; 9261cb0ef41Sopenharmony_ci case IrOpcode::kChangeInt32ToTagged: 9271cb0ef41Sopenharmony_ci result = LowerChangeInt32ToTagged(node); 9281cb0ef41Sopenharmony_ci break; 9291cb0ef41Sopenharmony_ci case IrOpcode::kChangeInt64ToTagged: 9301cb0ef41Sopenharmony_ci result = LowerChangeInt64ToTagged(node); 9311cb0ef41Sopenharmony_ci break; 9321cb0ef41Sopenharmony_ci case IrOpcode::kChangeUint32ToTagged: 9331cb0ef41Sopenharmony_ci result = LowerChangeUint32ToTagged(node); 9341cb0ef41Sopenharmony_ci break; 9351cb0ef41Sopenharmony_ci case IrOpcode::kChangeUint64ToTagged: 9361cb0ef41Sopenharmony_ci result = LowerChangeUint64ToTagged(node); 9371cb0ef41Sopenharmony_ci break; 9381cb0ef41Sopenharmony_ci case IrOpcode::kChangeFloat64ToTagged: 9391cb0ef41Sopenharmony_ci result = LowerChangeFloat64ToTagged(node); 9401cb0ef41Sopenharmony_ci break; 9411cb0ef41Sopenharmony_ci case IrOpcode::kChangeFloat64ToTaggedPointer: 9421cb0ef41Sopenharmony_ci result = LowerChangeFloat64ToTaggedPointer(node); 9431cb0ef41Sopenharmony_ci break; 9441cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedSignedToInt32: 9451cb0ef41Sopenharmony_ci result = LowerChangeTaggedSignedToInt32(node); 9461cb0ef41Sopenharmony_ci break; 9471cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedSignedToInt64: 9481cb0ef41Sopenharmony_ci result = LowerChangeTaggedSignedToInt64(node); 9491cb0ef41Sopenharmony_ci break; 9501cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedToBit: 9511cb0ef41Sopenharmony_ci result = LowerChangeTaggedToBit(node); 9521cb0ef41Sopenharmony_ci break; 9531cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedToInt32: 9541cb0ef41Sopenharmony_ci result = LowerChangeTaggedToInt32(node); 9551cb0ef41Sopenharmony_ci break; 9561cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedToUint32: 9571cb0ef41Sopenharmony_ci result = LowerChangeTaggedToUint32(node); 9581cb0ef41Sopenharmony_ci break; 9591cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedToInt64: 9601cb0ef41Sopenharmony_ci result = LowerChangeTaggedToInt64(node); 9611cb0ef41Sopenharmony_ci break; 9621cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedToFloat64: 9631cb0ef41Sopenharmony_ci result = LowerChangeTaggedToFloat64(node); 9641cb0ef41Sopenharmony_ci break; 9651cb0ef41Sopenharmony_ci case IrOpcode::kChangeTaggedToTaggedSigned: 9661cb0ef41Sopenharmony_ci result = LowerChangeTaggedToTaggedSigned(node); 9671cb0ef41Sopenharmony_ci break; 9681cb0ef41Sopenharmony_ci case IrOpcode::kTruncateTaggedToBit: 9691cb0ef41Sopenharmony_ci result = LowerTruncateTaggedToBit(node); 9701cb0ef41Sopenharmony_ci break; 9711cb0ef41Sopenharmony_ci case IrOpcode::kTruncateTaggedPointerToBit: 9721cb0ef41Sopenharmony_ci result = LowerTruncateTaggedPointerToBit(node); 9731cb0ef41Sopenharmony_ci break; 9741cb0ef41Sopenharmony_ci case IrOpcode::kTruncateTaggedToFloat64: 9751cb0ef41Sopenharmony_ci result = LowerTruncateTaggedToFloat64(node); 9761cb0ef41Sopenharmony_ci break; 9771cb0ef41Sopenharmony_ci case IrOpcode::kCheckClosure: 9781cb0ef41Sopenharmony_ci result = LowerCheckClosure(node, frame_state); 9791cb0ef41Sopenharmony_ci break; 9801cb0ef41Sopenharmony_ci case IrOpcode::kCheckMaps: 9811cb0ef41Sopenharmony_ci LowerCheckMaps(node, frame_state); 9821cb0ef41Sopenharmony_ci break; 9831cb0ef41Sopenharmony_ci case IrOpcode::kCompareMaps: 9841cb0ef41Sopenharmony_ci result = LowerCompareMaps(node); 9851cb0ef41Sopenharmony_ci break; 9861cb0ef41Sopenharmony_ci case IrOpcode::kCheckNumber: 9871cb0ef41Sopenharmony_ci result = LowerCheckNumber(node, frame_state); 9881cb0ef41Sopenharmony_ci break; 9891cb0ef41Sopenharmony_ci case IrOpcode::kCheckReceiver: 9901cb0ef41Sopenharmony_ci result = LowerCheckReceiver(node, frame_state); 9911cb0ef41Sopenharmony_ci break; 9921cb0ef41Sopenharmony_ci case IrOpcode::kCheckReceiverOrNullOrUndefined: 9931cb0ef41Sopenharmony_ci result = LowerCheckReceiverOrNullOrUndefined(node, frame_state); 9941cb0ef41Sopenharmony_ci break; 9951cb0ef41Sopenharmony_ci case IrOpcode::kCheckSymbol: 9961cb0ef41Sopenharmony_ci result = LowerCheckSymbol(node, frame_state); 9971cb0ef41Sopenharmony_ci break; 9981cb0ef41Sopenharmony_ci case IrOpcode::kCheckString: 9991cb0ef41Sopenharmony_ci result = LowerCheckString(node, frame_state); 10001cb0ef41Sopenharmony_ci break; 10011cb0ef41Sopenharmony_ci case IrOpcode::kCheckBigInt: 10021cb0ef41Sopenharmony_ci result = LowerCheckBigInt(node, frame_state); 10031cb0ef41Sopenharmony_ci break; 10041cb0ef41Sopenharmony_ci case IrOpcode::kCheckInternalizedString: 10051cb0ef41Sopenharmony_ci result = LowerCheckInternalizedString(node, frame_state); 10061cb0ef41Sopenharmony_ci break; 10071cb0ef41Sopenharmony_ci case IrOpcode::kCheckIf: 10081cb0ef41Sopenharmony_ci LowerCheckIf(node, frame_state); 10091cb0ef41Sopenharmony_ci break; 10101cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt32Add: 10111cb0ef41Sopenharmony_ci result = LowerCheckedInt32Add(node, frame_state); 10121cb0ef41Sopenharmony_ci break; 10131cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt32Sub: 10141cb0ef41Sopenharmony_ci result = LowerCheckedInt32Sub(node, frame_state); 10151cb0ef41Sopenharmony_ci break; 10161cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt32Div: 10171cb0ef41Sopenharmony_ci result = LowerCheckedInt32Div(node, frame_state); 10181cb0ef41Sopenharmony_ci break; 10191cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt32Mod: 10201cb0ef41Sopenharmony_ci result = LowerCheckedInt32Mod(node, frame_state); 10211cb0ef41Sopenharmony_ci break; 10221cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint32Div: 10231cb0ef41Sopenharmony_ci result = LowerCheckedUint32Div(node, frame_state); 10241cb0ef41Sopenharmony_ci break; 10251cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint32Mod: 10261cb0ef41Sopenharmony_ci result = LowerCheckedUint32Mod(node, frame_state); 10271cb0ef41Sopenharmony_ci break; 10281cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt32Mul: 10291cb0ef41Sopenharmony_ci result = LowerCheckedInt32Mul(node, frame_state); 10301cb0ef41Sopenharmony_ci break; 10311cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt32ToTaggedSigned: 10321cb0ef41Sopenharmony_ci result = LowerCheckedInt32ToTaggedSigned(node, frame_state); 10331cb0ef41Sopenharmony_ci break; 10341cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt64ToInt32: 10351cb0ef41Sopenharmony_ci result = LowerCheckedInt64ToInt32(node, frame_state); 10361cb0ef41Sopenharmony_ci break; 10371cb0ef41Sopenharmony_ci case IrOpcode::kCheckedInt64ToTaggedSigned: 10381cb0ef41Sopenharmony_ci result = LowerCheckedInt64ToTaggedSigned(node, frame_state); 10391cb0ef41Sopenharmony_ci break; 10401cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint32Bounds: 10411cb0ef41Sopenharmony_ci result = LowerCheckedUint32Bounds(node, frame_state); 10421cb0ef41Sopenharmony_ci break; 10431cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint32ToInt32: 10441cb0ef41Sopenharmony_ci result = LowerCheckedUint32ToInt32(node, frame_state); 10451cb0ef41Sopenharmony_ci break; 10461cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint32ToTaggedSigned: 10471cb0ef41Sopenharmony_ci result = LowerCheckedUint32ToTaggedSigned(node, frame_state); 10481cb0ef41Sopenharmony_ci break; 10491cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint64Bounds: 10501cb0ef41Sopenharmony_ci result = LowerCheckedUint64Bounds(node, frame_state); 10511cb0ef41Sopenharmony_ci break; 10521cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint64ToInt32: 10531cb0ef41Sopenharmony_ci result = LowerCheckedUint64ToInt32(node, frame_state); 10541cb0ef41Sopenharmony_ci break; 10551cb0ef41Sopenharmony_ci case IrOpcode::kCheckedUint64ToTaggedSigned: 10561cb0ef41Sopenharmony_ci result = LowerCheckedUint64ToTaggedSigned(node, frame_state); 10571cb0ef41Sopenharmony_ci break; 10581cb0ef41Sopenharmony_ci case IrOpcode::kCheckedFloat64ToInt32: 10591cb0ef41Sopenharmony_ci result = LowerCheckedFloat64ToInt32(node, frame_state); 10601cb0ef41Sopenharmony_ci break; 10611cb0ef41Sopenharmony_ci case IrOpcode::kCheckedFloat64ToInt64: 10621cb0ef41Sopenharmony_ci result = LowerCheckedFloat64ToInt64(node, frame_state); 10631cb0ef41Sopenharmony_ci break; 10641cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTaggedSignedToInt32: 10651cb0ef41Sopenharmony_ci if (frame_state == nullptr) { 10661cb0ef41Sopenharmony_ci FATAL("No frame state (zapped by #%d: %s)", frame_state_zapper_->id(), 10671cb0ef41Sopenharmony_ci frame_state_zapper_->op()->mnemonic()); 10681cb0ef41Sopenharmony_ci } 10691cb0ef41Sopenharmony_ci result = LowerCheckedTaggedSignedToInt32(node, frame_state); 10701cb0ef41Sopenharmony_ci break; 10711cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTaggedToArrayIndex: 10721cb0ef41Sopenharmony_ci result = LowerCheckedTaggedToArrayIndex(node, frame_state); 10731cb0ef41Sopenharmony_ci break; 10741cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTaggedToInt32: 10751cb0ef41Sopenharmony_ci result = LowerCheckedTaggedToInt32(node, frame_state); 10761cb0ef41Sopenharmony_ci break; 10771cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTaggedToInt64: 10781cb0ef41Sopenharmony_ci result = LowerCheckedTaggedToInt64(node, frame_state); 10791cb0ef41Sopenharmony_ci break; 10801cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTaggedToFloat64: 10811cb0ef41Sopenharmony_ci result = LowerCheckedTaggedToFloat64(node, frame_state); 10821cb0ef41Sopenharmony_ci break; 10831cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTaggedToTaggedSigned: 10841cb0ef41Sopenharmony_ci result = LowerCheckedTaggedToTaggedSigned(node, frame_state); 10851cb0ef41Sopenharmony_ci break; 10861cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTaggedToTaggedPointer: 10871cb0ef41Sopenharmony_ci result = LowerCheckedTaggedToTaggedPointer(node, frame_state); 10881cb0ef41Sopenharmony_ci break; 10891cb0ef41Sopenharmony_ci case IrOpcode::kChangeInt64ToBigInt: 10901cb0ef41Sopenharmony_ci result = LowerChangeInt64ToBigInt(node); 10911cb0ef41Sopenharmony_ci break; 10921cb0ef41Sopenharmony_ci case IrOpcode::kChangeUint64ToBigInt: 10931cb0ef41Sopenharmony_ci result = LowerChangeUint64ToBigInt(node); 10941cb0ef41Sopenharmony_ci break; 10951cb0ef41Sopenharmony_ci case IrOpcode::kTruncateBigIntToWord64: 10961cb0ef41Sopenharmony_ci result = LowerTruncateBigIntToWord64(node); 10971cb0ef41Sopenharmony_ci break; 10981cb0ef41Sopenharmony_ci case IrOpcode::kTruncateTaggedToWord32: 10991cb0ef41Sopenharmony_ci result = LowerTruncateTaggedToWord32(node); 11001cb0ef41Sopenharmony_ci break; 11011cb0ef41Sopenharmony_ci case IrOpcode::kCheckedTruncateTaggedToWord32: 11021cb0ef41Sopenharmony_ci result = LowerCheckedTruncateTaggedToWord32(node, frame_state); 11031cb0ef41Sopenharmony_ci break; 11041cb0ef41Sopenharmony_ci case IrOpcode::kNumberToString: 11051cb0ef41Sopenharmony_ci result = LowerNumberToString(node); 11061cb0ef41Sopenharmony_ci break; 11071cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsArrayBufferView: 11081cb0ef41Sopenharmony_ci result = LowerObjectIsArrayBufferView(node); 11091cb0ef41Sopenharmony_ci break; 11101cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsBigInt: 11111cb0ef41Sopenharmony_ci result = LowerObjectIsBigInt(node); 11121cb0ef41Sopenharmony_ci break; 11131cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsCallable: 11141cb0ef41Sopenharmony_ci result = LowerObjectIsCallable(node); 11151cb0ef41Sopenharmony_ci break; 11161cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsConstructor: 11171cb0ef41Sopenharmony_ci result = LowerObjectIsConstructor(node); 11181cb0ef41Sopenharmony_ci break; 11191cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsDetectableCallable: 11201cb0ef41Sopenharmony_ci result = LowerObjectIsDetectableCallable(node); 11211cb0ef41Sopenharmony_ci break; 11221cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsMinusZero: 11231cb0ef41Sopenharmony_ci result = LowerObjectIsMinusZero(node); 11241cb0ef41Sopenharmony_ci break; 11251cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsMinusZero: 11261cb0ef41Sopenharmony_ci result = LowerNumberIsMinusZero(node); 11271cb0ef41Sopenharmony_ci break; 11281cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsNaN: 11291cb0ef41Sopenharmony_ci result = LowerObjectIsNaN(node); 11301cb0ef41Sopenharmony_ci break; 11311cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsNaN: 11321cb0ef41Sopenharmony_ci result = LowerNumberIsNaN(node); 11331cb0ef41Sopenharmony_ci break; 11341cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsNonCallable: 11351cb0ef41Sopenharmony_ci result = LowerObjectIsNonCallable(node); 11361cb0ef41Sopenharmony_ci break; 11371cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsNumber: 11381cb0ef41Sopenharmony_ci result = LowerObjectIsNumber(node); 11391cb0ef41Sopenharmony_ci break; 11401cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsReceiver: 11411cb0ef41Sopenharmony_ci result = LowerObjectIsReceiver(node); 11421cb0ef41Sopenharmony_ci break; 11431cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsSmi: 11441cb0ef41Sopenharmony_ci result = LowerObjectIsSmi(node); 11451cb0ef41Sopenharmony_ci break; 11461cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsString: 11471cb0ef41Sopenharmony_ci result = LowerObjectIsString(node); 11481cb0ef41Sopenharmony_ci break; 11491cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsSymbol: 11501cb0ef41Sopenharmony_ci result = LowerObjectIsSymbol(node); 11511cb0ef41Sopenharmony_ci break; 11521cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsUndetectable: 11531cb0ef41Sopenharmony_ci result = LowerObjectIsUndetectable(node); 11541cb0ef41Sopenharmony_ci break; 11551cb0ef41Sopenharmony_ci case IrOpcode::kArgumentsLength: 11561cb0ef41Sopenharmony_ci result = LowerArgumentsLength(node); 11571cb0ef41Sopenharmony_ci break; 11581cb0ef41Sopenharmony_ci case IrOpcode::kRestLength: 11591cb0ef41Sopenharmony_ci result = LowerRestLength(node); 11601cb0ef41Sopenharmony_ci break; 11611cb0ef41Sopenharmony_ci case IrOpcode::kToBoolean: 11621cb0ef41Sopenharmony_ci result = LowerToBoolean(node); 11631cb0ef41Sopenharmony_ci break; 11641cb0ef41Sopenharmony_ci case IrOpcode::kTypeOf: 11651cb0ef41Sopenharmony_ci result = LowerTypeOf(node); 11661cb0ef41Sopenharmony_ci break; 11671cb0ef41Sopenharmony_ci case IrOpcode::kNewDoubleElements: 11681cb0ef41Sopenharmony_ci result = LowerNewDoubleElements(node); 11691cb0ef41Sopenharmony_ci break; 11701cb0ef41Sopenharmony_ci case IrOpcode::kNewSmiOrObjectElements: 11711cb0ef41Sopenharmony_ci result = LowerNewSmiOrObjectElements(node); 11721cb0ef41Sopenharmony_ci break; 11731cb0ef41Sopenharmony_ci case IrOpcode::kNewArgumentsElements: 11741cb0ef41Sopenharmony_ci result = LowerNewArgumentsElements(node); 11751cb0ef41Sopenharmony_ci break; 11761cb0ef41Sopenharmony_ci case IrOpcode::kNewConsString: 11771cb0ef41Sopenharmony_ci result = LowerNewConsString(node); 11781cb0ef41Sopenharmony_ci break; 11791cb0ef41Sopenharmony_ci case IrOpcode::kSameValue: 11801cb0ef41Sopenharmony_ci result = LowerSameValue(node); 11811cb0ef41Sopenharmony_ci break; 11821cb0ef41Sopenharmony_ci case IrOpcode::kSameValueNumbersOnly: 11831cb0ef41Sopenharmony_ci result = LowerSameValueNumbersOnly(node); 11841cb0ef41Sopenharmony_ci break; 11851cb0ef41Sopenharmony_ci case IrOpcode::kNumberSameValue: 11861cb0ef41Sopenharmony_ci result = LowerNumberSameValue(node); 11871cb0ef41Sopenharmony_ci break; 11881cb0ef41Sopenharmony_ci case IrOpcode::kDeadValue: 11891cb0ef41Sopenharmony_ci result = LowerDeadValue(node); 11901cb0ef41Sopenharmony_ci break; 11911cb0ef41Sopenharmony_ci case IrOpcode::kStringConcat: 11921cb0ef41Sopenharmony_ci result = LowerStringConcat(node); 11931cb0ef41Sopenharmony_ci break; 11941cb0ef41Sopenharmony_ci case IrOpcode::kStringFromSingleCharCode: 11951cb0ef41Sopenharmony_ci result = LowerStringFromSingleCharCode(node); 11961cb0ef41Sopenharmony_ci break; 11971cb0ef41Sopenharmony_ci case IrOpcode::kStringFromSingleCodePoint: 11981cb0ef41Sopenharmony_ci result = LowerStringFromSingleCodePoint(node); 11991cb0ef41Sopenharmony_ci break; 12001cb0ef41Sopenharmony_ci case IrOpcode::kStringIndexOf: 12011cb0ef41Sopenharmony_ci result = LowerStringIndexOf(node); 12021cb0ef41Sopenharmony_ci break; 12031cb0ef41Sopenharmony_ci case IrOpcode::kStringFromCodePointAt: 12041cb0ef41Sopenharmony_ci result = LowerStringFromCodePointAt(node); 12051cb0ef41Sopenharmony_ci break; 12061cb0ef41Sopenharmony_ci case IrOpcode::kStringLength: 12071cb0ef41Sopenharmony_ci result = LowerStringLength(node); 12081cb0ef41Sopenharmony_ci break; 12091cb0ef41Sopenharmony_ci case IrOpcode::kStringToNumber: 12101cb0ef41Sopenharmony_ci result = LowerStringToNumber(node); 12111cb0ef41Sopenharmony_ci break; 12121cb0ef41Sopenharmony_ci case IrOpcode::kStringCharCodeAt: 12131cb0ef41Sopenharmony_ci result = LowerStringCharCodeAt(node); 12141cb0ef41Sopenharmony_ci break; 12151cb0ef41Sopenharmony_ci case IrOpcode::kStringCodePointAt: 12161cb0ef41Sopenharmony_ci result = LowerStringCodePointAt(node); 12171cb0ef41Sopenharmony_ci break; 12181cb0ef41Sopenharmony_ci case IrOpcode::kStringToLowerCaseIntl: 12191cb0ef41Sopenharmony_ci result = LowerStringToLowerCaseIntl(node); 12201cb0ef41Sopenharmony_ci break; 12211cb0ef41Sopenharmony_ci case IrOpcode::kStringToUpperCaseIntl: 12221cb0ef41Sopenharmony_ci result = LowerStringToUpperCaseIntl(node); 12231cb0ef41Sopenharmony_ci break; 12241cb0ef41Sopenharmony_ci case IrOpcode::kStringSubstring: 12251cb0ef41Sopenharmony_ci result = LowerStringSubstring(node); 12261cb0ef41Sopenharmony_ci break; 12271cb0ef41Sopenharmony_ci case IrOpcode::kStringEqual: 12281cb0ef41Sopenharmony_ci result = LowerStringEqual(node); 12291cb0ef41Sopenharmony_ci break; 12301cb0ef41Sopenharmony_ci case IrOpcode::kStringLessThan: 12311cb0ef41Sopenharmony_ci result = LowerStringLessThan(node); 12321cb0ef41Sopenharmony_ci break; 12331cb0ef41Sopenharmony_ci case IrOpcode::kStringLessThanOrEqual: 12341cb0ef41Sopenharmony_ci result = LowerStringLessThanOrEqual(node); 12351cb0ef41Sopenharmony_ci break; 12361cb0ef41Sopenharmony_ci case IrOpcode::kBigIntAdd: 12371cb0ef41Sopenharmony_ci result = LowerBigIntAdd(node, frame_state); 12381cb0ef41Sopenharmony_ci break; 12391cb0ef41Sopenharmony_ci case IrOpcode::kBigIntSubtract: 12401cb0ef41Sopenharmony_ci result = LowerBigIntSubtract(node, frame_state); 12411cb0ef41Sopenharmony_ci break; 12421cb0ef41Sopenharmony_ci case IrOpcode::kBigIntNegate: 12431cb0ef41Sopenharmony_ci result = LowerBigIntNegate(node); 12441cb0ef41Sopenharmony_ci break; 12451cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsFloat64Hole: 12461cb0ef41Sopenharmony_ci result = LowerNumberIsFloat64Hole(node); 12471cb0ef41Sopenharmony_ci break; 12481cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsFinite: 12491cb0ef41Sopenharmony_ci result = LowerNumberIsFinite(node); 12501cb0ef41Sopenharmony_ci break; 12511cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsFiniteNumber: 12521cb0ef41Sopenharmony_ci result = LowerObjectIsFiniteNumber(node); 12531cb0ef41Sopenharmony_ci break; 12541cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsInteger: 12551cb0ef41Sopenharmony_ci result = LowerNumberIsInteger(node); 12561cb0ef41Sopenharmony_ci break; 12571cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsInteger: 12581cb0ef41Sopenharmony_ci result = LowerObjectIsInteger(node); 12591cb0ef41Sopenharmony_ci break; 12601cb0ef41Sopenharmony_ci case IrOpcode::kNumberIsSafeInteger: 12611cb0ef41Sopenharmony_ci result = LowerNumberIsSafeInteger(node); 12621cb0ef41Sopenharmony_ci break; 12631cb0ef41Sopenharmony_ci case IrOpcode::kObjectIsSafeInteger: 12641cb0ef41Sopenharmony_ci result = LowerObjectIsSafeInteger(node); 12651cb0ef41Sopenharmony_ci break; 12661cb0ef41Sopenharmony_ci case IrOpcode::kCheckFloat64Hole: 12671cb0ef41Sopenharmony_ci result = LowerCheckFloat64Hole(node, frame_state); 12681cb0ef41Sopenharmony_ci break; 12691cb0ef41Sopenharmony_ci case IrOpcode::kCheckNotTaggedHole: 12701cb0ef41Sopenharmony_ci result = LowerCheckNotTaggedHole(node, frame_state); 12711cb0ef41Sopenharmony_ci break; 12721cb0ef41Sopenharmony_ci case IrOpcode::kConvertTaggedHoleToUndefined: 12731cb0ef41Sopenharmony_ci result = LowerConvertTaggedHoleToUndefined(node); 12741cb0ef41Sopenharmony_ci break; 12751cb0ef41Sopenharmony_ci case IrOpcode::kCheckEqualsInternalizedString: 12761cb0ef41Sopenharmony_ci LowerCheckEqualsInternalizedString(node, frame_state); 12771cb0ef41Sopenharmony_ci break; 12781cb0ef41Sopenharmony_ci case IrOpcode::kAllocate: 12791cb0ef41Sopenharmony_ci result = LowerAllocate(node); 12801cb0ef41Sopenharmony_ci break; 12811cb0ef41Sopenharmony_ci case IrOpcode::kCheckEqualsSymbol: 12821cb0ef41Sopenharmony_ci LowerCheckEqualsSymbol(node, frame_state); 12831cb0ef41Sopenharmony_ci break; 12841cb0ef41Sopenharmony_ci case IrOpcode::kPlainPrimitiveToNumber: 12851cb0ef41Sopenharmony_ci result = LowerPlainPrimitiveToNumber(node); 12861cb0ef41Sopenharmony_ci break; 12871cb0ef41Sopenharmony_ci case IrOpcode::kPlainPrimitiveToWord32: 12881cb0ef41Sopenharmony_ci result = LowerPlainPrimitiveToWord32(node); 12891cb0ef41Sopenharmony_ci break; 12901cb0ef41Sopenharmony_ci case IrOpcode::kPlainPrimitiveToFloat64: 12911cb0ef41Sopenharmony_ci result = LowerPlainPrimitiveToFloat64(node); 12921cb0ef41Sopenharmony_ci break; 12931cb0ef41Sopenharmony_ci case IrOpcode::kEnsureWritableFastElements: 12941cb0ef41Sopenharmony_ci result = LowerEnsureWritableFastElements(node); 12951cb0ef41Sopenharmony_ci break; 12961cb0ef41Sopenharmony_ci case IrOpcode::kMaybeGrowFastElements: 12971cb0ef41Sopenharmony_ci result = LowerMaybeGrowFastElements(node, frame_state); 12981cb0ef41Sopenharmony_ci break; 12991cb0ef41Sopenharmony_ci case IrOpcode::kTransitionElementsKind: 13001cb0ef41Sopenharmony_ci LowerTransitionElementsKind(node); 13011cb0ef41Sopenharmony_ci break; 13021cb0ef41Sopenharmony_ci case IrOpcode::kLoadMessage: 13031cb0ef41Sopenharmony_ci result = LowerLoadMessage(node); 13041cb0ef41Sopenharmony_ci break; 13051cb0ef41Sopenharmony_ci case IrOpcode::kStoreMessage: 13061cb0ef41Sopenharmony_ci LowerStoreMessage(node); 13071cb0ef41Sopenharmony_ci break; 13081cb0ef41Sopenharmony_ci case IrOpcode::kFastApiCall: 13091cb0ef41Sopenharmony_ci result = LowerFastApiCall(node); 13101cb0ef41Sopenharmony_ci break; 13111cb0ef41Sopenharmony_ci case IrOpcode::kLoadFieldByIndex: 13121cb0ef41Sopenharmony_ci result = LowerLoadFieldByIndex(node); 13131cb0ef41Sopenharmony_ci break; 13141cb0ef41Sopenharmony_ci case IrOpcode::kLoadTypedElement: 13151cb0ef41Sopenharmony_ci result = LowerLoadTypedElement(node); 13161cb0ef41Sopenharmony_ci break; 13171cb0ef41Sopenharmony_ci case IrOpcode::kLoadDataViewElement: 13181cb0ef41Sopenharmony_ci result = LowerLoadDataViewElement(node); 13191cb0ef41Sopenharmony_ci break; 13201cb0ef41Sopenharmony_ci case IrOpcode::kLoadStackArgument: 13211cb0ef41Sopenharmony_ci result = LowerLoadStackArgument(node); 13221cb0ef41Sopenharmony_ci break; 13231cb0ef41Sopenharmony_ci case IrOpcode::kStoreTypedElement: 13241cb0ef41Sopenharmony_ci LowerStoreTypedElement(node); 13251cb0ef41Sopenharmony_ci break; 13261cb0ef41Sopenharmony_ci case IrOpcode::kStoreDataViewElement: 13271cb0ef41Sopenharmony_ci LowerStoreDataViewElement(node); 13281cb0ef41Sopenharmony_ci break; 13291cb0ef41Sopenharmony_ci case IrOpcode::kStoreSignedSmallElement: 13301cb0ef41Sopenharmony_ci LowerStoreSignedSmallElement(node); 13311cb0ef41Sopenharmony_ci break; 13321cb0ef41Sopenharmony_ci case IrOpcode::kFindOrderedHashMapEntry: 13331cb0ef41Sopenharmony_ci result = LowerFindOrderedHashMapEntry(node); 13341cb0ef41Sopenharmony_ci break; 13351cb0ef41Sopenharmony_ci case IrOpcode::kFindOrderedHashMapEntryForInt32Key: 13361cb0ef41Sopenharmony_ci result = LowerFindOrderedHashMapEntryForInt32Key(node); 13371cb0ef41Sopenharmony_ci break; 13381cb0ef41Sopenharmony_ci case IrOpcode::kTransitionAndStoreNumberElement: 13391cb0ef41Sopenharmony_ci LowerTransitionAndStoreNumberElement(node); 13401cb0ef41Sopenharmony_ci break; 13411cb0ef41Sopenharmony_ci case IrOpcode::kTransitionAndStoreNonNumberElement: 13421cb0ef41Sopenharmony_ci LowerTransitionAndStoreNonNumberElement(node); 13431cb0ef41Sopenharmony_ci break; 13441cb0ef41Sopenharmony_ci case IrOpcode::kTransitionAndStoreElement: 13451cb0ef41Sopenharmony_ci LowerTransitionAndStoreElement(node); 13461cb0ef41Sopenharmony_ci break; 13471cb0ef41Sopenharmony_ci case IrOpcode::kRuntimeAbort: 13481cb0ef41Sopenharmony_ci LowerRuntimeAbort(node); 13491cb0ef41Sopenharmony_ci break; 13501cb0ef41Sopenharmony_ci case IrOpcode::kAssertType: 13511cb0ef41Sopenharmony_ci result = LowerAssertType(node); 13521cb0ef41Sopenharmony_ci break; 13531cb0ef41Sopenharmony_ci case IrOpcode::kConvertReceiver: 13541cb0ef41Sopenharmony_ci result = LowerConvertReceiver(node); 13551cb0ef41Sopenharmony_ci break; 13561cb0ef41Sopenharmony_ci case IrOpcode::kFloat64RoundUp: 13571cb0ef41Sopenharmony_ci if (!LowerFloat64RoundUp(node).To(&result)) { 13581cb0ef41Sopenharmony_ci return false; 13591cb0ef41Sopenharmony_ci } 13601cb0ef41Sopenharmony_ci break; 13611cb0ef41Sopenharmony_ci case IrOpcode::kFloat64RoundDown: 13621cb0ef41Sopenharmony_ci if (!LowerFloat64RoundDown(node).To(&result)) { 13631cb0ef41Sopenharmony_ci return false; 13641cb0ef41Sopenharmony_ci } 13651cb0ef41Sopenharmony_ci break; 13661cb0ef41Sopenharmony_ci case IrOpcode::kFloat64RoundTruncate: 13671cb0ef41Sopenharmony_ci if (!LowerFloat64RoundTruncate(node).To(&result)) { 13681cb0ef41Sopenharmony_ci return false; 13691cb0ef41Sopenharmony_ci } 13701cb0ef41Sopenharmony_ci break; 13711cb0ef41Sopenharmony_ci case IrOpcode::kFloat64RoundTiesEven: 13721cb0ef41Sopenharmony_ci if (!LowerFloat64RoundTiesEven(node).To(&result)) { 13731cb0ef41Sopenharmony_ci return false; 13741cb0ef41Sopenharmony_ci } 13751cb0ef41Sopenharmony_ci break; 13761cb0ef41Sopenharmony_ci case IrOpcode::kDateNow: 13771cb0ef41Sopenharmony_ci result = LowerDateNow(node); 13781cb0ef41Sopenharmony_ci break; 13791cb0ef41Sopenharmony_ci case IrOpcode::kFoldConstant: 13801cb0ef41Sopenharmony_ci result = LowerFoldConstant(node); 13811cb0ef41Sopenharmony_ci break; 13821cb0ef41Sopenharmony_ci default: 13831cb0ef41Sopenharmony_ci return false; 13841cb0ef41Sopenharmony_ci } 13851cb0ef41Sopenharmony_ci 13861cb0ef41Sopenharmony_ci if ((result ? 1 : 0) != node->op()->ValueOutputCount()) { 13871cb0ef41Sopenharmony_ci FATAL( 13881cb0ef41Sopenharmony_ci "Effect control linearizer lowering of '%s':" 13891cb0ef41Sopenharmony_ci " value output count does not agree.", 13901cb0ef41Sopenharmony_ci node->op()->mnemonic()); 13911cb0ef41Sopenharmony_ci } 13921cb0ef41Sopenharmony_ci 13931cb0ef41Sopenharmony_ci NodeProperties::ReplaceUses(node, result, gasm()->effect(), 13941cb0ef41Sopenharmony_ci gasm()->control()); 13951cb0ef41Sopenharmony_ci return true; 13961cb0ef41Sopenharmony_ci} 13971cb0ef41Sopenharmony_ci 13981cb0ef41Sopenharmony_ci#define __ gasm()-> 13991cb0ef41Sopenharmony_ci 14001cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) { 14011cb0ef41Sopenharmony_ci CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); 14021cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 14031cb0ef41Sopenharmony_ci return ChangeFloat64ToTagged(value, mode); 14041cb0ef41Sopenharmony_ci} 14051cb0ef41Sopenharmony_ci 14061cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeFloat64ToTagged( 14071cb0ef41Sopenharmony_ci Node* value, CheckForMinusZeroMode mode) { 14081cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 14091cb0ef41Sopenharmony_ci auto if_heapnumber = __ MakeDeferredLabel(); 14101cb0ef41Sopenharmony_ci auto if_int32 = __ MakeLabel(); 14111cb0ef41Sopenharmony_ci 14121cb0ef41Sopenharmony_ci Node* value32 = __ RoundFloat64ToInt32(value); 14131cb0ef41Sopenharmony_ci __ GotoIf(__ Float64Equal(value, __ ChangeInt32ToFloat64(value32)), 14141cb0ef41Sopenharmony_ci &if_int32); 14151cb0ef41Sopenharmony_ci __ Goto(&if_heapnumber); 14161cb0ef41Sopenharmony_ci 14171cb0ef41Sopenharmony_ci __ Bind(&if_int32); 14181cb0ef41Sopenharmony_ci { 14191cb0ef41Sopenharmony_ci if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { 14201cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 14211cb0ef41Sopenharmony_ci auto if_zero = __ MakeDeferredLabel(); 14221cb0ef41Sopenharmony_ci auto if_smi = __ MakeLabel(); 14231cb0ef41Sopenharmony_ci 14241cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(value32, zero), &if_zero); 14251cb0ef41Sopenharmony_ci __ Goto(&if_smi); 14261cb0ef41Sopenharmony_ci 14271cb0ef41Sopenharmony_ci __ Bind(&if_zero); 14281cb0ef41Sopenharmony_ci { 14291cb0ef41Sopenharmony_ci // In case of 0, we need to check the high bits for the IEEE -0 pattern. 14301cb0ef41Sopenharmony_ci __ GotoIf(__ Int32LessThan(__ Float64ExtractHighWord32(value), zero), 14311cb0ef41Sopenharmony_ci &if_heapnumber); 14321cb0ef41Sopenharmony_ci __ Goto(&if_smi); 14331cb0ef41Sopenharmony_ci } 14341cb0ef41Sopenharmony_ci 14351cb0ef41Sopenharmony_ci __ Bind(&if_smi); 14361cb0ef41Sopenharmony_ci } 14371cb0ef41Sopenharmony_ci 14381cb0ef41Sopenharmony_ci if (SmiValuesAre32Bits()) { 14391cb0ef41Sopenharmony_ci Node* value_smi = ChangeInt32ToSmi(value32); 14401cb0ef41Sopenharmony_ci __ Goto(&done, value_smi); 14411cb0ef41Sopenharmony_ci } else { 14421cb0ef41Sopenharmony_ci SmiTagOrOverflow(value32, &if_heapnumber, &done); 14431cb0ef41Sopenharmony_ci } 14441cb0ef41Sopenharmony_ci } 14451cb0ef41Sopenharmony_ci 14461cb0ef41Sopenharmony_ci __ Bind(&if_heapnumber); 14471cb0ef41Sopenharmony_ci { 14481cb0ef41Sopenharmony_ci Node* value_number = AllocateHeapNumberWithValue(value); 14491cb0ef41Sopenharmony_ci __ Goto(&done, value_number); 14501cb0ef41Sopenharmony_ci } 14511cb0ef41Sopenharmony_ci 14521cb0ef41Sopenharmony_ci __ Bind(&done); 14531cb0ef41Sopenharmony_ci return done.PhiAt(0); 14541cb0ef41Sopenharmony_ci} 14551cb0ef41Sopenharmony_ci 14561cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) { 14571cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 14581cb0ef41Sopenharmony_ci return AllocateHeapNumberWithValue(value); 14591cb0ef41Sopenharmony_ci} 14601cb0ef41Sopenharmony_ci 14611cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) { 14621cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 14631cb0ef41Sopenharmony_ci return ChangeBitToTagged(value); 14641cb0ef41Sopenharmony_ci} 14651cb0ef41Sopenharmony_ci 14661cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeBitToTagged(Node* value) { 14671cb0ef41Sopenharmony_ci auto if_true = __ MakeLabel(); 14681cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 14691cb0ef41Sopenharmony_ci 14701cb0ef41Sopenharmony_ci __ GotoIf(value, &if_true); 14711cb0ef41Sopenharmony_ci __ Goto(&done, __ FalseConstant()); 14721cb0ef41Sopenharmony_ci 14731cb0ef41Sopenharmony_ci __ Bind(&if_true); 14741cb0ef41Sopenharmony_ci __ Goto(&done, __ TrueConstant()); 14751cb0ef41Sopenharmony_ci 14761cb0ef41Sopenharmony_ci __ Bind(&done); 14771cb0ef41Sopenharmony_ci return done.PhiAt(0); 14781cb0ef41Sopenharmony_ci} 14791cb0ef41Sopenharmony_ci 14801cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) { 14811cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 14821cb0ef41Sopenharmony_ci return ChangeInt32ToSmi(value); 14831cb0ef41Sopenharmony_ci} 14841cb0ef41Sopenharmony_ci 14851cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) { 14861cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 14871cb0ef41Sopenharmony_ci return ChangeInt32ToTagged(value); 14881cb0ef41Sopenharmony_ci} 14891cb0ef41Sopenharmony_ci 14901cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeInt32ToTagged(Node* value) { 14911cb0ef41Sopenharmony_ci if (SmiValuesAre32Bits()) { 14921cb0ef41Sopenharmony_ci return ChangeInt32ToSmi(value); 14931cb0ef41Sopenharmony_ci } 14941cb0ef41Sopenharmony_ci DCHECK(SmiValuesAre31Bits()); 14951cb0ef41Sopenharmony_ci 14961cb0ef41Sopenharmony_ci auto if_overflow = __ MakeDeferredLabel(); 14971cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 14981cb0ef41Sopenharmony_ci 14991cb0ef41Sopenharmony_ci SmiTagOrOverflow(value, &if_overflow, &done); 15001cb0ef41Sopenharmony_ci 15011cb0ef41Sopenharmony_ci __ Bind(&if_overflow); 15021cb0ef41Sopenharmony_ci Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value)); 15031cb0ef41Sopenharmony_ci __ Goto(&done, number); 15041cb0ef41Sopenharmony_ci 15051cb0ef41Sopenharmony_ci __ Bind(&done); 15061cb0ef41Sopenharmony_ci return done.PhiAt(0); 15071cb0ef41Sopenharmony_ci} 15081cb0ef41Sopenharmony_ci 15091cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeInt64ToTagged(Node* node) { 15101cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 15111cb0ef41Sopenharmony_ci 15121cb0ef41Sopenharmony_ci auto if_not_in_smi_range = __ MakeDeferredLabel(); 15131cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 15141cb0ef41Sopenharmony_ci 15151cb0ef41Sopenharmony_ci Node* value32 = __ TruncateInt64ToInt32(value); 15161cb0ef41Sopenharmony_ci __ GotoIfNot(__ Word64Equal(__ ChangeInt32ToInt64(value32), value), 15171cb0ef41Sopenharmony_ci &if_not_in_smi_range); 15181cb0ef41Sopenharmony_ci 15191cb0ef41Sopenharmony_ci if (SmiValuesAre32Bits()) { 15201cb0ef41Sopenharmony_ci Node* value_smi = ChangeInt64ToSmi(value); 15211cb0ef41Sopenharmony_ci __ Goto(&done, value_smi); 15221cb0ef41Sopenharmony_ci } else { 15231cb0ef41Sopenharmony_ci SmiTagOrOverflow(value32, &if_not_in_smi_range, &done); 15241cb0ef41Sopenharmony_ci } 15251cb0ef41Sopenharmony_ci 15261cb0ef41Sopenharmony_ci __ Bind(&if_not_in_smi_range); 15271cb0ef41Sopenharmony_ci Node* number = AllocateHeapNumberWithValue(__ ChangeInt64ToFloat64(value)); 15281cb0ef41Sopenharmony_ci __ Goto(&done, number); 15291cb0ef41Sopenharmony_ci 15301cb0ef41Sopenharmony_ci __ Bind(&done); 15311cb0ef41Sopenharmony_ci return done.PhiAt(0); 15321cb0ef41Sopenharmony_ci} 15331cb0ef41Sopenharmony_ci 15341cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) { 15351cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 15361cb0ef41Sopenharmony_ci return ChangeUint32ToTagged(value); 15371cb0ef41Sopenharmony_ci} 15381cb0ef41Sopenharmony_ci 15391cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeUint32ToTagged(Node* value) { 15401cb0ef41Sopenharmony_ci auto if_not_in_smi_range = __ MakeDeferredLabel(); 15411cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 15421cb0ef41Sopenharmony_ci 15431cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); 15441cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_in_smi_range); 15451cb0ef41Sopenharmony_ci __ Goto(&done, ChangeUint32ToSmi(value)); 15461cb0ef41Sopenharmony_ci 15471cb0ef41Sopenharmony_ci __ Bind(&if_not_in_smi_range); 15481cb0ef41Sopenharmony_ci Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value)); 15491cb0ef41Sopenharmony_ci 15501cb0ef41Sopenharmony_ci __ Goto(&done, number); 15511cb0ef41Sopenharmony_ci __ Bind(&done); 15521cb0ef41Sopenharmony_ci 15531cb0ef41Sopenharmony_ci return done.PhiAt(0); 15541cb0ef41Sopenharmony_ci} 15551cb0ef41Sopenharmony_ci 15561cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeUint64ToTagged(Node* node) { 15571cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 15581cb0ef41Sopenharmony_ci 15591cb0ef41Sopenharmony_ci auto if_not_in_smi_range = __ MakeDeferredLabel(); 15601cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 15611cb0ef41Sopenharmony_ci 15621cb0ef41Sopenharmony_ci Node* check = 15631cb0ef41Sopenharmony_ci __ Uint64LessThanOrEqual(value, __ Int64Constant(Smi::kMaxValue)); 15641cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_in_smi_range); 15651cb0ef41Sopenharmony_ci __ Goto(&done, ChangeInt64ToSmi(value)); 15661cb0ef41Sopenharmony_ci 15671cb0ef41Sopenharmony_ci __ Bind(&if_not_in_smi_range); 15681cb0ef41Sopenharmony_ci Node* number = AllocateHeapNumberWithValue(__ ChangeInt64ToFloat64(value)); 15691cb0ef41Sopenharmony_ci 15701cb0ef41Sopenharmony_ci __ Goto(&done, number); 15711cb0ef41Sopenharmony_ci __ Bind(&done); 15721cb0ef41Sopenharmony_ci 15731cb0ef41Sopenharmony_ci return done.PhiAt(0); 15741cb0ef41Sopenharmony_ci} 15751cb0ef41Sopenharmony_ci 15761cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) { 15771cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 15781cb0ef41Sopenharmony_ci return ChangeSmiToInt32(value); 15791cb0ef41Sopenharmony_ci} 15801cb0ef41Sopenharmony_ci 15811cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedSignedToInt64(Node* node) { 15821cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 15831cb0ef41Sopenharmony_ci return ChangeSmiToInt64(value); 15841cb0ef41Sopenharmony_ci} 15851cb0ef41Sopenharmony_ci 15861cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) { 15871cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 15881cb0ef41Sopenharmony_ci return __ TaggedEqual(value, __ TrueConstant()); 15891cb0ef41Sopenharmony_ci} 15901cb0ef41Sopenharmony_ci 15911cb0ef41Sopenharmony_civoid EffectControlLinearizer::TruncateTaggedPointerToBit( 15921cb0ef41Sopenharmony_ci Node* node, GraphAssemblerLabel<1>* done) { 15931cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 15941cb0ef41Sopenharmony_ci 15951cb0ef41Sopenharmony_ci auto if_heapnumber = __ MakeDeferredLabel(); 15961cb0ef41Sopenharmony_ci auto if_bigint = __ MakeDeferredLabel(); 15971cb0ef41Sopenharmony_ci 15981cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 15991cb0ef41Sopenharmony_ci Node* fzero = __ Float64Constant(0.0); 16001cb0ef41Sopenharmony_ci 16011cb0ef41Sopenharmony_ci // Check if {value} is false. 16021cb0ef41Sopenharmony_ci __ GotoIf(__ TaggedEqual(value, __ FalseConstant()), done, zero); 16031cb0ef41Sopenharmony_ci 16041cb0ef41Sopenharmony_ci // Check if {value} is the empty string. 16051cb0ef41Sopenharmony_ci __ GotoIf(__ TaggedEqual(value, __ EmptyStringConstant()), done, zero); 16061cb0ef41Sopenharmony_ci 16071cb0ef41Sopenharmony_ci // Load the map of {value}. 16081cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 16091cb0ef41Sopenharmony_ci 16101cb0ef41Sopenharmony_ci // Check if the {value} is undetectable and immediately return false. 16111cb0ef41Sopenharmony_ci // This includes undefined and null. 16121cb0ef41Sopenharmony_ci Node* value_map_bitfield = 16131cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapBitField(), value_map); 16141cb0ef41Sopenharmony_ci __ GotoIfNot( 16151cb0ef41Sopenharmony_ci __ Word32Equal( 16161cb0ef41Sopenharmony_ci __ Word32And(value_map_bitfield, 16171cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsUndetectableBit::kMask)), 16181cb0ef41Sopenharmony_ci zero), 16191cb0ef41Sopenharmony_ci done, zero); 16201cb0ef41Sopenharmony_ci 16211cb0ef41Sopenharmony_ci // Check if {value} is a HeapNumber. 16221cb0ef41Sopenharmony_ci __ GotoIf(__ TaggedEqual(value_map, __ HeapNumberMapConstant()), 16231cb0ef41Sopenharmony_ci &if_heapnumber); 16241cb0ef41Sopenharmony_ci 16251cb0ef41Sopenharmony_ci // Check if {value} is a BigInt. 16261cb0ef41Sopenharmony_ci __ GotoIf(__ TaggedEqual(value_map, __ BigIntMapConstant()), &if_bigint); 16271cb0ef41Sopenharmony_ci 16281cb0ef41Sopenharmony_ci // All other values that reach here are true. 16291cb0ef41Sopenharmony_ci __ Goto(done, __ Int32Constant(1)); 16301cb0ef41Sopenharmony_ci 16311cb0ef41Sopenharmony_ci __ Bind(&if_heapnumber); 16321cb0ef41Sopenharmony_ci { 16331cb0ef41Sopenharmony_ci // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or 16341cb0ef41Sopenharmony_ci // NaN. 16351cb0ef41Sopenharmony_ci Node* value_value = 16361cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 16371cb0ef41Sopenharmony_ci __ Goto(done, __ Float64LessThan(fzero, __ Float64Abs(value_value))); 16381cb0ef41Sopenharmony_ci } 16391cb0ef41Sopenharmony_ci 16401cb0ef41Sopenharmony_ci __ Bind(&if_bigint); 16411cb0ef41Sopenharmony_ci { 16421cb0ef41Sopenharmony_ci Node* bitfield = __ LoadField(AccessBuilder::ForBigIntBitfield(), value); 16431cb0ef41Sopenharmony_ci Node* length_is_zero = __ Word32Equal( 16441cb0ef41Sopenharmony_ci __ Word32And(bitfield, __ Int32Constant(BigInt::LengthBits::kMask)), 16451cb0ef41Sopenharmony_ci __ Int32Constant(0)); 16461cb0ef41Sopenharmony_ci __ Goto(done, __ Word32Equal(length_is_zero, zero)); 16471cb0ef41Sopenharmony_ci } 16481cb0ef41Sopenharmony_ci} 16491cb0ef41Sopenharmony_ci 16501cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) { 16511cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 16521cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 16531cb0ef41Sopenharmony_ci 16541cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 16551cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &if_smi); 16561cb0ef41Sopenharmony_ci 16571cb0ef41Sopenharmony_ci TruncateTaggedPointerToBit(node, &done); 16581cb0ef41Sopenharmony_ci 16591cb0ef41Sopenharmony_ci __ Bind(&if_smi); 16601cb0ef41Sopenharmony_ci { 16611cb0ef41Sopenharmony_ci // If {value} is a Smi, then we only need to check that it's not zero. 16621cb0ef41Sopenharmony_ci __ Goto(&done, __ Word32Equal(__ TaggedEqual(value, __ SmiConstant(0)), 16631cb0ef41Sopenharmony_ci __ Int32Constant(0))); 16641cb0ef41Sopenharmony_ci } 16651cb0ef41Sopenharmony_ci 16661cb0ef41Sopenharmony_ci __ Bind(&done); 16671cb0ef41Sopenharmony_ci return done.PhiAt(0); 16681cb0ef41Sopenharmony_ci} 16691cb0ef41Sopenharmony_ci 16701cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerTruncateTaggedPointerToBit(Node* node) { 16711cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 16721cb0ef41Sopenharmony_ci 16731cb0ef41Sopenharmony_ci TruncateTaggedPointerToBit(node, &done); 16741cb0ef41Sopenharmony_ci 16751cb0ef41Sopenharmony_ci __ Bind(&done); 16761cb0ef41Sopenharmony_ci return done.PhiAt(0); 16771cb0ef41Sopenharmony_ci} 16781cb0ef41Sopenharmony_ci 16791cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) { 16801cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 16811cb0ef41Sopenharmony_ci 16821cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 16831cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 16841cb0ef41Sopenharmony_ci 16851cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 16861cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 16871cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt32(value)); 16881cb0ef41Sopenharmony_ci 16891cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 16901cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 16911cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 16921cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 16931cb0ef41Sopenharmony_ci vfalse = __ ChangeFloat64ToInt32(vfalse); 16941cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 16951cb0ef41Sopenharmony_ci 16961cb0ef41Sopenharmony_ci __ Bind(&done); 16971cb0ef41Sopenharmony_ci return done.PhiAt(0); 16981cb0ef41Sopenharmony_ci} 16991cb0ef41Sopenharmony_ci 17001cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) { 17011cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 17021cb0ef41Sopenharmony_ci 17031cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 17041cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 17051cb0ef41Sopenharmony_ci 17061cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 17071cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 17081cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt32(value)); 17091cb0ef41Sopenharmony_ci 17101cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 17111cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 17121cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 17131cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 17141cb0ef41Sopenharmony_ci vfalse = __ ChangeFloat64ToUint32(vfalse); 17151cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 17161cb0ef41Sopenharmony_ci 17171cb0ef41Sopenharmony_ci __ Bind(&done); 17181cb0ef41Sopenharmony_ci return done.PhiAt(0); 17191cb0ef41Sopenharmony_ci} 17201cb0ef41Sopenharmony_ci 17211cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedToInt64(Node* node) { 17221cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 17231cb0ef41Sopenharmony_ci 17241cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 17251cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord64); 17261cb0ef41Sopenharmony_ci 17271cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 17281cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 17291cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt64(value)); 17301cb0ef41Sopenharmony_ci 17311cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 17321cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 17331cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 17341cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 17351cb0ef41Sopenharmony_ci vfalse = __ ChangeFloat64ToInt64(vfalse); 17361cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 17371cb0ef41Sopenharmony_ci 17381cb0ef41Sopenharmony_ci __ Bind(&done); 17391cb0ef41Sopenharmony_ci return done.PhiAt(0); 17401cb0ef41Sopenharmony_ci} 17411cb0ef41Sopenharmony_ci 17421cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) { 17431cb0ef41Sopenharmony_ci return LowerTruncateTaggedToFloat64(node); 17441cb0ef41Sopenharmony_ci} 17451cb0ef41Sopenharmony_ci 17461cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) { 17471cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 17481cb0ef41Sopenharmony_ci 17491cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 17501cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 17511cb0ef41Sopenharmony_ci 17521cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 17531cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 17541cb0ef41Sopenharmony_ci __ Goto(&done, value); 17551cb0ef41Sopenharmony_ci 17561cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 17571cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 17581cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 17591cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 17601cb0ef41Sopenharmony_ci vfalse = __ ChangeFloat64ToInt32(vfalse); 17611cb0ef41Sopenharmony_ci vfalse = ChangeInt32ToSmi(vfalse); 17621cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 17631cb0ef41Sopenharmony_ci 17641cb0ef41Sopenharmony_ci __ Bind(&done); 17651cb0ef41Sopenharmony_ci return done.PhiAt(0); 17661cb0ef41Sopenharmony_ci} 17671cb0ef41Sopenharmony_ci 17681cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) { 17691cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 17701cb0ef41Sopenharmony_ci 17711cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 17721cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kFloat64); 17731cb0ef41Sopenharmony_ci 17741cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 17751cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 17761cb0ef41Sopenharmony_ci Node* vtrue = ChangeSmiToInt32(value); 17771cb0ef41Sopenharmony_ci vtrue = __ ChangeInt32ToFloat64(vtrue); 17781cb0ef41Sopenharmony_ci __ Goto(&done, vtrue); 17791cb0ef41Sopenharmony_ci 17801cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 17811cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 17821cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 17831cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 17841cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 17851cb0ef41Sopenharmony_ci 17861cb0ef41Sopenharmony_ci __ Bind(&done); 17871cb0ef41Sopenharmony_ci return done.PhiAt(0); 17881cb0ef41Sopenharmony_ci} 17891cb0ef41Sopenharmony_ci 17901cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckClosure(Node* node, 17911cb0ef41Sopenharmony_ci Node* frame_state) { 17921cb0ef41Sopenharmony_ci Handle<FeedbackCell> feedback_cell = FeedbackCellOf(node->op()); 17931cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 17941cb0ef41Sopenharmony_ci 17951cb0ef41Sopenharmony_ci // Check that {value} is actually a JSFunction. 17961cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 17971cb0ef41Sopenharmony_ci Node* value_instance_type = 17981cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 17991cb0ef41Sopenharmony_ci Node* check_instance_type = __ Uint32LessThanOrEqual( 18001cb0ef41Sopenharmony_ci __ Int32Sub(value_instance_type, 18011cb0ef41Sopenharmony_ci __ Int32Constant(FIRST_JS_FUNCTION_TYPE)), 18021cb0ef41Sopenharmony_ci __ Int32Constant(LAST_JS_FUNCTION_TYPE - FIRST_JS_FUNCTION_TYPE)); 18031cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongCallTarget, FeedbackSource(), 18041cb0ef41Sopenharmony_ci check_instance_type, frame_state); 18051cb0ef41Sopenharmony_ci 18061cb0ef41Sopenharmony_ci // Check that the {value}s feedback vector cell matches the one 18071cb0ef41Sopenharmony_ci // we recorded before. 18081cb0ef41Sopenharmony_ci Node* value_cell = 18091cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForJSFunctionFeedbackCell(), value); 18101cb0ef41Sopenharmony_ci Node* check_cell = __ WordEqual(value_cell, __ HeapConstant(feedback_cell)); 18111cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongFeedbackCell, FeedbackSource(), 18121cb0ef41Sopenharmony_ci check_cell, frame_state); 18131cb0ef41Sopenharmony_ci return value; 18141cb0ef41Sopenharmony_ci} 18151cb0ef41Sopenharmony_ci 18161cb0ef41Sopenharmony_civoid EffectControlLinearizer::MigrateInstanceOrDeopt( 18171cb0ef41Sopenharmony_ci Node* value, Node* value_map, Node* frame_state, 18181cb0ef41Sopenharmony_ci FeedbackSource const& feedback_source, DeoptimizeReason reason) { 18191cb0ef41Sopenharmony_ci // If map is not deprecated the migration attempt does not make sense. 18201cb0ef41Sopenharmony_ci Node* bitfield3 = __ LoadField(AccessBuilder::ForMapBitField3(), value_map); 18211cb0ef41Sopenharmony_ci Node* is_not_deprecated = __ Word32Equal( 18221cb0ef41Sopenharmony_ci __ Word32And(bitfield3, 18231cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits3::IsDeprecatedBit::kMask)), 18241cb0ef41Sopenharmony_ci __ Int32Constant(0)); 18251cb0ef41Sopenharmony_ci __ DeoptimizeIf(reason, feedback_source, is_not_deprecated, frame_state); 18261cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 18271cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kTryMigrateInstance; 18281cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 18291cb0ef41Sopenharmony_ci graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); 18301cb0ef41Sopenharmony_ci Node* result = __ Call(call_descriptor, __ CEntryStubConstant(1), value, 18311cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 18321cb0ef41Sopenharmony_ci __ Int32Constant(1), __ NoContextConstant()); 18331cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(result); 18341cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, feedback_source, 18351cb0ef41Sopenharmony_ci check, frame_state); 18361cb0ef41Sopenharmony_ci} 18371cb0ef41Sopenharmony_ci 18381cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { 18391cb0ef41Sopenharmony_ci CheckMapsParameters const& p = CheckMapsParametersOf(node->op()); 18401cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 18411cb0ef41Sopenharmony_ci 18421cb0ef41Sopenharmony_ci ZoneHandleSet<Map> const& maps = p.maps(); 18431cb0ef41Sopenharmony_ci size_t const map_count = maps.size(); 18441cb0ef41Sopenharmony_ci 18451cb0ef41Sopenharmony_ci if (p.flags() & CheckMapsFlag::kTryMigrateInstance) { 18461cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 18471cb0ef41Sopenharmony_ci auto migrate = __ MakeDeferredLabel(); 18481cb0ef41Sopenharmony_ci 18491cb0ef41Sopenharmony_ci // Load the current map of the {value}. 18501cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 18511cb0ef41Sopenharmony_ci 18521cb0ef41Sopenharmony_ci // Perform the map checks. 18531cb0ef41Sopenharmony_ci for (size_t i = 0; i < map_count; ++i) { 18541cb0ef41Sopenharmony_ci Node* map = __ HeapConstant(maps[i]); 18551cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value_map, map); 18561cb0ef41Sopenharmony_ci if (i == map_count - 1) { 18571cb0ef41Sopenharmony_ci __ BranchWithCriticalSafetyCheck(check, &done, &migrate); 18581cb0ef41Sopenharmony_ci } else { 18591cb0ef41Sopenharmony_ci auto next_map = __ MakeLabel(); 18601cb0ef41Sopenharmony_ci __ BranchWithCriticalSafetyCheck(check, &done, &next_map); 18611cb0ef41Sopenharmony_ci __ Bind(&next_map); 18621cb0ef41Sopenharmony_ci } 18631cb0ef41Sopenharmony_ci } 18641cb0ef41Sopenharmony_ci 18651cb0ef41Sopenharmony_ci // Perform the (deferred) instance migration. 18661cb0ef41Sopenharmony_ci __ Bind(&migrate); 18671cb0ef41Sopenharmony_ci MigrateInstanceOrDeopt(value, value_map, frame_state, p.feedback(), 18681cb0ef41Sopenharmony_ci DeoptimizeReason::kWrongMap); 18691cb0ef41Sopenharmony_ci 18701cb0ef41Sopenharmony_ci // Reload the current map of the {value}. 18711cb0ef41Sopenharmony_ci value_map = __ LoadField(AccessBuilder::ForMap(), value); 18721cb0ef41Sopenharmony_ci 18731cb0ef41Sopenharmony_ci // Perform the map checks again. 18741cb0ef41Sopenharmony_ci for (size_t i = 0; i < map_count; ++i) { 18751cb0ef41Sopenharmony_ci Node* map = __ HeapConstant(maps[i]); 18761cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value_map, map); 18771cb0ef41Sopenharmony_ci if (i == map_count - 1) { 18781cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check, 18791cb0ef41Sopenharmony_ci frame_state); 18801cb0ef41Sopenharmony_ci } else { 18811cb0ef41Sopenharmony_ci auto next_map = __ MakeLabel(); 18821cb0ef41Sopenharmony_ci __ BranchWithCriticalSafetyCheck(check, &done, &next_map); 18831cb0ef41Sopenharmony_ci __ Bind(&next_map); 18841cb0ef41Sopenharmony_ci } 18851cb0ef41Sopenharmony_ci } 18861cb0ef41Sopenharmony_ci 18871cb0ef41Sopenharmony_ci __ Goto(&done); 18881cb0ef41Sopenharmony_ci __ Bind(&done); 18891cb0ef41Sopenharmony_ci } else { 18901cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 18911cb0ef41Sopenharmony_ci 18921cb0ef41Sopenharmony_ci // Load the current map of the {value}. 18931cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 18941cb0ef41Sopenharmony_ci 18951cb0ef41Sopenharmony_ci for (size_t i = 0; i < map_count; ++i) { 18961cb0ef41Sopenharmony_ci Node* map = __ HeapConstant(maps[i]); 18971cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value_map, map); 18981cb0ef41Sopenharmony_ci 18991cb0ef41Sopenharmony_ci if (i == map_count - 1) { 19001cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check, 19011cb0ef41Sopenharmony_ci frame_state); 19021cb0ef41Sopenharmony_ci } else { 19031cb0ef41Sopenharmony_ci auto next_map = __ MakeLabel(); 19041cb0ef41Sopenharmony_ci __ BranchWithCriticalSafetyCheck(check, &done, &next_map); 19051cb0ef41Sopenharmony_ci __ Bind(&next_map); 19061cb0ef41Sopenharmony_ci } 19071cb0ef41Sopenharmony_ci } 19081cb0ef41Sopenharmony_ci __ Goto(&done); 19091cb0ef41Sopenharmony_ci __ Bind(&done); 19101cb0ef41Sopenharmony_ci } 19111cb0ef41Sopenharmony_ci} 19121cb0ef41Sopenharmony_ci 19131cb0ef41Sopenharmony_civoid EffectControlLinearizer::TryMigrateInstance(Node* value, Node* value_map) { 19141cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 19151cb0ef41Sopenharmony_ci // If map is not deprecated the migration attempt does not make sense. 19161cb0ef41Sopenharmony_ci Node* bitfield3 = __ LoadField(AccessBuilder::ForMapBitField3(), value_map); 19171cb0ef41Sopenharmony_ci Node* is_not_deprecated = __ Word32Equal( 19181cb0ef41Sopenharmony_ci __ Word32And(bitfield3, 19191cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits3::IsDeprecatedBit::kMask)), 19201cb0ef41Sopenharmony_ci __ Int32Constant(0)); 19211cb0ef41Sopenharmony_ci __ GotoIf(is_not_deprecated, &done); 19221cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 19231cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kTryMigrateInstance; 19241cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 19251cb0ef41Sopenharmony_ci graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); 19261cb0ef41Sopenharmony_ci __ Call(call_descriptor, __ CEntryStubConstant(1), value, 19271cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 19281cb0ef41Sopenharmony_ci __ Int32Constant(1), __ NoContextConstant()); 19291cb0ef41Sopenharmony_ci __ Goto(&done); 19301cb0ef41Sopenharmony_ci __ Bind(&done); 19311cb0ef41Sopenharmony_ci} 19321cb0ef41Sopenharmony_ci 19331cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCompareMaps(Node* node) { 19341cb0ef41Sopenharmony_ci ZoneHandleSet<Map> const& maps = CompareMapsParametersOf(node->op()); 19351cb0ef41Sopenharmony_ci size_t const map_count = maps.size(); 19361cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 19371cb0ef41Sopenharmony_ci 19381cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 19391cb0ef41Sopenharmony_ci 19401cb0ef41Sopenharmony_ci // Load the current map of the {value}. 19411cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 19421cb0ef41Sopenharmony_ci 19431cb0ef41Sopenharmony_ci for (size_t i = 0; i < map_count; ++i) { 19441cb0ef41Sopenharmony_ci Node* map = __ HeapConstant(maps[i]); 19451cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value_map, map); 19461cb0ef41Sopenharmony_ci 19471cb0ef41Sopenharmony_ci auto next_map = __ MakeLabel(); 19481cb0ef41Sopenharmony_ci auto passed = __ MakeLabel(); 19491cb0ef41Sopenharmony_ci __ BranchWithCriticalSafetyCheck(check, &passed, &next_map); 19501cb0ef41Sopenharmony_ci 19511cb0ef41Sopenharmony_ci __ Bind(&passed); 19521cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(1)); 19531cb0ef41Sopenharmony_ci 19541cb0ef41Sopenharmony_ci __ Bind(&next_map); 19551cb0ef41Sopenharmony_ci } 19561cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 19571cb0ef41Sopenharmony_ci 19581cb0ef41Sopenharmony_ci __ Bind(&done); 19591cb0ef41Sopenharmony_ci return done.PhiAt(0); 19601cb0ef41Sopenharmony_ci} 19611cb0ef41Sopenharmony_ci 19621cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) { 19631cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 19641cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 19651cb0ef41Sopenharmony_ci 19661cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 19671cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 19681cb0ef41Sopenharmony_ci 19691cb0ef41Sopenharmony_ci Node* check0 = ObjectIsSmi(value); 19701cb0ef41Sopenharmony_ci __ GotoIfNot(check0, &if_not_smi); 19711cb0ef41Sopenharmony_ci __ Goto(&done); 19721cb0ef41Sopenharmony_ci 19731cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 19741cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 19751cb0ef41Sopenharmony_ci Node* check1 = __ TaggedEqual(value_map, __ HeapNumberMapConstant()); 19761cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, params.feedback(), 19771cb0ef41Sopenharmony_ci check1, frame_state); 19781cb0ef41Sopenharmony_ci __ Goto(&done); 19791cb0ef41Sopenharmony_ci 19801cb0ef41Sopenharmony_ci __ Bind(&done); 19811cb0ef41Sopenharmony_ci return value; 19821cb0ef41Sopenharmony_ci} 19831cb0ef41Sopenharmony_ci 19841cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckReceiver(Node* node, 19851cb0ef41Sopenharmony_ci Node* frame_state) { 19861cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 19871cb0ef41Sopenharmony_ci 19881cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 19891cb0ef41Sopenharmony_ci Node* value_instance_type = 19901cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 19911cb0ef41Sopenharmony_ci 19921cb0ef41Sopenharmony_ci STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 19931cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThanOrEqual( 19941cb0ef41Sopenharmony_ci __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type); 19951cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAJavaScriptObject, FeedbackSource(), 19961cb0ef41Sopenharmony_ci check, frame_state); 19971cb0ef41Sopenharmony_ci return value; 19981cb0ef41Sopenharmony_ci} 19991cb0ef41Sopenharmony_ci 20001cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckReceiverOrNullOrUndefined( 20011cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 20021cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 20031cb0ef41Sopenharmony_ci 20041cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 20051cb0ef41Sopenharmony_ci Node* value_instance_type = 20061cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 20071cb0ef41Sopenharmony_ci 20081cb0ef41Sopenharmony_ci // Rule out all primitives except oddballs (true, false, undefined, null). 20091cb0ef41Sopenharmony_ci STATIC_ASSERT(LAST_PRIMITIVE_HEAP_OBJECT_TYPE == ODDBALL_TYPE); 20101cb0ef41Sopenharmony_ci STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 20111cb0ef41Sopenharmony_ci Node* check0 = __ Uint32LessThanOrEqual(__ Uint32Constant(ODDBALL_TYPE), 20121cb0ef41Sopenharmony_ci value_instance_type); 20131cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAJavaScriptObjectOrNullOrUndefined, 20141cb0ef41Sopenharmony_ci FeedbackSource(), check0, frame_state); 20151cb0ef41Sopenharmony_ci 20161cb0ef41Sopenharmony_ci // Rule out booleans. 20171cb0ef41Sopenharmony_ci Node* check1 = __ TaggedEqual(value_map, __ BooleanMapConstant()); 20181cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kNotAJavaScriptObjectOrNullOrUndefined, 20191cb0ef41Sopenharmony_ci FeedbackSource(), check1, frame_state); 20201cb0ef41Sopenharmony_ci return value; 20211cb0ef41Sopenharmony_ci} 20221cb0ef41Sopenharmony_ci 20231cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckSymbol(Node* node, Node* frame_state) { 20241cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 20251cb0ef41Sopenharmony_ci 20261cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 20271cb0ef41Sopenharmony_ci 20281cb0ef41Sopenharmony_ci Node* check = 20291cb0ef41Sopenharmony_ci __ TaggedEqual(value_map, __ HeapConstant(factory()->symbol_map())); 20301cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotASymbol, FeedbackSource(), check, 20311cb0ef41Sopenharmony_ci frame_state); 20321cb0ef41Sopenharmony_ci return value; 20331cb0ef41Sopenharmony_ci} 20341cb0ef41Sopenharmony_ci 20351cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) { 20361cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 20371cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 20381cb0ef41Sopenharmony_ci 20391cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 20401cb0ef41Sopenharmony_ci Node* value_instance_type = 20411cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 20421cb0ef41Sopenharmony_ci 20431cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThan(value_instance_type, 20441cb0ef41Sopenharmony_ci __ Uint32Constant(FIRST_NONSTRING_TYPE)); 20451cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAString, params.feedback(), check, 20461cb0ef41Sopenharmony_ci frame_state); 20471cb0ef41Sopenharmony_ci return value; 20481cb0ef41Sopenharmony_ci} 20491cb0ef41Sopenharmony_ci 20501cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckInternalizedString(Node* node, 20511cb0ef41Sopenharmony_ci Node* frame_state) { 20521cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 20531cb0ef41Sopenharmony_ci 20541cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 20551cb0ef41Sopenharmony_ci Node* value_instance_type = 20561cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 20571cb0ef41Sopenharmony_ci 20581cb0ef41Sopenharmony_ci Node* check = __ Word32Equal( 20591cb0ef41Sopenharmony_ci __ Word32And(value_instance_type, 20601cb0ef41Sopenharmony_ci __ Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)), 20611cb0ef41Sopenharmony_ci __ Int32Constant(kInternalizedTag)); 20621cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongInstanceType, FeedbackSource(), 20631cb0ef41Sopenharmony_ci check, frame_state); 20641cb0ef41Sopenharmony_ci 20651cb0ef41Sopenharmony_ci return value; 20661cb0ef41Sopenharmony_ci} 20671cb0ef41Sopenharmony_ci 20681cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) { 20691cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 20701cb0ef41Sopenharmony_ci const CheckIfParameters& p = CheckIfParametersOf(node->op()); 20711cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(p.reason(), p.feedback(), value, frame_state); 20721cb0ef41Sopenharmony_ci} 20731cb0ef41Sopenharmony_ci 20741cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringConcat(Node* node) { 20751cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(1); 20761cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(2); 20771cb0ef41Sopenharmony_ci 20781cb0ef41Sopenharmony_ci Callable const callable = 20791cb0ef41Sopenharmony_ci CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE); 20801cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 20811cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 20821cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags, 20831cb0ef41Sopenharmony_ci Operator::kNoDeopt | Operator::kNoWrite | Operator::kNoThrow); 20841cb0ef41Sopenharmony_ci 20851cb0ef41Sopenharmony_ci Node* value = __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, 20861cb0ef41Sopenharmony_ci rhs, __ NoContextConstant()); 20871cb0ef41Sopenharmony_ci 20881cb0ef41Sopenharmony_ci return value; 20891cb0ef41Sopenharmony_ci} 20901cb0ef41Sopenharmony_ci 20911cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt32Add(Node* node, 20921cb0ef41Sopenharmony_ci Node* frame_state) { 20931cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 20941cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 20951cb0ef41Sopenharmony_ci 20961cb0ef41Sopenharmony_ci Node* value = __ Int32AddWithOverflow(lhs, rhs); 20971cb0ef41Sopenharmony_ci Node* check = __ Projection(1, value); 20981cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kOverflow, FeedbackSource(), check, 20991cb0ef41Sopenharmony_ci frame_state); 21001cb0ef41Sopenharmony_ci return __ Projection(0, value); 21011cb0ef41Sopenharmony_ci} 21021cb0ef41Sopenharmony_ci 21031cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, 21041cb0ef41Sopenharmony_ci Node* frame_state) { 21051cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 21061cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 21071cb0ef41Sopenharmony_ci 21081cb0ef41Sopenharmony_ci Node* value = __ Int32SubWithOverflow(lhs, rhs); 21091cb0ef41Sopenharmony_ci Node* check = __ Projection(1, value); 21101cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kOverflow, FeedbackSource(), check, 21111cb0ef41Sopenharmony_ci frame_state); 21121cb0ef41Sopenharmony_ci return __ Projection(0, value); 21131cb0ef41Sopenharmony_ci} 21141cb0ef41Sopenharmony_ci 21151cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt32Div(Node* node, 21161cb0ef41Sopenharmony_ci Node* frame_state) { 21171cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 21181cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 21191cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 21201cb0ef41Sopenharmony_ci 21211cb0ef41Sopenharmony_ci // Check if the {rhs} is a known power of two. 21221cb0ef41Sopenharmony_ci Int32Matcher m(rhs); 21231cb0ef41Sopenharmony_ci if (m.IsPowerOf2()) { 21241cb0ef41Sopenharmony_ci // Since we know that {rhs} is a power of two, we can perform a fast 21251cb0ef41Sopenharmony_ci // check to see if the relevant least significant bits of the {lhs} 21261cb0ef41Sopenharmony_ci // are all zero, and if so we know that we can perform a division 21271cb0ef41Sopenharmony_ci // safely (and fast by doing an arithmetic - aka sign preserving - 21281cb0ef41Sopenharmony_ci // right shift on {lhs}). 21291cb0ef41Sopenharmony_ci int32_t divisor = m.ResolvedValue(); 21301cb0ef41Sopenharmony_ci Node* mask = __ Int32Constant(divisor - 1); 21311cb0ef41Sopenharmony_ci Node* shift = __ Int32Constant(base::bits::WhichPowerOfTwo(divisor)); 21321cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(__ Word32And(lhs, mask), zero); 21331cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, FeedbackSource(), 21341cb0ef41Sopenharmony_ci check, frame_state); 21351cb0ef41Sopenharmony_ci return __ Word32Sar(lhs, shift); 21361cb0ef41Sopenharmony_ci } else { 21371cb0ef41Sopenharmony_ci auto if_rhs_positive = __ MakeLabel(); 21381cb0ef41Sopenharmony_ci auto if_rhs_negative = __ MakeDeferredLabel(); 21391cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 21401cb0ef41Sopenharmony_ci 21411cb0ef41Sopenharmony_ci // Check if {rhs} is positive (and not zero). 21421cb0ef41Sopenharmony_ci Node* check_rhs_positive = __ Int32LessThan(zero, rhs); 21431cb0ef41Sopenharmony_ci __ Branch(check_rhs_positive, &if_rhs_positive, &if_rhs_negative); 21441cb0ef41Sopenharmony_ci 21451cb0ef41Sopenharmony_ci __ Bind(&if_rhs_positive); 21461cb0ef41Sopenharmony_ci { 21471cb0ef41Sopenharmony_ci // Fast case, no additional checking required. 21481cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Div(lhs, rhs)); 21491cb0ef41Sopenharmony_ci } 21501cb0ef41Sopenharmony_ci 21511cb0ef41Sopenharmony_ci __ Bind(&if_rhs_negative); 21521cb0ef41Sopenharmony_ci { 21531cb0ef41Sopenharmony_ci auto if_lhs_minint = __ MakeDeferredLabel(); 21541cb0ef41Sopenharmony_ci auto if_lhs_notminint = __ MakeLabel(); 21551cb0ef41Sopenharmony_ci 21561cb0ef41Sopenharmony_ci // Check if {rhs} is zero. 21571cb0ef41Sopenharmony_ci Node* check_rhs_zero = __ Word32Equal(rhs, zero); 21581cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, FeedbackSource(), 21591cb0ef41Sopenharmony_ci check_rhs_zero, frame_state); 21601cb0ef41Sopenharmony_ci 21611cb0ef41Sopenharmony_ci // Check if {lhs} is zero, as that would produce minus zero. 21621cb0ef41Sopenharmony_ci Node* check_lhs_zero = __ Word32Equal(lhs, zero); 21631cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kMinusZero, FeedbackSource(), 21641cb0ef41Sopenharmony_ci check_lhs_zero, frame_state); 21651cb0ef41Sopenharmony_ci 21661cb0ef41Sopenharmony_ci // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have 21671cb0ef41Sopenharmony_ci // to return -kMinInt, which is not representable as Word32. 21681cb0ef41Sopenharmony_ci Node* check_lhs_minint = __ Word32Equal(lhs, __ Int32Constant(kMinInt)); 21691cb0ef41Sopenharmony_ci __ Branch(check_lhs_minint, &if_lhs_minint, &if_lhs_notminint); 21701cb0ef41Sopenharmony_ci 21711cb0ef41Sopenharmony_ci __ Bind(&if_lhs_minint); 21721cb0ef41Sopenharmony_ci { 21731cb0ef41Sopenharmony_ci // Check that {rhs} is not -1, otherwise result would be -kMinInt. 21741cb0ef41Sopenharmony_ci Node* check_rhs_minusone = __ Word32Equal(rhs, __ Int32Constant(-1)); 21751cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kOverflow, FeedbackSource(), 21761cb0ef41Sopenharmony_ci check_rhs_minusone, frame_state); 21771cb0ef41Sopenharmony_ci 21781cb0ef41Sopenharmony_ci // Perform the actual integer division. 21791cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Div(lhs, rhs)); 21801cb0ef41Sopenharmony_ci } 21811cb0ef41Sopenharmony_ci 21821cb0ef41Sopenharmony_ci __ Bind(&if_lhs_notminint); 21831cb0ef41Sopenharmony_ci { 21841cb0ef41Sopenharmony_ci // Perform the actual integer division. 21851cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Div(lhs, rhs)); 21861cb0ef41Sopenharmony_ci } 21871cb0ef41Sopenharmony_ci } 21881cb0ef41Sopenharmony_ci 21891cb0ef41Sopenharmony_ci __ Bind(&done); 21901cb0ef41Sopenharmony_ci Node* value = done.PhiAt(0); 21911cb0ef41Sopenharmony_ci 21921cb0ef41Sopenharmony_ci // Check if the remainder is non-zero. 21931cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(lhs, __ Int32Mul(value, rhs)); 21941cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, FeedbackSource(), 21951cb0ef41Sopenharmony_ci check, frame_state); 21961cb0ef41Sopenharmony_ci 21971cb0ef41Sopenharmony_ci return value; 21981cb0ef41Sopenharmony_ci } 21991cb0ef41Sopenharmony_ci} 22001cb0ef41Sopenharmony_ci 22011cb0ef41Sopenharmony_citemplate <size_t VarCount, size_t VarCount2> 22021cb0ef41Sopenharmony_civoid EffectControlLinearizer::SmiTagOrOverflow( 22031cb0ef41Sopenharmony_ci Node* value, GraphAssemblerLabel<VarCount>* if_overflow, 22041cb0ef41Sopenharmony_ci GraphAssemblerLabel<VarCount2>* done) { 22051cb0ef41Sopenharmony_ci DCHECK(SmiValuesAre31Bits()); 22061cb0ef41Sopenharmony_ci // Check for overflow at the same time that we are smi tagging. 22071cb0ef41Sopenharmony_ci // Since smi tagging shifts left by one, it's the same as adding value twice. 22081cb0ef41Sopenharmony_ci Node* add = __ Int32AddWithOverflow(value, value); 22091cb0ef41Sopenharmony_ci Node* ovf = __ Projection(1, add); 22101cb0ef41Sopenharmony_ci __ GotoIf(ovf, if_overflow); 22111cb0ef41Sopenharmony_ci Node* value_smi = __ Projection(0, add); 22121cb0ef41Sopenharmony_ci value_smi = ChangeTaggedInt32ToSmi(value_smi); 22131cb0ef41Sopenharmony_ci __ Goto(done, value_smi); 22141cb0ef41Sopenharmony_ci} 22151cb0ef41Sopenharmony_ci 22161cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::SmiTagOrDeopt(Node* value, 22171cb0ef41Sopenharmony_ci const CheckParameters& params, 22181cb0ef41Sopenharmony_ci Node* frame_state) { 22191cb0ef41Sopenharmony_ci DCHECK(SmiValuesAre31Bits()); 22201cb0ef41Sopenharmony_ci // Check for the lost precision at the same time that we are smi tagging. 22211cb0ef41Sopenharmony_ci // Since smi tagging shifts left by one, it's the same as adding value twice. 22221cb0ef41Sopenharmony_ci Node* add = __ Int32AddWithOverflow(value, value); 22231cb0ef41Sopenharmony_ci Node* check = __ Projection(1, add); 22241cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, params.feedback(), check, 22251cb0ef41Sopenharmony_ci frame_state); 22261cb0ef41Sopenharmony_ci Node* result = __ Projection(0, add); 22271cb0ef41Sopenharmony_ci return ChangeTaggedInt32ToSmi(result); 22281cb0ef41Sopenharmony_ci} 22291cb0ef41Sopenharmony_ci 22301cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildUint32Mod(Node* lhs, Node* rhs) { 22311cb0ef41Sopenharmony_ci auto if_rhs_power_of_two = __ MakeLabel(); 22321cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 22331cb0ef41Sopenharmony_ci 22341cb0ef41Sopenharmony_ci // Compute the mask for the {rhs}. 22351cb0ef41Sopenharmony_ci Node* one = __ Int32Constant(1); 22361cb0ef41Sopenharmony_ci Node* msk = __ Int32Sub(rhs, one); 22371cb0ef41Sopenharmony_ci 22381cb0ef41Sopenharmony_ci // Check if the {rhs} is a power of two. 22391cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(__ Word32And(rhs, msk), __ Int32Constant(0)), 22401cb0ef41Sopenharmony_ci &if_rhs_power_of_two); 22411cb0ef41Sopenharmony_ci { 22421cb0ef41Sopenharmony_ci // The {rhs} is not a power of two, do a generic Uint32Mod. 22431cb0ef41Sopenharmony_ci __ Goto(&done, __ Uint32Mod(lhs, rhs)); 22441cb0ef41Sopenharmony_ci } 22451cb0ef41Sopenharmony_ci 22461cb0ef41Sopenharmony_ci __ Bind(&if_rhs_power_of_two); 22471cb0ef41Sopenharmony_ci { 22481cb0ef41Sopenharmony_ci // The {rhs} is a power of two, just do a fast bit masking. 22491cb0ef41Sopenharmony_ci __ Goto(&done, __ Word32And(lhs, msk)); 22501cb0ef41Sopenharmony_ci } 22511cb0ef41Sopenharmony_ci 22521cb0ef41Sopenharmony_ci __ Bind(&done); 22531cb0ef41Sopenharmony_ci return done.PhiAt(0); 22541cb0ef41Sopenharmony_ci} 22551cb0ef41Sopenharmony_ci 22561cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, 22571cb0ef41Sopenharmony_ci Node* frame_state) { 22581cb0ef41Sopenharmony_ci // General case for signed integer modulus, with optimization for (unknown) 22591cb0ef41Sopenharmony_ci // power of 2 right hand side. 22601cb0ef41Sopenharmony_ci // 22611cb0ef41Sopenharmony_ci // if rhs <= 0 then 22621cb0ef41Sopenharmony_ci // rhs = -rhs 22631cb0ef41Sopenharmony_ci // deopt if rhs == 0 22641cb0ef41Sopenharmony_ci // let msk = rhs - 1 in 22651cb0ef41Sopenharmony_ci // if lhs < 0 then 22661cb0ef41Sopenharmony_ci // let lhs_abs = -lsh in 22671cb0ef41Sopenharmony_ci // let res = if rhs & msk == 0 then 22681cb0ef41Sopenharmony_ci // lhs_abs & msk 22691cb0ef41Sopenharmony_ci // else 22701cb0ef41Sopenharmony_ci // lhs_abs % rhs in 22711cb0ef41Sopenharmony_ci // if lhs < 0 then 22721cb0ef41Sopenharmony_ci // deopt if res == 0 22731cb0ef41Sopenharmony_ci // -res 22741cb0ef41Sopenharmony_ci // else 22751cb0ef41Sopenharmony_ci // res 22761cb0ef41Sopenharmony_ci // else 22771cb0ef41Sopenharmony_ci // if rhs & msk == 0 then 22781cb0ef41Sopenharmony_ci // lhs & msk 22791cb0ef41Sopenharmony_ci // else 22801cb0ef41Sopenharmony_ci // lhs % rhs 22811cb0ef41Sopenharmony_ci // 22821cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 22831cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 22841cb0ef41Sopenharmony_ci 22851cb0ef41Sopenharmony_ci auto if_rhs_not_positive = __ MakeDeferredLabel(); 22861cb0ef41Sopenharmony_ci auto if_lhs_negative = __ MakeDeferredLabel(); 22871cb0ef41Sopenharmony_ci auto if_rhs_power_of_two = __ MakeLabel(); 22881cb0ef41Sopenharmony_ci auto rhs_checked = __ MakeLabel(MachineRepresentation::kWord32); 22891cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 22901cb0ef41Sopenharmony_ci 22911cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 22921cb0ef41Sopenharmony_ci 22931cb0ef41Sopenharmony_ci // Check if {rhs} is not strictly positive. 22941cb0ef41Sopenharmony_ci Node* check0 = __ Int32LessThanOrEqual(rhs, zero); 22951cb0ef41Sopenharmony_ci __ GotoIf(check0, &if_rhs_not_positive); 22961cb0ef41Sopenharmony_ci __ Goto(&rhs_checked, rhs); 22971cb0ef41Sopenharmony_ci 22981cb0ef41Sopenharmony_ci __ Bind(&if_rhs_not_positive); 22991cb0ef41Sopenharmony_ci { 23001cb0ef41Sopenharmony_ci // Negate {rhs}, might still produce a negative result in case of 23011cb0ef41Sopenharmony_ci // -2^31, but that is handled safely below. 23021cb0ef41Sopenharmony_ci Node* vtrue0 = __ Int32Sub(zero, rhs); 23031cb0ef41Sopenharmony_ci 23041cb0ef41Sopenharmony_ci // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. 23051cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, FeedbackSource(), 23061cb0ef41Sopenharmony_ci __ Word32Equal(vtrue0, zero), frame_state); 23071cb0ef41Sopenharmony_ci __ Goto(&rhs_checked, vtrue0); 23081cb0ef41Sopenharmony_ci } 23091cb0ef41Sopenharmony_ci 23101cb0ef41Sopenharmony_ci __ Bind(&rhs_checked); 23111cb0ef41Sopenharmony_ci rhs = rhs_checked.PhiAt(0); 23121cb0ef41Sopenharmony_ci 23131cb0ef41Sopenharmony_ci __ GotoIf(__ Int32LessThan(lhs, zero), &if_lhs_negative); 23141cb0ef41Sopenharmony_ci { 23151cb0ef41Sopenharmony_ci // The {lhs} is a non-negative integer. 23161cb0ef41Sopenharmony_ci __ Goto(&done, BuildUint32Mod(lhs, rhs)); 23171cb0ef41Sopenharmony_ci } 23181cb0ef41Sopenharmony_ci 23191cb0ef41Sopenharmony_ci __ Bind(&if_lhs_negative); 23201cb0ef41Sopenharmony_ci { 23211cb0ef41Sopenharmony_ci // The {lhs} is a negative integer. This is very unlikely and 23221cb0ef41Sopenharmony_ci // we intentionally don't use the BuildUint32Mod() here, which 23231cb0ef41Sopenharmony_ci // would try to figure out whether {rhs} is a power of two, 23241cb0ef41Sopenharmony_ci // since this is intended to be a slow-path. 23251cb0ef41Sopenharmony_ci Node* res = __ Uint32Mod(__ Int32Sub(zero, lhs), rhs); 23261cb0ef41Sopenharmony_ci 23271cb0ef41Sopenharmony_ci // Check if we would have to return -0. 23281cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kMinusZero, FeedbackSource(), 23291cb0ef41Sopenharmony_ci __ Word32Equal(res, zero), frame_state); 23301cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Sub(zero, res)); 23311cb0ef41Sopenharmony_ci } 23321cb0ef41Sopenharmony_ci 23331cb0ef41Sopenharmony_ci __ Bind(&done); 23341cb0ef41Sopenharmony_ci return done.PhiAt(0); 23351cb0ef41Sopenharmony_ci} 23361cb0ef41Sopenharmony_ci 23371cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint32Div(Node* node, 23381cb0ef41Sopenharmony_ci Node* frame_state) { 23391cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 23401cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 23411cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 23421cb0ef41Sopenharmony_ci 23431cb0ef41Sopenharmony_ci // Check if the {rhs} is a known power of two. 23441cb0ef41Sopenharmony_ci Uint32Matcher m(rhs); 23451cb0ef41Sopenharmony_ci if (m.IsPowerOf2()) { 23461cb0ef41Sopenharmony_ci // Since we know that {rhs} is a power of two, we can perform a fast 23471cb0ef41Sopenharmony_ci // check to see if the relevant least significant bits of the {lhs} 23481cb0ef41Sopenharmony_ci // are all zero, and if so we know that we can perform a division 23491cb0ef41Sopenharmony_ci // safely (and fast by doing a logical - aka zero extending - right 23501cb0ef41Sopenharmony_ci // shift on {lhs}). 23511cb0ef41Sopenharmony_ci uint32_t divisor = m.ResolvedValue(); 23521cb0ef41Sopenharmony_ci Node* mask = __ Uint32Constant(divisor - 1); 23531cb0ef41Sopenharmony_ci Node* shift = __ Uint32Constant(base::bits::WhichPowerOfTwo(divisor)); 23541cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(__ Word32And(lhs, mask), zero); 23551cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, FeedbackSource(), 23561cb0ef41Sopenharmony_ci check, frame_state); 23571cb0ef41Sopenharmony_ci return __ Word32Shr(lhs, shift); 23581cb0ef41Sopenharmony_ci } else { 23591cb0ef41Sopenharmony_ci // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. 23601cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(rhs, zero); 23611cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, FeedbackSource(), check, 23621cb0ef41Sopenharmony_ci frame_state); 23631cb0ef41Sopenharmony_ci 23641cb0ef41Sopenharmony_ci // Perform the actual unsigned integer division. 23651cb0ef41Sopenharmony_ci Node* value = __ Uint32Div(lhs, rhs); 23661cb0ef41Sopenharmony_ci 23671cb0ef41Sopenharmony_ci // Check if the remainder is non-zero. 23681cb0ef41Sopenharmony_ci check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); 23691cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, FeedbackSource(), 23701cb0ef41Sopenharmony_ci check, frame_state); 23711cb0ef41Sopenharmony_ci return value; 23721cb0ef41Sopenharmony_ci } 23731cb0ef41Sopenharmony_ci} 23741cb0ef41Sopenharmony_ci 23751cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, 23761cb0ef41Sopenharmony_ci Node* frame_state) { 23771cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 23781cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 23791cb0ef41Sopenharmony_ci 23801cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 23811cb0ef41Sopenharmony_ci 23821cb0ef41Sopenharmony_ci // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. 23831cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(rhs, zero); 23841cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, FeedbackSource(), check, 23851cb0ef41Sopenharmony_ci frame_state); 23861cb0ef41Sopenharmony_ci 23871cb0ef41Sopenharmony_ci // Perform the actual unsigned integer modulus. 23881cb0ef41Sopenharmony_ci return BuildUint32Mod(lhs, rhs); 23891cb0ef41Sopenharmony_ci} 23901cb0ef41Sopenharmony_ci 23911cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node, 23921cb0ef41Sopenharmony_ci Node* frame_state) { 23931cb0ef41Sopenharmony_ci CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); 23941cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 23951cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 23961cb0ef41Sopenharmony_ci 23971cb0ef41Sopenharmony_ci Node* projection = __ Int32MulWithOverflow(lhs, rhs); 23981cb0ef41Sopenharmony_ci Node* check = __ Projection(1, projection); 23991cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kOverflow, FeedbackSource(), check, 24001cb0ef41Sopenharmony_ci frame_state); 24011cb0ef41Sopenharmony_ci 24021cb0ef41Sopenharmony_ci Node* value = __ Projection(0, projection); 24031cb0ef41Sopenharmony_ci 24041cb0ef41Sopenharmony_ci if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { 24051cb0ef41Sopenharmony_ci auto if_zero = __ MakeDeferredLabel(); 24061cb0ef41Sopenharmony_ci auto check_done = __ MakeLabel(); 24071cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 24081cb0ef41Sopenharmony_ci Node* check_zero = __ Word32Equal(value, zero); 24091cb0ef41Sopenharmony_ci __ GotoIf(check_zero, &if_zero); 24101cb0ef41Sopenharmony_ci __ Goto(&check_done); 24111cb0ef41Sopenharmony_ci 24121cb0ef41Sopenharmony_ci __ Bind(&if_zero); 24131cb0ef41Sopenharmony_ci // We may need to return negative zero. 24141cb0ef41Sopenharmony_ci Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero); 24151cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kMinusZero, FeedbackSource(), check_or, 24161cb0ef41Sopenharmony_ci frame_state); 24171cb0ef41Sopenharmony_ci __ Goto(&check_done); 24181cb0ef41Sopenharmony_ci 24191cb0ef41Sopenharmony_ci __ Bind(&check_done); 24201cb0ef41Sopenharmony_ci } 24211cb0ef41Sopenharmony_ci 24221cb0ef41Sopenharmony_ci return value; 24231cb0ef41Sopenharmony_ci} 24241cb0ef41Sopenharmony_ci 24251cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned( 24261cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 24271cb0ef41Sopenharmony_ci DCHECK(SmiValuesAre31Bits()); 24281cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 24291cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 24301cb0ef41Sopenharmony_ci return SmiTagOrDeopt(value, params, frame_state); 24311cb0ef41Sopenharmony_ci} 24321cb0ef41Sopenharmony_ci 24331cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt64ToInt32(Node* node, 24341cb0ef41Sopenharmony_ci Node* frame_state) { 24351cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 24361cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 24371cb0ef41Sopenharmony_ci 24381cb0ef41Sopenharmony_ci Node* value32 = __ TruncateInt64ToInt32(value); 24391cb0ef41Sopenharmony_ci Node* check = __ Word64Equal(__ ChangeInt32ToInt64(value32), value); 24401cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, 24411cb0ef41Sopenharmony_ci frame_state); 24421cb0ef41Sopenharmony_ci return value32; 24431cb0ef41Sopenharmony_ci} 24441cb0ef41Sopenharmony_ci 24451cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedInt64ToTaggedSigned( 24461cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 24471cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 24481cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 24491cb0ef41Sopenharmony_ci 24501cb0ef41Sopenharmony_ci Node* value32 = __ TruncateInt64ToInt32(value); 24511cb0ef41Sopenharmony_ci Node* check = __ Word64Equal(__ ChangeInt32ToInt64(value32), value); 24521cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, 24531cb0ef41Sopenharmony_ci frame_state); 24541cb0ef41Sopenharmony_ci 24551cb0ef41Sopenharmony_ci if (SmiValuesAre32Bits()) { 24561cb0ef41Sopenharmony_ci return ChangeInt64ToSmi(value); 24571cb0ef41Sopenharmony_ci } else { 24581cb0ef41Sopenharmony_ci return SmiTagOrDeopt(value32, params, frame_state); 24591cb0ef41Sopenharmony_ci } 24601cb0ef41Sopenharmony_ci} 24611cb0ef41Sopenharmony_ci 24621cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint32Bounds(Node* node, 24631cb0ef41Sopenharmony_ci Node* frame_state) { 24641cb0ef41Sopenharmony_ci Node* index = node->InputAt(0); 24651cb0ef41Sopenharmony_ci Node* limit = node->InputAt(1); 24661cb0ef41Sopenharmony_ci const CheckBoundsParameters& params = CheckBoundsParametersOf(node->op()); 24671cb0ef41Sopenharmony_ci 24681cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThan(index, limit); 24691cb0ef41Sopenharmony_ci if (!(params.flags() & CheckBoundsFlag::kAbortOnOutOfBounds)) { 24701cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kOutOfBounds, 24711cb0ef41Sopenharmony_ci params.check_parameters().feedback(), check, 24721cb0ef41Sopenharmony_ci frame_state); 24731cb0ef41Sopenharmony_ci } else { 24741cb0ef41Sopenharmony_ci auto if_abort = __ MakeDeferredLabel(); 24751cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 24761cb0ef41Sopenharmony_ci 24771cb0ef41Sopenharmony_ci __ Branch(check, &done, &if_abort); 24781cb0ef41Sopenharmony_ci 24791cb0ef41Sopenharmony_ci __ Bind(&if_abort); 24801cb0ef41Sopenharmony_ci __ Unreachable(&done); 24811cb0ef41Sopenharmony_ci 24821cb0ef41Sopenharmony_ci __ Bind(&done); 24831cb0ef41Sopenharmony_ci } 24841cb0ef41Sopenharmony_ci 24851cb0ef41Sopenharmony_ci return index; 24861cb0ef41Sopenharmony_ci} 24871cb0ef41Sopenharmony_ci 24881cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, 24891cb0ef41Sopenharmony_ci Node* frame_state) { 24901cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 24911cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 24921cb0ef41Sopenharmony_ci Node* unsafe = __ Int32LessThan(value, __ Int32Constant(0)); 24931cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kLostPrecision, params.feedback(), unsafe, 24941cb0ef41Sopenharmony_ci frame_state); 24951cb0ef41Sopenharmony_ci return value; 24961cb0ef41Sopenharmony_ci} 24971cb0ef41Sopenharmony_ci 24981cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned( 24991cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 25001cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 25011cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 25021cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); 25031cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, 25041cb0ef41Sopenharmony_ci frame_state); 25051cb0ef41Sopenharmony_ci return ChangeUint32ToSmi(value); 25061cb0ef41Sopenharmony_ci} 25071cb0ef41Sopenharmony_ci 25081cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint64Bounds(Node* node, 25091cb0ef41Sopenharmony_ci Node* frame_state) { 25101cb0ef41Sopenharmony_ci Node* const index = node->InputAt(0); 25111cb0ef41Sopenharmony_ci Node* const limit = node->InputAt(1); 25121cb0ef41Sopenharmony_ci const CheckBoundsParameters& params = CheckBoundsParametersOf(node->op()); 25131cb0ef41Sopenharmony_ci 25141cb0ef41Sopenharmony_ci Node* check = __ Uint64LessThan(index, limit); 25151cb0ef41Sopenharmony_ci if (!(params.flags() & CheckBoundsFlag::kAbortOnOutOfBounds)) { 25161cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kOutOfBounds, 25171cb0ef41Sopenharmony_ci params.check_parameters().feedback(), check, 25181cb0ef41Sopenharmony_ci frame_state); 25191cb0ef41Sopenharmony_ci } else { 25201cb0ef41Sopenharmony_ci auto if_abort = __ MakeDeferredLabel(); 25211cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 25221cb0ef41Sopenharmony_ci 25231cb0ef41Sopenharmony_ci __ Branch(check, &done, &if_abort); 25241cb0ef41Sopenharmony_ci 25251cb0ef41Sopenharmony_ci __ Bind(&if_abort); 25261cb0ef41Sopenharmony_ci __ Unreachable(&done); 25271cb0ef41Sopenharmony_ci 25281cb0ef41Sopenharmony_ci __ Bind(&done); 25291cb0ef41Sopenharmony_ci } 25301cb0ef41Sopenharmony_ci return index; 25311cb0ef41Sopenharmony_ci} 25321cb0ef41Sopenharmony_ci 25331cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint64ToInt32(Node* node, 25341cb0ef41Sopenharmony_ci Node* frame_state) { 25351cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 25361cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 25371cb0ef41Sopenharmony_ci 25381cb0ef41Sopenharmony_ci Node* check = __ Uint64LessThanOrEqual(value, __ Int64Constant(kMaxInt)); 25391cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, 25401cb0ef41Sopenharmony_ci frame_state); 25411cb0ef41Sopenharmony_ci return __ TruncateInt64ToInt32(value); 25421cb0ef41Sopenharmony_ci} 25431cb0ef41Sopenharmony_ci 25441cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedUint64ToTaggedSigned( 25451cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 25461cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 25471cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 25481cb0ef41Sopenharmony_ci 25491cb0ef41Sopenharmony_ci Node* check = 25501cb0ef41Sopenharmony_ci __ Uint64LessThanOrEqual(value, __ Int64Constant(Smi::kMaxValue)); 25511cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check, 25521cb0ef41Sopenharmony_ci frame_state); 25531cb0ef41Sopenharmony_ci return ChangeInt64ToSmi(value); 25541cb0ef41Sopenharmony_ci} 25551cb0ef41Sopenharmony_ci 25561cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildCheckedFloat64ToInt32( 25571cb0ef41Sopenharmony_ci CheckForMinusZeroMode mode, const FeedbackSource& feedback, Node* value, 25581cb0ef41Sopenharmony_ci Node* frame_state) { 25591cb0ef41Sopenharmony_ci Node* value32 = __ RoundFloat64ToInt32(value); 25601cb0ef41Sopenharmony_ci Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32)); 25611cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback, 25621cb0ef41Sopenharmony_ci check_same, frame_state); 25631cb0ef41Sopenharmony_ci 25641cb0ef41Sopenharmony_ci if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { 25651cb0ef41Sopenharmony_ci // Check if {value} is -0. 25661cb0ef41Sopenharmony_ci auto if_zero = __ MakeDeferredLabel(); 25671cb0ef41Sopenharmony_ci auto check_done = __ MakeLabel(); 25681cb0ef41Sopenharmony_ci 25691cb0ef41Sopenharmony_ci Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0)); 25701cb0ef41Sopenharmony_ci __ GotoIf(check_zero, &if_zero); 25711cb0ef41Sopenharmony_ci __ Goto(&check_done); 25721cb0ef41Sopenharmony_ci 25731cb0ef41Sopenharmony_ci __ Bind(&if_zero); 25741cb0ef41Sopenharmony_ci // In case of 0, we need to check the high bits for the IEEE -0 pattern. 25751cb0ef41Sopenharmony_ci Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value), 25761cb0ef41Sopenharmony_ci __ Int32Constant(0)); 25771cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kMinusZero, feedback, check_negative, 25781cb0ef41Sopenharmony_ci frame_state); 25791cb0ef41Sopenharmony_ci __ Goto(&check_done); 25801cb0ef41Sopenharmony_ci 25811cb0ef41Sopenharmony_ci __ Bind(&check_done); 25821cb0ef41Sopenharmony_ci } 25831cb0ef41Sopenharmony_ci return value32; 25841cb0ef41Sopenharmony_ci} 25851cb0ef41Sopenharmony_ci 25861cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildCheckedFloat64ToIndex( 25871cb0ef41Sopenharmony_ci const FeedbackSource& feedback, Node* value, Node* frame_state) { 25881cb0ef41Sopenharmony_ci if (machine()->Is64()) { 25891cb0ef41Sopenharmony_ci Node* value64 = 25901cb0ef41Sopenharmony_ci __ TruncateFloat64ToInt64(value, TruncateKind::kArchitectureDefault); 25911cb0ef41Sopenharmony_ci // The TruncateKind above means there will be a precision loss in case 25921cb0ef41Sopenharmony_ci // INT64_MAX input is passed, but that precision loss would not be 25931cb0ef41Sopenharmony_ci // detected and would not lead to a deoptimization from the first check. 25941cb0ef41Sopenharmony_ci // But in this case, we'll deopt anyway because of the following checks. 25951cb0ef41Sopenharmony_ci Node* check_same = __ Float64Equal(value, __ ChangeInt64ToFloat64(value64)); 25961cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback, 25971cb0ef41Sopenharmony_ci check_same, frame_state); 25981cb0ef41Sopenharmony_ci Node* check_max = 25991cb0ef41Sopenharmony_ci __ IntLessThan(value64, __ Int64Constant(kMaxSafeInteger)); 26001cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAnArrayIndex, feedback, check_max, 26011cb0ef41Sopenharmony_ci frame_state); 26021cb0ef41Sopenharmony_ci Node* check_min = 26031cb0ef41Sopenharmony_ci __ IntLessThan(__ Int64Constant(-kMaxSafeInteger), value64); 26041cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAnArrayIndex, feedback, check_min, 26051cb0ef41Sopenharmony_ci frame_state); 26061cb0ef41Sopenharmony_ci return value64; 26071cb0ef41Sopenharmony_ci } else { 26081cb0ef41Sopenharmony_ci Node* value32 = __ RoundFloat64ToInt32(value); 26091cb0ef41Sopenharmony_ci Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32)); 26101cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback, 26111cb0ef41Sopenharmony_ci check_same, frame_state); 26121cb0ef41Sopenharmony_ci return value32; 26131cb0ef41Sopenharmony_ci } 26141cb0ef41Sopenharmony_ci} 26151cb0ef41Sopenharmony_ci 26161cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, 26171cb0ef41Sopenharmony_ci Node* frame_state) { 26181cb0ef41Sopenharmony_ci const CheckMinusZeroParameters& params = 26191cb0ef41Sopenharmony_ci CheckMinusZeroParametersOf(node->op()); 26201cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 26211cb0ef41Sopenharmony_ci return BuildCheckedFloat64ToInt32(params.mode(), params.feedback(), value, 26221cb0ef41Sopenharmony_ci frame_state); 26231cb0ef41Sopenharmony_ci} 26241cb0ef41Sopenharmony_ci 26251cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildCheckedFloat64ToInt64( 26261cb0ef41Sopenharmony_ci CheckForMinusZeroMode mode, const FeedbackSource& feedback, Node* value, 26271cb0ef41Sopenharmony_ci Node* frame_state) { 26281cb0ef41Sopenharmony_ci Node* value64 = 26291cb0ef41Sopenharmony_ci __ TruncateFloat64ToInt64(value, TruncateKind::kSetOverflowToMin); 26301cb0ef41Sopenharmony_ci Node* check_same = __ Float64Equal(value, __ ChangeInt64ToFloat64(value64)); 26311cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback, 26321cb0ef41Sopenharmony_ci check_same, frame_state); 26331cb0ef41Sopenharmony_ci 26341cb0ef41Sopenharmony_ci if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { 26351cb0ef41Sopenharmony_ci // Check if {value} is -0. 26361cb0ef41Sopenharmony_ci auto if_zero = __ MakeDeferredLabel(); 26371cb0ef41Sopenharmony_ci auto check_done = __ MakeLabel(); 26381cb0ef41Sopenharmony_ci 26391cb0ef41Sopenharmony_ci Node* check_zero = __ Word64Equal(value64, __ Int64Constant(0)); 26401cb0ef41Sopenharmony_ci __ GotoIf(check_zero, &if_zero); 26411cb0ef41Sopenharmony_ci __ Goto(&check_done); 26421cb0ef41Sopenharmony_ci 26431cb0ef41Sopenharmony_ci __ Bind(&if_zero); 26441cb0ef41Sopenharmony_ci // In case of 0, we need to check the high bits for the IEEE -0 pattern. 26451cb0ef41Sopenharmony_ci Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value), 26461cb0ef41Sopenharmony_ci __ Int32Constant(0)); 26471cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kMinusZero, feedback, check_negative, 26481cb0ef41Sopenharmony_ci frame_state); 26491cb0ef41Sopenharmony_ci __ Goto(&check_done); 26501cb0ef41Sopenharmony_ci 26511cb0ef41Sopenharmony_ci __ Bind(&check_done); 26521cb0ef41Sopenharmony_ci } 26531cb0ef41Sopenharmony_ci return value64; 26541cb0ef41Sopenharmony_ci} 26551cb0ef41Sopenharmony_ci 26561cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedFloat64ToInt64(Node* node, 26571cb0ef41Sopenharmony_ci Node* frame_state) { 26581cb0ef41Sopenharmony_ci const CheckMinusZeroParameters& params = 26591cb0ef41Sopenharmony_ci CheckMinusZeroParametersOf(node->op()); 26601cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 26611cb0ef41Sopenharmony_ci return BuildCheckedFloat64ToInt64(params.mode(), params.feedback(), value, 26621cb0ef41Sopenharmony_ci frame_state); 26631cb0ef41Sopenharmony_ci} 26641cb0ef41Sopenharmony_ci 26651cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32( 26661cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 26671cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 26681cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 26691cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 26701cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotASmi, params.feedback(), check, 26711cb0ef41Sopenharmony_ci frame_state); 26721cb0ef41Sopenharmony_ci return ChangeSmiToInt32(value); 26731cb0ef41Sopenharmony_ci} 26741cb0ef41Sopenharmony_ci 26751cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTaggedToArrayIndex( 26761cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 26771cb0ef41Sopenharmony_ci CheckParameters const& params = CheckParametersOf(node->op()); 26781cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 26791cb0ef41Sopenharmony_ci 26801cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 26811cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineType::PointerRepresentation()); 26821cb0ef41Sopenharmony_ci 26831cb0ef41Sopenharmony_ci __ GotoIfNot(ObjectIsSmi(value), &if_not_smi); 26841cb0ef41Sopenharmony_ci // In the Smi case, just convert to intptr_t. 26851cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToIntPtr(value)); 26861cb0ef41Sopenharmony_ci 26871cb0ef41Sopenharmony_ci // In the non-Smi case, check the heap numberness, load the number and convert 26881cb0ef41Sopenharmony_ci // to integer. 26891cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 26901cb0ef41Sopenharmony_ci auto if_not_heap_number = __ MakeDeferredLabel(); 26911cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 26921cb0ef41Sopenharmony_ci Node* is_heap_number = __ TaggedEqual(value_map, __ HeapNumberMapConstant()); 26931cb0ef41Sopenharmony_ci __ GotoIfNot(is_heap_number, &if_not_heap_number); 26941cb0ef41Sopenharmony_ci 26951cb0ef41Sopenharmony_ci Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 26961cb0ef41Sopenharmony_ci number = BuildCheckedFloat64ToIndex(params.feedback(), number, frame_state); 26971cb0ef41Sopenharmony_ci __ Goto(&done, number); 26981cb0ef41Sopenharmony_ci 26991cb0ef41Sopenharmony_ci __ Bind(&if_not_heap_number); 27001cb0ef41Sopenharmony_ci auto calculate_index = __ MakeDeferredLabel(); 27011cb0ef41Sopenharmony_ci Node* value_instance_type = 27021cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 27031cb0ef41Sopenharmony_ci Node* is_string = __ Uint32LessThan(value_instance_type, 27041cb0ef41Sopenharmony_ci __ Uint32Constant(FIRST_NONSTRING_TYPE)); 27051cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAString, params.feedback(), 27061cb0ef41Sopenharmony_ci is_string, frame_state); 27071cb0ef41Sopenharmony_ci 27081cb0ef41Sopenharmony_ci MachineSignature::Builder builder(graph()->zone(), 1, 1); 27091cb0ef41Sopenharmony_ci builder.AddReturn(MachineType::IntPtr()); 27101cb0ef41Sopenharmony_ci builder.AddParam(MachineType::TaggedPointer()); 27111cb0ef41Sopenharmony_ci Node* string_to_array_index_function = 27121cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::string_to_array_index_function()); 27131cb0ef41Sopenharmony_ci auto call_descriptor = 27141cb0ef41Sopenharmony_ci Linkage::GetSimplifiedCDescriptor(graph()->zone(), builder.Build()); 27151cb0ef41Sopenharmony_ci Node* index = __ Call(common()->Call(call_descriptor), 27161cb0ef41Sopenharmony_ci string_to_array_index_function, value); 27171cb0ef41Sopenharmony_ci 27181cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kNotAnArrayIndex, params.feedback(), 27191cb0ef41Sopenharmony_ci __ Word32Equal(index, __ Int32Constant(-1)), frame_state); 27201cb0ef41Sopenharmony_ci 27211cb0ef41Sopenharmony_ci __ Goto(&done, index); 27221cb0ef41Sopenharmony_ci 27231cb0ef41Sopenharmony_ci __ Bind(&done); 27241cb0ef41Sopenharmony_ci return done.PhiAt(0); 27251cb0ef41Sopenharmony_ci} 27261cb0ef41Sopenharmony_ci 27271cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, 27281cb0ef41Sopenharmony_ci Node* frame_state) { 27291cb0ef41Sopenharmony_ci const CheckMinusZeroParameters& params = 27301cb0ef41Sopenharmony_ci CheckMinusZeroParametersOf(node->op()); 27311cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 27321cb0ef41Sopenharmony_ci 27331cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 27341cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 27351cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 27361cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 27371cb0ef41Sopenharmony_ci // In the Smi case, just convert to int32. 27381cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt32(value)); 27391cb0ef41Sopenharmony_ci 27401cb0ef41Sopenharmony_ci // In the non-Smi case, check the heap numberness, load the number and convert 27411cb0ef41Sopenharmony_ci // to int32. 27421cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 27431cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 27441cb0ef41Sopenharmony_ci Node* check_map = __ TaggedEqual(value_map, __ HeapNumberMapConstant()); 27451cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, params.feedback(), 27461cb0ef41Sopenharmony_ci check_map, frame_state); 27471cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 27481cb0ef41Sopenharmony_ci vfalse = BuildCheckedFloat64ToInt32(params.mode(), params.feedback(), vfalse, 27491cb0ef41Sopenharmony_ci frame_state); 27501cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 27511cb0ef41Sopenharmony_ci 27521cb0ef41Sopenharmony_ci __ Bind(&done); 27531cb0ef41Sopenharmony_ci return done.PhiAt(0); 27541cb0ef41Sopenharmony_ci} 27551cb0ef41Sopenharmony_ci 27561cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTaggedToInt64(Node* node, 27571cb0ef41Sopenharmony_ci Node* frame_state) { 27581cb0ef41Sopenharmony_ci const CheckMinusZeroParameters& params = 27591cb0ef41Sopenharmony_ci CheckMinusZeroParametersOf(node->op()); 27601cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 27611cb0ef41Sopenharmony_ci 27621cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 27631cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord64); 27641cb0ef41Sopenharmony_ci 27651cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 27661cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 27671cb0ef41Sopenharmony_ci // In the Smi case, just convert to int64. 27681cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt64(value)); 27691cb0ef41Sopenharmony_ci 27701cb0ef41Sopenharmony_ci // In the non-Smi case, check the heap numberness, load the number and convert 27711cb0ef41Sopenharmony_ci // to int64. 27721cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 27731cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 27741cb0ef41Sopenharmony_ci Node* check_map = __ TaggedEqual(value_map, __ HeapNumberMapConstant()); 27751cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, params.feedback(), 27761cb0ef41Sopenharmony_ci check_map, frame_state); 27771cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 27781cb0ef41Sopenharmony_ci vfalse = BuildCheckedFloat64ToInt64(params.mode(), params.feedback(), vfalse, 27791cb0ef41Sopenharmony_ci frame_state); 27801cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 27811cb0ef41Sopenharmony_ci 27821cb0ef41Sopenharmony_ci __ Bind(&done); 27831cb0ef41Sopenharmony_ci return done.PhiAt(0); 27841cb0ef41Sopenharmony_ci} 27851cb0ef41Sopenharmony_ci 27861cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64( 27871cb0ef41Sopenharmony_ci CheckTaggedInputMode mode, const FeedbackSource& feedback, Node* value, 27881cb0ef41Sopenharmony_ci Node* frame_state) { 27891cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 27901cb0ef41Sopenharmony_ci Node* check_number = __ TaggedEqual(value_map, __ HeapNumberMapConstant()); 27911cb0ef41Sopenharmony_ci switch (mode) { 27921cb0ef41Sopenharmony_ci case CheckTaggedInputMode::kNumber: { 27931cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotAHeapNumber, feedback, 27941cb0ef41Sopenharmony_ci check_number, frame_state); 27951cb0ef41Sopenharmony_ci break; 27961cb0ef41Sopenharmony_ci } 27971cb0ef41Sopenharmony_ci case CheckTaggedInputMode::kNumberOrBoolean: { 27981cb0ef41Sopenharmony_ci auto check_done = __ MakeLabel(); 27991cb0ef41Sopenharmony_ci 28001cb0ef41Sopenharmony_ci __ GotoIf(check_number, &check_done); 28011cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotANumberOrBoolean, feedback, 28021cb0ef41Sopenharmony_ci __ TaggedEqual(value_map, __ BooleanMapConstant()), 28031cb0ef41Sopenharmony_ci frame_state); 28041cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 28051cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 28061cb0ef41Sopenharmony_ci __ Goto(&check_done); 28071cb0ef41Sopenharmony_ci 28081cb0ef41Sopenharmony_ci __ Bind(&check_done); 28091cb0ef41Sopenharmony_ci break; 28101cb0ef41Sopenharmony_ci } 28111cb0ef41Sopenharmony_ci case CheckTaggedInputMode::kNumberOrOddball: { 28121cb0ef41Sopenharmony_ci auto check_done = __ MakeLabel(); 28131cb0ef41Sopenharmony_ci 28141cb0ef41Sopenharmony_ci __ GotoIf(check_number, &check_done); 28151cb0ef41Sopenharmony_ci // For oddballs also contain the numeric value, let us just check that 28161cb0ef41Sopenharmony_ci // we have an oddball here. 28171cb0ef41Sopenharmony_ci Node* instance_type = 28181cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 28191cb0ef41Sopenharmony_ci Node* check_oddball = 28201cb0ef41Sopenharmony_ci __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE)); 28211cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotANumberOrOddball, feedback, 28221cb0ef41Sopenharmony_ci check_oddball, frame_state); 28231cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 28241cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 28251cb0ef41Sopenharmony_ci __ Goto(&check_done); 28261cb0ef41Sopenharmony_ci 28271cb0ef41Sopenharmony_ci __ Bind(&check_done); 28281cb0ef41Sopenharmony_ci break; 28291cb0ef41Sopenharmony_ci } 28301cb0ef41Sopenharmony_ci } 28311cb0ef41Sopenharmony_ci return __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 28321cb0ef41Sopenharmony_ci} 28331cb0ef41Sopenharmony_ci 28341cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, 28351cb0ef41Sopenharmony_ci Node* frame_state) { 28361cb0ef41Sopenharmony_ci CheckTaggedInputParameters const& p = 28371cb0ef41Sopenharmony_ci CheckTaggedInputParametersOf(node->op()); 28381cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 28391cb0ef41Sopenharmony_ci 28401cb0ef41Sopenharmony_ci auto if_smi = __ MakeLabel(); 28411cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kFloat64); 28421cb0ef41Sopenharmony_ci 28431cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 28441cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 28451cb0ef41Sopenharmony_ci 28461cb0ef41Sopenharmony_ci // In the Smi case, just convert to int32 and then float64. 28471cb0ef41Sopenharmony_ci // Otherwise, check heap numberness and load the number. 28481cb0ef41Sopenharmony_ci Node* number = BuildCheckedHeapNumberOrOddballToFloat64( 28491cb0ef41Sopenharmony_ci p.mode(), p.feedback(), value, frame_state); 28501cb0ef41Sopenharmony_ci __ Goto(&done, number); 28511cb0ef41Sopenharmony_ci 28521cb0ef41Sopenharmony_ci __ Bind(&if_smi); 28531cb0ef41Sopenharmony_ci Node* from_smi = ChangeSmiToInt32(value); 28541cb0ef41Sopenharmony_ci from_smi = __ ChangeInt32ToFloat64(from_smi); 28551cb0ef41Sopenharmony_ci __ Goto(&done, from_smi); 28561cb0ef41Sopenharmony_ci 28571cb0ef41Sopenharmony_ci __ Bind(&done); 28581cb0ef41Sopenharmony_ci return done.PhiAt(0); 28591cb0ef41Sopenharmony_ci} 28601cb0ef41Sopenharmony_ci 28611cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned( 28621cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 28631cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 28641cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 28651cb0ef41Sopenharmony_ci 28661cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 28671cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kNotASmi, params.feedback(), check, 28681cb0ef41Sopenharmony_ci frame_state); 28691cb0ef41Sopenharmony_ci 28701cb0ef41Sopenharmony_ci return value; 28711cb0ef41Sopenharmony_ci} 28721cb0ef41Sopenharmony_ci 28731cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer( 28741cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 28751cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 28761cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 28771cb0ef41Sopenharmony_ci 28781cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 28791cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kSmi, params.feedback(), check, 28801cb0ef41Sopenharmony_ci frame_state); 28811cb0ef41Sopenharmony_ci return value; 28821cb0ef41Sopenharmony_ci} 28831cb0ef41Sopenharmony_ci 28841cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckBigInt(Node* node, Node* frame_state) { 28851cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 28861cb0ef41Sopenharmony_ci const CheckParameters& params = CheckParametersOf(node->op()); 28871cb0ef41Sopenharmony_ci 28881cb0ef41Sopenharmony_ci // Check for Smi. 28891cb0ef41Sopenharmony_ci Node* smi_check = ObjectIsSmi(value); 28901cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kSmi, params.feedback(), smi_check, 28911cb0ef41Sopenharmony_ci frame_state); 28921cb0ef41Sopenharmony_ci 28931cb0ef41Sopenharmony_ci // Check for BigInt. 28941cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 28951cb0ef41Sopenharmony_ci Node* bi_check = __ TaggedEqual(value_map, __ BigIntMapConstant()); 28961cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongInstanceType, params.feedback(), 28971cb0ef41Sopenharmony_ci bi_check, frame_state); 28981cb0ef41Sopenharmony_ci 28991cb0ef41Sopenharmony_ci return value; 29001cb0ef41Sopenharmony_ci} 29011cb0ef41Sopenharmony_ci 29021cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeInt64ToBigInt(Node* node) { 29031cb0ef41Sopenharmony_ci DCHECK(machine()->Is64()); 29041cb0ef41Sopenharmony_ci 29051cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 29061cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 29071cb0ef41Sopenharmony_ci 29081cb0ef41Sopenharmony_ci // BigInts with value 0 must be of size 0 (canonical form). 29091cb0ef41Sopenharmony_ci __ GotoIf(__ Word64Equal(value, __ IntPtrConstant(0)), &done, 29101cb0ef41Sopenharmony_ci BuildAllocateBigInt(nullptr, nullptr)); 29111cb0ef41Sopenharmony_ci 29121cb0ef41Sopenharmony_ci // Shift sign bit into BigInt's sign bit position. 29131cb0ef41Sopenharmony_ci Node* sign = 29141cb0ef41Sopenharmony_ci __ Word64Shr(value, __ IntPtrConstant(63 - BigInt::SignBits::kShift)); 29151cb0ef41Sopenharmony_ci Node* bitfield = 29161cb0ef41Sopenharmony_ci __ Word32Or(__ Int32Constant(BigInt::LengthBits::encode(1)), sign); 29171cb0ef41Sopenharmony_ci 29181cb0ef41Sopenharmony_ci // We use (value XOR (value >>> 63)) - (value >>> 63) to compute the 29191cb0ef41Sopenharmony_ci // absolute value, in a branchless fashion. 29201cb0ef41Sopenharmony_ci Node* sign_mask = __ Word64Sar(value, __ Int64Constant(63)); 29211cb0ef41Sopenharmony_ci Node* absolute_value = __ Int64Sub(__ Word64Xor(value, sign_mask), sign_mask); 29221cb0ef41Sopenharmony_ci __ Goto(&done, BuildAllocateBigInt(bitfield, absolute_value)); 29231cb0ef41Sopenharmony_ci 29241cb0ef41Sopenharmony_ci __ Bind(&done); 29251cb0ef41Sopenharmony_ci return done.PhiAt(0); 29261cb0ef41Sopenharmony_ci} 29271cb0ef41Sopenharmony_ci 29281cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerChangeUint64ToBigInt(Node* node) { 29291cb0ef41Sopenharmony_ci DCHECK(machine()->Is64()); 29301cb0ef41Sopenharmony_ci 29311cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 29321cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 29331cb0ef41Sopenharmony_ci 29341cb0ef41Sopenharmony_ci // BigInts with value 0 must be of size 0 (canonical form). 29351cb0ef41Sopenharmony_ci __ GotoIf(__ Word64Equal(value, __ IntPtrConstant(0)), &done, 29361cb0ef41Sopenharmony_ci BuildAllocateBigInt(nullptr, nullptr)); 29371cb0ef41Sopenharmony_ci 29381cb0ef41Sopenharmony_ci const auto bitfield = BigInt::LengthBits::encode(1); 29391cb0ef41Sopenharmony_ci __ Goto(&done, BuildAllocateBigInt(__ Int32Constant(bitfield), value)); 29401cb0ef41Sopenharmony_ci 29411cb0ef41Sopenharmony_ci __ Bind(&done); 29421cb0ef41Sopenharmony_ci return done.PhiAt(0); 29431cb0ef41Sopenharmony_ci} 29441cb0ef41Sopenharmony_ci 29451cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerTruncateBigIntToWord64(Node* node) { 29461cb0ef41Sopenharmony_ci DCHECK(machine()->Is64()); 29471cb0ef41Sopenharmony_ci 29481cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord64); 29491cb0ef41Sopenharmony_ci auto if_neg = __ MakeLabel(); 29501cb0ef41Sopenharmony_ci auto if_not_zero = __ MakeLabel(); 29511cb0ef41Sopenharmony_ci 29521cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 29531cb0ef41Sopenharmony_ci 29541cb0ef41Sopenharmony_ci Node* bitfield = __ LoadField(AccessBuilder::ForBigIntBitfield(), value); 29551cb0ef41Sopenharmony_ci __ GotoIfNot(__ Word32Equal(bitfield, __ Int32Constant(0)), &if_not_zero); 29561cb0ef41Sopenharmony_ci __ Goto(&done, __ Int64Constant(0)); 29571cb0ef41Sopenharmony_ci 29581cb0ef41Sopenharmony_ci __ Bind(&if_not_zero); 29591cb0ef41Sopenharmony_ci { 29601cb0ef41Sopenharmony_ci Node* lsd = 29611cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForBigIntLeastSignificantDigit64(), value); 29621cb0ef41Sopenharmony_ci Node* sign = 29631cb0ef41Sopenharmony_ci __ Word32And(bitfield, __ Int32Constant(BigInt::SignBits::kMask)); 29641cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(sign, __ Int32Constant(1)), &if_neg); 29651cb0ef41Sopenharmony_ci __ Goto(&done, lsd); 29661cb0ef41Sopenharmony_ci 29671cb0ef41Sopenharmony_ci __ Bind(&if_neg); 29681cb0ef41Sopenharmony_ci __ Goto(&done, __ Int64Sub(__ Int64Constant(0), lsd)); 29691cb0ef41Sopenharmony_ci } 29701cb0ef41Sopenharmony_ci 29711cb0ef41Sopenharmony_ci __ Bind(&done); 29721cb0ef41Sopenharmony_ci return done.PhiAt(0); 29731cb0ef41Sopenharmony_ci} 29741cb0ef41Sopenharmony_ci 29751cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) { 29761cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 29771cb0ef41Sopenharmony_ci 29781cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 29791cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 29801cb0ef41Sopenharmony_ci 29811cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 29821cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 29831cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt32(value)); 29841cb0ef41Sopenharmony_ci 29851cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 29861cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 29871cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 29881cb0ef41Sopenharmony_ci Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 29891cb0ef41Sopenharmony_ci vfalse = __ TruncateFloat64ToWord32(vfalse); 29901cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 29911cb0ef41Sopenharmony_ci 29921cb0ef41Sopenharmony_ci __ Bind(&done); 29931cb0ef41Sopenharmony_ci return done.PhiAt(0); 29941cb0ef41Sopenharmony_ci} 29951cb0ef41Sopenharmony_ci 29961cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32( 29971cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 29981cb0ef41Sopenharmony_ci const CheckTaggedInputParameters& params = 29991cb0ef41Sopenharmony_ci CheckTaggedInputParametersOf(node->op()); 30001cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 30011cb0ef41Sopenharmony_ci 30021cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeLabel(); 30031cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 30041cb0ef41Sopenharmony_ci 30051cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 30061cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_smi); 30071cb0ef41Sopenharmony_ci // In the Smi case, just convert to int32. 30081cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt32(value)); 30091cb0ef41Sopenharmony_ci 30101cb0ef41Sopenharmony_ci // Otherwise, check that it's a heap number or oddball and truncate the value 30111cb0ef41Sopenharmony_ci // to int32. 30121cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 30131cb0ef41Sopenharmony_ci Node* number = BuildCheckedHeapNumberOrOddballToFloat64( 30141cb0ef41Sopenharmony_ci params.mode(), params.feedback(), value, frame_state); 30151cb0ef41Sopenharmony_ci number = __ TruncateFloat64ToWord32(number); 30161cb0ef41Sopenharmony_ci __ Goto(&done, number); 30171cb0ef41Sopenharmony_ci 30181cb0ef41Sopenharmony_ci __ Bind(&done); 30191cb0ef41Sopenharmony_ci return done.PhiAt(0); 30201cb0ef41Sopenharmony_ci} 30211cb0ef41Sopenharmony_ci 30221cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerAllocate(Node* node) { 30231cb0ef41Sopenharmony_ci Node* size = node->InputAt(0); 30241cb0ef41Sopenharmony_ci AllocationType allocation = AllocationTypeOf(node->op()); 30251cb0ef41Sopenharmony_ci Node* new_node = __ Allocate(allocation, size); 30261cb0ef41Sopenharmony_ci return new_node; 30271cb0ef41Sopenharmony_ci} 30281cb0ef41Sopenharmony_ci 30291cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberToString(Node* node) { 30301cb0ef41Sopenharmony_ci Node* argument = node->InputAt(0); 30311cb0ef41Sopenharmony_ci 30321cb0ef41Sopenharmony_ci Callable const callable = 30331cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kNumberToString); 30341cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 30351cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 30361cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 30371cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 30381cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 30391cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), argument, 30401cb0ef41Sopenharmony_ci __ NoContextConstant()); 30411cb0ef41Sopenharmony_ci} 30421cb0ef41Sopenharmony_ci 30431cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsArrayBufferView(Node* node) { 30441cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 30451cb0ef41Sopenharmony_ci 30461cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 30471cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 30481cb0ef41Sopenharmony_ci 30491cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 30501cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 30511cb0ef41Sopenharmony_ci 30521cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 30531cb0ef41Sopenharmony_ci Node* value_instance_type = 30541cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 30551cb0ef41Sopenharmony_ci Node* vfalse = __ Uint32LessThan( 30561cb0ef41Sopenharmony_ci __ Int32Sub(value_instance_type, 30571cb0ef41Sopenharmony_ci __ Int32Constant(FIRST_JS_ARRAY_BUFFER_VIEW_TYPE)), 30581cb0ef41Sopenharmony_ci __ Int32Constant(LAST_JS_ARRAY_BUFFER_VIEW_TYPE - 30591cb0ef41Sopenharmony_ci FIRST_JS_ARRAY_BUFFER_VIEW_TYPE + 1)); 30601cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 30611cb0ef41Sopenharmony_ci 30621cb0ef41Sopenharmony_ci __ Bind(&if_smi); 30631cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 30641cb0ef41Sopenharmony_ci 30651cb0ef41Sopenharmony_ci __ Bind(&done); 30661cb0ef41Sopenharmony_ci return done.PhiAt(0); 30671cb0ef41Sopenharmony_ci} 30681cb0ef41Sopenharmony_ci 30691cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsBigInt(Node* node) { 30701cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 30711cb0ef41Sopenharmony_ci 30721cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 30731cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 30741cb0ef41Sopenharmony_ci 30751cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 30761cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 30771cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 30781cb0ef41Sopenharmony_ci Node* vfalse = __ TaggedEqual(value_map, __ BigIntMapConstant()); 30791cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 30801cb0ef41Sopenharmony_ci 30811cb0ef41Sopenharmony_ci __ Bind(&if_smi); 30821cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 30831cb0ef41Sopenharmony_ci 30841cb0ef41Sopenharmony_ci __ Bind(&done); 30851cb0ef41Sopenharmony_ci return done.PhiAt(0); 30861cb0ef41Sopenharmony_ci} 30871cb0ef41Sopenharmony_ci 30881cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsCallable(Node* node) { 30891cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 30901cb0ef41Sopenharmony_ci 30911cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 30921cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 30931cb0ef41Sopenharmony_ci 30941cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 30951cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 30961cb0ef41Sopenharmony_ci 30971cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 30981cb0ef41Sopenharmony_ci Node* value_bit_field = 30991cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapBitField(), value_map); 31001cb0ef41Sopenharmony_ci Node* vfalse = __ Word32Equal( 31011cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsCallableBit::kMask), 31021cb0ef41Sopenharmony_ci __ Word32And(value_bit_field, 31031cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsCallableBit::kMask))); 31041cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 31051cb0ef41Sopenharmony_ci 31061cb0ef41Sopenharmony_ci __ Bind(&if_smi); 31071cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 31081cb0ef41Sopenharmony_ci 31091cb0ef41Sopenharmony_ci __ Bind(&done); 31101cb0ef41Sopenharmony_ci return done.PhiAt(0); 31111cb0ef41Sopenharmony_ci} 31121cb0ef41Sopenharmony_ci 31131cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsConstructor(Node* node) { 31141cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 31151cb0ef41Sopenharmony_ci 31161cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 31171cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 31181cb0ef41Sopenharmony_ci 31191cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 31201cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 31211cb0ef41Sopenharmony_ci 31221cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 31231cb0ef41Sopenharmony_ci Node* value_bit_field = 31241cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapBitField(), value_map); 31251cb0ef41Sopenharmony_ci Node* vfalse = __ Word32Equal( 31261cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsConstructorBit::kMask), 31271cb0ef41Sopenharmony_ci __ Word32And(value_bit_field, 31281cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsConstructorBit::kMask))); 31291cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 31301cb0ef41Sopenharmony_ci 31311cb0ef41Sopenharmony_ci __ Bind(&if_smi); 31321cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 31331cb0ef41Sopenharmony_ci 31341cb0ef41Sopenharmony_ci __ Bind(&done); 31351cb0ef41Sopenharmony_ci return done.PhiAt(0); 31361cb0ef41Sopenharmony_ci} 31371cb0ef41Sopenharmony_ci 31381cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) { 31391cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 31401cb0ef41Sopenharmony_ci 31411cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 31421cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 31431cb0ef41Sopenharmony_ci 31441cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 31451cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 31461cb0ef41Sopenharmony_ci 31471cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 31481cb0ef41Sopenharmony_ci Node* value_bit_field = 31491cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapBitField(), value_map); 31501cb0ef41Sopenharmony_ci Node* vfalse = __ Word32Equal( 31511cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsCallableBit::kMask), 31521cb0ef41Sopenharmony_ci __ Word32And(value_bit_field, 31531cb0ef41Sopenharmony_ci __ Int32Constant((Map::Bits1::IsCallableBit::kMask) | 31541cb0ef41Sopenharmony_ci (Map::Bits1::IsUndetectableBit::kMask)))); 31551cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 31561cb0ef41Sopenharmony_ci 31571cb0ef41Sopenharmony_ci __ Bind(&if_smi); 31581cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 31591cb0ef41Sopenharmony_ci 31601cb0ef41Sopenharmony_ci __ Bind(&done); 31611cb0ef41Sopenharmony_ci return done.PhiAt(0); 31621cb0ef41Sopenharmony_ci} 31631cb0ef41Sopenharmony_ci 31641cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberIsFloat64Hole(Node* node) { 31651cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 31661cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value), 31671cb0ef41Sopenharmony_ci __ Int32Constant(kHoleNanUpper32)); 31681cb0ef41Sopenharmony_ci return check; 31691cb0ef41Sopenharmony_ci} 31701cb0ef41Sopenharmony_ci 31711cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberIsFinite(Node* node) { 31721cb0ef41Sopenharmony_ci Node* number = node->InputAt(0); 31731cb0ef41Sopenharmony_ci Node* diff = __ Float64Sub(number, number); 31741cb0ef41Sopenharmony_ci Node* check = __ Float64Equal(diff, diff); 31751cb0ef41Sopenharmony_ci return check; 31761cb0ef41Sopenharmony_ci} 31771cb0ef41Sopenharmony_ci 31781cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsFiniteNumber(Node* node) { 31791cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 31801cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 31811cb0ef41Sopenharmony_ci Node* one = __ Int32Constant(1); 31821cb0ef41Sopenharmony_ci 31831cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 31841cb0ef41Sopenharmony_ci 31851cb0ef41Sopenharmony_ci // Check if {object} is a Smi. 31861cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(object), &done, one); 31871cb0ef41Sopenharmony_ci 31881cb0ef41Sopenharmony_ci // Check if {object} is a HeapNumber. 31891cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), object); 31901cb0ef41Sopenharmony_ci __ GotoIfNot(__ TaggedEqual(value_map, __ HeapNumberMapConstant()), &done, 31911cb0ef41Sopenharmony_ci zero); 31921cb0ef41Sopenharmony_ci 31931cb0ef41Sopenharmony_ci // {object} is a HeapNumber. 31941cb0ef41Sopenharmony_ci Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object); 31951cb0ef41Sopenharmony_ci Node* diff = __ Float64Sub(value, value); 31961cb0ef41Sopenharmony_ci Node* check = __ Float64Equal(diff, diff); 31971cb0ef41Sopenharmony_ci __ Goto(&done, check); 31981cb0ef41Sopenharmony_ci 31991cb0ef41Sopenharmony_ci __ Bind(&done); 32001cb0ef41Sopenharmony_ci return done.PhiAt(0); 32011cb0ef41Sopenharmony_ci} 32021cb0ef41Sopenharmony_ci 32031cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberIsInteger(Node* node) { 32041cb0ef41Sopenharmony_ci Node* number = node->InputAt(0); 32051cb0ef41Sopenharmony_ci Node* trunc = BuildFloat64RoundTruncate(number); 32061cb0ef41Sopenharmony_ci Node* diff = __ Float64Sub(number, trunc); 32071cb0ef41Sopenharmony_ci Node* check = __ Float64Equal(diff, __ Float64Constant(0)); 32081cb0ef41Sopenharmony_ci return check; 32091cb0ef41Sopenharmony_ci} 32101cb0ef41Sopenharmony_ci 32111cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsInteger(Node* node) { 32121cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 32131cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 32141cb0ef41Sopenharmony_ci Node* one = __ Int32Constant(1); 32151cb0ef41Sopenharmony_ci 32161cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 32171cb0ef41Sopenharmony_ci 32181cb0ef41Sopenharmony_ci // Check if {object} is a Smi. 32191cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(object), &done, one); 32201cb0ef41Sopenharmony_ci 32211cb0ef41Sopenharmony_ci // Check if {object} is a HeapNumber. 32221cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), object); 32231cb0ef41Sopenharmony_ci __ GotoIfNot(__ TaggedEqual(value_map, __ HeapNumberMapConstant()), &done, 32241cb0ef41Sopenharmony_ci zero); 32251cb0ef41Sopenharmony_ci 32261cb0ef41Sopenharmony_ci // {object} is a HeapNumber. 32271cb0ef41Sopenharmony_ci Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object); 32281cb0ef41Sopenharmony_ci Node* trunc = BuildFloat64RoundTruncate(value); 32291cb0ef41Sopenharmony_ci Node* diff = __ Float64Sub(value, trunc); 32301cb0ef41Sopenharmony_ci Node* check = __ Float64Equal(diff, __ Float64Constant(0)); 32311cb0ef41Sopenharmony_ci __ Goto(&done, check); 32321cb0ef41Sopenharmony_ci 32331cb0ef41Sopenharmony_ci __ Bind(&done); 32341cb0ef41Sopenharmony_ci return done.PhiAt(0); 32351cb0ef41Sopenharmony_ci} 32361cb0ef41Sopenharmony_ci 32371cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberIsSafeInteger(Node* node) { 32381cb0ef41Sopenharmony_ci Node* number = node->InputAt(0); 32391cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 32401cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 32411cb0ef41Sopenharmony_ci 32421cb0ef41Sopenharmony_ci Node* trunc = BuildFloat64RoundTruncate(number); 32431cb0ef41Sopenharmony_ci Node* diff = __ Float64Sub(number, trunc); 32441cb0ef41Sopenharmony_ci Node* check = __ Float64Equal(diff, __ Float64Constant(0)); 32451cb0ef41Sopenharmony_ci __ GotoIfNot(check, &done, zero); 32461cb0ef41Sopenharmony_ci Node* in_range = __ Float64LessThanOrEqual( 32471cb0ef41Sopenharmony_ci __ Float64Abs(trunc), __ Float64Constant(kMaxSafeInteger)); 32481cb0ef41Sopenharmony_ci __ Goto(&done, in_range); 32491cb0ef41Sopenharmony_ci 32501cb0ef41Sopenharmony_ci __ Bind(&done); 32511cb0ef41Sopenharmony_ci return done.PhiAt(0); 32521cb0ef41Sopenharmony_ci} 32531cb0ef41Sopenharmony_ci 32541cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsSafeInteger(Node* node) { 32551cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 32561cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 32571cb0ef41Sopenharmony_ci Node* one = __ Int32Constant(1); 32581cb0ef41Sopenharmony_ci 32591cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 32601cb0ef41Sopenharmony_ci 32611cb0ef41Sopenharmony_ci // Check if {object} is a Smi. 32621cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(object), &done, one); 32631cb0ef41Sopenharmony_ci 32641cb0ef41Sopenharmony_ci // Check if {object} is a HeapNumber. 32651cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), object); 32661cb0ef41Sopenharmony_ci __ GotoIfNot(__ TaggedEqual(value_map, __ HeapNumberMapConstant()), &done, 32671cb0ef41Sopenharmony_ci zero); 32681cb0ef41Sopenharmony_ci 32691cb0ef41Sopenharmony_ci // {object} is a HeapNumber. 32701cb0ef41Sopenharmony_ci Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), object); 32711cb0ef41Sopenharmony_ci Node* trunc = BuildFloat64RoundTruncate(value); 32721cb0ef41Sopenharmony_ci Node* diff = __ Float64Sub(value, trunc); 32731cb0ef41Sopenharmony_ci Node* check = __ Float64Equal(diff, __ Float64Constant(0)); 32741cb0ef41Sopenharmony_ci __ GotoIfNot(check, &done, zero); 32751cb0ef41Sopenharmony_ci Node* in_range = __ Float64LessThanOrEqual( 32761cb0ef41Sopenharmony_ci __ Float64Abs(trunc), __ Float64Constant(kMaxSafeInteger)); 32771cb0ef41Sopenharmony_ci __ Goto(&done, in_range); 32781cb0ef41Sopenharmony_ci 32791cb0ef41Sopenharmony_ci __ Bind(&done); 32801cb0ef41Sopenharmony_ci return done.PhiAt(0); 32811cb0ef41Sopenharmony_ci} 32821cb0ef41Sopenharmony_ci 32831cb0ef41Sopenharmony_cinamespace { 32841cb0ef41Sopenharmony_ci 32851cb0ef41Sopenharmony_ci// There is no (currently) available constexpr version of bit_cast, so we have 32861cb0ef41Sopenharmony_ci// to make do with constructing the -0.0 bits manually (by setting the sign bit 32871cb0ef41Sopenharmony_ci// to 1 and everything else to 0). 32881cb0ef41Sopenharmony_ci// TODO(leszeks): Revisit when upgrading to C++20. 32891cb0ef41Sopenharmony_ciconstexpr int32_t kMinusZeroLoBits = static_cast<int32_t>(0); 32901cb0ef41Sopenharmony_ciconstexpr int32_t kMinusZeroHiBits = static_cast<int32_t>(1) << 31; 32911cb0ef41Sopenharmony_ciconstexpr int64_t kMinusZeroBits = 32921cb0ef41Sopenharmony_ci (static_cast<uint64_t>(kMinusZeroHiBits) << 32) | kMinusZeroLoBits; 32931cb0ef41Sopenharmony_ci 32941cb0ef41Sopenharmony_ci} // namespace 32951cb0ef41Sopenharmony_ci 32961cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsMinusZero(Node* node) { 32971cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 32981cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 32991cb0ef41Sopenharmony_ci 33001cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 33011cb0ef41Sopenharmony_ci 33021cb0ef41Sopenharmony_ci // Check if {value} is a Smi. 33031cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &done, zero); 33041cb0ef41Sopenharmony_ci 33051cb0ef41Sopenharmony_ci // Check if {value} is a HeapNumber. 33061cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 33071cb0ef41Sopenharmony_ci __ GotoIfNot(__ TaggedEqual(value_map, __ HeapNumberMapConstant()), &done, 33081cb0ef41Sopenharmony_ci zero); 33091cb0ef41Sopenharmony_ci 33101cb0ef41Sopenharmony_ci // Check if {value} contains -0. 33111cb0ef41Sopenharmony_ci Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 33121cb0ef41Sopenharmony_ci if (machine()->Is64()) { 33131cb0ef41Sopenharmony_ci Node* value64 = __ BitcastFloat64ToInt64(value_value); 33141cb0ef41Sopenharmony_ci __ Goto(&done, __ Word64Equal(value64, __ Int64Constant(kMinusZeroBits))); 33151cb0ef41Sopenharmony_ci } else { 33161cb0ef41Sopenharmony_ci Node* value_lo = __ Float64ExtractLowWord32(value_value); 33171cb0ef41Sopenharmony_ci __ GotoIfNot(__ Word32Equal(value_lo, __ Int32Constant(kMinusZeroLoBits)), 33181cb0ef41Sopenharmony_ci &done, zero); 33191cb0ef41Sopenharmony_ci Node* value_hi = __ Float64ExtractHighWord32(value_value); 33201cb0ef41Sopenharmony_ci __ Goto(&done, 33211cb0ef41Sopenharmony_ci __ Word32Equal(value_hi, __ Int32Constant(kMinusZeroHiBits))); 33221cb0ef41Sopenharmony_ci } 33231cb0ef41Sopenharmony_ci 33241cb0ef41Sopenharmony_ci __ Bind(&done); 33251cb0ef41Sopenharmony_ci return done.PhiAt(0); 33261cb0ef41Sopenharmony_ci} 33271cb0ef41Sopenharmony_ci 33281cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberIsMinusZero(Node* node) { 33291cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 33301cb0ef41Sopenharmony_ci 33311cb0ef41Sopenharmony_ci if (machine()->Is64()) { 33321cb0ef41Sopenharmony_ci Node* value64 = __ BitcastFloat64ToInt64(value); 33331cb0ef41Sopenharmony_ci return __ Word64Equal(value64, __ Int64Constant(kMinusZeroBits)); 33341cb0ef41Sopenharmony_ci } else { 33351cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 33361cb0ef41Sopenharmony_ci 33371cb0ef41Sopenharmony_ci Node* value_lo = __ Float64ExtractLowWord32(value); 33381cb0ef41Sopenharmony_ci __ GotoIfNot(__ Word32Equal(value_lo, __ Int32Constant(kMinusZeroLoBits)), 33391cb0ef41Sopenharmony_ci &done, __ Int32Constant(0)); 33401cb0ef41Sopenharmony_ci Node* value_hi = __ Float64ExtractHighWord32(value); 33411cb0ef41Sopenharmony_ci __ Goto(&done, 33421cb0ef41Sopenharmony_ci __ Word32Equal(value_hi, __ Int32Constant(kMinusZeroHiBits))); 33431cb0ef41Sopenharmony_ci 33441cb0ef41Sopenharmony_ci __ Bind(&done); 33451cb0ef41Sopenharmony_ci return done.PhiAt(0); 33461cb0ef41Sopenharmony_ci } 33471cb0ef41Sopenharmony_ci} 33481cb0ef41Sopenharmony_ci 33491cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsNaN(Node* node) { 33501cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 33511cb0ef41Sopenharmony_ci Node* zero = __ Int32Constant(0); 33521cb0ef41Sopenharmony_ci 33531cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 33541cb0ef41Sopenharmony_ci 33551cb0ef41Sopenharmony_ci // Check if {value} is a Smi. 33561cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &done, zero); 33571cb0ef41Sopenharmony_ci 33581cb0ef41Sopenharmony_ci // Check if {value} is a HeapNumber. 33591cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 33601cb0ef41Sopenharmony_ci __ GotoIfNot(__ TaggedEqual(value_map, __ HeapNumberMapConstant()), &done, 33611cb0ef41Sopenharmony_ci zero); 33621cb0ef41Sopenharmony_ci 33631cb0ef41Sopenharmony_ci // Check if {value} contains a NaN. 33641cb0ef41Sopenharmony_ci Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 33651cb0ef41Sopenharmony_ci __ Goto(&done, 33661cb0ef41Sopenharmony_ci __ Word32Equal(__ Float64Equal(value_value, value_value), zero)); 33671cb0ef41Sopenharmony_ci 33681cb0ef41Sopenharmony_ci __ Bind(&done); 33691cb0ef41Sopenharmony_ci return done.PhiAt(0); 33701cb0ef41Sopenharmony_ci} 33711cb0ef41Sopenharmony_ci 33721cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberIsNaN(Node* node) { 33731cb0ef41Sopenharmony_ci Node* number = node->InputAt(0); 33741cb0ef41Sopenharmony_ci Node* diff = __ Float64Equal(number, number); 33751cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(diff, __ Int32Constant(0)); 33761cb0ef41Sopenharmony_ci return check; 33771cb0ef41Sopenharmony_ci} 33781cb0ef41Sopenharmony_ci 33791cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) { 33801cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 33811cb0ef41Sopenharmony_ci 33821cb0ef41Sopenharmony_ci auto if_primitive = __ MakeDeferredLabel(); 33831cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 33841cb0ef41Sopenharmony_ci 33851cb0ef41Sopenharmony_ci Node* check0 = ObjectIsSmi(value); 33861cb0ef41Sopenharmony_ci __ GotoIf(check0, &if_primitive); 33871cb0ef41Sopenharmony_ci 33881cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 33891cb0ef41Sopenharmony_ci Node* value_instance_type = 33901cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 33911cb0ef41Sopenharmony_ci STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 33921cb0ef41Sopenharmony_ci Node* check1 = __ Uint32LessThanOrEqual( 33931cb0ef41Sopenharmony_ci __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type); 33941cb0ef41Sopenharmony_ci __ GotoIfNot(check1, &if_primitive); 33951cb0ef41Sopenharmony_ci 33961cb0ef41Sopenharmony_ci Node* value_bit_field = 33971cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapBitField(), value_map); 33981cb0ef41Sopenharmony_ci Node* check2 = __ Word32Equal( 33991cb0ef41Sopenharmony_ci __ Int32Constant(0), 34001cb0ef41Sopenharmony_ci __ Word32And(value_bit_field, 34011cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsCallableBit::kMask))); 34021cb0ef41Sopenharmony_ci __ Goto(&done, check2); 34031cb0ef41Sopenharmony_ci 34041cb0ef41Sopenharmony_ci __ Bind(&if_primitive); 34051cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 34061cb0ef41Sopenharmony_ci 34071cb0ef41Sopenharmony_ci __ Bind(&done); 34081cb0ef41Sopenharmony_ci return done.PhiAt(0); 34091cb0ef41Sopenharmony_ci} 34101cb0ef41Sopenharmony_ci 34111cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsNumber(Node* node) { 34121cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 34131cb0ef41Sopenharmony_ci 34141cb0ef41Sopenharmony_ci auto if_smi = __ MakeLabel(); 34151cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 34161cb0ef41Sopenharmony_ci 34171cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &if_smi); 34181cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 34191cb0ef41Sopenharmony_ci __ Goto(&done, __ TaggedEqual(value_map, __ HeapNumberMapConstant())); 34201cb0ef41Sopenharmony_ci 34211cb0ef41Sopenharmony_ci __ Bind(&if_smi); 34221cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(1)); 34231cb0ef41Sopenharmony_ci 34241cb0ef41Sopenharmony_ci __ Bind(&done); 34251cb0ef41Sopenharmony_ci return done.PhiAt(0); 34261cb0ef41Sopenharmony_ci} 34271cb0ef41Sopenharmony_ci 34281cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) { 34291cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 34301cb0ef41Sopenharmony_ci 34311cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 34321cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 34331cb0ef41Sopenharmony_ci 34341cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &if_smi); 34351cb0ef41Sopenharmony_ci 34361cb0ef41Sopenharmony_ci STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 34371cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 34381cb0ef41Sopenharmony_ci Node* value_instance_type = 34391cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 34401cb0ef41Sopenharmony_ci Node* result = __ Uint32LessThanOrEqual( 34411cb0ef41Sopenharmony_ci __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type); 34421cb0ef41Sopenharmony_ci __ Goto(&done, result); 34431cb0ef41Sopenharmony_ci 34441cb0ef41Sopenharmony_ci __ Bind(&if_smi); 34451cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 34461cb0ef41Sopenharmony_ci 34471cb0ef41Sopenharmony_ci __ Bind(&done); 34481cb0ef41Sopenharmony_ci return done.PhiAt(0); 34491cb0ef41Sopenharmony_ci} 34501cb0ef41Sopenharmony_ci 34511cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsSmi(Node* node) { 34521cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 34531cb0ef41Sopenharmony_ci return ObjectIsSmi(value); 34541cb0ef41Sopenharmony_ci} 34551cb0ef41Sopenharmony_ci 34561cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsString(Node* node) { 34571cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 34581cb0ef41Sopenharmony_ci 34591cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 34601cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 34611cb0ef41Sopenharmony_ci 34621cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 34631cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 34641cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 34651cb0ef41Sopenharmony_ci Node* value_instance_type = 34661cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 34671cb0ef41Sopenharmony_ci Node* vfalse = __ Uint32LessThan(value_instance_type, 34681cb0ef41Sopenharmony_ci __ Uint32Constant(FIRST_NONSTRING_TYPE)); 34691cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 34701cb0ef41Sopenharmony_ci 34711cb0ef41Sopenharmony_ci __ Bind(&if_smi); 34721cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 34731cb0ef41Sopenharmony_ci 34741cb0ef41Sopenharmony_ci __ Bind(&done); 34751cb0ef41Sopenharmony_ci return done.PhiAt(0); 34761cb0ef41Sopenharmony_ci} 34771cb0ef41Sopenharmony_ci 34781cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsSymbol(Node* node) { 34791cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 34801cb0ef41Sopenharmony_ci 34811cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 34821cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 34831cb0ef41Sopenharmony_ci 34841cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 34851cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 34861cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 34871cb0ef41Sopenharmony_ci Node* value_instance_type = 34881cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 34891cb0ef41Sopenharmony_ci Node* vfalse = 34901cb0ef41Sopenharmony_ci __ Word32Equal(value_instance_type, __ Uint32Constant(SYMBOL_TYPE)); 34911cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 34921cb0ef41Sopenharmony_ci 34931cb0ef41Sopenharmony_ci __ Bind(&if_smi); 34941cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 34951cb0ef41Sopenharmony_ci 34961cb0ef41Sopenharmony_ci __ Bind(&done); 34971cb0ef41Sopenharmony_ci return done.PhiAt(0); 34981cb0ef41Sopenharmony_ci} 34991cb0ef41Sopenharmony_ci 35001cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) { 35011cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 35021cb0ef41Sopenharmony_ci 35031cb0ef41Sopenharmony_ci auto if_smi = __ MakeDeferredLabel(); 35041cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 35051cb0ef41Sopenharmony_ci 35061cb0ef41Sopenharmony_ci Node* check = ObjectIsSmi(value); 35071cb0ef41Sopenharmony_ci __ GotoIf(check, &if_smi); 35081cb0ef41Sopenharmony_ci 35091cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 35101cb0ef41Sopenharmony_ci Node* value_bit_field = 35111cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapBitField(), value_map); 35121cb0ef41Sopenharmony_ci Node* vfalse = __ Word32Equal( 35131cb0ef41Sopenharmony_ci __ Word32Equal( 35141cb0ef41Sopenharmony_ci __ Int32Constant(0), 35151cb0ef41Sopenharmony_ci __ Word32And(value_bit_field, 35161cb0ef41Sopenharmony_ci __ Int32Constant(Map::Bits1::IsUndetectableBit::kMask))), 35171cb0ef41Sopenharmony_ci __ Int32Constant(0)); 35181cb0ef41Sopenharmony_ci __ Goto(&done, vfalse); 35191cb0ef41Sopenharmony_ci 35201cb0ef41Sopenharmony_ci __ Bind(&if_smi); 35211cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(0)); 35221cb0ef41Sopenharmony_ci 35231cb0ef41Sopenharmony_ci __ Bind(&done); 35241cb0ef41Sopenharmony_ci return done.PhiAt(0); 35251cb0ef41Sopenharmony_ci} 35261cb0ef41Sopenharmony_ci 35271cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerTypeOf(Node* node) { 35281cb0ef41Sopenharmony_ci Node* obj = node->InputAt(0); 35291cb0ef41Sopenharmony_ci Callable const callable = Builtins::CallableFor(isolate(), Builtin::kTypeof); 35301cb0ef41Sopenharmony_ci Operator::Properties const properties = Operator::kEliminatable; 35311cb0ef41Sopenharmony_ci CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate; 35321cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 35331cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 35341cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 35351cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), obj, 35361cb0ef41Sopenharmony_ci __ NoContextConstant()); 35371cb0ef41Sopenharmony_ci} 35381cb0ef41Sopenharmony_ci 35391cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerToBoolean(Node* node) { 35401cb0ef41Sopenharmony_ci Node* obj = node->InputAt(0); 35411cb0ef41Sopenharmony_ci Callable const callable = 35421cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kToBoolean); 35431cb0ef41Sopenharmony_ci Operator::Properties const properties = Operator::kEliminatable; 35441cb0ef41Sopenharmony_ci CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate; 35451cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 35461cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 35471cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 35481cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), obj); 35491cb0ef41Sopenharmony_ci} 35501cb0ef41Sopenharmony_ci 35511cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerArgumentsLength(Node* node) { 35521cb0ef41Sopenharmony_ci Node* arguments_length = ChangeIntPtrToSmi( 35531cb0ef41Sopenharmony_ci __ Load(MachineType::Pointer(), __ LoadFramePointer(), 35541cb0ef41Sopenharmony_ci __ IntPtrConstant(StandardFrameConstants::kArgCOffset))); 35551cb0ef41Sopenharmony_ci arguments_length = 35561cb0ef41Sopenharmony_ci __ SmiSub(arguments_length, __ SmiConstant(kJSArgcReceiverSlots)); 35571cb0ef41Sopenharmony_ci return arguments_length; 35581cb0ef41Sopenharmony_ci} 35591cb0ef41Sopenharmony_ci 35601cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerRestLength(Node* node) { 35611cb0ef41Sopenharmony_ci int formal_parameter_count = FormalParameterCountOf(node->op()); 35621cb0ef41Sopenharmony_ci DCHECK_LE(0, formal_parameter_count); 35631cb0ef41Sopenharmony_ci 35641cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTaggedSigned); 35651cb0ef41Sopenharmony_ci Node* frame = __ LoadFramePointer(); 35661cb0ef41Sopenharmony_ci 35671cb0ef41Sopenharmony_ci Node* arguments_length = ChangeIntPtrToSmi( 35681cb0ef41Sopenharmony_ci __ Load(MachineType::Pointer(), frame, 35691cb0ef41Sopenharmony_ci __ IntPtrConstant(StandardFrameConstants::kArgCOffset))); 35701cb0ef41Sopenharmony_ci arguments_length = 35711cb0ef41Sopenharmony_ci __ SmiSub(arguments_length, __ SmiConstant(kJSArgcReceiverSlots)); 35721cb0ef41Sopenharmony_ci Node* rest_length = 35731cb0ef41Sopenharmony_ci __ SmiSub(arguments_length, __ SmiConstant(formal_parameter_count)); 35741cb0ef41Sopenharmony_ci __ GotoIf(__ SmiLessThan(rest_length, __ SmiConstant(0)), &done, 35751cb0ef41Sopenharmony_ci __ SmiConstant(0)); 35761cb0ef41Sopenharmony_ci __ Goto(&done, rest_length); 35771cb0ef41Sopenharmony_ci 35781cb0ef41Sopenharmony_ci __ Bind(&done); 35791cb0ef41Sopenharmony_ci return done.PhiAt(0); 35801cb0ef41Sopenharmony_ci} 35811cb0ef41Sopenharmony_ci 35821cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNewDoubleElements(Node* node) { 35831cb0ef41Sopenharmony_ci AllocationType const allocation = AllocationTypeOf(node->op()); 35841cb0ef41Sopenharmony_ci Node* length = node->InputAt(0); 35851cb0ef41Sopenharmony_ci 35861cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer); 35871cb0ef41Sopenharmony_ci Node* zero_length = __ IntPtrEqual(length, __ IntPtrConstant(0)); 35881cb0ef41Sopenharmony_ci __ GotoIf(zero_length, &done, 35891cb0ef41Sopenharmony_ci __ HeapConstant(factory()->empty_fixed_array())); 35901cb0ef41Sopenharmony_ci 35911cb0ef41Sopenharmony_ci // Compute the effective size of the backing store. 35921cb0ef41Sopenharmony_ci Node* size = __ IntAdd(__ WordShl(length, __ IntPtrConstant(kDoubleSizeLog2)), 35931cb0ef41Sopenharmony_ci __ IntPtrConstant(FixedDoubleArray::kHeaderSize)); 35941cb0ef41Sopenharmony_ci 35951cb0ef41Sopenharmony_ci // Allocate the result and initialize the header. 35961cb0ef41Sopenharmony_ci Node* result = __ Allocate(allocation, size); 35971cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), result, 35981cb0ef41Sopenharmony_ci __ FixedDoubleArrayMapConstant()); 35991cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForFixedArrayLength(), result, 36001cb0ef41Sopenharmony_ci ChangeIntPtrToSmi(length)); 36011cb0ef41Sopenharmony_ci 36021cb0ef41Sopenharmony_ci // Initialize the backing store with holes. 36031cb0ef41Sopenharmony_ci STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset, 36041cb0ef41Sopenharmony_ci Oddball::kToNumberRawOffset); 36051cb0ef41Sopenharmony_ci Node* the_hole = 36061cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForHeapNumberValue(), __ TheHoleConstant()); 36071cb0ef41Sopenharmony_ci auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation()); 36081cb0ef41Sopenharmony_ci __ Goto(&loop, __ IntPtrConstant(0)); 36091cb0ef41Sopenharmony_ci __ Bind(&loop); 36101cb0ef41Sopenharmony_ci { 36111cb0ef41Sopenharmony_ci // Check if we've initialized everything. 36121cb0ef41Sopenharmony_ci Node* index = loop.PhiAt(0); 36131cb0ef41Sopenharmony_ci Node* check = __ UintLessThan(index, length); 36141cb0ef41Sopenharmony_ci __ GotoIfNot(check, &done, result); 36151cb0ef41Sopenharmony_ci 36161cb0ef41Sopenharmony_ci ElementAccess const access = {kTaggedBase, FixedDoubleArray::kHeaderSize, 36171cb0ef41Sopenharmony_ci Type::NumberOrHole(), MachineType::Float64(), 36181cb0ef41Sopenharmony_ci kNoWriteBarrier}; 36191cb0ef41Sopenharmony_ci __ StoreElement(access, result, index, the_hole); 36201cb0ef41Sopenharmony_ci 36211cb0ef41Sopenharmony_ci // Advance the {index}. 36221cb0ef41Sopenharmony_ci index = __ IntAdd(index, __ IntPtrConstant(1)); 36231cb0ef41Sopenharmony_ci __ Goto(&loop, index); 36241cb0ef41Sopenharmony_ci } 36251cb0ef41Sopenharmony_ci 36261cb0ef41Sopenharmony_ci __ Bind(&done); 36271cb0ef41Sopenharmony_ci return done.PhiAt(0); 36281cb0ef41Sopenharmony_ci} 36291cb0ef41Sopenharmony_ci 36301cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNewSmiOrObjectElements(Node* node) { 36311cb0ef41Sopenharmony_ci AllocationType const allocation = AllocationTypeOf(node->op()); 36321cb0ef41Sopenharmony_ci Node* length = node->InputAt(0); 36331cb0ef41Sopenharmony_ci 36341cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer); 36351cb0ef41Sopenharmony_ci Node* zero_length = __ IntPtrEqual(length, __ IntPtrConstant(0)); 36361cb0ef41Sopenharmony_ci __ GotoIf(zero_length, &done, 36371cb0ef41Sopenharmony_ci __ HeapConstant(factory()->empty_fixed_array())); 36381cb0ef41Sopenharmony_ci 36391cb0ef41Sopenharmony_ci // Compute the effective size of the backing store. 36401cb0ef41Sopenharmony_ci Node* size = __ IntAdd(__ WordShl(length, __ IntPtrConstant(kTaggedSizeLog2)), 36411cb0ef41Sopenharmony_ci __ IntPtrConstant(FixedArray::kHeaderSize)); 36421cb0ef41Sopenharmony_ci 36431cb0ef41Sopenharmony_ci // Allocate the result and initialize the header. 36441cb0ef41Sopenharmony_ci Node* result = __ Allocate(allocation, size); 36451cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), result, __ FixedArrayMapConstant()); 36461cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForFixedArrayLength(), result, 36471cb0ef41Sopenharmony_ci ChangeIntPtrToSmi(length)); 36481cb0ef41Sopenharmony_ci 36491cb0ef41Sopenharmony_ci // Initialize the backing store with holes. 36501cb0ef41Sopenharmony_ci Node* the_hole = __ TheHoleConstant(); 36511cb0ef41Sopenharmony_ci auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation()); 36521cb0ef41Sopenharmony_ci __ Goto(&loop, __ IntPtrConstant(0)); 36531cb0ef41Sopenharmony_ci __ Bind(&loop); 36541cb0ef41Sopenharmony_ci { 36551cb0ef41Sopenharmony_ci // Check if we've initialized everything. 36561cb0ef41Sopenharmony_ci Node* index = loop.PhiAt(0); 36571cb0ef41Sopenharmony_ci Node* check = __ UintLessThan(index, length); 36581cb0ef41Sopenharmony_ci __ GotoIfNot(check, &done, result); 36591cb0ef41Sopenharmony_ci 36601cb0ef41Sopenharmony_ci // Storing "the_hole" doesn't need a write barrier. 36611cb0ef41Sopenharmony_ci ElementAccess const access = {kTaggedBase, FixedArray::kHeaderSize, 36621cb0ef41Sopenharmony_ci Type::Any(), MachineType::AnyTagged(), 36631cb0ef41Sopenharmony_ci kNoWriteBarrier}; 36641cb0ef41Sopenharmony_ci __ StoreElement(access, result, index, the_hole); 36651cb0ef41Sopenharmony_ci 36661cb0ef41Sopenharmony_ci // Advance the {index}. 36671cb0ef41Sopenharmony_ci index = __ IntAdd(index, __ IntPtrConstant(1)); 36681cb0ef41Sopenharmony_ci __ Goto(&loop, index); 36691cb0ef41Sopenharmony_ci } 36701cb0ef41Sopenharmony_ci 36711cb0ef41Sopenharmony_ci __ Bind(&done); 36721cb0ef41Sopenharmony_ci return done.PhiAt(0); 36731cb0ef41Sopenharmony_ci} 36741cb0ef41Sopenharmony_ci 36751cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNewArgumentsElements(Node* node) { 36761cb0ef41Sopenharmony_ci const NewArgumentsElementsParameters& parameters = 36771cb0ef41Sopenharmony_ci NewArgumentsElementsParametersOf(node->op()); 36781cb0ef41Sopenharmony_ci CreateArgumentsType type = parameters.arguments_type(); 36791cb0ef41Sopenharmony_ci Operator::Properties const properties = node->op()->properties(); 36801cb0ef41Sopenharmony_ci CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; 36811cb0ef41Sopenharmony_ci Node* frame = __ LoadFramePointer(); 36821cb0ef41Sopenharmony_ci Node* arguments_count = NodeProperties::GetValueInput(node, 0); 36831cb0ef41Sopenharmony_ci Builtin builtin_name; 36841cb0ef41Sopenharmony_ci switch (type) { 36851cb0ef41Sopenharmony_ci case CreateArgumentsType::kMappedArguments: 36861cb0ef41Sopenharmony_ci builtin_name = Builtin::kNewSloppyArgumentsElements; 36871cb0ef41Sopenharmony_ci break; 36881cb0ef41Sopenharmony_ci case CreateArgumentsType::kUnmappedArguments: 36891cb0ef41Sopenharmony_ci builtin_name = Builtin::kNewStrictArgumentsElements; 36901cb0ef41Sopenharmony_ci break; 36911cb0ef41Sopenharmony_ci case CreateArgumentsType::kRestParameter: 36921cb0ef41Sopenharmony_ci builtin_name = Builtin::kNewRestArgumentsElements; 36931cb0ef41Sopenharmony_ci break; 36941cb0ef41Sopenharmony_ci } 36951cb0ef41Sopenharmony_ci Callable const callable = Builtins::CallableFor(isolate(), builtin_name); 36961cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 36971cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 36981cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 36991cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), frame, 37001cb0ef41Sopenharmony_ci __ IntPtrConstant(parameters.formal_parameter_count()), 37011cb0ef41Sopenharmony_ci arguments_count); 37021cb0ef41Sopenharmony_ci} 37031cb0ef41Sopenharmony_ci 37041cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNewConsString(Node* node) { 37051cb0ef41Sopenharmony_ci Node* length = node->InputAt(0); 37061cb0ef41Sopenharmony_ci Node* first = node->InputAt(1); 37071cb0ef41Sopenharmony_ci Node* second = node->InputAt(2); 37081cb0ef41Sopenharmony_ci 37091cb0ef41Sopenharmony_ci // Determine the instance types of {first} and {second}. 37101cb0ef41Sopenharmony_ci Node* first_map = __ LoadField(AccessBuilder::ForMap(), first); 37111cb0ef41Sopenharmony_ci Node* first_instance_type = 37121cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), first_map); 37131cb0ef41Sopenharmony_ci Node* second_map = __ LoadField(AccessBuilder::ForMap(), second); 37141cb0ef41Sopenharmony_ci Node* second_instance_type = 37151cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), second_map); 37161cb0ef41Sopenharmony_ci 37171cb0ef41Sopenharmony_ci // Determine the proper map for the resulting ConsString. 37181cb0ef41Sopenharmony_ci // If both {first} and {second} are one-byte strings, we 37191cb0ef41Sopenharmony_ci // create a new ConsOneByteString, otherwise we create a 37201cb0ef41Sopenharmony_ci // new ConsString instead. 37211cb0ef41Sopenharmony_ci auto if_onebyte = __ MakeLabel(); 37221cb0ef41Sopenharmony_ci auto if_twobyte = __ MakeLabel(); 37231cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer); 37241cb0ef41Sopenharmony_ci STATIC_ASSERT(kOneByteStringTag != 0); 37251cb0ef41Sopenharmony_ci STATIC_ASSERT(kTwoByteStringTag == 0); 37261cb0ef41Sopenharmony_ci Node* instance_type = __ Word32And(first_instance_type, second_instance_type); 37271cb0ef41Sopenharmony_ci Node* encoding = 37281cb0ef41Sopenharmony_ci __ Word32And(instance_type, __ Int32Constant(kStringEncodingMask)); 37291cb0ef41Sopenharmony_ci __ Branch(__ Word32Equal(encoding, __ Int32Constant(kTwoByteStringTag)), 37301cb0ef41Sopenharmony_ci &if_twobyte, &if_onebyte); 37311cb0ef41Sopenharmony_ci __ Bind(&if_onebyte); 37321cb0ef41Sopenharmony_ci __ Goto(&done, __ HeapConstant(factory()->cons_one_byte_string_map())); 37331cb0ef41Sopenharmony_ci __ Bind(&if_twobyte); 37341cb0ef41Sopenharmony_ci __ Goto(&done, __ HeapConstant(factory()->cons_string_map())); 37351cb0ef41Sopenharmony_ci __ Bind(&done); 37361cb0ef41Sopenharmony_ci Node* result_map = done.PhiAt(0); 37371cb0ef41Sopenharmony_ci 37381cb0ef41Sopenharmony_ci // Allocate the resulting ConsString. 37391cb0ef41Sopenharmony_ci Node* result = 37401cb0ef41Sopenharmony_ci __ Allocate(AllocationType::kYoung, __ IntPtrConstant(ConsString::kSize)); 37411cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), result, result_map); 37421cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForNameRawHashField(), result, 37431cb0ef41Sopenharmony_ci __ Int32Constant(Name::kEmptyHashField)); 37441cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForStringLength(), result, length); 37451cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForConsStringFirst(), result, first); 37461cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForConsStringSecond(), result, second); 37471cb0ef41Sopenharmony_ci return result; 37481cb0ef41Sopenharmony_ci} 37491cb0ef41Sopenharmony_ci 37501cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerSameValue(Node* node) { 37511cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 37521cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 37531cb0ef41Sopenharmony_ci 37541cb0ef41Sopenharmony_ci Callable const callable = 37551cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kSameValue); 37561cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 37571cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 37581cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 37591cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 37601cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 37611cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs, 37621cb0ef41Sopenharmony_ci __ NoContextConstant()); 37631cb0ef41Sopenharmony_ci} 37641cb0ef41Sopenharmony_ci 37651cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerSameValueNumbersOnly(Node* node) { 37661cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 37671cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 37681cb0ef41Sopenharmony_ci 37691cb0ef41Sopenharmony_ci Callable const callable = 37701cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kSameValueNumbersOnly); 37711cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 37721cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 37731cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 37741cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 37751cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 37761cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs, 37771cb0ef41Sopenharmony_ci __ NoContextConstant()); 37781cb0ef41Sopenharmony_ci} 37791cb0ef41Sopenharmony_ci 37801cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerNumberSameValue(Node* node) { 37811cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 37821cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 37831cb0ef41Sopenharmony_ci 37841cb0ef41Sopenharmony_ci auto is_float64_equal = __ MakeLabel(); 37851cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kBit); 37861cb0ef41Sopenharmony_ci 37871cb0ef41Sopenharmony_ci __ GotoIf(__ Float64Equal(lhs, rhs), &is_float64_equal); 37881cb0ef41Sopenharmony_ci 37891cb0ef41Sopenharmony_ci // Return true iff both {lhs} and {rhs} are NaN. 37901cb0ef41Sopenharmony_ci __ GotoIf(__ Float64Equal(lhs, lhs), &done, __ Int32Constant(0)); 37911cb0ef41Sopenharmony_ci __ GotoIf(__ Float64Equal(rhs, rhs), &done, __ Int32Constant(0)); 37921cb0ef41Sopenharmony_ci __ Goto(&done, __ Int32Constant(1)); 37931cb0ef41Sopenharmony_ci 37941cb0ef41Sopenharmony_ci __ Bind(&is_float64_equal); 37951cb0ef41Sopenharmony_ci // Even if the values are float64-equal, we still need to distinguish 37961cb0ef41Sopenharmony_ci // zero and minus zero. 37971cb0ef41Sopenharmony_ci Node* lhs_hi = __ Float64ExtractHighWord32(lhs); 37981cb0ef41Sopenharmony_ci Node* rhs_hi = __ Float64ExtractHighWord32(rhs); 37991cb0ef41Sopenharmony_ci __ Goto(&done, __ Word32Equal(lhs_hi, rhs_hi)); 38001cb0ef41Sopenharmony_ci 38011cb0ef41Sopenharmony_ci __ Bind(&done); 38021cb0ef41Sopenharmony_ci return done.PhiAt(0); 38031cb0ef41Sopenharmony_ci} 38041cb0ef41Sopenharmony_ci 38051cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerDeadValue(Node* node) { 38061cb0ef41Sopenharmony_ci Node* input = NodeProperties::GetValueInput(node, 0); 38071cb0ef41Sopenharmony_ci if (input->opcode() != IrOpcode::kUnreachable) { 38081cb0ef41Sopenharmony_ci // There is no fundamental reason not to connect to end here, except it 38091cb0ef41Sopenharmony_ci // integrates into the way the graph is constructed in a simpler way at 38101cb0ef41Sopenharmony_ci // this point. 38111cb0ef41Sopenharmony_ci // TODO(jgruber): Connect to end here as well. 38121cb0ef41Sopenharmony_ci Node* unreachable = __ UnreachableWithoutConnectToEnd(); 38131cb0ef41Sopenharmony_ci NodeProperties::ReplaceValueInput(node, unreachable, 0); 38141cb0ef41Sopenharmony_ci } 38151cb0ef41Sopenharmony_ci return gasm()->AddNode(node); 38161cb0ef41Sopenharmony_ci} 38171cb0ef41Sopenharmony_ci 38181cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringToNumber(Node* node) { 38191cb0ef41Sopenharmony_ci Node* string = node->InputAt(0); 38201cb0ef41Sopenharmony_ci 38211cb0ef41Sopenharmony_ci Callable const callable = 38221cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kStringToNumber); 38231cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 38241cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 38251cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 38261cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 38271cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 38281cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), string, 38291cb0ef41Sopenharmony_ci __ NoContextConstant()); 38301cb0ef41Sopenharmony_ci} 38311cb0ef41Sopenharmony_ci 38321cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::StringCharCodeAt(Node* receiver, 38331cb0ef41Sopenharmony_ci Node* position) { 38341cb0ef41Sopenharmony_ci // We need a loop here to properly deal with indirect strings 38351cb0ef41Sopenharmony_ci // (SlicedString, ConsString and ThinString). 38361cb0ef41Sopenharmony_ci auto loop = __ MakeLoopLabel(MachineRepresentation::kTagged, 38371cb0ef41Sopenharmony_ci MachineType::PointerRepresentation()); 38381cb0ef41Sopenharmony_ci auto loop_next = __ MakeLabel(MachineRepresentation::kTagged, 38391cb0ef41Sopenharmony_ci MachineType::PointerRepresentation()); 38401cb0ef41Sopenharmony_ci auto loop_done = __ MakeLabel(MachineRepresentation::kWord32); 38411cb0ef41Sopenharmony_ci __ Goto(&loop, receiver, position); 38421cb0ef41Sopenharmony_ci __ Bind(&loop); 38431cb0ef41Sopenharmony_ci { 38441cb0ef41Sopenharmony_ci receiver = loop.PhiAt(0); 38451cb0ef41Sopenharmony_ci position = loop.PhiAt(1); 38461cb0ef41Sopenharmony_ci Node* receiver_map = __ LoadField(AccessBuilder::ForMap(), receiver); 38471cb0ef41Sopenharmony_ci Node* receiver_instance_type = 38481cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), receiver_map); 38491cb0ef41Sopenharmony_ci Node* receiver_representation = __ Word32And( 38501cb0ef41Sopenharmony_ci receiver_instance_type, __ Int32Constant(kStringRepresentationMask)); 38511cb0ef41Sopenharmony_ci 38521cb0ef41Sopenharmony_ci // Dispatch on the current {receiver}s string representation. 38531cb0ef41Sopenharmony_ci auto if_lessthanoreq_cons = __ MakeLabel(); 38541cb0ef41Sopenharmony_ci auto if_greaterthan_cons = __ MakeLabel(); 38551cb0ef41Sopenharmony_ci auto if_seqstring = __ MakeLabel(); 38561cb0ef41Sopenharmony_ci auto if_consstring = __ MakeLabel(); 38571cb0ef41Sopenharmony_ci auto if_thinstring = __ MakeLabel(); 38581cb0ef41Sopenharmony_ci auto if_externalstring = __ MakeLabel(); 38591cb0ef41Sopenharmony_ci auto if_slicedstring = __ MakeLabel(); 38601cb0ef41Sopenharmony_ci auto if_runtime = __ MakeDeferredLabel(); 38611cb0ef41Sopenharmony_ci 38621cb0ef41Sopenharmony_ci __ Branch(__ Int32LessThanOrEqual(receiver_representation, 38631cb0ef41Sopenharmony_ci __ Int32Constant(kConsStringTag)), 38641cb0ef41Sopenharmony_ci &if_lessthanoreq_cons, &if_greaterthan_cons); 38651cb0ef41Sopenharmony_ci 38661cb0ef41Sopenharmony_ci __ Bind(&if_lessthanoreq_cons); 38671cb0ef41Sopenharmony_ci { 38681cb0ef41Sopenharmony_ci __ Branch(__ Word32Equal(receiver_representation, 38691cb0ef41Sopenharmony_ci __ Int32Constant(kConsStringTag)), 38701cb0ef41Sopenharmony_ci &if_consstring, &if_seqstring); 38711cb0ef41Sopenharmony_ci } 38721cb0ef41Sopenharmony_ci 38731cb0ef41Sopenharmony_ci __ Bind(&if_greaterthan_cons); 38741cb0ef41Sopenharmony_ci { 38751cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(receiver_representation, 38761cb0ef41Sopenharmony_ci __ Int32Constant(kThinStringTag)), 38771cb0ef41Sopenharmony_ci &if_thinstring); 38781cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(receiver_representation, 38791cb0ef41Sopenharmony_ci __ Int32Constant(kExternalStringTag)), 38801cb0ef41Sopenharmony_ci &if_externalstring); 38811cb0ef41Sopenharmony_ci __ Branch(__ Word32Equal(receiver_representation, 38821cb0ef41Sopenharmony_ci __ Int32Constant(kSlicedStringTag)), 38831cb0ef41Sopenharmony_ci &if_slicedstring, &if_runtime); 38841cb0ef41Sopenharmony_ci } 38851cb0ef41Sopenharmony_ci 38861cb0ef41Sopenharmony_ci __ Bind(&if_seqstring); 38871cb0ef41Sopenharmony_ci { 38881cb0ef41Sopenharmony_ci Node* receiver_is_onebyte = __ Word32Equal( 38891cb0ef41Sopenharmony_ci __ Word32Equal(__ Word32And(receiver_instance_type, 38901cb0ef41Sopenharmony_ci __ Int32Constant(kStringEncodingMask)), 38911cb0ef41Sopenharmony_ci __ Int32Constant(kTwoByteStringTag)), 38921cb0ef41Sopenharmony_ci __ Int32Constant(0)); 38931cb0ef41Sopenharmony_ci Node* result = LoadFromSeqString(receiver, position, receiver_is_onebyte); 38941cb0ef41Sopenharmony_ci __ Goto(&loop_done, result); 38951cb0ef41Sopenharmony_ci } 38961cb0ef41Sopenharmony_ci 38971cb0ef41Sopenharmony_ci __ Bind(&if_consstring); 38981cb0ef41Sopenharmony_ci { 38991cb0ef41Sopenharmony_ci Node* receiver_second = 39001cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForConsStringSecond(), receiver); 39011cb0ef41Sopenharmony_ci __ GotoIfNot(__ TaggedEqual(receiver_second, __ EmptyStringConstant()), 39021cb0ef41Sopenharmony_ci &if_runtime); 39031cb0ef41Sopenharmony_ci Node* receiver_first = 39041cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForConsStringFirst(), receiver); 39051cb0ef41Sopenharmony_ci __ Goto(&loop_next, receiver_first, position); 39061cb0ef41Sopenharmony_ci } 39071cb0ef41Sopenharmony_ci 39081cb0ef41Sopenharmony_ci __ Bind(&if_thinstring); 39091cb0ef41Sopenharmony_ci { 39101cb0ef41Sopenharmony_ci Node* receiver_actual = 39111cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForThinStringActual(), receiver); 39121cb0ef41Sopenharmony_ci __ Goto(&loop_next, receiver_actual, position); 39131cb0ef41Sopenharmony_ci } 39141cb0ef41Sopenharmony_ci 39151cb0ef41Sopenharmony_ci __ Bind(&if_externalstring); 39161cb0ef41Sopenharmony_ci { 39171cb0ef41Sopenharmony_ci // We need to bailout to the runtime for uncached external strings. 39181cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal( 39191cb0ef41Sopenharmony_ci __ Word32And(receiver_instance_type, 39201cb0ef41Sopenharmony_ci __ Int32Constant(kUncachedExternalStringMask)), 39211cb0ef41Sopenharmony_ci __ Int32Constant(kUncachedExternalStringTag)), 39221cb0ef41Sopenharmony_ci &if_runtime); 39231cb0ef41Sopenharmony_ci 39241cb0ef41Sopenharmony_ci Node* receiver_data = __ LoadField( 39251cb0ef41Sopenharmony_ci AccessBuilder::ForExternalStringResourceData(), receiver); 39261cb0ef41Sopenharmony_ci 39271cb0ef41Sopenharmony_ci auto if_onebyte = __ MakeLabel(); 39281cb0ef41Sopenharmony_ci auto if_twobyte = __ MakeLabel(); 39291cb0ef41Sopenharmony_ci __ Branch( 39301cb0ef41Sopenharmony_ci __ Word32Equal(__ Word32And(receiver_instance_type, 39311cb0ef41Sopenharmony_ci __ Int32Constant(kStringEncodingMask)), 39321cb0ef41Sopenharmony_ci __ Int32Constant(kTwoByteStringTag)), 39331cb0ef41Sopenharmony_ci &if_twobyte, &if_onebyte); 39341cb0ef41Sopenharmony_ci 39351cb0ef41Sopenharmony_ci __ Bind(&if_onebyte); 39361cb0ef41Sopenharmony_ci { 39371cb0ef41Sopenharmony_ci Node* result = __ Load(MachineType::Uint8(), receiver_data, position); 39381cb0ef41Sopenharmony_ci __ Goto(&loop_done, result); 39391cb0ef41Sopenharmony_ci } 39401cb0ef41Sopenharmony_ci 39411cb0ef41Sopenharmony_ci __ Bind(&if_twobyte); 39421cb0ef41Sopenharmony_ci { 39431cb0ef41Sopenharmony_ci Node* result = __ Load(MachineType::Uint16(), receiver_data, 39441cb0ef41Sopenharmony_ci __ WordShl(position, __ IntPtrConstant(1))); 39451cb0ef41Sopenharmony_ci __ Goto(&loop_done, result); 39461cb0ef41Sopenharmony_ci } 39471cb0ef41Sopenharmony_ci } 39481cb0ef41Sopenharmony_ci 39491cb0ef41Sopenharmony_ci __ Bind(&if_slicedstring); 39501cb0ef41Sopenharmony_ci { 39511cb0ef41Sopenharmony_ci Node* receiver_offset = 39521cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForSlicedStringOffset(), receiver); 39531cb0ef41Sopenharmony_ci Node* receiver_parent = 39541cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForSlicedStringParent(), receiver); 39551cb0ef41Sopenharmony_ci __ Goto(&loop_next, receiver_parent, 39561cb0ef41Sopenharmony_ci __ IntAdd(position, ChangeSmiToIntPtr(receiver_offset))); 39571cb0ef41Sopenharmony_ci } 39581cb0ef41Sopenharmony_ci 39591cb0ef41Sopenharmony_ci __ Bind(&if_runtime); 39601cb0ef41Sopenharmony_ci { 39611cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 39621cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kStringCharCodeAt; 39631cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 39641cb0ef41Sopenharmony_ci graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); 39651cb0ef41Sopenharmony_ci Node* result = __ Call(call_descriptor, __ CEntryStubConstant(1), 39661cb0ef41Sopenharmony_ci receiver, ChangeIntPtrToSmi(position), 39671cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 39681cb0ef41Sopenharmony_ci __ Int32Constant(2), __ NoContextConstant()); 39691cb0ef41Sopenharmony_ci __ Goto(&loop_done, ChangeSmiToInt32(result)); 39701cb0ef41Sopenharmony_ci } 39711cb0ef41Sopenharmony_ci 39721cb0ef41Sopenharmony_ci __ Bind(&loop_next); 39731cb0ef41Sopenharmony_ci __ Goto(&loop, loop_next.PhiAt(0), loop_next.PhiAt(1)); 39741cb0ef41Sopenharmony_ci } 39751cb0ef41Sopenharmony_ci __ Bind(&loop_done); 39761cb0ef41Sopenharmony_ci return loop_done.PhiAt(0); 39771cb0ef41Sopenharmony_ci} 39781cb0ef41Sopenharmony_ci 39791cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { 39801cb0ef41Sopenharmony_ci Node* receiver = node->InputAt(0); 39811cb0ef41Sopenharmony_ci Node* position = node->InputAt(1); 39821cb0ef41Sopenharmony_ci return StringCharCodeAt(receiver, position); 39831cb0ef41Sopenharmony_ci} 39841cb0ef41Sopenharmony_ci 39851cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringCodePointAt(Node* node) { 39861cb0ef41Sopenharmony_ci Node* receiver = node->InputAt(0); 39871cb0ef41Sopenharmony_ci Node* position = node->InputAt(1); 39881cb0ef41Sopenharmony_ci 39891cb0ef41Sopenharmony_ci auto return_result = __ MakeLabel(MachineRepresentation::kWord32); 39901cb0ef41Sopenharmony_ci Node* first_code_unit = StringCharCodeAt(receiver, position); 39911cb0ef41Sopenharmony_ci 39921cb0ef41Sopenharmony_ci __ GotoIfNot( 39931cb0ef41Sopenharmony_ci __ Word32Equal(__ Word32And(first_code_unit, __ Int32Constant(0xFC00)), 39941cb0ef41Sopenharmony_ci __ Int32Constant(0xD800)), 39951cb0ef41Sopenharmony_ci &return_result, BranchHint::kFalse, first_code_unit); 39961cb0ef41Sopenharmony_ci 39971cb0ef41Sopenharmony_ci auto length = __ LoadField(AccessBuilder::ForStringLength(), receiver); 39981cb0ef41Sopenharmony_ci auto next_index = __ IntAdd(position, __ IntPtrConstant(1)); 39991cb0ef41Sopenharmony_ci __ GotoIfNot(__ IntLessThan(next_index, length), &return_result, 40001cb0ef41Sopenharmony_ci first_code_unit); 40011cb0ef41Sopenharmony_ci Node* second_code_unit = StringCharCodeAt(receiver, next_index); 40021cb0ef41Sopenharmony_ci __ GotoIfNot( 40031cb0ef41Sopenharmony_ci __ Word32Equal(__ Word32And(second_code_unit, __ Int32Constant(0xFC00)), 40041cb0ef41Sopenharmony_ci __ Int32Constant(0xDC00)), 40051cb0ef41Sopenharmony_ci &return_result, first_code_unit); 40061cb0ef41Sopenharmony_ci 40071cb0ef41Sopenharmony_ci auto surrogate_offset = __ Int32Constant(0x10000 - (0xD800 << 10) - 0xDC00); 40081cb0ef41Sopenharmony_ci auto result = __ Int32Add(__ Word32Shl(first_code_unit, __ Int32Constant(10)), 40091cb0ef41Sopenharmony_ci __ Int32Add(second_code_unit, surrogate_offset)); 40101cb0ef41Sopenharmony_ci __ Goto(&return_result, result); 40111cb0ef41Sopenharmony_ci 40121cb0ef41Sopenharmony_ci __ Bind(&return_result); 40131cb0ef41Sopenharmony_ci return return_result.PhiAt(0); 40141cb0ef41Sopenharmony_ci} 40151cb0ef41Sopenharmony_ci 40161cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LoadFromSeqString(Node* receiver, Node* position, 40171cb0ef41Sopenharmony_ci Node* is_one_byte) { 40181cb0ef41Sopenharmony_ci auto one_byte_load = __ MakeLabel(); 40191cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 40201cb0ef41Sopenharmony_ci __ GotoIf(is_one_byte, &one_byte_load); 40211cb0ef41Sopenharmony_ci Node* two_byte_result = __ LoadElement( 40221cb0ef41Sopenharmony_ci AccessBuilder::ForSeqTwoByteStringCharacter(), receiver, position); 40231cb0ef41Sopenharmony_ci __ Goto(&done, two_byte_result); 40241cb0ef41Sopenharmony_ci 40251cb0ef41Sopenharmony_ci __ Bind(&one_byte_load); 40261cb0ef41Sopenharmony_ci Node* one_byte_element = __ LoadElement( 40271cb0ef41Sopenharmony_ci AccessBuilder::ForSeqOneByteStringCharacter(), receiver, position); 40281cb0ef41Sopenharmony_ci __ Goto(&done, one_byte_element); 40291cb0ef41Sopenharmony_ci 40301cb0ef41Sopenharmony_ci __ Bind(&done); 40311cb0ef41Sopenharmony_ci return done.PhiAt(0); 40321cb0ef41Sopenharmony_ci} 40331cb0ef41Sopenharmony_ci 40341cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringFromSingleCharCode(Node* node) { 40351cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 40361cb0ef41Sopenharmony_ci Node* code = __ Word32And(value, __ Uint32Constant(0xFFFF)); 40371cb0ef41Sopenharmony_ci 40381cb0ef41Sopenharmony_ci auto if_not_one_byte = __ MakeDeferredLabel(); 40391cb0ef41Sopenharmony_ci auto cache_miss = __ MakeDeferredLabel(); 40401cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 40411cb0ef41Sopenharmony_ci 40421cb0ef41Sopenharmony_ci // Check if the {code} is a one byte character 40431cb0ef41Sopenharmony_ci Node* check1 = __ Uint32LessThanOrEqual( 40441cb0ef41Sopenharmony_ci code, __ Uint32Constant(String::kMaxOneByteCharCode)); 40451cb0ef41Sopenharmony_ci __ GotoIfNot(check1, &if_not_one_byte); 40461cb0ef41Sopenharmony_ci { 40471cb0ef41Sopenharmony_ci // Load the isolate wide single character string cache. 40481cb0ef41Sopenharmony_ci Node* cache = __ HeapConstant(factory()->single_character_string_cache()); 40491cb0ef41Sopenharmony_ci 40501cb0ef41Sopenharmony_ci // Compute the {cache} index for {code}. 40511cb0ef41Sopenharmony_ci Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); 40521cb0ef41Sopenharmony_ci 40531cb0ef41Sopenharmony_ci // Check if we have an entry for the {code} in the single character string 40541cb0ef41Sopenharmony_ci // cache already. 40551cb0ef41Sopenharmony_ci Node* entry = 40561cb0ef41Sopenharmony_ci __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); 40571cb0ef41Sopenharmony_ci 40581cb0ef41Sopenharmony_ci Node* check2 = __ TaggedEqual(entry, __ UndefinedConstant()); 40591cb0ef41Sopenharmony_ci __ GotoIf(check2, &cache_miss); 40601cb0ef41Sopenharmony_ci 40611cb0ef41Sopenharmony_ci // Use the {entry} from the {cache}. 40621cb0ef41Sopenharmony_ci __ Goto(&done, entry); 40631cb0ef41Sopenharmony_ci 40641cb0ef41Sopenharmony_ci __ Bind(&cache_miss); 40651cb0ef41Sopenharmony_ci { 40661cb0ef41Sopenharmony_ci // Allocate a new SeqOneByteString for {code}. 40671cb0ef41Sopenharmony_ci Node* vtrue2 = 40681cb0ef41Sopenharmony_ci __ Allocate(AllocationType::kYoung, 40691cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqOneByteString::SizeFor(1))); 40701cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), vtrue2, 40711cb0ef41Sopenharmony_ci __ HeapConstant(factory()->one_byte_string_map())); 40721cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForNameRawHashField(), vtrue2, 40731cb0ef41Sopenharmony_ci __ Int32Constant(Name::kEmptyHashField)); 40741cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForStringLength(), vtrue2, 40751cb0ef41Sopenharmony_ci __ Int32Constant(1)); 40761cb0ef41Sopenharmony_ci __ Store( 40771cb0ef41Sopenharmony_ci StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), 40781cb0ef41Sopenharmony_ci vtrue2, 40791cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), 40801cb0ef41Sopenharmony_ci code); 40811cb0ef41Sopenharmony_ci 40821cb0ef41Sopenharmony_ci // Remember it in the {cache}. 40831cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index, 40841cb0ef41Sopenharmony_ci vtrue2); 40851cb0ef41Sopenharmony_ci __ Goto(&done, vtrue2); 40861cb0ef41Sopenharmony_ci } 40871cb0ef41Sopenharmony_ci } 40881cb0ef41Sopenharmony_ci 40891cb0ef41Sopenharmony_ci __ Bind(&if_not_one_byte); 40901cb0ef41Sopenharmony_ci { 40911cb0ef41Sopenharmony_ci // Allocate a new SeqTwoByteString for {code}. 40921cb0ef41Sopenharmony_ci Node* vfalse1 = 40931cb0ef41Sopenharmony_ci __ Allocate(AllocationType::kYoung, 40941cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqTwoByteString::SizeFor(1))); 40951cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), vfalse1, 40961cb0ef41Sopenharmony_ci __ HeapConstant(factory()->string_map())); 40971cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForNameRawHashField(), vfalse1, 40981cb0ef41Sopenharmony_ci __ Int32Constant(Name::kEmptyHashField)); 40991cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForStringLength(), vfalse1, 41001cb0ef41Sopenharmony_ci __ Int32Constant(1)); 41011cb0ef41Sopenharmony_ci __ Store( 41021cb0ef41Sopenharmony_ci StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier), 41031cb0ef41Sopenharmony_ci vfalse1, 41041cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), 41051cb0ef41Sopenharmony_ci code); 41061cb0ef41Sopenharmony_ci __ Goto(&done, vfalse1); 41071cb0ef41Sopenharmony_ci } 41081cb0ef41Sopenharmony_ci 41091cb0ef41Sopenharmony_ci __ Bind(&done); 41101cb0ef41Sopenharmony_ci return done.PhiAt(0); 41111cb0ef41Sopenharmony_ci} 41121cb0ef41Sopenharmony_ci 41131cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT 41141cb0ef41Sopenharmony_ci 41151cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringToLowerCaseIntl(Node* node) { 41161cb0ef41Sopenharmony_ci Node* receiver = node->InputAt(0); 41171cb0ef41Sopenharmony_ci 41181cb0ef41Sopenharmony_ci Callable callable = 41191cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kStringToLowerCaseIntl); 41201cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 41211cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 41221cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 41231cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 41241cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 41251cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver, 41261cb0ef41Sopenharmony_ci __ NoContextConstant()); 41271cb0ef41Sopenharmony_ci} 41281cb0ef41Sopenharmony_ci 41291cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringToUpperCaseIntl(Node* node) { 41301cb0ef41Sopenharmony_ci Node* receiver = node->InputAt(0); 41311cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 41321cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kStringToUpperCaseIntl; 41331cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 41341cb0ef41Sopenharmony_ci graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); 41351cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ CEntryStubConstant(1), receiver, 41361cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 41371cb0ef41Sopenharmony_ci __ Int32Constant(1), __ NoContextConstant()); 41381cb0ef41Sopenharmony_ci} 41391cb0ef41Sopenharmony_ci 41401cb0ef41Sopenharmony_ci#else 41411cb0ef41Sopenharmony_ci 41421cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringToLowerCaseIntl(Node* node) { 41431cb0ef41Sopenharmony_ci UNREACHABLE(); 41441cb0ef41Sopenharmony_ci} 41451cb0ef41Sopenharmony_ci 41461cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringToUpperCaseIntl(Node* node) { 41471cb0ef41Sopenharmony_ci UNREACHABLE(); 41481cb0ef41Sopenharmony_ci} 41491cb0ef41Sopenharmony_ci 41501cb0ef41Sopenharmony_ci#endif // V8_INTL_SUPPORT 41511cb0ef41Sopenharmony_ci 41521cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringFromSingleCodePoint(Node* node) { 41531cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 41541cb0ef41Sopenharmony_ci Node* code = value; 41551cb0ef41Sopenharmony_ci 41561cb0ef41Sopenharmony_ci auto if_not_single_code = __ MakeDeferredLabel(); 41571cb0ef41Sopenharmony_ci auto if_not_one_byte = __ MakeDeferredLabel(); 41581cb0ef41Sopenharmony_ci auto cache_miss = __ MakeDeferredLabel(); 41591cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 41601cb0ef41Sopenharmony_ci 41611cb0ef41Sopenharmony_ci // Check if the {code} is a single code unit 41621cb0ef41Sopenharmony_ci Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF)); 41631cb0ef41Sopenharmony_ci __ GotoIfNot(check0, &if_not_single_code); 41641cb0ef41Sopenharmony_ci 41651cb0ef41Sopenharmony_ci { 41661cb0ef41Sopenharmony_ci // Check if the {code} is a one byte character 41671cb0ef41Sopenharmony_ci Node* check1 = __ Uint32LessThanOrEqual( 41681cb0ef41Sopenharmony_ci code, __ Uint32Constant(String::kMaxOneByteCharCode)); 41691cb0ef41Sopenharmony_ci __ GotoIfNot(check1, &if_not_one_byte); 41701cb0ef41Sopenharmony_ci { 41711cb0ef41Sopenharmony_ci // Load the isolate wide single character string cache. 41721cb0ef41Sopenharmony_ci Node* cache = __ HeapConstant(factory()->single_character_string_cache()); 41731cb0ef41Sopenharmony_ci 41741cb0ef41Sopenharmony_ci // Compute the {cache} index for {code}. 41751cb0ef41Sopenharmony_ci Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); 41761cb0ef41Sopenharmony_ci 41771cb0ef41Sopenharmony_ci // Check if we have an entry for the {code} in the single character string 41781cb0ef41Sopenharmony_ci // cache already. 41791cb0ef41Sopenharmony_ci Node* entry = 41801cb0ef41Sopenharmony_ci __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); 41811cb0ef41Sopenharmony_ci 41821cb0ef41Sopenharmony_ci Node* check2 = __ TaggedEqual(entry, __ UndefinedConstant()); 41831cb0ef41Sopenharmony_ci __ GotoIf(check2, &cache_miss); 41841cb0ef41Sopenharmony_ci 41851cb0ef41Sopenharmony_ci // Use the {entry} from the {cache}. 41861cb0ef41Sopenharmony_ci __ Goto(&done, entry); 41871cb0ef41Sopenharmony_ci 41881cb0ef41Sopenharmony_ci __ Bind(&cache_miss); 41891cb0ef41Sopenharmony_ci { 41901cb0ef41Sopenharmony_ci // Allocate a new SeqOneByteString for {code}. 41911cb0ef41Sopenharmony_ci Node* vtrue2 = 41921cb0ef41Sopenharmony_ci __ Allocate(AllocationType::kYoung, 41931cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqOneByteString::SizeFor(1))); 41941cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), vtrue2, 41951cb0ef41Sopenharmony_ci __ HeapConstant(factory()->one_byte_string_map())); 41961cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForNameRawHashField(), vtrue2, 41971cb0ef41Sopenharmony_ci __ Int32Constant(Name::kEmptyHashField)); 41981cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForStringLength(), vtrue2, 41991cb0ef41Sopenharmony_ci __ Int32Constant(1)); 42001cb0ef41Sopenharmony_ci __ Store( 42011cb0ef41Sopenharmony_ci StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), 42021cb0ef41Sopenharmony_ci vtrue2, 42031cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), 42041cb0ef41Sopenharmony_ci code); 42051cb0ef41Sopenharmony_ci 42061cb0ef41Sopenharmony_ci // Remember it in the {cache}. 42071cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index, 42081cb0ef41Sopenharmony_ci vtrue2); 42091cb0ef41Sopenharmony_ci __ Goto(&done, vtrue2); 42101cb0ef41Sopenharmony_ci } 42111cb0ef41Sopenharmony_ci } 42121cb0ef41Sopenharmony_ci 42131cb0ef41Sopenharmony_ci __ Bind(&if_not_one_byte); 42141cb0ef41Sopenharmony_ci { 42151cb0ef41Sopenharmony_ci // Allocate a new SeqTwoByteString for {code}. 42161cb0ef41Sopenharmony_ci Node* vfalse1 = 42171cb0ef41Sopenharmony_ci __ Allocate(AllocationType::kYoung, 42181cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqTwoByteString::SizeFor(1))); 42191cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), vfalse1, 42201cb0ef41Sopenharmony_ci __ HeapConstant(factory()->string_map())); 42211cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForNameRawHashField(), vfalse1, 42221cb0ef41Sopenharmony_ci __ IntPtrConstant(Name::kEmptyHashField)); 42231cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForStringLength(), vfalse1, 42241cb0ef41Sopenharmony_ci __ Int32Constant(1)); 42251cb0ef41Sopenharmony_ci __ Store( 42261cb0ef41Sopenharmony_ci StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier), 42271cb0ef41Sopenharmony_ci vfalse1, 42281cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), 42291cb0ef41Sopenharmony_ci code); 42301cb0ef41Sopenharmony_ci __ Goto(&done, vfalse1); 42311cb0ef41Sopenharmony_ci } 42321cb0ef41Sopenharmony_ci } 42331cb0ef41Sopenharmony_ci 42341cb0ef41Sopenharmony_ci __ Bind(&if_not_single_code); 42351cb0ef41Sopenharmony_ci // Generate surrogate pair string 42361cb0ef41Sopenharmony_ci { 42371cb0ef41Sopenharmony_ci // Convert UTF32 to UTF16 code units, and store as a 32 bit word. 42381cb0ef41Sopenharmony_ci Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10)); 42391cb0ef41Sopenharmony_ci 42401cb0ef41Sopenharmony_ci // lead = (codepoint >> 10) + LEAD_OFFSET 42411cb0ef41Sopenharmony_ci Node* lead = 42421cb0ef41Sopenharmony_ci __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset); 42431cb0ef41Sopenharmony_ci 42441cb0ef41Sopenharmony_ci // trail = (codepoint & 0x3FF) + 0xDC00; 42451cb0ef41Sopenharmony_ci Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)), 42461cb0ef41Sopenharmony_ci __ Int32Constant(0xDC00)); 42471cb0ef41Sopenharmony_ci 42481cb0ef41Sopenharmony_ci // codpoint = (trail << 16) | lead; 42491cb0ef41Sopenharmony_ci#if V8_TARGET_BIG_ENDIAN 42501cb0ef41Sopenharmony_ci code = __ Word32Or(__ Word32Shl(lead, __ Int32Constant(16)), trail); 42511cb0ef41Sopenharmony_ci#else 42521cb0ef41Sopenharmony_ci code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead); 42531cb0ef41Sopenharmony_ci#endif 42541cb0ef41Sopenharmony_ci 42551cb0ef41Sopenharmony_ci // Allocate a new SeqTwoByteString for {code}. 42561cb0ef41Sopenharmony_ci Node* vfalse0 = 42571cb0ef41Sopenharmony_ci __ Allocate(AllocationType::kYoung, 42581cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqTwoByteString::SizeFor(2))); 42591cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), vfalse0, 42601cb0ef41Sopenharmony_ci __ HeapConstant(factory()->string_map())); 42611cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForNameRawHashField(), vfalse0, 42621cb0ef41Sopenharmony_ci __ Int32Constant(Name::kEmptyHashField)); 42631cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForStringLength(), vfalse0, 42641cb0ef41Sopenharmony_ci __ Int32Constant(2)); 42651cb0ef41Sopenharmony_ci __ Store( 42661cb0ef41Sopenharmony_ci StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier), 42671cb0ef41Sopenharmony_ci vfalse0, 42681cb0ef41Sopenharmony_ci __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), 42691cb0ef41Sopenharmony_ci code); 42701cb0ef41Sopenharmony_ci __ Goto(&done, vfalse0); 42711cb0ef41Sopenharmony_ci } 42721cb0ef41Sopenharmony_ci 42731cb0ef41Sopenharmony_ci __ Bind(&done); 42741cb0ef41Sopenharmony_ci return done.PhiAt(0); 42751cb0ef41Sopenharmony_ci} 42761cb0ef41Sopenharmony_ci 42771cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringIndexOf(Node* node) { 42781cb0ef41Sopenharmony_ci Node* subject = node->InputAt(0); 42791cb0ef41Sopenharmony_ci Node* search_string = node->InputAt(1); 42801cb0ef41Sopenharmony_ci Node* position = node->InputAt(2); 42811cb0ef41Sopenharmony_ci 42821cb0ef41Sopenharmony_ci Callable callable = Builtins::CallableFor(isolate(), Builtin::kStringIndexOf); 42831cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 42841cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 42851cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 42861cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 42871cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 42881cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), subject, 42891cb0ef41Sopenharmony_ci search_string, position, __ NoContextConstant()); 42901cb0ef41Sopenharmony_ci} 42911cb0ef41Sopenharmony_ci 42921cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringFromCodePointAt(Node* node) { 42931cb0ef41Sopenharmony_ci Node* string = node->InputAt(0); 42941cb0ef41Sopenharmony_ci Node* index = node->InputAt(1); 42951cb0ef41Sopenharmony_ci 42961cb0ef41Sopenharmony_ci Callable callable = 42971cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kStringFromCodePointAt); 42981cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 42991cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 43001cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 43011cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 43021cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 43031cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), string, 43041cb0ef41Sopenharmony_ci index, __ NoContextConstant()); 43051cb0ef41Sopenharmony_ci} 43061cb0ef41Sopenharmony_ci 43071cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringLength(Node* node) { 43081cb0ef41Sopenharmony_ci Node* subject = node->InputAt(0); 43091cb0ef41Sopenharmony_ci 43101cb0ef41Sopenharmony_ci return __ LoadField(AccessBuilder::ForStringLength(), subject); 43111cb0ef41Sopenharmony_ci} 43121cb0ef41Sopenharmony_ci 43131cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringComparison(Callable const& callable, 43141cb0ef41Sopenharmony_ci Node* node) { 43151cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 43161cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 43171cb0ef41Sopenharmony_ci 43181cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 43191cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 43201cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 43211cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 43221cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 43231cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs, 43241cb0ef41Sopenharmony_ci __ NoContextConstant()); 43251cb0ef41Sopenharmony_ci} 43261cb0ef41Sopenharmony_ci 43271cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringSubstring(Node* node) { 43281cb0ef41Sopenharmony_ci Node* receiver = node->InputAt(0); 43291cb0ef41Sopenharmony_ci Node* start = ChangeInt32ToIntPtr(node->InputAt(1)); 43301cb0ef41Sopenharmony_ci Node* end = ChangeInt32ToIntPtr(node->InputAt(2)); 43311cb0ef41Sopenharmony_ci 43321cb0ef41Sopenharmony_ci Callable callable = 43331cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kStringSubstring); 43341cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 43351cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 43361cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 43371cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 43381cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 43391cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), receiver, 43401cb0ef41Sopenharmony_ci start, end, __ NoContextConstant()); 43411cb0ef41Sopenharmony_ci} 43421cb0ef41Sopenharmony_ci 43431cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringEqual(Node* node) { 43441cb0ef41Sopenharmony_ci return LowerStringComparison( 43451cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kStringEqual), node); 43461cb0ef41Sopenharmony_ci} 43471cb0ef41Sopenharmony_ci 43481cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringLessThan(Node* node) { 43491cb0ef41Sopenharmony_ci return LowerStringComparison( 43501cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kStringLessThan), node); 43511cb0ef41Sopenharmony_ci} 43521cb0ef41Sopenharmony_ci 43531cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) { 43541cb0ef41Sopenharmony_ci return LowerStringComparison( 43551cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kStringLessThanOrEqual), node); 43561cb0ef41Sopenharmony_ci} 43571cb0ef41Sopenharmony_ci 43581cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerBigIntAdd(Node* node, Node* frame_state) { 43591cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 43601cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 43611cb0ef41Sopenharmony_ci 43621cb0ef41Sopenharmony_ci Callable const callable = 43631cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kBigIntAddNoThrow); 43641cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 43651cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 43661cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags, 43671cb0ef41Sopenharmony_ci Operator::kFoldable | Operator::kNoThrow); 43681cb0ef41Sopenharmony_ci Node* value = __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, 43691cb0ef41Sopenharmony_ci rhs, __ NoContextConstant()); 43701cb0ef41Sopenharmony_ci 43711cb0ef41Sopenharmony_ci // Check for exception sentinel: Smi is returned to signal BigIntTooBig. 43721cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kBigIntTooBig, FeedbackSource{}, 43731cb0ef41Sopenharmony_ci ObjectIsSmi(value), frame_state); 43741cb0ef41Sopenharmony_ci 43751cb0ef41Sopenharmony_ci return value; 43761cb0ef41Sopenharmony_ci} 43771cb0ef41Sopenharmony_ci 43781cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerBigIntSubtract(Node* node, 43791cb0ef41Sopenharmony_ci Node* frame_state) { 43801cb0ef41Sopenharmony_ci Node* lhs = node->InputAt(0); 43811cb0ef41Sopenharmony_ci Node* rhs = node->InputAt(1); 43821cb0ef41Sopenharmony_ci 43831cb0ef41Sopenharmony_ci Callable const callable = 43841cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kBigIntSubtractNoThrow); 43851cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 43861cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 43871cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags, 43881cb0ef41Sopenharmony_ci Operator::kFoldable | Operator::kNoThrow); 43891cb0ef41Sopenharmony_ci Node* value = __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, 43901cb0ef41Sopenharmony_ci rhs, __ NoContextConstant()); 43911cb0ef41Sopenharmony_ci 43921cb0ef41Sopenharmony_ci // Check for exception sentinel: Smi is returned to signal BigIntTooBig. 43931cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kBigIntTooBig, FeedbackSource{}, 43941cb0ef41Sopenharmony_ci ObjectIsSmi(value), frame_state); 43951cb0ef41Sopenharmony_ci 43961cb0ef41Sopenharmony_ci return value; 43971cb0ef41Sopenharmony_ci} 43981cb0ef41Sopenharmony_ci 43991cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerBigIntNegate(Node* node) { 44001cb0ef41Sopenharmony_ci Callable const callable = 44011cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kBigIntUnaryMinus); 44021cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 44031cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 44041cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags, 44051cb0ef41Sopenharmony_ci Operator::kFoldable | Operator::kNoThrow); 44061cb0ef41Sopenharmony_ci Node* value = __ Call(call_descriptor, __ HeapConstant(callable.code()), 44071cb0ef41Sopenharmony_ci node->InputAt(0), __ NoContextConstant()); 44081cb0ef41Sopenharmony_ci 44091cb0ef41Sopenharmony_ci return value; 44101cb0ef41Sopenharmony_ci} 44111cb0ef41Sopenharmony_ci 44121cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, 44131cb0ef41Sopenharmony_ci Node* frame_state) { 44141cb0ef41Sopenharmony_ci // If we reach this point w/o eliminating the {node} that's marked 44151cb0ef41Sopenharmony_ci // with allow-return-hole, we cannot do anything, so just deoptimize 44161cb0ef41Sopenharmony_ci // in case of the hole NaN. 44171cb0ef41Sopenharmony_ci CheckFloat64HoleParameters const& params = 44181cb0ef41Sopenharmony_ci CheckFloat64HoleParametersOf(node->op()); 44191cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 44201cb0ef41Sopenharmony_ci 44211cb0ef41Sopenharmony_ci auto if_nan = __ MakeDeferredLabel(); 44221cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 44231cb0ef41Sopenharmony_ci 44241cb0ef41Sopenharmony_ci // First check whether {value} is a NaN at all... 44251cb0ef41Sopenharmony_ci __ Branch(__ Float64Equal(value, value), &done, &if_nan); 44261cb0ef41Sopenharmony_ci 44271cb0ef41Sopenharmony_ci __ Bind(&if_nan); 44281cb0ef41Sopenharmony_ci { 44291cb0ef41Sopenharmony_ci // ...and only if {value} is a NaN, perform the expensive bit 44301cb0ef41Sopenharmony_ci // check. See http://crbug.com/v8/8264 for details. 44311cb0ef41Sopenharmony_ci Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value), 44321cb0ef41Sopenharmony_ci __ Int32Constant(kHoleNanUpper32)); 44331cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kHole, params.feedback(), check, 44341cb0ef41Sopenharmony_ci frame_state); 44351cb0ef41Sopenharmony_ci __ Goto(&done); 44361cb0ef41Sopenharmony_ci } 44371cb0ef41Sopenharmony_ci 44381cb0ef41Sopenharmony_ci __ Bind(&done); 44391cb0ef41Sopenharmony_ci return value; 44401cb0ef41Sopenharmony_ci} 44411cb0ef41Sopenharmony_ci 44421cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerCheckNotTaggedHole(Node* node, 44431cb0ef41Sopenharmony_ci Node* frame_state) { 44441cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 44451cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value, __ TheHoleConstant()); 44461cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kHole, FeedbackSource(), check, 44471cb0ef41Sopenharmony_ci frame_state); 44481cb0ef41Sopenharmony_ci return value; 44491cb0ef41Sopenharmony_ci} 44501cb0ef41Sopenharmony_ci 44511cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) { 44521cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 44531cb0ef41Sopenharmony_ci 44541cb0ef41Sopenharmony_ci auto if_is_hole = __ MakeDeferredLabel(); 44551cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 44561cb0ef41Sopenharmony_ci 44571cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value, __ TheHoleConstant()); 44581cb0ef41Sopenharmony_ci __ GotoIf(check, &if_is_hole); 44591cb0ef41Sopenharmony_ci __ Goto(&done, value); 44601cb0ef41Sopenharmony_ci 44611cb0ef41Sopenharmony_ci __ Bind(&if_is_hole); 44621cb0ef41Sopenharmony_ci __ Goto(&done, __ UndefinedConstant()); 44631cb0ef41Sopenharmony_ci 44641cb0ef41Sopenharmony_ci __ Bind(&done); 44651cb0ef41Sopenharmony_ci return done.PhiAt(0); 44661cb0ef41Sopenharmony_ci} 44671cb0ef41Sopenharmony_ci 44681cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerCheckEqualsInternalizedString( 44691cb0ef41Sopenharmony_ci Node* node, Node* frame_state) { 44701cb0ef41Sopenharmony_ci Node* exp = node->InputAt(0); 44711cb0ef41Sopenharmony_ci Node* val = node->InputAt(1); 44721cb0ef41Sopenharmony_ci 44731cb0ef41Sopenharmony_ci auto if_same = __ MakeLabel(); 44741cb0ef41Sopenharmony_ci auto if_notsame = __ MakeDeferredLabel(); 44751cb0ef41Sopenharmony_ci auto if_thinstring = __ MakeLabel(); 44761cb0ef41Sopenharmony_ci auto if_notthinstring = __ MakeLabel(); 44771cb0ef41Sopenharmony_ci 44781cb0ef41Sopenharmony_ci // Check if {exp} and {val} are the same, which is the likely case. 44791cb0ef41Sopenharmony_ci __ Branch(__ TaggedEqual(exp, val), &if_same, &if_notsame); 44801cb0ef41Sopenharmony_ci 44811cb0ef41Sopenharmony_ci __ Bind(&if_notsame); 44821cb0ef41Sopenharmony_ci { 44831cb0ef41Sopenharmony_ci // Now {val} could still be a non-internalized String that matches {exp}. 44841cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kWrongName, FeedbackSource(), 44851cb0ef41Sopenharmony_ci ObjectIsSmi(val), frame_state); 44861cb0ef41Sopenharmony_ci Node* val_map = __ LoadField(AccessBuilder::ForMap(), val); 44871cb0ef41Sopenharmony_ci Node* val_instance_type = 44881cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), val_map); 44891cb0ef41Sopenharmony_ci 44901cb0ef41Sopenharmony_ci // Check for the common case of ThinString first. 44911cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(val_instance_type, 44921cb0ef41Sopenharmony_ci __ Int32Constant(THIN_ONE_BYTE_STRING_TYPE)), 44931cb0ef41Sopenharmony_ci &if_thinstring); 44941cb0ef41Sopenharmony_ci __ Branch( 44951cb0ef41Sopenharmony_ci __ Word32Equal(val_instance_type, __ Int32Constant(THIN_STRING_TYPE)), 44961cb0ef41Sopenharmony_ci &if_thinstring, &if_notthinstring); 44971cb0ef41Sopenharmony_ci 44981cb0ef41Sopenharmony_ci __ Bind(&if_notthinstring); 44991cb0ef41Sopenharmony_ci { 45001cb0ef41Sopenharmony_ci // Check that the {val} is a non-internalized String, if it's anything 45011cb0ef41Sopenharmony_ci // else it cannot match the recorded feedback {exp} anyways. 45021cb0ef41Sopenharmony_ci __ DeoptimizeIfNot( 45031cb0ef41Sopenharmony_ci DeoptimizeReason::kWrongName, FeedbackSource(), 45041cb0ef41Sopenharmony_ci __ Word32Equal(__ Word32And(val_instance_type, 45051cb0ef41Sopenharmony_ci __ Int32Constant(kIsNotStringMask | 45061cb0ef41Sopenharmony_ci kIsNotInternalizedMask)), 45071cb0ef41Sopenharmony_ci __ Int32Constant(kStringTag | kNotInternalizedTag)), 45081cb0ef41Sopenharmony_ci frame_state); 45091cb0ef41Sopenharmony_ci 45101cb0ef41Sopenharmony_ci // Try to find the {val} in the string table. 45111cb0ef41Sopenharmony_ci MachineSignature::Builder builder(graph()->zone(), 1, 2); 45121cb0ef41Sopenharmony_ci builder.AddReturn(MachineType::AnyTagged()); 45131cb0ef41Sopenharmony_ci builder.AddParam(MachineType::Pointer()); 45141cb0ef41Sopenharmony_ci builder.AddParam(MachineType::AnyTagged()); 45151cb0ef41Sopenharmony_ci Node* try_string_to_index_or_lookup_existing = __ ExternalConstant( 45161cb0ef41Sopenharmony_ci ExternalReference::try_string_to_index_or_lookup_existing()); 45171cb0ef41Sopenharmony_ci Node* const isolate_ptr = 45181cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::isolate_address(isolate())); 45191cb0ef41Sopenharmony_ci auto call_descriptor = 45201cb0ef41Sopenharmony_ci Linkage::GetSimplifiedCDescriptor(graph()->zone(), builder.Build()); 45211cb0ef41Sopenharmony_ci Node* val_internalized = 45221cb0ef41Sopenharmony_ci __ Call(common()->Call(call_descriptor), 45231cb0ef41Sopenharmony_ci try_string_to_index_or_lookup_existing, isolate_ptr, val); 45241cb0ef41Sopenharmony_ci 45251cb0ef41Sopenharmony_ci // Now see if the results match. 45261cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongName, FeedbackSource(), 45271cb0ef41Sopenharmony_ci __ TaggedEqual(exp, val_internalized), frame_state); 45281cb0ef41Sopenharmony_ci __ Goto(&if_same); 45291cb0ef41Sopenharmony_ci } 45301cb0ef41Sopenharmony_ci 45311cb0ef41Sopenharmony_ci __ Bind(&if_thinstring); 45321cb0ef41Sopenharmony_ci { 45331cb0ef41Sopenharmony_ci // The {val} is a ThinString, let's check the actual value. 45341cb0ef41Sopenharmony_ci Node* val_actual = 45351cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForThinStringActual(), val); 45361cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongName, FeedbackSource(), 45371cb0ef41Sopenharmony_ci __ TaggedEqual(exp, val_actual), frame_state); 45381cb0ef41Sopenharmony_ci __ Goto(&if_same); 45391cb0ef41Sopenharmony_ci } 45401cb0ef41Sopenharmony_ci } 45411cb0ef41Sopenharmony_ci 45421cb0ef41Sopenharmony_ci __ Bind(&if_same); 45431cb0ef41Sopenharmony_ci} 45441cb0ef41Sopenharmony_ci 45451cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerCheckEqualsSymbol(Node* node, 45461cb0ef41Sopenharmony_ci Node* frame_state) { 45471cb0ef41Sopenharmony_ci Node* exp = node->InputAt(0); 45481cb0ef41Sopenharmony_ci Node* val = node->InputAt(1); 45491cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(exp, val); 45501cb0ef41Sopenharmony_ci __ DeoptimizeIfNot(DeoptimizeReason::kWrongName, FeedbackSource(), check, 45511cb0ef41Sopenharmony_ci frame_state); 45521cb0ef41Sopenharmony_ci} 45531cb0ef41Sopenharmony_ci 45541cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) { 45551cb0ef41Sopenharmony_ci Node* result = 45561cb0ef41Sopenharmony_ci __ Allocate(AllocationType::kYoung, __ IntPtrConstant(HeapNumber::kSize)); 45571cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant()); 45581cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value); 45591cb0ef41Sopenharmony_ci return result; 45601cb0ef41Sopenharmony_ci} 45611cb0ef41Sopenharmony_ci 45621cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeIntPtrToSmi(Node* value) { 45631cb0ef41Sopenharmony_ci // Do shift on 32bit values if Smis are stored in the lower word. 45641cb0ef41Sopenharmony_ci if (machine()->Is64() && SmiValuesAre31Bits()) { 45651cb0ef41Sopenharmony_ci return ChangeTaggedInt32ToSmi(__ Word32Shl(value, SmiShiftBitsConstant())); 45661cb0ef41Sopenharmony_ci } 45671cb0ef41Sopenharmony_ci return __ WordShl(value, SmiShiftBitsConstant()); 45681cb0ef41Sopenharmony_ci} 45691cb0ef41Sopenharmony_ci 45701cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeTaggedInt32ToSmi(Node* value) { 45711cb0ef41Sopenharmony_ci DCHECK(SmiValuesAre31Bits()); 45721cb0ef41Sopenharmony_ci // In pointer compression, we smi-corrupt. Then, the upper bits are not 45731cb0ef41Sopenharmony_ci // important. 45741cb0ef41Sopenharmony_ci return COMPRESS_POINTERS_BOOL ? __ BitcastWord32ToWord64(value) 45751cb0ef41Sopenharmony_ci : ChangeInt32ToIntPtr(value); 45761cb0ef41Sopenharmony_ci} 45771cb0ef41Sopenharmony_ci 45781cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeInt32ToIntPtr(Node* value) { 45791cb0ef41Sopenharmony_ci if (machine()->Is64()) { 45801cb0ef41Sopenharmony_ci value = __ ChangeInt32ToInt64(value); 45811cb0ef41Sopenharmony_ci } 45821cb0ef41Sopenharmony_ci return value; 45831cb0ef41Sopenharmony_ci} 45841cb0ef41Sopenharmony_ci 45851cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeIntPtrToInt32(Node* value) { 45861cb0ef41Sopenharmony_ci if (machine()->Is64()) { 45871cb0ef41Sopenharmony_ci value = __ TruncateInt64ToInt32(value); 45881cb0ef41Sopenharmony_ci } 45891cb0ef41Sopenharmony_ci return value; 45901cb0ef41Sopenharmony_ci} 45911cb0ef41Sopenharmony_ci 45921cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) { 45931cb0ef41Sopenharmony_ci // Do shift on 32bit values if Smis are stored in the lower word. 45941cb0ef41Sopenharmony_ci if (machine()->Is64() && SmiValuesAre31Bits()) { 45951cb0ef41Sopenharmony_ci return ChangeIntPtrToSmi(value); 45961cb0ef41Sopenharmony_ci } 45971cb0ef41Sopenharmony_ci return ChangeIntPtrToSmi(ChangeInt32ToIntPtr(value)); 45981cb0ef41Sopenharmony_ci} 45991cb0ef41Sopenharmony_ci 46001cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeInt64ToSmi(Node* value) { 46011cb0ef41Sopenharmony_ci DCHECK(machine()->Is64()); 46021cb0ef41Sopenharmony_ci return ChangeIntPtrToSmi(value); 46031cb0ef41Sopenharmony_ci} 46041cb0ef41Sopenharmony_ci 46051cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeUint32ToUintPtr(Node* value) { 46061cb0ef41Sopenharmony_ci if (machine()->Is64()) { 46071cb0ef41Sopenharmony_ci value = __ ChangeUint32ToUint64(value); 46081cb0ef41Sopenharmony_ci } 46091cb0ef41Sopenharmony_ci return value; 46101cb0ef41Sopenharmony_ci} 46111cb0ef41Sopenharmony_ci 46121cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) { 46131cb0ef41Sopenharmony_ci // Do shift on 32bit values if Smis are stored in the lower word. 46141cb0ef41Sopenharmony_ci if (machine()->Is64() && SmiValuesAre31Bits()) { 46151cb0ef41Sopenharmony_ci Node* smi_value = __ Word32Shl(value, SmiShiftBitsConstant()); 46161cb0ef41Sopenharmony_ci // In pointer compression, we smi-corrupt. Then, the upper bits are not 46171cb0ef41Sopenharmony_ci // important. 46181cb0ef41Sopenharmony_ci return COMPRESS_POINTERS_BOOL ? __ BitcastWord32ToWord64(smi_value) 46191cb0ef41Sopenharmony_ci : __ ChangeUint32ToUint64(smi_value); 46201cb0ef41Sopenharmony_ci } else { 46211cb0ef41Sopenharmony_ci return __ WordShl(ChangeUint32ToUintPtr(value), SmiShiftBitsConstant()); 46221cb0ef41Sopenharmony_ci } 46231cb0ef41Sopenharmony_ci} 46241cb0ef41Sopenharmony_ci 46251cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeSmiToIntPtr(Node* value) { 46261cb0ef41Sopenharmony_ci if (machine()->Is64() && SmiValuesAre31Bits()) { 46271cb0ef41Sopenharmony_ci // First sign-extend the upper half, then shift away the Smi tag. 46281cb0ef41Sopenharmony_ci return __ WordSarShiftOutZeros( 46291cb0ef41Sopenharmony_ci __ ChangeInt32ToInt64(__ TruncateInt64ToInt32(value)), 46301cb0ef41Sopenharmony_ci SmiShiftBitsConstant()); 46311cb0ef41Sopenharmony_ci } 46321cb0ef41Sopenharmony_ci return __ WordSarShiftOutZeros(value, SmiShiftBitsConstant()); 46331cb0ef41Sopenharmony_ci} 46341cb0ef41Sopenharmony_ci 46351cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeSmiToInt32(Node* value) { 46361cb0ef41Sopenharmony_ci // Do shift on 32bit values if Smis are stored in the lower word. 46371cb0ef41Sopenharmony_ci if (machine()->Is64() && SmiValuesAre31Bits()) { 46381cb0ef41Sopenharmony_ci return __ Word32SarShiftOutZeros(__ TruncateInt64ToInt32(value), 46391cb0ef41Sopenharmony_ci SmiShiftBitsConstant()); 46401cb0ef41Sopenharmony_ci } 46411cb0ef41Sopenharmony_ci if (machine()->Is64()) { 46421cb0ef41Sopenharmony_ci return __ TruncateInt64ToInt32(ChangeSmiToIntPtr(value)); 46431cb0ef41Sopenharmony_ci } 46441cb0ef41Sopenharmony_ci return ChangeSmiToIntPtr(value); 46451cb0ef41Sopenharmony_ci} 46461cb0ef41Sopenharmony_ci 46471cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ChangeSmiToInt64(Node* value) { 46481cb0ef41Sopenharmony_ci CHECK(machine()->Is64()); 46491cb0ef41Sopenharmony_ci return ChangeSmiToIntPtr(value); 46501cb0ef41Sopenharmony_ci} 46511cb0ef41Sopenharmony_ci 46521cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ObjectIsSmi(Node* value) { 46531cb0ef41Sopenharmony_ci return __ Word32Equal(__ Word32And(value, __ Int32Constant(kSmiTagMask)), 46541cb0ef41Sopenharmony_ci __ Int32Constant(kSmiTag)); 46551cb0ef41Sopenharmony_ci} 46561cb0ef41Sopenharmony_ci 46571cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::SmiMaxValueConstant() { 46581cb0ef41Sopenharmony_ci return __ Int32Constant(Smi::kMaxValue); 46591cb0ef41Sopenharmony_ci} 46601cb0ef41Sopenharmony_ci 46611cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::SmiShiftBitsConstant() { 46621cb0ef41Sopenharmony_ci if (machine()->Is64() && SmiValuesAre31Bits()) { 46631cb0ef41Sopenharmony_ci return __ Int32Constant(kSmiShiftSize + kSmiTagSize); 46641cb0ef41Sopenharmony_ci } 46651cb0ef41Sopenharmony_ci return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize); 46661cb0ef41Sopenharmony_ci} 46671cb0ef41Sopenharmony_ci 46681cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) { 46691cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 46701cb0ef41Sopenharmony_ci return __ PlainPrimitiveToNumber(TNode<Object>::UncheckedCast(value)); 46711cb0ef41Sopenharmony_ci} 46721cb0ef41Sopenharmony_ci 46731cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) { 46741cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 46751cb0ef41Sopenharmony_ci 46761cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 46771cb0ef41Sopenharmony_ci auto if_to_number_smi = __ MakeLabel(); 46781cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kWord32); 46791cb0ef41Sopenharmony_ci 46801cb0ef41Sopenharmony_ci Node* check0 = ObjectIsSmi(value); 46811cb0ef41Sopenharmony_ci __ GotoIfNot(check0, &if_not_smi); 46821cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt32(value)); 46831cb0ef41Sopenharmony_ci 46841cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 46851cb0ef41Sopenharmony_ci Node* to_number = 46861cb0ef41Sopenharmony_ci __ PlainPrimitiveToNumber(TNode<Object>::UncheckedCast(value)); 46871cb0ef41Sopenharmony_ci 46881cb0ef41Sopenharmony_ci Node* check1 = ObjectIsSmi(to_number); 46891cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_to_number_smi); 46901cb0ef41Sopenharmony_ci Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number); 46911cb0ef41Sopenharmony_ci __ Goto(&done, __ TruncateFloat64ToWord32(number)); 46921cb0ef41Sopenharmony_ci 46931cb0ef41Sopenharmony_ci __ Bind(&if_to_number_smi); 46941cb0ef41Sopenharmony_ci __ Goto(&done, ChangeSmiToInt32(to_number)); 46951cb0ef41Sopenharmony_ci 46961cb0ef41Sopenharmony_ci __ Bind(&done); 46971cb0ef41Sopenharmony_ci return done.PhiAt(0); 46981cb0ef41Sopenharmony_ci} 46991cb0ef41Sopenharmony_ci 47001cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) { 47011cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 47021cb0ef41Sopenharmony_ci 47031cb0ef41Sopenharmony_ci auto if_not_smi = __ MakeDeferredLabel(); 47041cb0ef41Sopenharmony_ci auto if_to_number_smi = __ MakeLabel(); 47051cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kFloat64); 47061cb0ef41Sopenharmony_ci 47071cb0ef41Sopenharmony_ci Node* check0 = ObjectIsSmi(value); 47081cb0ef41Sopenharmony_ci __ GotoIfNot(check0, &if_not_smi); 47091cb0ef41Sopenharmony_ci Node* from_smi = ChangeSmiToInt32(value); 47101cb0ef41Sopenharmony_ci __ Goto(&done, __ ChangeInt32ToFloat64(from_smi)); 47111cb0ef41Sopenharmony_ci 47121cb0ef41Sopenharmony_ci __ Bind(&if_not_smi); 47131cb0ef41Sopenharmony_ci Node* to_number = 47141cb0ef41Sopenharmony_ci __ PlainPrimitiveToNumber(TNode<Object>::UncheckedCast(value)); 47151cb0ef41Sopenharmony_ci Node* check1 = ObjectIsSmi(to_number); 47161cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_to_number_smi); 47171cb0ef41Sopenharmony_ci 47181cb0ef41Sopenharmony_ci Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number); 47191cb0ef41Sopenharmony_ci __ Goto(&done, number); 47201cb0ef41Sopenharmony_ci 47211cb0ef41Sopenharmony_ci __ Bind(&if_to_number_smi); 47221cb0ef41Sopenharmony_ci Node* number_from_smi = ChangeSmiToInt32(to_number); 47231cb0ef41Sopenharmony_ci number_from_smi = __ ChangeInt32ToFloat64(number_from_smi); 47241cb0ef41Sopenharmony_ci __ Goto(&done, number_from_smi); 47251cb0ef41Sopenharmony_ci 47261cb0ef41Sopenharmony_ci __ Bind(&done); 47271cb0ef41Sopenharmony_ci return done.PhiAt(0); 47281cb0ef41Sopenharmony_ci} 47291cb0ef41Sopenharmony_ci 47301cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) { 47311cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 47321cb0ef41Sopenharmony_ci Node* elements = node->InputAt(1); 47331cb0ef41Sopenharmony_ci 47341cb0ef41Sopenharmony_ci auto if_not_fixed_array = __ MakeDeferredLabel(); 47351cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 47361cb0ef41Sopenharmony_ci 47371cb0ef41Sopenharmony_ci // Load the current map of {elements}. 47381cb0ef41Sopenharmony_ci Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements); 47391cb0ef41Sopenharmony_ci 47401cb0ef41Sopenharmony_ci // Check if {elements} is not a copy-on-write FixedArray. 47411cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(elements_map, __ FixedArrayMapConstant()); 47421cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_not_fixed_array); 47431cb0ef41Sopenharmony_ci // Nothing to do if the {elements} are not copy-on-write. 47441cb0ef41Sopenharmony_ci __ Goto(&done, elements); 47451cb0ef41Sopenharmony_ci 47461cb0ef41Sopenharmony_ci __ Bind(&if_not_fixed_array); 47471cb0ef41Sopenharmony_ci // We need to take a copy of the {elements} and set them up for {object}. 47481cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 47491cb0ef41Sopenharmony_ci Callable callable = 47501cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kCopyFastSmiOrObjectElements); 47511cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 47521cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 47531cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 47541cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 47551cb0ef41Sopenharmony_ci Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()), 47561cb0ef41Sopenharmony_ci object, __ NoContextConstant()); 47571cb0ef41Sopenharmony_ci __ Goto(&done, result); 47581cb0ef41Sopenharmony_ci 47591cb0ef41Sopenharmony_ci __ Bind(&done); 47601cb0ef41Sopenharmony_ci return done.PhiAt(0); 47611cb0ef41Sopenharmony_ci} 47621cb0ef41Sopenharmony_ci 47631cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node, 47641cb0ef41Sopenharmony_ci Node* frame_state) { 47651cb0ef41Sopenharmony_ci GrowFastElementsParameters params = GrowFastElementsParametersOf(node->op()); 47661cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 47671cb0ef41Sopenharmony_ci Node* elements = node->InputAt(1); 47681cb0ef41Sopenharmony_ci Node* index = node->InputAt(2); 47691cb0ef41Sopenharmony_ci Node* elements_length = node->InputAt(3); 47701cb0ef41Sopenharmony_ci 47711cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 47721cb0ef41Sopenharmony_ci auto if_grow = __ MakeDeferredLabel(); 47731cb0ef41Sopenharmony_ci auto if_not_grow = __ MakeLabel(); 47741cb0ef41Sopenharmony_ci 47751cb0ef41Sopenharmony_ci // Check if we need to grow the {elements} backing store. 47761cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThan(index, elements_length); 47771cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_grow); 47781cb0ef41Sopenharmony_ci __ Goto(&done, elements); 47791cb0ef41Sopenharmony_ci 47801cb0ef41Sopenharmony_ci __ Bind(&if_grow); 47811cb0ef41Sopenharmony_ci // We need to grow the {elements} for {object}. 47821cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 47831cb0ef41Sopenharmony_ci Callable callable = 47841cb0ef41Sopenharmony_ci (params.mode() == GrowFastElementsMode::kDoubleElements) 47851cb0ef41Sopenharmony_ci ? Builtins::CallableFor(isolate(), Builtin::kGrowFastDoubleElements) 47861cb0ef41Sopenharmony_ci : Builtins::CallableFor(isolate(), 47871cb0ef41Sopenharmony_ci Builtin::kGrowFastSmiOrObjectElements); 47881cb0ef41Sopenharmony_ci CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags; 47891cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 47901cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 47911cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), call_flags, properties); 47921cb0ef41Sopenharmony_ci Node* new_elements = 47931cb0ef41Sopenharmony_ci __ Call(call_descriptor, __ HeapConstant(callable.code()), object, 47941cb0ef41Sopenharmony_ci ChangeInt32ToSmi(index), __ NoContextConstant()); 47951cb0ef41Sopenharmony_ci 47961cb0ef41Sopenharmony_ci // Ensure that we were able to grow the {elements}. 47971cb0ef41Sopenharmony_ci __ DeoptimizeIf(DeoptimizeReason::kCouldNotGrowElements, params.feedback(), 47981cb0ef41Sopenharmony_ci ObjectIsSmi(new_elements), frame_state); 47991cb0ef41Sopenharmony_ci __ Goto(&done, new_elements); 48001cb0ef41Sopenharmony_ci 48011cb0ef41Sopenharmony_ci __ Bind(&done); 48021cb0ef41Sopenharmony_ci return done.PhiAt(0); 48031cb0ef41Sopenharmony_ci} 48041cb0ef41Sopenharmony_ci 48051cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerTransitionElementsKind(Node* node) { 48061cb0ef41Sopenharmony_ci ElementsTransition const transition = ElementsTransitionOf(node->op()); 48071cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 48081cb0ef41Sopenharmony_ci 48091cb0ef41Sopenharmony_ci auto if_map_same = __ MakeDeferredLabel(); 48101cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 48111cb0ef41Sopenharmony_ci 48121cb0ef41Sopenharmony_ci Node* source_map = __ HeapConstant(transition.source()); 48131cb0ef41Sopenharmony_ci Node* target_map = __ HeapConstant(transition.target()); 48141cb0ef41Sopenharmony_ci 48151cb0ef41Sopenharmony_ci // Load the current map of {object}. 48161cb0ef41Sopenharmony_ci Node* object_map = __ LoadField(AccessBuilder::ForMap(), object); 48171cb0ef41Sopenharmony_ci 48181cb0ef41Sopenharmony_ci // Check if {object_map} is the same as {source_map}. 48191cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(object_map, source_map); 48201cb0ef41Sopenharmony_ci __ GotoIf(check, &if_map_same); 48211cb0ef41Sopenharmony_ci __ Goto(&done); 48221cb0ef41Sopenharmony_ci 48231cb0ef41Sopenharmony_ci __ Bind(&if_map_same); 48241cb0ef41Sopenharmony_ci switch (transition.mode()) { 48251cb0ef41Sopenharmony_ci case ElementsTransition::kFastTransition: 48261cb0ef41Sopenharmony_ci // In-place migration of {object}, just store the {target_map}. 48271cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), object, target_map); 48281cb0ef41Sopenharmony_ci break; 48291cb0ef41Sopenharmony_ci case ElementsTransition::kSlowTransition: { 48301cb0ef41Sopenharmony_ci // Instance migration, call out to the runtime for {object}. 48311cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 48321cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kTransitionElementsKind; 48331cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 48341cb0ef41Sopenharmony_ci graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); 48351cb0ef41Sopenharmony_ci __ Call(call_descriptor, __ CEntryStubConstant(1), object, target_map, 48361cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 48371cb0ef41Sopenharmony_ci __ Int32Constant(2), __ NoContextConstant()); 48381cb0ef41Sopenharmony_ci break; 48391cb0ef41Sopenharmony_ci } 48401cb0ef41Sopenharmony_ci } 48411cb0ef41Sopenharmony_ci __ Goto(&done); 48421cb0ef41Sopenharmony_ci 48431cb0ef41Sopenharmony_ci __ Bind(&done); 48441cb0ef41Sopenharmony_ci} 48451cb0ef41Sopenharmony_ci 48461cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerLoadMessage(Node* node) { 48471cb0ef41Sopenharmony_ci Node* offset = node->InputAt(0); 48481cb0ef41Sopenharmony_ci Node* object_pattern = 48491cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForExternalIntPtr(), offset); 48501cb0ef41Sopenharmony_ci return __ BitcastWordToTagged(object_pattern); 48511cb0ef41Sopenharmony_ci} 48521cb0ef41Sopenharmony_ci 48531cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerStoreMessage(Node* node) { 48541cb0ef41Sopenharmony_ci Node* offset = node->InputAt(0); 48551cb0ef41Sopenharmony_ci Node* object = node->InputAt(1); 48561cb0ef41Sopenharmony_ci Node* object_pattern = __ BitcastTaggedToWord(object); 48571cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForExternalIntPtr(), offset, object_pattern); 48581cb0ef41Sopenharmony_ci} 48591cb0ef41Sopenharmony_ci 48601cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::AdaptFastCallTypedArrayArgument( 48611cb0ef41Sopenharmony_ci Node* node, ElementsKind expected_elements_kind, 48621cb0ef41Sopenharmony_ci GraphAssemblerLabel<0>* bailout) { 48631cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), node); 48641cb0ef41Sopenharmony_ci Node* value_instance_type = 48651cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 48661cb0ef41Sopenharmony_ci Node* value_is_typed_array = __ Word32Equal( 48671cb0ef41Sopenharmony_ci value_instance_type, __ Int32Constant(JS_TYPED_ARRAY_TYPE)); 48681cb0ef41Sopenharmony_ci __ GotoIfNot(value_is_typed_array, bailout); 48691cb0ef41Sopenharmony_ci 48701cb0ef41Sopenharmony_ci Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), value_map); 48711cb0ef41Sopenharmony_ci Node* mask = __ Int32Constant(Map::Bits2::ElementsKindBits::kMask); 48721cb0ef41Sopenharmony_ci Node* andit = __ Word32And(bit_field2, mask); 48731cb0ef41Sopenharmony_ci Node* shift = __ Int32Constant(Map::Bits2::ElementsKindBits::kShift); 48741cb0ef41Sopenharmony_ci Node* kind = __ Word32Shr(andit, shift); 48751cb0ef41Sopenharmony_ci 48761cb0ef41Sopenharmony_ci Node* value_is_expected_elements_kind = 48771cb0ef41Sopenharmony_ci __ Word32Equal(kind, __ Int32Constant(expected_elements_kind)); 48781cb0ef41Sopenharmony_ci __ GotoIfNot(value_is_expected_elements_kind, bailout); 48791cb0ef41Sopenharmony_ci 48801cb0ef41Sopenharmony_ci Node* buffer = 48811cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForJSArrayBufferViewBuffer(), node); 48821cb0ef41Sopenharmony_ci Node* buffer_bit_field = 48831cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), buffer); 48841cb0ef41Sopenharmony_ci 48851cb0ef41Sopenharmony_ci // Go to the slow path if the {buffer} was detached. 48861cb0ef41Sopenharmony_ci Node* buffer_is_not_detached = __ Word32Equal( 48871cb0ef41Sopenharmony_ci __ Word32And(buffer_bit_field, 48881cb0ef41Sopenharmony_ci __ Int32Constant(JSArrayBuffer::WasDetachedBit::kMask)), 48891cb0ef41Sopenharmony_ci __ ZeroConstant()); 48901cb0ef41Sopenharmony_ci __ GotoIfNot(buffer_is_not_detached, bailout); 48911cb0ef41Sopenharmony_ci 48921cb0ef41Sopenharmony_ci // Go to the slow path if the {buffer} is shared. 48931cb0ef41Sopenharmony_ci Node* buffer_is_not_shared = __ Word32Equal( 48941cb0ef41Sopenharmony_ci __ Word32And(buffer_bit_field, 48951cb0ef41Sopenharmony_ci __ Int32Constant(JSArrayBuffer::IsSharedBit::kMask)), 48961cb0ef41Sopenharmony_ci __ ZeroConstant()); 48971cb0ef41Sopenharmony_ci __ GotoIfNot(buffer_is_not_shared, bailout); 48981cb0ef41Sopenharmony_ci 48991cb0ef41Sopenharmony_ci // Unpack the store and length, and store them to a struct 49001cb0ef41Sopenharmony_ci // FastApiTypedArray. 49011cb0ef41Sopenharmony_ci Node* external_pointer = 49021cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForJSTypedArrayExternalPointer(), node); 49031cb0ef41Sopenharmony_ci 49041cb0ef41Sopenharmony_ci // Load the base pointer for the buffer. This will always be Smi 49051cb0ef41Sopenharmony_ci // zero unless we allow on-heap TypedArrays, which is only the case 49061cb0ef41Sopenharmony_ci // for Chrome. Node and Electron both set this limit to 0. Setting 49071cb0ef41Sopenharmony_ci // the base to Smi zero here allows the BuildTypedArrayDataPointer 49081cb0ef41Sopenharmony_ci // to optimize away the tricky part of the access later. 49091cb0ef41Sopenharmony_ci Node* base_pointer = 49101cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForJSTypedArrayBasePointer(), node); 49111cb0ef41Sopenharmony_ci if (JSTypedArray::kMaxSizeInHeap == 0) { 49121cb0ef41Sopenharmony_ci base_pointer = jsgraph()->ZeroConstant(); 49131cb0ef41Sopenharmony_ci } 49141cb0ef41Sopenharmony_ci Node* data_ptr = BuildTypedArrayDataPointer(base_pointer, external_pointer); 49151cb0ef41Sopenharmony_ci Node* length_in_bytes = 49161cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForJSTypedArrayLength(), node); 49171cb0ef41Sopenharmony_ci 49181cb0ef41Sopenharmony_ci // We hard-code int32_t here, because all specializations of 49191cb0ef41Sopenharmony_ci // FastApiTypedArray have the same size. 49201cb0ef41Sopenharmony_ci constexpr int kAlign = alignof(FastApiTypedArray<int32_t>); 49211cb0ef41Sopenharmony_ci constexpr int kSize = sizeof(FastApiTypedArray<int32_t>); 49221cb0ef41Sopenharmony_ci static_assert(kAlign == alignof(FastApiTypedArray<double>), 49231cb0ef41Sopenharmony_ci "Alignment mismatch between different specializations of " 49241cb0ef41Sopenharmony_ci "FastApiTypedArray"); 49251cb0ef41Sopenharmony_ci static_assert(kSize == sizeof(FastApiTypedArray<double>), 49261cb0ef41Sopenharmony_ci "Size mismatch between different specializations of " 49271cb0ef41Sopenharmony_ci "FastApiTypedArray"); 49281cb0ef41Sopenharmony_ci static_assert( 49291cb0ef41Sopenharmony_ci kSize == sizeof(uintptr_t) + sizeof(size_t), 49301cb0ef41Sopenharmony_ci "The size of " 49311cb0ef41Sopenharmony_ci "FastApiTypedArray isn't equal to the sum of its expected members."); 49321cb0ef41Sopenharmony_ci Node* stack_slot = __ StackSlot(kSize, kAlign); 49331cb0ef41Sopenharmony_ci 49341cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 49351cb0ef41Sopenharmony_ci kNoWriteBarrier), 49361cb0ef41Sopenharmony_ci stack_slot, 0, length_in_bytes); 49371cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 49381cb0ef41Sopenharmony_ci kNoWriteBarrier), 49391cb0ef41Sopenharmony_ci stack_slot, sizeof(size_t), data_ptr); 49401cb0ef41Sopenharmony_ci static_assert(sizeof(uintptr_t) == sizeof(size_t), 49411cb0ef41Sopenharmony_ci "The buffer length can't " 49421cb0ef41Sopenharmony_ci "fit the PointerRepresentation used to store it."); 49431cb0ef41Sopenharmony_ci 49441cb0ef41Sopenharmony_ci return stack_slot; 49451cb0ef41Sopenharmony_ci} 49461cb0ef41Sopenharmony_ci 49471cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::AdaptFastCallArgument( 49481cb0ef41Sopenharmony_ci Node* node, CTypeInfo arg_type, GraphAssemblerLabel<0>* if_error) { 49491cb0ef41Sopenharmony_ci int kAlign = alignof(uintptr_t); 49501cb0ef41Sopenharmony_ci int kSize = sizeof(uintptr_t); 49511cb0ef41Sopenharmony_ci switch (arg_type.GetSequenceType()) { 49521cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kScalar: { 49531cb0ef41Sopenharmony_ci switch (arg_type.GetType()) { 49541cb0ef41Sopenharmony_ci case CTypeInfo::Type::kV8Value: { 49551cb0ef41Sopenharmony_ci Node* stack_slot = __ StackSlot(kSize, kAlign); 49561cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 49571cb0ef41Sopenharmony_ci kNoWriteBarrier), 49581cb0ef41Sopenharmony_ci stack_slot, 0, node); 49591cb0ef41Sopenharmony_ci 49601cb0ef41Sopenharmony_ci return stack_slot; 49611cb0ef41Sopenharmony_ci } 49621cb0ef41Sopenharmony_ci case CTypeInfo::Type::kFloat32: { 49631cb0ef41Sopenharmony_ci return __ TruncateFloat64ToFloat32(node); 49641cb0ef41Sopenharmony_ci } 49651cb0ef41Sopenharmony_ci default: { 49661cb0ef41Sopenharmony_ci return node; 49671cb0ef41Sopenharmony_ci } 49681cb0ef41Sopenharmony_ci } 49691cb0ef41Sopenharmony_ci } 49701cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kIsSequence: { 49711cb0ef41Sopenharmony_ci CHECK_EQ(arg_type.GetType(), CTypeInfo::Type::kVoid); 49721cb0ef41Sopenharmony_ci 49731cb0ef41Sopenharmony_ci // Check that the value is a HeapObject. 49741cb0ef41Sopenharmony_ci Node* value_is_smi = ObjectIsSmi(node); 49751cb0ef41Sopenharmony_ci __ GotoIf(value_is_smi, if_error); 49761cb0ef41Sopenharmony_ci 49771cb0ef41Sopenharmony_ci Node* stack_slot = __ StackSlot(kSize, kAlign); 49781cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 49791cb0ef41Sopenharmony_ci kNoWriteBarrier), 49801cb0ef41Sopenharmony_ci stack_slot, 0, node); 49811cb0ef41Sopenharmony_ci 49821cb0ef41Sopenharmony_ci // Check that the value is a JSArray. 49831cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), node); 49841cb0ef41Sopenharmony_ci Node* value_instance_type = 49851cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 49861cb0ef41Sopenharmony_ci Node* value_is_js_array = 49871cb0ef41Sopenharmony_ci __ Word32Equal(value_instance_type, __ Int32Constant(JS_ARRAY_TYPE)); 49881cb0ef41Sopenharmony_ci __ GotoIfNot(value_is_js_array, if_error); 49891cb0ef41Sopenharmony_ci 49901cb0ef41Sopenharmony_ci return stack_slot; 49911cb0ef41Sopenharmony_ci } 49921cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kIsTypedArray: { 49931cb0ef41Sopenharmony_ci // Check that the value is a HeapObject. 49941cb0ef41Sopenharmony_ci Node* value_is_smi = ObjectIsSmi(node); 49951cb0ef41Sopenharmony_ci __ GotoIf(value_is_smi, if_error); 49961cb0ef41Sopenharmony_ci 49971cb0ef41Sopenharmony_ci return AdaptFastCallTypedArrayArgument( 49981cb0ef41Sopenharmony_ci node, fast_api_call::GetTypedArrayElementsKind(arg_type.GetType()), 49991cb0ef41Sopenharmony_ci if_error); 50001cb0ef41Sopenharmony_ci } 50011cb0ef41Sopenharmony_ci default: { 50021cb0ef41Sopenharmony_ci UNREACHABLE(); 50031cb0ef41Sopenharmony_ci } 50041cb0ef41Sopenharmony_ci } 50051cb0ef41Sopenharmony_ci} 50061cb0ef41Sopenharmony_ci 50071cb0ef41Sopenharmony_ciEffectControlLinearizer::AdaptOverloadedFastCallResult 50081cb0ef41Sopenharmony_ciEffectControlLinearizer::AdaptOverloadedFastCallArgument( 50091cb0ef41Sopenharmony_ci Node* node, const FastApiCallFunctionVector& c_functions, 50101cb0ef41Sopenharmony_ci const fast_api_call::OverloadsResolutionResult& overloads_resolution_result, 50111cb0ef41Sopenharmony_ci GraphAssemblerLabel<0>* if_error) { 50121cb0ef41Sopenharmony_ci static constexpr int kReceiver = 1; 50131cb0ef41Sopenharmony_ci 50141cb0ef41Sopenharmony_ci auto merge = __ MakeLabel(MachineRepresentation::kTagged, 50151cb0ef41Sopenharmony_ci MachineRepresentation::kTagged); 50161cb0ef41Sopenharmony_ci 50171cb0ef41Sopenharmony_ci for (size_t func_index = 0; func_index < c_functions.size(); func_index++) { 50181cb0ef41Sopenharmony_ci const CFunctionInfo* c_signature = c_functions[func_index].signature; 50191cb0ef41Sopenharmony_ci CTypeInfo arg_type = c_signature->ArgumentInfo( 50201cb0ef41Sopenharmony_ci overloads_resolution_result.distinguishable_arg_index + kReceiver); 50211cb0ef41Sopenharmony_ci 50221cb0ef41Sopenharmony_ci auto next = __ MakeLabel(); 50231cb0ef41Sopenharmony_ci 50241cb0ef41Sopenharmony_ci // Check that the value is a HeapObject. 50251cb0ef41Sopenharmony_ci Node* value_is_smi = ObjectIsSmi(node); 50261cb0ef41Sopenharmony_ci __ GotoIf(value_is_smi, if_error); 50271cb0ef41Sopenharmony_ci 50281cb0ef41Sopenharmony_ci ExternalReference::Type ref_type = ExternalReference::FAST_C_CALL; 50291cb0ef41Sopenharmony_ci 50301cb0ef41Sopenharmony_ci switch (arg_type.GetSequenceType()) { 50311cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kIsSequence: { 50321cb0ef41Sopenharmony_ci CHECK_EQ(arg_type.GetType(), CTypeInfo::Type::kVoid); 50331cb0ef41Sopenharmony_ci 50341cb0ef41Sopenharmony_ci // Check that the value is a JSArray. 50351cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), node); 50361cb0ef41Sopenharmony_ci Node* value_instance_type = 50371cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 50381cb0ef41Sopenharmony_ci Node* value_is_js_array = __ Word32Equal( 50391cb0ef41Sopenharmony_ci value_instance_type, __ Int32Constant(JS_ARRAY_TYPE)); 50401cb0ef41Sopenharmony_ci __ GotoIfNot(value_is_js_array, &next); 50411cb0ef41Sopenharmony_ci 50421cb0ef41Sopenharmony_ci int kAlign = alignof(uintptr_t); 50431cb0ef41Sopenharmony_ci int kSize = sizeof(uintptr_t); 50441cb0ef41Sopenharmony_ci Node* stack_slot = __ StackSlot(kSize, kAlign); 50451cb0ef41Sopenharmony_ci 50461cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 50471cb0ef41Sopenharmony_ci kNoWriteBarrier), 50481cb0ef41Sopenharmony_ci stack_slot, 0, node); 50491cb0ef41Sopenharmony_ci 50501cb0ef41Sopenharmony_ci Node* target_address = __ ExternalConstant(ExternalReference::Create( 50511cb0ef41Sopenharmony_ci c_functions[func_index].address, ref_type)); 50521cb0ef41Sopenharmony_ci __ Goto(&merge, target_address, stack_slot); 50531cb0ef41Sopenharmony_ci break; 50541cb0ef41Sopenharmony_ci } 50551cb0ef41Sopenharmony_ci 50561cb0ef41Sopenharmony_ci case CTypeInfo::SequenceType::kIsTypedArray: { 50571cb0ef41Sopenharmony_ci // Check that the value is a TypedArray with a type that matches the 50581cb0ef41Sopenharmony_ci // type declared in the c-function. 50591cb0ef41Sopenharmony_ci Node* stack_slot = AdaptFastCallTypedArrayArgument( 50601cb0ef41Sopenharmony_ci node, 50611cb0ef41Sopenharmony_ci fast_api_call::GetTypedArrayElementsKind( 50621cb0ef41Sopenharmony_ci overloads_resolution_result.element_type), 50631cb0ef41Sopenharmony_ci &next); 50641cb0ef41Sopenharmony_ci Node* target_address = __ ExternalConstant(ExternalReference::Create( 50651cb0ef41Sopenharmony_ci c_functions[func_index].address, ref_type)); 50661cb0ef41Sopenharmony_ci __ Goto(&merge, target_address, stack_slot); 50671cb0ef41Sopenharmony_ci break; 50681cb0ef41Sopenharmony_ci } 50691cb0ef41Sopenharmony_ci 50701cb0ef41Sopenharmony_ci default: { 50711cb0ef41Sopenharmony_ci UNREACHABLE(); 50721cb0ef41Sopenharmony_ci } 50731cb0ef41Sopenharmony_ci } 50741cb0ef41Sopenharmony_ci 50751cb0ef41Sopenharmony_ci __ Bind(&next); 50761cb0ef41Sopenharmony_ci } 50771cb0ef41Sopenharmony_ci __ Goto(if_error); 50781cb0ef41Sopenharmony_ci 50791cb0ef41Sopenharmony_ci __ Bind(&merge); 50801cb0ef41Sopenharmony_ci return {merge.PhiAt(0), merge.PhiAt(1)}; 50811cb0ef41Sopenharmony_ci} 50821cb0ef41Sopenharmony_ci 50831cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::WrapFastCall( 50841cb0ef41Sopenharmony_ci const CallDescriptor* call_descriptor, int inputs_size, Node** inputs, 50851cb0ef41Sopenharmony_ci Node* target, const CFunctionInfo* c_signature, int c_arg_count, 50861cb0ef41Sopenharmony_ci Node* stack_slot) { 50871cb0ef41Sopenharmony_ci // CPU profiler support 50881cb0ef41Sopenharmony_ci Node* target_address = __ ExternalConstant( 50891cb0ef41Sopenharmony_ci ExternalReference::fast_api_call_target_address(isolate())); 50901cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 50911cb0ef41Sopenharmony_ci kNoWriteBarrier), 50921cb0ef41Sopenharmony_ci target_address, 0, target); 50931cb0ef41Sopenharmony_ci 50941cb0ef41Sopenharmony_ci // Disable JS execution 50951cb0ef41Sopenharmony_ci Node* javascript_execution_assert = __ ExternalConstant( 50961cb0ef41Sopenharmony_ci ExternalReference::javascript_execution_assert(isolate())); 50971cb0ef41Sopenharmony_ci static_assert(sizeof(bool) == 1, "Wrong assumption about boolean size."); 50981cb0ef41Sopenharmony_ci 50991cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 51001cb0ef41Sopenharmony_ci auto do_store = __ MakeLabel(); 51011cb0ef41Sopenharmony_ci Node* old_scope_value = 51021cb0ef41Sopenharmony_ci __ Load(MachineType::Int8(), javascript_execution_assert, 0); 51031cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(old_scope_value, __ Int32Constant(1)), &do_store); 51041cb0ef41Sopenharmony_ci 51051cb0ef41Sopenharmony_ci // We expect that JS execution is enabled, otherwise assert. 51061cb0ef41Sopenharmony_ci __ Unreachable(&do_store); 51071cb0ef41Sopenharmony_ci __ Bind(&do_store); 51081cb0ef41Sopenharmony_ci } 51091cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), 51101cb0ef41Sopenharmony_ci javascript_execution_assert, 0, __ Int32Constant(0)); 51111cb0ef41Sopenharmony_ci 51121cb0ef41Sopenharmony_ci // Update effect and control 51131cb0ef41Sopenharmony_ci if (c_signature->HasOptions()) { 51141cb0ef41Sopenharmony_ci inputs[c_arg_count + 1] = stack_slot; 51151cb0ef41Sopenharmony_ci inputs[c_arg_count + 2] = __ effect(); 51161cb0ef41Sopenharmony_ci inputs[c_arg_count + 3] = __ control(); 51171cb0ef41Sopenharmony_ci } else { 51181cb0ef41Sopenharmony_ci inputs[c_arg_count + 1] = __ effect(); 51191cb0ef41Sopenharmony_ci inputs[c_arg_count + 2] = __ control(); 51201cb0ef41Sopenharmony_ci } 51211cb0ef41Sopenharmony_ci 51221cb0ef41Sopenharmony_ci // Create the fast call 51231cb0ef41Sopenharmony_ci Node* call = __ Call(call_descriptor, inputs_size, inputs); 51241cb0ef41Sopenharmony_ci 51251cb0ef41Sopenharmony_ci // Reenable JS execution 51261cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), 51271cb0ef41Sopenharmony_ci javascript_execution_assert, 0, __ Int32Constant(1)); 51281cb0ef41Sopenharmony_ci 51291cb0ef41Sopenharmony_ci // Reset the CPU profiler target address. 51301cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 51311cb0ef41Sopenharmony_ci kNoWriteBarrier), 51321cb0ef41Sopenharmony_ci target_address, 0, __ IntPtrConstant(0)); 51331cb0ef41Sopenharmony_ci 51341cb0ef41Sopenharmony_ci return call; 51351cb0ef41Sopenharmony_ci} 51361cb0ef41Sopenharmony_ci 51371cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::GenerateSlowApiCall(Node* node) { 51381cb0ef41Sopenharmony_ci FastApiCallNode n(node); 51391cb0ef41Sopenharmony_ci FastApiCallParameters const& params = n.Parameters(); 51401cb0ef41Sopenharmony_ci const CFunctionInfo* c_signature = params.c_functions()[0].signature; 51411cb0ef41Sopenharmony_ci const int c_arg_count = c_signature->ArgumentCount(); 51421cb0ef41Sopenharmony_ci 51431cb0ef41Sopenharmony_ci Node** const slow_inputs = graph()->zone()->NewArray<Node*>( 51441cb0ef41Sopenharmony_ci n.SlowCallArgumentCount() + FastApiCallNode::kEffectAndControlInputCount); 51451cb0ef41Sopenharmony_ci 51461cb0ef41Sopenharmony_ci int fast_call_params = c_arg_count; 51471cb0ef41Sopenharmony_ci CHECK_EQ(node->op()->ValueInputCount() - fast_call_params, 51481cb0ef41Sopenharmony_ci n.SlowCallArgumentCount()); 51491cb0ef41Sopenharmony_ci int index = 0; 51501cb0ef41Sopenharmony_ci for (; index < n.SlowCallArgumentCount(); ++index) { 51511cb0ef41Sopenharmony_ci slow_inputs[index] = n.SlowCallArgument(index); 51521cb0ef41Sopenharmony_ci } 51531cb0ef41Sopenharmony_ci 51541cb0ef41Sopenharmony_ci slow_inputs[index] = __ effect(); 51551cb0ef41Sopenharmony_ci slow_inputs[index + 1] = __ control(); 51561cb0ef41Sopenharmony_ci Node* slow_call_result = __ Call( 51571cb0ef41Sopenharmony_ci params.descriptor(), index + FastApiCallNode::kEffectAndControlInputCount, 51581cb0ef41Sopenharmony_ci slow_inputs); 51591cb0ef41Sopenharmony_ci return slow_call_result; 51601cb0ef41Sopenharmony_ci} 51611cb0ef41Sopenharmony_ci 51621cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerFastApiCall(Node* node) { 51631cb0ef41Sopenharmony_ci FastApiCallNode n(node); 51641cb0ef41Sopenharmony_ci FastApiCallParameters const& params = n.Parameters(); 51651cb0ef41Sopenharmony_ci 51661cb0ef41Sopenharmony_ci static constexpr int kReceiver = 1; 51671cb0ef41Sopenharmony_ci 51681cb0ef41Sopenharmony_ci const FastApiCallFunctionVector& c_functions = params.c_functions(); 51691cb0ef41Sopenharmony_ci const CFunctionInfo* c_signature = params.c_functions()[0].signature; 51701cb0ef41Sopenharmony_ci const int c_arg_count = c_signature->ArgumentCount(); 51711cb0ef41Sopenharmony_ci CallDescriptor* js_call_descriptor = params.descriptor(); 51721cb0ef41Sopenharmony_ci int js_arg_count = static_cast<int>(js_call_descriptor->ParameterCount()); 51731cb0ef41Sopenharmony_ci const int value_input_count = node->op()->ValueInputCount(); 51741cb0ef41Sopenharmony_ci CHECK_EQ(FastApiCallNode::ArityForArgc(c_arg_count, js_arg_count), 51751cb0ef41Sopenharmony_ci value_input_count); 51761cb0ef41Sopenharmony_ci 51771cb0ef41Sopenharmony_ci Node* stack_slot = nullptr; 51781cb0ef41Sopenharmony_ci int kAlign = alignof(v8::FastApiCallbackOptions); 51791cb0ef41Sopenharmony_ci int kSize = sizeof(v8::FastApiCallbackOptions); 51801cb0ef41Sopenharmony_ci // If this check fails, you've probably added new fields to 51811cb0ef41Sopenharmony_ci // v8::FastApiCallbackOptions, which means you'll need to write code 51821cb0ef41Sopenharmony_ci // that initializes and reads from them too. 51831cb0ef41Sopenharmony_ci CHECK_EQ(kSize, sizeof(uintptr_t) * 2); 51841cb0ef41Sopenharmony_ci stack_slot = __ StackSlot(kSize, kAlign); 51851cb0ef41Sopenharmony_ci if (c_signature->HasOptions()) { 51861cb0ef41Sopenharmony_ci __ Store( 51871cb0ef41Sopenharmony_ci StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier), 51881cb0ef41Sopenharmony_ci stack_slot, 51891cb0ef41Sopenharmony_ci static_cast<int>(offsetof(v8::FastApiCallbackOptions, fallback)), 51901cb0ef41Sopenharmony_ci __ Int32Constant(0)); 51911cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 51921cb0ef41Sopenharmony_ci kNoWriteBarrier), 51931cb0ef41Sopenharmony_ci stack_slot, 51941cb0ef41Sopenharmony_ci static_cast<int>(offsetof(v8::FastApiCallbackOptions, data)), 51951cb0ef41Sopenharmony_ci n.SlowCallArgument(FastApiCallNode::kSlowCallDataArgumentIndex)); 51961cb0ef41Sopenharmony_ci } else { 51971cb0ef41Sopenharmony_ci __ Store( 51981cb0ef41Sopenharmony_ci StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier), 51991cb0ef41Sopenharmony_ci stack_slot, 52001cb0ef41Sopenharmony_ci 0, // fallback = false 52011cb0ef41Sopenharmony_ci __ Int32Constant(0)); 52021cb0ef41Sopenharmony_ci __ Store(StoreRepresentation(MachineType::PointerRepresentation(), 52031cb0ef41Sopenharmony_ci kNoWriteBarrier), 52041cb0ef41Sopenharmony_ci stack_slot, 52051cb0ef41Sopenharmony_ci 0, // no data 52061cb0ef41Sopenharmony_ci n.SlowCallArgument(FastApiCallNode::kSlowCallDataArgumentIndex)); 52071cb0ef41Sopenharmony_ci } 52081cb0ef41Sopenharmony_ci 52091cb0ef41Sopenharmony_ci MachineSignature::Builder builder( 52101cb0ef41Sopenharmony_ci graph()->zone(), 1, c_arg_count + (c_signature->HasOptions() ? 1 : 0)); 52111cb0ef41Sopenharmony_ci MachineType return_type = 52121cb0ef41Sopenharmony_ci MachineType::TypeForCType(c_signature->ReturnInfo()); 52131cb0ef41Sopenharmony_ci builder.AddReturn(return_type); 52141cb0ef41Sopenharmony_ci for (int i = 0; i < c_arg_count; ++i) { 52151cb0ef41Sopenharmony_ci CTypeInfo type = c_signature->ArgumentInfo(i); 52161cb0ef41Sopenharmony_ci MachineType machine_type = 52171cb0ef41Sopenharmony_ci type.GetSequenceType() == CTypeInfo::SequenceType::kScalar 52181cb0ef41Sopenharmony_ci ? MachineType::TypeForCType(type) 52191cb0ef41Sopenharmony_ci : MachineType::AnyTagged(); 52201cb0ef41Sopenharmony_ci builder.AddParam(machine_type); 52211cb0ef41Sopenharmony_ci } 52221cb0ef41Sopenharmony_ci if (c_signature->HasOptions()) { 52231cb0ef41Sopenharmony_ci builder.AddParam(MachineType::Pointer()); // stack_slot 52241cb0ef41Sopenharmony_ci } 52251cb0ef41Sopenharmony_ci 52261cb0ef41Sopenharmony_ci CallDescriptor* call_descriptor = 52271cb0ef41Sopenharmony_ci Linkage::GetSimplifiedCDescriptor(graph()->zone(), builder.Build()); 52281cb0ef41Sopenharmony_ci 52291cb0ef41Sopenharmony_ci // Hint to fast path. 52301cb0ef41Sopenharmony_ci auto if_success = __ MakeLabel(); 52311cb0ef41Sopenharmony_ci auto if_error = __ MakeDeferredLabel(); 52321cb0ef41Sopenharmony_ci 52331cb0ef41Sopenharmony_ci // Overload resolution 52341cb0ef41Sopenharmony_ci 52351cb0ef41Sopenharmony_ci bool generate_fast_call = false; 52361cb0ef41Sopenharmony_ci int distinguishable_arg_index = INT_MIN; 52371cb0ef41Sopenharmony_ci fast_api_call::OverloadsResolutionResult overloads_resolution_result = 52381cb0ef41Sopenharmony_ci fast_api_call::OverloadsResolutionResult::Invalid(); 52391cb0ef41Sopenharmony_ci 52401cb0ef41Sopenharmony_ci if (c_functions.size() == 1) { 52411cb0ef41Sopenharmony_ci generate_fast_call = true; 52421cb0ef41Sopenharmony_ci } else { 52431cb0ef41Sopenharmony_ci DCHECK_EQ(c_functions.size(), 2); 52441cb0ef41Sopenharmony_ci overloads_resolution_result = fast_api_call::ResolveOverloads( 52451cb0ef41Sopenharmony_ci graph()->zone(), c_functions, c_arg_count); 52461cb0ef41Sopenharmony_ci if (overloads_resolution_result.is_valid()) { 52471cb0ef41Sopenharmony_ci generate_fast_call = true; 52481cb0ef41Sopenharmony_ci distinguishable_arg_index = 52491cb0ef41Sopenharmony_ci overloads_resolution_result.distinguishable_arg_index; 52501cb0ef41Sopenharmony_ci } 52511cb0ef41Sopenharmony_ci } 52521cb0ef41Sopenharmony_ci 52531cb0ef41Sopenharmony_ci if (!generate_fast_call) { 52541cb0ef41Sopenharmony_ci // Only generate the slow call. 52551cb0ef41Sopenharmony_ci return GenerateSlowApiCall(node); 52561cb0ef41Sopenharmony_ci } 52571cb0ef41Sopenharmony_ci 52581cb0ef41Sopenharmony_ci // Generate fast call. 52591cb0ef41Sopenharmony_ci 52601cb0ef41Sopenharmony_ci const int kFastTargetAddressInputIndex = 0; 52611cb0ef41Sopenharmony_ci const int kFastTargetAddressInputCount = 1; 52621cb0ef41Sopenharmony_ci 52631cb0ef41Sopenharmony_ci Node** const inputs = graph()->zone()->NewArray<Node*>( 52641cb0ef41Sopenharmony_ci kFastTargetAddressInputCount + c_arg_count + n.FastCallExtraInputCount()); 52651cb0ef41Sopenharmony_ci 52661cb0ef41Sopenharmony_ci ExternalReference::Type ref_type = ExternalReference::FAST_C_CALL; 52671cb0ef41Sopenharmony_ci 52681cb0ef41Sopenharmony_ci // The inputs to {Call} node for the fast call look like: 52691cb0ef41Sopenharmony_ci // [fast callee, receiver, ... C arguments, [optional Options], effect, 52701cb0ef41Sopenharmony_ci // control]. 52711cb0ef41Sopenharmony_ci // 52721cb0ef41Sopenharmony_ci // The first input node represents the target address for the fast call. 52731cb0ef41Sopenharmony_ci // If the function is not overloaded (c_functions.size() == 1) this is the 52741cb0ef41Sopenharmony_ci // address associated to the first and only element in the c_functions vector. 52751cb0ef41Sopenharmony_ci // If there are multiple overloads the value of this input will be set later 52761cb0ef41Sopenharmony_ci // with a Phi node created by AdaptOverloadedFastCallArgument. 52771cb0ef41Sopenharmony_ci inputs[kFastTargetAddressInputIndex] = 52781cb0ef41Sopenharmony_ci (c_functions.size() == 1) ? __ ExternalConstant(ExternalReference::Create( 52791cb0ef41Sopenharmony_ci c_functions[0].address, ref_type)) 52801cb0ef41Sopenharmony_ci : nullptr; 52811cb0ef41Sopenharmony_ci 52821cb0ef41Sopenharmony_ci for (int i = 0; i < c_arg_count; ++i) { 52831cb0ef41Sopenharmony_ci Node* value = NodeProperties::GetValueInput(node, i); 52841cb0ef41Sopenharmony_ci 52851cb0ef41Sopenharmony_ci if (i == distinguishable_arg_index + kReceiver) { 52861cb0ef41Sopenharmony_ci // This only happens when the FastApiCall node represents multiple 52871cb0ef41Sopenharmony_ci // overloaded functions and {i} is the index of the distinguishable 52881cb0ef41Sopenharmony_ci // argument. 52891cb0ef41Sopenharmony_ci AdaptOverloadedFastCallResult nodes = AdaptOverloadedFastCallArgument( 52901cb0ef41Sopenharmony_ci value, c_functions, overloads_resolution_result, &if_error); 52911cb0ef41Sopenharmony_ci inputs[i + kFastTargetAddressInputCount] = nodes.argument; 52921cb0ef41Sopenharmony_ci 52931cb0ef41Sopenharmony_ci // Replace the target address node with a Phi node that represents the 52941cb0ef41Sopenharmony_ci // choice between the target addreseses of overloaded functions. 52951cb0ef41Sopenharmony_ci inputs[kFastTargetAddressInputIndex] = nodes.target_address; 52961cb0ef41Sopenharmony_ci } else { 52971cb0ef41Sopenharmony_ci CTypeInfo type = c_signature->ArgumentInfo(i); 52981cb0ef41Sopenharmony_ci inputs[i + kFastTargetAddressInputCount] = 52991cb0ef41Sopenharmony_ci AdaptFastCallArgument(value, type, &if_error); 53001cb0ef41Sopenharmony_ci } 53011cb0ef41Sopenharmony_ci } 53021cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(inputs[0]); 53031cb0ef41Sopenharmony_ci 53041cb0ef41Sopenharmony_ci Node* c_call_result = WrapFastCall( 53051cb0ef41Sopenharmony_ci call_descriptor, c_arg_count + n.FastCallExtraInputCount() + 1, inputs, 53061cb0ef41Sopenharmony_ci inputs[0], c_signature, c_arg_count, stack_slot); 53071cb0ef41Sopenharmony_ci 53081cb0ef41Sopenharmony_ci Node* fast_call_result = nullptr; 53091cb0ef41Sopenharmony_ci switch (c_signature->ReturnInfo().GetType()) { 53101cb0ef41Sopenharmony_ci case CTypeInfo::Type::kVoid: 53111cb0ef41Sopenharmony_ci fast_call_result = __ UndefinedConstant(); 53121cb0ef41Sopenharmony_ci break; 53131cb0ef41Sopenharmony_ci case CTypeInfo::Type::kBool: 53141cb0ef41Sopenharmony_ci static_assert(sizeof(bool) == 1, "unsupported bool size"); 53151cb0ef41Sopenharmony_ci fast_call_result = ChangeBitToTagged( 53161cb0ef41Sopenharmony_ci __ Word32And(c_call_result, __ Int32Constant(0xFF))); 53171cb0ef41Sopenharmony_ci break; 53181cb0ef41Sopenharmony_ci case CTypeInfo::Type::kInt32: 53191cb0ef41Sopenharmony_ci fast_call_result = ChangeInt32ToTagged(c_call_result); 53201cb0ef41Sopenharmony_ci break; 53211cb0ef41Sopenharmony_ci case CTypeInfo::Type::kUint32: 53221cb0ef41Sopenharmony_ci fast_call_result = ChangeUint32ToTagged(c_call_result); 53231cb0ef41Sopenharmony_ci break; 53241cb0ef41Sopenharmony_ci case CTypeInfo::Type::kInt64: 53251cb0ef41Sopenharmony_ci case CTypeInfo::Type::kUint64: 53261cb0ef41Sopenharmony_ci UNREACHABLE(); 53271cb0ef41Sopenharmony_ci case CTypeInfo::Type::kFloat32: 53281cb0ef41Sopenharmony_ci fast_call_result = 53291cb0ef41Sopenharmony_ci ChangeFloat64ToTagged(__ ChangeFloat32ToFloat64(c_call_result), 53301cb0ef41Sopenharmony_ci CheckForMinusZeroMode::kCheckForMinusZero); 53311cb0ef41Sopenharmony_ci break; 53321cb0ef41Sopenharmony_ci case CTypeInfo::Type::kFloat64: 53331cb0ef41Sopenharmony_ci fast_call_result = ChangeFloat64ToTagged( 53341cb0ef41Sopenharmony_ci c_call_result, CheckForMinusZeroMode::kCheckForMinusZero); 53351cb0ef41Sopenharmony_ci break; 53361cb0ef41Sopenharmony_ci case CTypeInfo::Type::kV8Value: 53371cb0ef41Sopenharmony_ci case CTypeInfo::Type::kApiObject: 53381cb0ef41Sopenharmony_ci UNREACHABLE(); 53391cb0ef41Sopenharmony_ci case CTypeInfo::Type::kAny: 53401cb0ef41Sopenharmony_ci fast_call_result = 53411cb0ef41Sopenharmony_ci ChangeFloat64ToTagged(__ ChangeInt64ToFloat64(c_call_result), 53421cb0ef41Sopenharmony_ci CheckForMinusZeroMode::kCheckForMinusZero); 53431cb0ef41Sopenharmony_ci break; 53441cb0ef41Sopenharmony_ci } 53451cb0ef41Sopenharmony_ci 53461cb0ef41Sopenharmony_ci auto merge = __ MakeLabel(MachineRepresentation::kTagged); 53471cb0ef41Sopenharmony_ci if (c_signature->HasOptions()) { 53481cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(stack_slot); 53491cb0ef41Sopenharmony_ci Node* load = __ Load( 53501cb0ef41Sopenharmony_ci MachineType::Int32(), stack_slot, 53511cb0ef41Sopenharmony_ci static_cast<int>(offsetof(v8::FastApiCallbackOptions, fallback))); 53521cb0ef41Sopenharmony_ci 53531cb0ef41Sopenharmony_ci Node* is_zero = __ Word32Equal(load, __ Int32Constant(0)); 53541cb0ef41Sopenharmony_ci __ Branch(is_zero, &if_success, &if_error); 53551cb0ef41Sopenharmony_ci } else { 53561cb0ef41Sopenharmony_ci Node* true_constant = __ TrueConstant(); 53571cb0ef41Sopenharmony_ci __ Branch(true_constant, &if_success, &if_error); 53581cb0ef41Sopenharmony_ci } 53591cb0ef41Sopenharmony_ci 53601cb0ef41Sopenharmony_ci __ Bind(&if_success); 53611cb0ef41Sopenharmony_ci __ Goto(&merge, fast_call_result); 53621cb0ef41Sopenharmony_ci 53631cb0ef41Sopenharmony_ci // Generate direct slow call. 53641cb0ef41Sopenharmony_ci __ Bind(&if_error); 53651cb0ef41Sopenharmony_ci { 53661cb0ef41Sopenharmony_ci Node* slow_call_result = GenerateSlowApiCall(node); 53671cb0ef41Sopenharmony_ci __ Goto(&merge, slow_call_result); 53681cb0ef41Sopenharmony_ci } 53691cb0ef41Sopenharmony_ci 53701cb0ef41Sopenharmony_ci __ Bind(&merge); 53711cb0ef41Sopenharmony_ci return merge.PhiAt(0); 53721cb0ef41Sopenharmony_ci} 53731cb0ef41Sopenharmony_ci 53741cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) { 53751cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 53761cb0ef41Sopenharmony_ci Node* index = node->InputAt(1); 53771cb0ef41Sopenharmony_ci Node* zero = __ IntPtrConstant(0); 53781cb0ef41Sopenharmony_ci Node* one = __ IntPtrConstant(1); 53791cb0ef41Sopenharmony_ci 53801cb0ef41Sopenharmony_ci // Sign-extend the {index} on 64-bit architectures. 53811cb0ef41Sopenharmony_ci if (machine()->Is64()) { 53821cb0ef41Sopenharmony_ci index = __ ChangeInt32ToInt64(index); 53831cb0ef41Sopenharmony_ci } 53841cb0ef41Sopenharmony_ci 53851cb0ef41Sopenharmony_ci auto if_double = __ MakeDeferredLabel(); 53861cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kTagged); 53871cb0ef41Sopenharmony_ci auto loaded_field = __ MakeLabel(MachineRepresentation::kTagged); 53881cb0ef41Sopenharmony_ci auto done_double = __ MakeLabel(MachineRepresentation::kFloat64); 53891cb0ef41Sopenharmony_ci 53901cb0ef41Sopenharmony_ci // Check if field is a mutable double field. 53911cb0ef41Sopenharmony_ci __ GotoIfNot(__ IntPtrEqual(__ WordAnd(index, one), zero), &if_double); 53921cb0ef41Sopenharmony_ci 53931cb0ef41Sopenharmony_ci // The field is a proper Tagged field on {object}. The {index} is shifted 53941cb0ef41Sopenharmony_ci // to the left by one in the code below. 53951cb0ef41Sopenharmony_ci { 53961cb0ef41Sopenharmony_ci // Check if field is in-object or out-of-object. 53971cb0ef41Sopenharmony_ci auto if_outofobject = __ MakeLabel(); 53981cb0ef41Sopenharmony_ci __ GotoIf(__ IntLessThan(index, zero), &if_outofobject); 53991cb0ef41Sopenharmony_ci 54001cb0ef41Sopenharmony_ci // The field is located in the {object} itself. 54011cb0ef41Sopenharmony_ci { 54021cb0ef41Sopenharmony_ci Node* offset = 54031cb0ef41Sopenharmony_ci __ IntAdd(__ WordShl(index, __ IntPtrConstant(kTaggedSizeLog2 - 1)), 54041cb0ef41Sopenharmony_ci __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag)); 54051cb0ef41Sopenharmony_ci Node* field = __ Load(MachineType::AnyTagged(), object, offset); 54061cb0ef41Sopenharmony_ci __ Goto(&loaded_field, field); 54071cb0ef41Sopenharmony_ci } 54081cb0ef41Sopenharmony_ci 54091cb0ef41Sopenharmony_ci // The field is located in the properties backing store of {object}. 54101cb0ef41Sopenharmony_ci // The {index} is equal to the negated out of property index plus 1. 54111cb0ef41Sopenharmony_ci __ Bind(&if_outofobject); 54121cb0ef41Sopenharmony_ci { 54131cb0ef41Sopenharmony_ci Node* properties = __ LoadField( 54141cb0ef41Sopenharmony_ci AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), object); 54151cb0ef41Sopenharmony_ci Node* offset = 54161cb0ef41Sopenharmony_ci __ IntAdd(__ WordShl(__ IntSub(zero, index), 54171cb0ef41Sopenharmony_ci __ IntPtrConstant(kTaggedSizeLog2 - 1)), 54181cb0ef41Sopenharmony_ci __ IntPtrConstant((FixedArray::kHeaderSize - kTaggedSize) - 54191cb0ef41Sopenharmony_ci kHeapObjectTag)); 54201cb0ef41Sopenharmony_ci Node* field = __ Load(MachineType::AnyTagged(), properties, offset); 54211cb0ef41Sopenharmony_ci __ Goto(&loaded_field, field); 54221cb0ef41Sopenharmony_ci } 54231cb0ef41Sopenharmony_ci } 54241cb0ef41Sopenharmony_ci 54251cb0ef41Sopenharmony_ci // The field is a Double field, either unboxed in the object on 64-bit 54261cb0ef41Sopenharmony_ci // architectures, or a mutable HeapNumber. 54271cb0ef41Sopenharmony_ci __ Bind(&if_double); 54281cb0ef41Sopenharmony_ci { 54291cb0ef41Sopenharmony_ci index = __ WordSar(index, one); 54301cb0ef41Sopenharmony_ci 54311cb0ef41Sopenharmony_ci // Check if field is in-object or out-of-object. 54321cb0ef41Sopenharmony_ci auto if_outofobject = __ MakeLabel(); 54331cb0ef41Sopenharmony_ci __ GotoIf(__ IntLessThan(index, zero), &if_outofobject); 54341cb0ef41Sopenharmony_ci 54351cb0ef41Sopenharmony_ci // The field is located in the {object} itself. 54361cb0ef41Sopenharmony_ci { 54371cb0ef41Sopenharmony_ci Node* offset = 54381cb0ef41Sopenharmony_ci __ IntAdd(__ WordShl(index, __ IntPtrConstant(kTaggedSizeLog2)), 54391cb0ef41Sopenharmony_ci __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag)); 54401cb0ef41Sopenharmony_ci Node* field = __ Load(MachineType::AnyTagged(), object, offset); 54411cb0ef41Sopenharmony_ci __ Goto(&loaded_field, field); 54421cb0ef41Sopenharmony_ci } 54431cb0ef41Sopenharmony_ci 54441cb0ef41Sopenharmony_ci __ Bind(&if_outofobject); 54451cb0ef41Sopenharmony_ci { 54461cb0ef41Sopenharmony_ci Node* properties = __ LoadField( 54471cb0ef41Sopenharmony_ci AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), object); 54481cb0ef41Sopenharmony_ci Node* offset = 54491cb0ef41Sopenharmony_ci __ IntAdd(__ WordShl(__ IntSub(zero, index), 54501cb0ef41Sopenharmony_ci __ IntPtrConstant(kTaggedSizeLog2)), 54511cb0ef41Sopenharmony_ci __ IntPtrConstant((FixedArray::kHeaderSize - kTaggedSize) - 54521cb0ef41Sopenharmony_ci kHeapObjectTag)); 54531cb0ef41Sopenharmony_ci Node* field = __ Load(MachineType::AnyTagged(), properties, offset); 54541cb0ef41Sopenharmony_ci __ Goto(&loaded_field, field); 54551cb0ef41Sopenharmony_ci } 54561cb0ef41Sopenharmony_ci } 54571cb0ef41Sopenharmony_ci 54581cb0ef41Sopenharmony_ci __ Bind(&loaded_field); 54591cb0ef41Sopenharmony_ci { 54601cb0ef41Sopenharmony_ci Node* field = loaded_field.PhiAt(0); 54611cb0ef41Sopenharmony_ci // We may have transitioned in-place away from double, so check that 54621cb0ef41Sopenharmony_ci // this is a HeapNumber -- otherwise the load is fine and we don't need 54631cb0ef41Sopenharmony_ci // to copy anything anyway. 54641cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(field), &done, field); 54651cb0ef41Sopenharmony_ci Node* field_map = __ LoadField(AccessBuilder::ForMap(), field); 54661cb0ef41Sopenharmony_ci __ GotoIfNot(__ TaggedEqual(field_map, __ HeapNumberMapConstant()), &done, 54671cb0ef41Sopenharmony_ci field); 54681cb0ef41Sopenharmony_ci 54691cb0ef41Sopenharmony_ci Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), field); 54701cb0ef41Sopenharmony_ci __ Goto(&done_double, value); 54711cb0ef41Sopenharmony_ci } 54721cb0ef41Sopenharmony_ci 54731cb0ef41Sopenharmony_ci __ Bind(&done_double); 54741cb0ef41Sopenharmony_ci { 54751cb0ef41Sopenharmony_ci Node* result = AllocateHeapNumberWithValue(done_double.PhiAt(0)); 54761cb0ef41Sopenharmony_ci __ Goto(&done, result); 54771cb0ef41Sopenharmony_ci } 54781cb0ef41Sopenharmony_ci 54791cb0ef41Sopenharmony_ci __ Bind(&done); 54801cb0ef41Sopenharmony_ci return done.PhiAt(0); 54811cb0ef41Sopenharmony_ci} 54821cb0ef41Sopenharmony_ci 54831cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildReverseBytes(ExternalArrayType type, 54841cb0ef41Sopenharmony_ci Node* value) { 54851cb0ef41Sopenharmony_ci switch (type) { 54861cb0ef41Sopenharmony_ci case kExternalInt8Array: 54871cb0ef41Sopenharmony_ci case kExternalUint8Array: 54881cb0ef41Sopenharmony_ci case kExternalUint8ClampedArray: 54891cb0ef41Sopenharmony_ci return value; 54901cb0ef41Sopenharmony_ci 54911cb0ef41Sopenharmony_ci case kExternalInt16Array: { 54921cb0ef41Sopenharmony_ci Node* result = __ Word32ReverseBytes(value); 54931cb0ef41Sopenharmony_ci result = __ Word32Sar(result, __ Int32Constant(16)); 54941cb0ef41Sopenharmony_ci return result; 54951cb0ef41Sopenharmony_ci } 54961cb0ef41Sopenharmony_ci 54971cb0ef41Sopenharmony_ci case kExternalUint16Array: { 54981cb0ef41Sopenharmony_ci Node* result = __ Word32ReverseBytes(value); 54991cb0ef41Sopenharmony_ci result = __ Word32Shr(result, __ Int32Constant(16)); 55001cb0ef41Sopenharmony_ci return result; 55011cb0ef41Sopenharmony_ci } 55021cb0ef41Sopenharmony_ci 55031cb0ef41Sopenharmony_ci case kExternalInt32Array: // Fall through. 55041cb0ef41Sopenharmony_ci case kExternalUint32Array: 55051cb0ef41Sopenharmony_ci return __ Word32ReverseBytes(value); 55061cb0ef41Sopenharmony_ci 55071cb0ef41Sopenharmony_ci case kExternalFloat32Array: { 55081cb0ef41Sopenharmony_ci Node* result = __ BitcastFloat32ToInt32(value); 55091cb0ef41Sopenharmony_ci result = __ Word32ReverseBytes(result); 55101cb0ef41Sopenharmony_ci result = __ BitcastInt32ToFloat32(result); 55111cb0ef41Sopenharmony_ci return result; 55121cb0ef41Sopenharmony_ci } 55131cb0ef41Sopenharmony_ci 55141cb0ef41Sopenharmony_ci case kExternalFloat64Array: { 55151cb0ef41Sopenharmony_ci if (machine()->Is64()) { 55161cb0ef41Sopenharmony_ci Node* result = __ BitcastFloat64ToInt64(value); 55171cb0ef41Sopenharmony_ci result = __ Word64ReverseBytes(result); 55181cb0ef41Sopenharmony_ci result = __ BitcastInt64ToFloat64(result); 55191cb0ef41Sopenharmony_ci return result; 55201cb0ef41Sopenharmony_ci } else { 55211cb0ef41Sopenharmony_ci Node* lo = __ Word32ReverseBytes(__ Float64ExtractLowWord32(value)); 55221cb0ef41Sopenharmony_ci Node* hi = __ Word32ReverseBytes(__ Float64ExtractHighWord32(value)); 55231cb0ef41Sopenharmony_ci Node* result = __ Float64Constant(0.0); 55241cb0ef41Sopenharmony_ci result = __ Float64InsertLowWord32(result, hi); 55251cb0ef41Sopenharmony_ci result = __ Float64InsertHighWord32(result, lo); 55261cb0ef41Sopenharmony_ci return result; 55271cb0ef41Sopenharmony_ci } 55281cb0ef41Sopenharmony_ci } 55291cb0ef41Sopenharmony_ci 55301cb0ef41Sopenharmony_ci case kExternalBigInt64Array: 55311cb0ef41Sopenharmony_ci case kExternalBigUint64Array: 55321cb0ef41Sopenharmony_ci UNREACHABLE(); 55331cb0ef41Sopenharmony_ci } 55341cb0ef41Sopenharmony_ci} 55351cb0ef41Sopenharmony_ci 55361cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerLoadDataViewElement(Node* node) { 55371cb0ef41Sopenharmony_ci ExternalArrayType element_type = ExternalArrayTypeOf(node->op()); 55381cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 55391cb0ef41Sopenharmony_ci Node* storage = node->InputAt(1); 55401cb0ef41Sopenharmony_ci Node* index = node->InputAt(2); 55411cb0ef41Sopenharmony_ci Node* is_little_endian = node->InputAt(3); 55421cb0ef41Sopenharmony_ci 55431cb0ef41Sopenharmony_ci // We need to keep the {object} (either the JSArrayBuffer or the JSDataView) 55441cb0ef41Sopenharmony_ci // alive so that the GC will not release the JSArrayBuffer (if there's any) 55451cb0ef41Sopenharmony_ci // as long as we are still operating on it. 55461cb0ef41Sopenharmony_ci __ Retain(object); 55471cb0ef41Sopenharmony_ci 55481cb0ef41Sopenharmony_ci MachineType const machine_type = 55491cb0ef41Sopenharmony_ci AccessBuilder::ForTypedArrayElement(element_type, true).machine_type; 55501cb0ef41Sopenharmony_ci 55511cb0ef41Sopenharmony_ci Node* value = __ LoadUnaligned(machine_type, storage, index); 55521cb0ef41Sopenharmony_ci auto big_endian = __ MakeLabel(); 55531cb0ef41Sopenharmony_ci auto done = __ MakeLabel(machine_type.representation()); 55541cb0ef41Sopenharmony_ci 55551cb0ef41Sopenharmony_ci __ GotoIfNot(is_little_endian, &big_endian); 55561cb0ef41Sopenharmony_ci { // Little-endian load. 55571cb0ef41Sopenharmony_ci#if V8_TARGET_LITTLE_ENDIAN 55581cb0ef41Sopenharmony_ci __ Goto(&done, value); 55591cb0ef41Sopenharmony_ci#else 55601cb0ef41Sopenharmony_ci __ Goto(&done, BuildReverseBytes(element_type, value)); 55611cb0ef41Sopenharmony_ci#endif // V8_TARGET_LITTLE_ENDIAN 55621cb0ef41Sopenharmony_ci } 55631cb0ef41Sopenharmony_ci 55641cb0ef41Sopenharmony_ci __ Bind(&big_endian); 55651cb0ef41Sopenharmony_ci { // Big-endian load. 55661cb0ef41Sopenharmony_ci#if V8_TARGET_LITTLE_ENDIAN 55671cb0ef41Sopenharmony_ci __ Goto(&done, BuildReverseBytes(element_type, value)); 55681cb0ef41Sopenharmony_ci#else 55691cb0ef41Sopenharmony_ci __ Goto(&done, value); 55701cb0ef41Sopenharmony_ci#endif // V8_TARGET_LITTLE_ENDIAN 55711cb0ef41Sopenharmony_ci } 55721cb0ef41Sopenharmony_ci 55731cb0ef41Sopenharmony_ci // We're done, return {result}. 55741cb0ef41Sopenharmony_ci __ Bind(&done); 55751cb0ef41Sopenharmony_ci return done.PhiAt(0); 55761cb0ef41Sopenharmony_ci} 55771cb0ef41Sopenharmony_ci 55781cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerStoreDataViewElement(Node* node) { 55791cb0ef41Sopenharmony_ci ExternalArrayType element_type = ExternalArrayTypeOf(node->op()); 55801cb0ef41Sopenharmony_ci Node* object = node->InputAt(0); 55811cb0ef41Sopenharmony_ci Node* storage = node->InputAt(1); 55821cb0ef41Sopenharmony_ci Node* index = node->InputAt(2); 55831cb0ef41Sopenharmony_ci Node* value = node->InputAt(3); 55841cb0ef41Sopenharmony_ci Node* is_little_endian = node->InputAt(4); 55851cb0ef41Sopenharmony_ci 55861cb0ef41Sopenharmony_ci // We need to keep the {object} (either the JSArrayBuffer or the JSDataView) 55871cb0ef41Sopenharmony_ci // alive so that the GC will not release the JSArrayBuffer (if there's any) 55881cb0ef41Sopenharmony_ci // as long as we are still operating on it. 55891cb0ef41Sopenharmony_ci __ Retain(object); 55901cb0ef41Sopenharmony_ci 55911cb0ef41Sopenharmony_ci MachineType const machine_type = 55921cb0ef41Sopenharmony_ci AccessBuilder::ForTypedArrayElement(element_type, true).machine_type; 55931cb0ef41Sopenharmony_ci 55941cb0ef41Sopenharmony_ci auto big_endian = __ MakeLabel(); 55951cb0ef41Sopenharmony_ci auto done = __ MakeLabel(machine_type.representation()); 55961cb0ef41Sopenharmony_ci 55971cb0ef41Sopenharmony_ci __ GotoIfNot(is_little_endian, &big_endian); 55981cb0ef41Sopenharmony_ci { // Little-endian store. 55991cb0ef41Sopenharmony_ci#if V8_TARGET_LITTLE_ENDIAN 56001cb0ef41Sopenharmony_ci __ Goto(&done, value); 56011cb0ef41Sopenharmony_ci#else 56021cb0ef41Sopenharmony_ci __ Goto(&done, BuildReverseBytes(element_type, value)); 56031cb0ef41Sopenharmony_ci#endif // V8_TARGET_LITTLE_ENDIAN 56041cb0ef41Sopenharmony_ci } 56051cb0ef41Sopenharmony_ci 56061cb0ef41Sopenharmony_ci __ Bind(&big_endian); 56071cb0ef41Sopenharmony_ci { // Big-endian store. 56081cb0ef41Sopenharmony_ci#if V8_TARGET_LITTLE_ENDIAN 56091cb0ef41Sopenharmony_ci __ Goto(&done, BuildReverseBytes(element_type, value)); 56101cb0ef41Sopenharmony_ci#else 56111cb0ef41Sopenharmony_ci __ Goto(&done, value); 56121cb0ef41Sopenharmony_ci#endif // V8_TARGET_LITTLE_ENDIAN 56131cb0ef41Sopenharmony_ci } 56141cb0ef41Sopenharmony_ci 56151cb0ef41Sopenharmony_ci __ Bind(&done); 56161cb0ef41Sopenharmony_ci __ StoreUnaligned(machine_type.representation(), storage, index, 56171cb0ef41Sopenharmony_ci done.PhiAt(0)); 56181cb0ef41Sopenharmony_ci} 56191cb0ef41Sopenharmony_ci 56201cb0ef41Sopenharmony_ci// Compute the data pointer, handling the case where the {external} pointer 56211cb0ef41Sopenharmony_ci// is the effective data pointer (i.e. the {base} is Smi zero). 56221cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildTypedArrayDataPointer(Node* base, 56231cb0ef41Sopenharmony_ci Node* external) { 56241cb0ef41Sopenharmony_ci if (IntPtrMatcher(base).Is(0)) { 56251cb0ef41Sopenharmony_ci return external; 56261cb0ef41Sopenharmony_ci } else { 56271cb0ef41Sopenharmony_ci if (COMPRESS_POINTERS_BOOL) { 56281cb0ef41Sopenharmony_ci base = __ BitcastTaggedToWord(base); 56291cb0ef41Sopenharmony_ci // Zero-extend Tagged_t to UintPtr according to current compression 56301cb0ef41Sopenharmony_ci // scheme so that the addition with |external_pointer| (which already 56311cb0ef41Sopenharmony_ci // contains compensated offset value) will decompress the tagged value. 56321cb0ef41Sopenharmony_ci // See JSTypedArray::ExternalPointerCompensationForOnHeapArray() for 56331cb0ef41Sopenharmony_ci // details. 56341cb0ef41Sopenharmony_ci base = ChangeUint32ToUintPtr(base); 56351cb0ef41Sopenharmony_ci } 56361cb0ef41Sopenharmony_ci return __ UnsafePointerAdd(base, external); 56371cb0ef41Sopenharmony_ci } 56381cb0ef41Sopenharmony_ci} 56391cb0ef41Sopenharmony_ci 56401cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerLoadTypedElement(Node* node) { 56411cb0ef41Sopenharmony_ci ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); 56421cb0ef41Sopenharmony_ci Node* buffer = node->InputAt(0); 56431cb0ef41Sopenharmony_ci Node* base = node->InputAt(1); 56441cb0ef41Sopenharmony_ci Node* external = node->InputAt(2); 56451cb0ef41Sopenharmony_ci Node* index = node->InputAt(3); 56461cb0ef41Sopenharmony_ci 56471cb0ef41Sopenharmony_ci // We need to keep the {buffer} alive so that the GC will not release the 56481cb0ef41Sopenharmony_ci // ArrayBuffer (if there's any) as long as we are still operating on it. 56491cb0ef41Sopenharmony_ci __ Retain(buffer); 56501cb0ef41Sopenharmony_ci 56511cb0ef41Sopenharmony_ci Node* data_ptr = BuildTypedArrayDataPointer(base, external); 56521cb0ef41Sopenharmony_ci 56531cb0ef41Sopenharmony_ci // Perform the actual typed element access. 56541cb0ef41Sopenharmony_ci return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true), 56551cb0ef41Sopenharmony_ci data_ptr, index); 56561cb0ef41Sopenharmony_ci} 56571cb0ef41Sopenharmony_ci 56581cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerLoadStackArgument(Node* node) { 56591cb0ef41Sopenharmony_ci Node* base = node->InputAt(0); 56601cb0ef41Sopenharmony_ci Node* index = node->InputAt(1); 56611cb0ef41Sopenharmony_ci 56621cb0ef41Sopenharmony_ci Node* argument = 56631cb0ef41Sopenharmony_ci __ LoadElement(AccessBuilder::ForStackArgument(), base, index); 56641cb0ef41Sopenharmony_ci 56651cb0ef41Sopenharmony_ci return __ BitcastWordToTagged(argument); 56661cb0ef41Sopenharmony_ci} 56671cb0ef41Sopenharmony_ci 56681cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerStoreTypedElement(Node* node) { 56691cb0ef41Sopenharmony_ci ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); 56701cb0ef41Sopenharmony_ci Node* buffer = node->InputAt(0); 56711cb0ef41Sopenharmony_ci Node* base = node->InputAt(1); 56721cb0ef41Sopenharmony_ci Node* external = node->InputAt(2); 56731cb0ef41Sopenharmony_ci Node* index = node->InputAt(3); 56741cb0ef41Sopenharmony_ci Node* value = node->InputAt(4); 56751cb0ef41Sopenharmony_ci 56761cb0ef41Sopenharmony_ci // We need to keep the {buffer} alive so that the GC will not release the 56771cb0ef41Sopenharmony_ci // ArrayBuffer (if there's any) as long as we are still operating on it. 56781cb0ef41Sopenharmony_ci __ Retain(buffer); 56791cb0ef41Sopenharmony_ci 56801cb0ef41Sopenharmony_ci Node* data_ptr = BuildTypedArrayDataPointer(base, external); 56811cb0ef41Sopenharmony_ci 56821cb0ef41Sopenharmony_ci // Perform the actual typed element access. 56831cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true), 56841cb0ef41Sopenharmony_ci data_ptr, index, value); 56851cb0ef41Sopenharmony_ci} 56861cb0ef41Sopenharmony_ci 56871cb0ef41Sopenharmony_civoid EffectControlLinearizer::TransitionElementsTo(Node* node, Node* array, 56881cb0ef41Sopenharmony_ci ElementsKind from, 56891cb0ef41Sopenharmony_ci ElementsKind to) { 56901cb0ef41Sopenharmony_ci DCHECK(IsMoreGeneralElementsKindTransition(from, to)); 56911cb0ef41Sopenharmony_ci DCHECK(to == HOLEY_ELEMENTS || to == HOLEY_DOUBLE_ELEMENTS); 56921cb0ef41Sopenharmony_ci 56931cb0ef41Sopenharmony_ci Handle<Map> target(to == HOLEY_ELEMENTS ? FastMapParameterOf(node->op()) 56941cb0ef41Sopenharmony_ci : DoubleMapParameterOf(node->op())); 56951cb0ef41Sopenharmony_ci Node* target_map = __ HeapConstant(target); 56961cb0ef41Sopenharmony_ci 56971cb0ef41Sopenharmony_ci if (IsSimpleMapChangeTransition(from, to)) { 56981cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), array, target_map); 56991cb0ef41Sopenharmony_ci } else { 57001cb0ef41Sopenharmony_ci // Instance migration, call out to the runtime for {array}. 57011cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 57021cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kTransitionElementsKind; 57031cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 57041cb0ef41Sopenharmony_ci graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); 57051cb0ef41Sopenharmony_ci __ Call(call_descriptor, __ CEntryStubConstant(1), array, target_map, 57061cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 57071cb0ef41Sopenharmony_ci __ Int32Constant(2), __ NoContextConstant()); 57081cb0ef41Sopenharmony_ci } 57091cb0ef41Sopenharmony_ci} 57101cb0ef41Sopenharmony_ci 57111cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::IsElementsKindGreaterThan( 57121cb0ef41Sopenharmony_ci Node* kind, ElementsKind reference_kind) { 57131cb0ef41Sopenharmony_ci Node* ref_kind = __ Int32Constant(reference_kind); 57141cb0ef41Sopenharmony_ci Node* ret = __ Int32LessThan(ref_kind, kind); 57151cb0ef41Sopenharmony_ci return ret; 57161cb0ef41Sopenharmony_ci} 57171cb0ef41Sopenharmony_ci 57181cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerTransitionAndStoreElement(Node* node) { 57191cb0ef41Sopenharmony_ci Node* array = node->InputAt(0); 57201cb0ef41Sopenharmony_ci Node* index = node->InputAt(1); 57211cb0ef41Sopenharmony_ci Node* value = node->InputAt(2); 57221cb0ef41Sopenharmony_ci 57231cb0ef41Sopenharmony_ci // Possibly transition array based on input and store. 57241cb0ef41Sopenharmony_ci // 57251cb0ef41Sopenharmony_ci // -- TRANSITION PHASE ----------------- 57261cb0ef41Sopenharmony_ci // kind = ElementsKind(array) 57271cb0ef41Sopenharmony_ci // if value is not smi { 57281cb0ef41Sopenharmony_ci // if kind == HOLEY_SMI_ELEMENTS { 57291cb0ef41Sopenharmony_ci // if value is heap number { 57301cb0ef41Sopenharmony_ci // Transition array to HOLEY_DOUBLE_ELEMENTS 57311cb0ef41Sopenharmony_ci // kind = HOLEY_DOUBLE_ELEMENTS 57321cb0ef41Sopenharmony_ci // } else { 57331cb0ef41Sopenharmony_ci // Transition array to HOLEY_ELEMENTS 57341cb0ef41Sopenharmony_ci // kind = HOLEY_ELEMENTS 57351cb0ef41Sopenharmony_ci // } 57361cb0ef41Sopenharmony_ci // } else if kind == HOLEY_DOUBLE_ELEMENTS { 57371cb0ef41Sopenharmony_ci // if value is not heap number { 57381cb0ef41Sopenharmony_ci // Transition array to HOLEY_ELEMENTS 57391cb0ef41Sopenharmony_ci // kind = HOLEY_ELEMENTS 57401cb0ef41Sopenharmony_ci // } 57411cb0ef41Sopenharmony_ci // } 57421cb0ef41Sopenharmony_ci // } 57431cb0ef41Sopenharmony_ci // 57441cb0ef41Sopenharmony_ci // -- STORE PHASE ---------------------- 57451cb0ef41Sopenharmony_ci // [make sure {kind} is up-to-date] 57461cb0ef41Sopenharmony_ci // if kind == HOLEY_DOUBLE_ELEMENTS { 57471cb0ef41Sopenharmony_ci // if value is smi { 57481cb0ef41Sopenharmony_ci // float_value = convert smi to float 57491cb0ef41Sopenharmony_ci // Store array[index] = float_value 57501cb0ef41Sopenharmony_ci // } else { 57511cb0ef41Sopenharmony_ci // float_value = value 57521cb0ef41Sopenharmony_ci // Store array[index] = float_value 57531cb0ef41Sopenharmony_ci // } 57541cb0ef41Sopenharmony_ci // } else { 57551cb0ef41Sopenharmony_ci // // kind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS 57561cb0ef41Sopenharmony_ci // Store array[index] = value 57571cb0ef41Sopenharmony_ci // } 57581cb0ef41Sopenharmony_ci // 57591cb0ef41Sopenharmony_ci Node* map = __ LoadField(AccessBuilder::ForMap(), array); 57601cb0ef41Sopenharmony_ci Node* kind; 57611cb0ef41Sopenharmony_ci { 57621cb0ef41Sopenharmony_ci Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map); 57631cb0ef41Sopenharmony_ci Node* mask = __ Int32Constant(Map::Bits2::ElementsKindBits::kMask); 57641cb0ef41Sopenharmony_ci Node* andit = __ Word32And(bit_field2, mask); 57651cb0ef41Sopenharmony_ci Node* shift = __ Int32Constant(Map::Bits2::ElementsKindBits::kShift); 57661cb0ef41Sopenharmony_ci kind = __ Word32Shr(andit, shift); 57671cb0ef41Sopenharmony_ci } 57681cb0ef41Sopenharmony_ci 57691cb0ef41Sopenharmony_ci auto do_store = __ MakeLabel(MachineRepresentation::kWord32); 57701cb0ef41Sopenharmony_ci // We can store a smi anywhere. 57711cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &do_store, kind); 57721cb0ef41Sopenharmony_ci 57731cb0ef41Sopenharmony_ci // {value} is a HeapObject. 57741cb0ef41Sopenharmony_ci auto transition_smi_array = __ MakeDeferredLabel(); 57751cb0ef41Sopenharmony_ci auto transition_double_to_fast = __ MakeDeferredLabel(); 57761cb0ef41Sopenharmony_ci { 57771cb0ef41Sopenharmony_ci __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), 57781cb0ef41Sopenharmony_ci &transition_smi_array); 57791cb0ef41Sopenharmony_ci __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &do_store, 57801cb0ef41Sopenharmony_ci kind); 57811cb0ef41Sopenharmony_ci 57821cb0ef41Sopenharmony_ci // We have double elements kind. Only a HeapNumber can be stored 57831cb0ef41Sopenharmony_ci // without effecting a transition. 57841cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 57851cb0ef41Sopenharmony_ci Node* heap_number_map = __ HeapNumberMapConstant(); 57861cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value_map, heap_number_map); 57871cb0ef41Sopenharmony_ci __ GotoIfNot(check, &transition_double_to_fast); 57881cb0ef41Sopenharmony_ci __ Goto(&do_store, kind); 57891cb0ef41Sopenharmony_ci } 57901cb0ef41Sopenharmony_ci 57911cb0ef41Sopenharmony_ci __ Bind(&transition_smi_array); // deferred code. 57921cb0ef41Sopenharmony_ci { 57931cb0ef41Sopenharmony_ci // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_DOUBLE_ELEMENTS or 57941cb0ef41Sopenharmony_ci // to HOLEY_ELEMENTS. 57951cb0ef41Sopenharmony_ci auto if_value_not_heap_number = __ MakeLabel(); 57961cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 57971cb0ef41Sopenharmony_ci Node* heap_number_map = __ HeapNumberMapConstant(); 57981cb0ef41Sopenharmony_ci Node* check = __ TaggedEqual(value_map, heap_number_map); 57991cb0ef41Sopenharmony_ci __ GotoIfNot(check, &if_value_not_heap_number); 58001cb0ef41Sopenharmony_ci { 58011cb0ef41Sopenharmony_ci // {value} is a HeapNumber. 58021cb0ef41Sopenharmony_ci TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, 58031cb0ef41Sopenharmony_ci HOLEY_DOUBLE_ELEMENTS); 58041cb0ef41Sopenharmony_ci __ Goto(&do_store, __ Int32Constant(HOLEY_DOUBLE_ELEMENTS)); 58051cb0ef41Sopenharmony_ci } 58061cb0ef41Sopenharmony_ci __ Bind(&if_value_not_heap_number); 58071cb0ef41Sopenharmony_ci { 58081cb0ef41Sopenharmony_ci TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS); 58091cb0ef41Sopenharmony_ci __ Goto(&do_store, __ Int32Constant(HOLEY_ELEMENTS)); 58101cb0ef41Sopenharmony_ci } 58111cb0ef41Sopenharmony_ci } 58121cb0ef41Sopenharmony_ci 58131cb0ef41Sopenharmony_ci __ Bind(&transition_double_to_fast); // deferred code. 58141cb0ef41Sopenharmony_ci { 58151cb0ef41Sopenharmony_ci TransitionElementsTo(node, array, HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS); 58161cb0ef41Sopenharmony_ci __ Goto(&do_store, __ Int32Constant(HOLEY_ELEMENTS)); 58171cb0ef41Sopenharmony_ci } 58181cb0ef41Sopenharmony_ci 58191cb0ef41Sopenharmony_ci // Make sure kind is up-to-date. 58201cb0ef41Sopenharmony_ci __ Bind(&do_store); 58211cb0ef41Sopenharmony_ci kind = do_store.PhiAt(0); 58221cb0ef41Sopenharmony_ci 58231cb0ef41Sopenharmony_ci Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array); 58241cb0ef41Sopenharmony_ci auto if_kind_is_double = __ MakeLabel(); 58251cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 58261cb0ef41Sopenharmony_ci __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), 58271cb0ef41Sopenharmony_ci &if_kind_is_double); 58281cb0ef41Sopenharmony_ci { 58291cb0ef41Sopenharmony_ci // Our ElementsKind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS. 58301cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForFixedArrayElement(HOLEY_ELEMENTS), 58311cb0ef41Sopenharmony_ci elements, index, value); 58321cb0ef41Sopenharmony_ci __ Goto(&done); 58331cb0ef41Sopenharmony_ci } 58341cb0ef41Sopenharmony_ci __ Bind(&if_kind_is_double); 58351cb0ef41Sopenharmony_ci { 58361cb0ef41Sopenharmony_ci // Our ElementsKind is HOLEY_DOUBLE_ELEMENTS. 58371cb0ef41Sopenharmony_ci auto do_double_store = __ MakeLabel(); 58381cb0ef41Sopenharmony_ci __ GotoIfNot(ObjectIsSmi(value), &do_double_store); 58391cb0ef41Sopenharmony_ci { 58401cb0ef41Sopenharmony_ci Node* int_value = ChangeSmiToInt32(value); 58411cb0ef41Sopenharmony_ci Node* float_value = __ ChangeInt32ToFloat64(int_value); 58421cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements, 58431cb0ef41Sopenharmony_ci index, float_value); 58441cb0ef41Sopenharmony_ci __ Goto(&done); 58451cb0ef41Sopenharmony_ci } 58461cb0ef41Sopenharmony_ci __ Bind(&do_double_store); 58471cb0ef41Sopenharmony_ci { 58481cb0ef41Sopenharmony_ci Node* float_value = 58491cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForHeapNumberValue(), value); 58501cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements, 58511cb0ef41Sopenharmony_ci index, __ Float64SilenceNaN(float_value)); 58521cb0ef41Sopenharmony_ci __ Goto(&done); 58531cb0ef41Sopenharmony_ci } 58541cb0ef41Sopenharmony_ci } 58551cb0ef41Sopenharmony_ci 58561cb0ef41Sopenharmony_ci __ Bind(&done); 58571cb0ef41Sopenharmony_ci} 58581cb0ef41Sopenharmony_ci 58591cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerTransitionAndStoreNumberElement(Node* node) { 58601cb0ef41Sopenharmony_ci Node* array = node->InputAt(0); 58611cb0ef41Sopenharmony_ci Node* index = node->InputAt(1); 58621cb0ef41Sopenharmony_ci Node* value = node->InputAt(2); // This is a Float64, not tagged. 58631cb0ef41Sopenharmony_ci 58641cb0ef41Sopenharmony_ci // Possibly transition array based on input and store. 58651cb0ef41Sopenharmony_ci // 58661cb0ef41Sopenharmony_ci // -- TRANSITION PHASE ----------------- 58671cb0ef41Sopenharmony_ci // kind = ElementsKind(array) 58681cb0ef41Sopenharmony_ci // if kind == HOLEY_SMI_ELEMENTS { 58691cb0ef41Sopenharmony_ci // Transition array to HOLEY_DOUBLE_ELEMENTS 58701cb0ef41Sopenharmony_ci // } else if kind != HOLEY_DOUBLE_ELEMENTS { 58711cb0ef41Sopenharmony_ci // This is UNREACHABLE, execute a debug break. 58721cb0ef41Sopenharmony_ci // } 58731cb0ef41Sopenharmony_ci // 58741cb0ef41Sopenharmony_ci // -- STORE PHASE ---------------------- 58751cb0ef41Sopenharmony_ci // Store array[index] = value (it's a float) 58761cb0ef41Sopenharmony_ci // 58771cb0ef41Sopenharmony_ci Node* map = __ LoadField(AccessBuilder::ForMap(), array); 58781cb0ef41Sopenharmony_ci Node* kind; 58791cb0ef41Sopenharmony_ci { 58801cb0ef41Sopenharmony_ci Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map); 58811cb0ef41Sopenharmony_ci Node* mask = __ Int32Constant(Map::Bits2::ElementsKindBits::kMask); 58821cb0ef41Sopenharmony_ci Node* andit = __ Word32And(bit_field2, mask); 58831cb0ef41Sopenharmony_ci Node* shift = __ Int32Constant(Map::Bits2::ElementsKindBits::kShift); 58841cb0ef41Sopenharmony_ci kind = __ Word32Shr(andit, shift); 58851cb0ef41Sopenharmony_ci } 58861cb0ef41Sopenharmony_ci 58871cb0ef41Sopenharmony_ci auto do_store = __ MakeLabel(); 58881cb0ef41Sopenharmony_ci 58891cb0ef41Sopenharmony_ci // {value} is a float64. 58901cb0ef41Sopenharmony_ci auto transition_smi_array = __ MakeDeferredLabel(); 58911cb0ef41Sopenharmony_ci { 58921cb0ef41Sopenharmony_ci __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), 58931cb0ef41Sopenharmony_ci &transition_smi_array); 58941cb0ef41Sopenharmony_ci // We expect that our input array started at HOLEY_SMI_ELEMENTS, and 58951cb0ef41Sopenharmony_ci // climbs the lattice up to HOLEY_DOUBLE_ELEMENTS. Force a debug break 58961cb0ef41Sopenharmony_ci // if this assumption is broken. It also would be the case that 58971cb0ef41Sopenharmony_ci // loop peeling can break this assumption. 58981cb0ef41Sopenharmony_ci __ GotoIf(__ Word32Equal(kind, __ Int32Constant(HOLEY_DOUBLE_ELEMENTS)), 58991cb0ef41Sopenharmony_ci &do_store); 59001cb0ef41Sopenharmony_ci __ Unreachable(&do_store); 59011cb0ef41Sopenharmony_ci } 59021cb0ef41Sopenharmony_ci 59031cb0ef41Sopenharmony_ci __ Bind(&transition_smi_array); // deferred code. 59041cb0ef41Sopenharmony_ci { 59051cb0ef41Sopenharmony_ci // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_DOUBLE_ELEMENTS. 59061cb0ef41Sopenharmony_ci TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, 59071cb0ef41Sopenharmony_ci HOLEY_DOUBLE_ELEMENTS); 59081cb0ef41Sopenharmony_ci __ Goto(&do_store); 59091cb0ef41Sopenharmony_ci } 59101cb0ef41Sopenharmony_ci 59111cb0ef41Sopenharmony_ci __ Bind(&do_store); 59121cb0ef41Sopenharmony_ci 59131cb0ef41Sopenharmony_ci Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array); 59141cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements, index, 59151cb0ef41Sopenharmony_ci __ Float64SilenceNaN(value)); 59161cb0ef41Sopenharmony_ci} 59171cb0ef41Sopenharmony_ci 59181cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerTransitionAndStoreNonNumberElement( 59191cb0ef41Sopenharmony_ci Node* node) { 59201cb0ef41Sopenharmony_ci Node* array = node->InputAt(0); 59211cb0ef41Sopenharmony_ci Node* index = node->InputAt(1); 59221cb0ef41Sopenharmony_ci Node* value = node->InputAt(2); 59231cb0ef41Sopenharmony_ci 59241cb0ef41Sopenharmony_ci // Possibly transition array based on input and store. 59251cb0ef41Sopenharmony_ci // 59261cb0ef41Sopenharmony_ci // -- TRANSITION PHASE ----------------- 59271cb0ef41Sopenharmony_ci // kind = ElementsKind(array) 59281cb0ef41Sopenharmony_ci // if kind == HOLEY_SMI_ELEMENTS { 59291cb0ef41Sopenharmony_ci // Transition array to HOLEY_ELEMENTS 59301cb0ef41Sopenharmony_ci // } else if kind == HOLEY_DOUBLE_ELEMENTS { 59311cb0ef41Sopenharmony_ci // Transition array to HOLEY_ELEMENTS 59321cb0ef41Sopenharmony_ci // } 59331cb0ef41Sopenharmony_ci // 59341cb0ef41Sopenharmony_ci // -- STORE PHASE ---------------------- 59351cb0ef41Sopenharmony_ci // // kind is HOLEY_ELEMENTS 59361cb0ef41Sopenharmony_ci // Store array[index] = value 59371cb0ef41Sopenharmony_ci // 59381cb0ef41Sopenharmony_ci Node* map = __ LoadField(AccessBuilder::ForMap(), array); 59391cb0ef41Sopenharmony_ci Node* kind; 59401cb0ef41Sopenharmony_ci { 59411cb0ef41Sopenharmony_ci Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map); 59421cb0ef41Sopenharmony_ci Node* mask = __ Int32Constant(Map::Bits2::ElementsKindBits::kMask); 59431cb0ef41Sopenharmony_ci Node* andit = __ Word32And(bit_field2, mask); 59441cb0ef41Sopenharmony_ci Node* shift = __ Int32Constant(Map::Bits2::ElementsKindBits::kShift); 59451cb0ef41Sopenharmony_ci kind = __ Word32Shr(andit, shift); 59461cb0ef41Sopenharmony_ci } 59471cb0ef41Sopenharmony_ci 59481cb0ef41Sopenharmony_ci auto do_store = __ MakeLabel(); 59491cb0ef41Sopenharmony_ci 59501cb0ef41Sopenharmony_ci auto transition_smi_array = __ MakeDeferredLabel(); 59511cb0ef41Sopenharmony_ci auto transition_double_to_fast = __ MakeDeferredLabel(); 59521cb0ef41Sopenharmony_ci { 59531cb0ef41Sopenharmony_ci __ GotoIfNot(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), 59541cb0ef41Sopenharmony_ci &transition_smi_array); 59551cb0ef41Sopenharmony_ci __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), 59561cb0ef41Sopenharmony_ci &transition_double_to_fast); 59571cb0ef41Sopenharmony_ci __ Goto(&do_store); 59581cb0ef41Sopenharmony_ci } 59591cb0ef41Sopenharmony_ci 59601cb0ef41Sopenharmony_ci __ Bind(&transition_smi_array); // deferred code. 59611cb0ef41Sopenharmony_ci { 59621cb0ef41Sopenharmony_ci // Transition {array} from HOLEY_SMI_ELEMENTS to HOLEY_ELEMENTS. 59631cb0ef41Sopenharmony_ci TransitionElementsTo(node, array, HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS); 59641cb0ef41Sopenharmony_ci __ Goto(&do_store); 59651cb0ef41Sopenharmony_ci } 59661cb0ef41Sopenharmony_ci 59671cb0ef41Sopenharmony_ci __ Bind(&transition_double_to_fast); // deferred code. 59681cb0ef41Sopenharmony_ci { 59691cb0ef41Sopenharmony_ci TransitionElementsTo(node, array, HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS); 59701cb0ef41Sopenharmony_ci __ Goto(&do_store); 59711cb0ef41Sopenharmony_ci } 59721cb0ef41Sopenharmony_ci 59731cb0ef41Sopenharmony_ci __ Bind(&do_store); 59741cb0ef41Sopenharmony_ci 59751cb0ef41Sopenharmony_ci Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array); 59761cb0ef41Sopenharmony_ci // Our ElementsKind is HOLEY_ELEMENTS. 59771cb0ef41Sopenharmony_ci ElementAccess access = AccessBuilder::ForFixedArrayElement(HOLEY_ELEMENTS); 59781cb0ef41Sopenharmony_ci Type value_type = ValueTypeParameterOf(node->op()); 59791cb0ef41Sopenharmony_ci if (value_type.Is(Type::BooleanOrNullOrUndefined())) { 59801cb0ef41Sopenharmony_ci access.type = value_type; 59811cb0ef41Sopenharmony_ci access.write_barrier_kind = kNoWriteBarrier; 59821cb0ef41Sopenharmony_ci } 59831cb0ef41Sopenharmony_ci __ StoreElement(access, elements, index, value); 59841cb0ef41Sopenharmony_ci} 59851cb0ef41Sopenharmony_ci 59861cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerStoreSignedSmallElement(Node* node) { 59871cb0ef41Sopenharmony_ci Node* array = node->InputAt(0); 59881cb0ef41Sopenharmony_ci Node* index = node->InputAt(1); 59891cb0ef41Sopenharmony_ci Node* value = node->InputAt(2); // int32 59901cb0ef41Sopenharmony_ci 59911cb0ef41Sopenharmony_ci // Store a signed small in an output array. 59921cb0ef41Sopenharmony_ci // 59931cb0ef41Sopenharmony_ci // kind = ElementsKind(array) 59941cb0ef41Sopenharmony_ci // 59951cb0ef41Sopenharmony_ci // -- STORE PHASE ---------------------- 59961cb0ef41Sopenharmony_ci // if kind == HOLEY_DOUBLE_ELEMENTS { 59971cb0ef41Sopenharmony_ci // float_value = convert int32 to float 59981cb0ef41Sopenharmony_ci // Store array[index] = float_value 59991cb0ef41Sopenharmony_ci // } else { 60001cb0ef41Sopenharmony_ci // // kind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS 60011cb0ef41Sopenharmony_ci // smi_value = convert int32 to smi 60021cb0ef41Sopenharmony_ci // Store array[index] = smi_value 60031cb0ef41Sopenharmony_ci // } 60041cb0ef41Sopenharmony_ci // 60051cb0ef41Sopenharmony_ci Node* map = __ LoadField(AccessBuilder::ForMap(), array); 60061cb0ef41Sopenharmony_ci Node* kind; 60071cb0ef41Sopenharmony_ci { 60081cb0ef41Sopenharmony_ci Node* bit_field2 = __ LoadField(AccessBuilder::ForMapBitField2(), map); 60091cb0ef41Sopenharmony_ci Node* mask = __ Int32Constant(Map::Bits2::ElementsKindBits::kMask); 60101cb0ef41Sopenharmony_ci Node* andit = __ Word32And(bit_field2, mask); 60111cb0ef41Sopenharmony_ci Node* shift = __ Int32Constant(Map::Bits2::ElementsKindBits::kShift); 60121cb0ef41Sopenharmony_ci kind = __ Word32Shr(andit, shift); 60131cb0ef41Sopenharmony_ci } 60141cb0ef41Sopenharmony_ci 60151cb0ef41Sopenharmony_ci Node* elements = __ LoadField(AccessBuilder::ForJSObjectElements(), array); 60161cb0ef41Sopenharmony_ci auto if_kind_is_double = __ MakeLabel(); 60171cb0ef41Sopenharmony_ci auto done = __ MakeLabel(); 60181cb0ef41Sopenharmony_ci __ GotoIf(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), 60191cb0ef41Sopenharmony_ci &if_kind_is_double); 60201cb0ef41Sopenharmony_ci { 60211cb0ef41Sopenharmony_ci // Our ElementsKind is HOLEY_SMI_ELEMENTS or HOLEY_ELEMENTS. 60221cb0ef41Sopenharmony_ci // In this case, we know our value is a signed small, and we can optimize 60231cb0ef41Sopenharmony_ci // the ElementAccess information. 60241cb0ef41Sopenharmony_ci ElementAccess access = AccessBuilder::ForFixedArrayElement(); 60251cb0ef41Sopenharmony_ci access.type = Type::SignedSmall(); 60261cb0ef41Sopenharmony_ci access.machine_type = MachineType::TaggedSigned(); 60271cb0ef41Sopenharmony_ci access.write_barrier_kind = kNoWriteBarrier; 60281cb0ef41Sopenharmony_ci Node* smi_value = ChangeInt32ToSmi(value); 60291cb0ef41Sopenharmony_ci __ StoreElement(access, elements, index, smi_value); 60301cb0ef41Sopenharmony_ci __ Goto(&done); 60311cb0ef41Sopenharmony_ci } 60321cb0ef41Sopenharmony_ci __ Bind(&if_kind_is_double); 60331cb0ef41Sopenharmony_ci { 60341cb0ef41Sopenharmony_ci // Our ElementsKind is HOLEY_DOUBLE_ELEMENTS. 60351cb0ef41Sopenharmony_ci Node* float_value = __ ChangeInt32ToFloat64(value); 60361cb0ef41Sopenharmony_ci __ StoreElement(AccessBuilder::ForFixedDoubleArrayElement(), elements, 60371cb0ef41Sopenharmony_ci index, float_value); 60381cb0ef41Sopenharmony_ci __ Goto(&done); 60391cb0ef41Sopenharmony_ci } 60401cb0ef41Sopenharmony_ci 60411cb0ef41Sopenharmony_ci __ Bind(&done); 60421cb0ef41Sopenharmony_ci} 60431cb0ef41Sopenharmony_ci 60441cb0ef41Sopenharmony_civoid EffectControlLinearizer::LowerRuntimeAbort(Node* node) { 60451cb0ef41Sopenharmony_ci AbortReason reason = AbortReasonOf(node->op()); 60461cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 60471cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kAbort; 60481cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 60491cb0ef41Sopenharmony_ci graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); 60501cb0ef41Sopenharmony_ci __ Call(call_descriptor, __ CEntryStubConstant(1), 60511cb0ef41Sopenharmony_ci __ SmiConstant(static_cast<int>(reason)), 60521cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 60531cb0ef41Sopenharmony_ci __ Int32Constant(1), __ NoContextConstant()); 60541cb0ef41Sopenharmony_ci} 60551cb0ef41Sopenharmony_ci 60561cb0ef41Sopenharmony_citemplate <typename... Args> 60571cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::CallBuiltin(Builtin builtin, 60581cb0ef41Sopenharmony_ci Operator::Properties properties, 60591cb0ef41Sopenharmony_ci Args... args) { 60601cb0ef41Sopenharmony_ci Callable const callable = Builtins::CallableFor(isolate(), builtin); 60611cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 60621cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 60631cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags, 60641cb0ef41Sopenharmony_ci properties); 60651cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), args..., 60661cb0ef41Sopenharmony_ci __ NoContextConstant()); 60671cb0ef41Sopenharmony_ci} 60681cb0ef41Sopenharmony_ci 60691cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerAssertType(Node* node) { 60701cb0ef41Sopenharmony_ci DCHECK_EQ(node->opcode(), IrOpcode::kAssertType); 60711cb0ef41Sopenharmony_ci Type type = OpParameter<Type>(node->op()); 60721cb0ef41Sopenharmony_ci CHECK(type.CanBeAsserted()); 60731cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 60741cb0ef41Sopenharmony_ci Node* allocated_type; 60751cb0ef41Sopenharmony_ci { 60761cb0ef41Sopenharmony_ci DCHECK(isolate()->CurrentLocalHeap()->is_main_thread()); 60771cb0ef41Sopenharmony_ci base::Optional<UnparkedScope> unparked_scope; 60781cb0ef41Sopenharmony_ci if (isolate()->CurrentLocalHeap()->IsParked()) { 60791cb0ef41Sopenharmony_ci unparked_scope.emplace(isolate()->main_thread_local_isolate()); 60801cb0ef41Sopenharmony_ci } 60811cb0ef41Sopenharmony_ci allocated_type = __ HeapConstant(type.AllocateOnHeap(factory())); 60821cb0ef41Sopenharmony_ci } 60831cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kCheckTurbofanType, node->op()->properties(), input, 60841cb0ef41Sopenharmony_ci allocated_type, __ SmiConstant(node->id())); 60851cb0ef41Sopenharmony_ci return input; 60861cb0ef41Sopenharmony_ci} 60871cb0ef41Sopenharmony_ci 60881cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerFoldConstant(Node* node) { 60891cb0ef41Sopenharmony_ci DCHECK_EQ(node->opcode(), IrOpcode::kFoldConstant); 60901cb0ef41Sopenharmony_ci Node* original = node->InputAt(0); 60911cb0ef41Sopenharmony_ci Node* constant = node->InputAt(1); 60921cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kCheckSameObject, node->op()->properties(), original, 60931cb0ef41Sopenharmony_ci constant); 60941cb0ef41Sopenharmony_ci return constant; 60951cb0ef41Sopenharmony_ci} 60961cb0ef41Sopenharmony_ci 60971cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerConvertReceiver(Node* node) { 60981cb0ef41Sopenharmony_ci ConvertReceiverMode const mode = ConvertReceiverModeOf(node->op()); 60991cb0ef41Sopenharmony_ci Node* value = node->InputAt(0); 61001cb0ef41Sopenharmony_ci Node* global_proxy = node->InputAt(1); 61011cb0ef41Sopenharmony_ci 61021cb0ef41Sopenharmony_ci switch (mode) { 61031cb0ef41Sopenharmony_ci case ConvertReceiverMode::kNullOrUndefined: { 61041cb0ef41Sopenharmony_ci return global_proxy; 61051cb0ef41Sopenharmony_ci } 61061cb0ef41Sopenharmony_ci case ConvertReceiverMode::kNotNullOrUndefined: { 61071cb0ef41Sopenharmony_ci auto convert_to_object = __ MakeDeferredLabel(); 61081cb0ef41Sopenharmony_ci auto done_convert = __ MakeLabel(MachineRepresentation::kTagged); 61091cb0ef41Sopenharmony_ci 61101cb0ef41Sopenharmony_ci // Check if {value} is already a JSReceiver. 61111cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &convert_to_object); 61121cb0ef41Sopenharmony_ci STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 61131cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 61141cb0ef41Sopenharmony_ci Node* value_instance_type = 61151cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 61161cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThan( 61171cb0ef41Sopenharmony_ci value_instance_type, __ Uint32Constant(FIRST_JS_RECEIVER_TYPE)); 61181cb0ef41Sopenharmony_ci __ GotoIf(check, &convert_to_object); 61191cb0ef41Sopenharmony_ci __ Goto(&done_convert, value); 61201cb0ef41Sopenharmony_ci 61211cb0ef41Sopenharmony_ci // Wrap the primitive {value} into a JSPrimitiveWrapper. 61221cb0ef41Sopenharmony_ci __ Bind(&convert_to_object); 61231cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 61241cb0ef41Sopenharmony_ci Callable callable = Builtins::CallableFor(isolate(), Builtin::kToObject); 61251cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 61261cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 61271cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 61281cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 61291cb0ef41Sopenharmony_ci Node* native_context = __ LoadField( 61301cb0ef41Sopenharmony_ci AccessBuilder::ForJSGlobalProxyNativeContext(), global_proxy); 61311cb0ef41Sopenharmony_ci Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()), 61321cb0ef41Sopenharmony_ci value, native_context); 61331cb0ef41Sopenharmony_ci __ Goto(&done_convert, result); 61341cb0ef41Sopenharmony_ci 61351cb0ef41Sopenharmony_ci __ Bind(&done_convert); 61361cb0ef41Sopenharmony_ci return done_convert.PhiAt(0); 61371cb0ef41Sopenharmony_ci } 61381cb0ef41Sopenharmony_ci case ConvertReceiverMode::kAny: { 61391cb0ef41Sopenharmony_ci auto convert_to_object = __ MakeDeferredLabel(); 61401cb0ef41Sopenharmony_ci auto convert_global_proxy = __ MakeDeferredLabel(); 61411cb0ef41Sopenharmony_ci auto done_convert = __ MakeLabel(MachineRepresentation::kTagged); 61421cb0ef41Sopenharmony_ci 61431cb0ef41Sopenharmony_ci // Check if {value} is already a JSReceiver, or null/undefined. 61441cb0ef41Sopenharmony_ci __ GotoIf(ObjectIsSmi(value), &convert_to_object); 61451cb0ef41Sopenharmony_ci STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 61461cb0ef41Sopenharmony_ci Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); 61471cb0ef41Sopenharmony_ci Node* value_instance_type = 61481cb0ef41Sopenharmony_ci __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); 61491cb0ef41Sopenharmony_ci Node* check = __ Uint32LessThan( 61501cb0ef41Sopenharmony_ci value_instance_type, __ Uint32Constant(FIRST_JS_RECEIVER_TYPE)); 61511cb0ef41Sopenharmony_ci __ GotoIf(check, &convert_to_object); 61521cb0ef41Sopenharmony_ci __ Goto(&done_convert, value); 61531cb0ef41Sopenharmony_ci 61541cb0ef41Sopenharmony_ci // Wrap the primitive {value} into a JSPrimitiveWrapper. 61551cb0ef41Sopenharmony_ci __ Bind(&convert_to_object); 61561cb0ef41Sopenharmony_ci __ GotoIf(__ TaggedEqual(value, __ UndefinedConstant()), 61571cb0ef41Sopenharmony_ci &convert_global_proxy); 61581cb0ef41Sopenharmony_ci __ GotoIf(__ TaggedEqual(value, __ NullConstant()), 61591cb0ef41Sopenharmony_ci &convert_global_proxy); 61601cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kEliminatable; 61611cb0ef41Sopenharmony_ci Callable callable = Builtins::CallableFor(isolate(), Builtin::kToObject); 61621cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 61631cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 61641cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 61651cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 61661cb0ef41Sopenharmony_ci Node* native_context = __ LoadField( 61671cb0ef41Sopenharmony_ci AccessBuilder::ForJSGlobalProxyNativeContext(), global_proxy); 61681cb0ef41Sopenharmony_ci Node* result = __ Call(call_descriptor, __ HeapConstant(callable.code()), 61691cb0ef41Sopenharmony_ci value, native_context); 61701cb0ef41Sopenharmony_ci __ Goto(&done_convert, result); 61711cb0ef41Sopenharmony_ci 61721cb0ef41Sopenharmony_ci // Replace the {value} with the {global_proxy}. 61731cb0ef41Sopenharmony_ci __ Bind(&convert_global_proxy); 61741cb0ef41Sopenharmony_ci __ Goto(&done_convert, global_proxy); 61751cb0ef41Sopenharmony_ci 61761cb0ef41Sopenharmony_ci __ Bind(&done_convert); 61771cb0ef41Sopenharmony_ci return done_convert.PhiAt(0); 61781cb0ef41Sopenharmony_ci } 61791cb0ef41Sopenharmony_ci } 61801cb0ef41Sopenharmony_ci 61811cb0ef41Sopenharmony_ci UNREACHABLE(); 61821cb0ef41Sopenharmony_ci} 61831cb0ef41Sopenharmony_ci 61841cb0ef41Sopenharmony_ciMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) { 61851cb0ef41Sopenharmony_ci // Nothing to be done if a fast hardware instruction is available. 61861cb0ef41Sopenharmony_ci if (machine()->Float64RoundUp().IsSupported()) { 61871cb0ef41Sopenharmony_ci return Nothing<Node*>(); 61881cb0ef41Sopenharmony_ci } 61891cb0ef41Sopenharmony_ci 61901cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 61911cb0ef41Sopenharmony_ci 61921cb0ef41Sopenharmony_ci // General case for ceil. 61931cb0ef41Sopenharmony_ci // 61941cb0ef41Sopenharmony_ci // if 0.0 < input then 61951cb0ef41Sopenharmony_ci // if 2^52 <= input then 61961cb0ef41Sopenharmony_ci // input 61971cb0ef41Sopenharmony_ci // else 61981cb0ef41Sopenharmony_ci // let temp1 = (2^52 + input) - 2^52 in 61991cb0ef41Sopenharmony_ci // if temp1 < input then 62001cb0ef41Sopenharmony_ci // temp1 + 1 62011cb0ef41Sopenharmony_ci // else 62021cb0ef41Sopenharmony_ci // temp1 62031cb0ef41Sopenharmony_ci // else 62041cb0ef41Sopenharmony_ci // if input == 0 then 62051cb0ef41Sopenharmony_ci // input 62061cb0ef41Sopenharmony_ci // else 62071cb0ef41Sopenharmony_ci // if input <= -2^52 then 62081cb0ef41Sopenharmony_ci // input 62091cb0ef41Sopenharmony_ci // else 62101cb0ef41Sopenharmony_ci // let temp1 = -0 - input in 62111cb0ef41Sopenharmony_ci // let temp2 = (2^52 + temp1) - 2^52 in 62121cb0ef41Sopenharmony_ci // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in 62131cb0ef41Sopenharmony_ci // -0 - temp3 62141cb0ef41Sopenharmony_ci 62151cb0ef41Sopenharmony_ci auto if_not_positive = __ MakeDeferredLabel(); 62161cb0ef41Sopenharmony_ci auto if_greater_than_two_52 = __ MakeDeferredLabel(); 62171cb0ef41Sopenharmony_ci auto if_less_than_minus_two_52 = __ MakeDeferredLabel(); 62181cb0ef41Sopenharmony_ci auto if_zero = __ MakeDeferredLabel(); 62191cb0ef41Sopenharmony_ci auto done_temp3 = __ MakeLabel(MachineRepresentation::kFloat64); 62201cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kFloat64); 62211cb0ef41Sopenharmony_ci 62221cb0ef41Sopenharmony_ci Node* const zero = __ Float64Constant(0.0); 62231cb0ef41Sopenharmony_ci Node* const two_52 = __ Float64Constant(4503599627370496.0E0); 62241cb0ef41Sopenharmony_ci Node* const one = __ Float64Constant(1.0); 62251cb0ef41Sopenharmony_ci 62261cb0ef41Sopenharmony_ci Node* check0 = __ Float64LessThan(zero, input); 62271cb0ef41Sopenharmony_ci __ GotoIfNot(check0, &if_not_positive); 62281cb0ef41Sopenharmony_ci { 62291cb0ef41Sopenharmony_ci Node* check1 = __ Float64LessThanOrEqual(two_52, input); 62301cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_greater_than_two_52); 62311cb0ef41Sopenharmony_ci { 62321cb0ef41Sopenharmony_ci Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); 62331cb0ef41Sopenharmony_ci __ GotoIfNot(__ Float64LessThan(temp1, input), &done, temp1); 62341cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Add(temp1, one)); 62351cb0ef41Sopenharmony_ci } 62361cb0ef41Sopenharmony_ci 62371cb0ef41Sopenharmony_ci __ Bind(&if_greater_than_two_52); 62381cb0ef41Sopenharmony_ci __ Goto(&done, input); 62391cb0ef41Sopenharmony_ci } 62401cb0ef41Sopenharmony_ci 62411cb0ef41Sopenharmony_ci __ Bind(&if_not_positive); 62421cb0ef41Sopenharmony_ci { 62431cb0ef41Sopenharmony_ci Node* check1 = __ Float64Equal(input, zero); 62441cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_zero); 62451cb0ef41Sopenharmony_ci 62461cb0ef41Sopenharmony_ci Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); 62471cb0ef41Sopenharmony_ci Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); 62481cb0ef41Sopenharmony_ci __ GotoIf(check2, &if_less_than_minus_two_52); 62491cb0ef41Sopenharmony_ci 62501cb0ef41Sopenharmony_ci { 62511cb0ef41Sopenharmony_ci Node* const minus_zero = __ Float64Constant(-0.0); 62521cb0ef41Sopenharmony_ci Node* temp1 = __ Float64Sub(minus_zero, input); 62531cb0ef41Sopenharmony_ci Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); 62541cb0ef41Sopenharmony_ci Node* check3 = __ Float64LessThan(temp1, temp2); 62551cb0ef41Sopenharmony_ci __ GotoIfNot(check3, &done_temp3, temp2); 62561cb0ef41Sopenharmony_ci __ Goto(&done_temp3, __ Float64Sub(temp2, one)); 62571cb0ef41Sopenharmony_ci 62581cb0ef41Sopenharmony_ci __ Bind(&done_temp3); 62591cb0ef41Sopenharmony_ci Node* temp3 = done_temp3.PhiAt(0); 62601cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Sub(minus_zero, temp3)); 62611cb0ef41Sopenharmony_ci } 62621cb0ef41Sopenharmony_ci __ Bind(&if_less_than_minus_two_52); 62631cb0ef41Sopenharmony_ci __ Goto(&done, input); 62641cb0ef41Sopenharmony_ci 62651cb0ef41Sopenharmony_ci __ Bind(&if_zero); 62661cb0ef41Sopenharmony_ci __ Goto(&done, input); 62671cb0ef41Sopenharmony_ci } 62681cb0ef41Sopenharmony_ci __ Bind(&done); 62691cb0ef41Sopenharmony_ci return Just(done.PhiAt(0)); 62701cb0ef41Sopenharmony_ci} 62711cb0ef41Sopenharmony_ci 62721cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) { 62731cb0ef41Sopenharmony_ci if (machine()->Float64RoundDown().IsSupported()) { 62741cb0ef41Sopenharmony_ci return __ Float64RoundDown(value); 62751cb0ef41Sopenharmony_ci } 62761cb0ef41Sopenharmony_ci 62771cb0ef41Sopenharmony_ci Node* const input = value; 62781cb0ef41Sopenharmony_ci 62791cb0ef41Sopenharmony_ci // General case for floor. 62801cb0ef41Sopenharmony_ci // 62811cb0ef41Sopenharmony_ci // if 0.0 < input then 62821cb0ef41Sopenharmony_ci // if 2^52 <= input then 62831cb0ef41Sopenharmony_ci // input 62841cb0ef41Sopenharmony_ci // else 62851cb0ef41Sopenharmony_ci // let temp1 = (2^52 + input) - 2^52 in 62861cb0ef41Sopenharmony_ci // if input < temp1 then 62871cb0ef41Sopenharmony_ci // temp1 - 1 62881cb0ef41Sopenharmony_ci // else 62891cb0ef41Sopenharmony_ci // temp1 62901cb0ef41Sopenharmony_ci // else 62911cb0ef41Sopenharmony_ci // if input == 0 then 62921cb0ef41Sopenharmony_ci // input 62931cb0ef41Sopenharmony_ci // else 62941cb0ef41Sopenharmony_ci // if input <= -2^52 then 62951cb0ef41Sopenharmony_ci // input 62961cb0ef41Sopenharmony_ci // else 62971cb0ef41Sopenharmony_ci // let temp1 = -0 - input in 62981cb0ef41Sopenharmony_ci // let temp2 = (2^52 + temp1) - 2^52 in 62991cb0ef41Sopenharmony_ci // if temp2 < temp1 then 63001cb0ef41Sopenharmony_ci // -1 - temp2 63011cb0ef41Sopenharmony_ci // else 63021cb0ef41Sopenharmony_ci // -0 - temp2 63031cb0ef41Sopenharmony_ci 63041cb0ef41Sopenharmony_ci auto if_not_positive = __ MakeDeferredLabel(); 63051cb0ef41Sopenharmony_ci auto if_greater_than_two_52 = __ MakeDeferredLabel(); 63061cb0ef41Sopenharmony_ci auto if_less_than_minus_two_52 = __ MakeDeferredLabel(); 63071cb0ef41Sopenharmony_ci auto if_temp2_lt_temp1 = __ MakeLabel(); 63081cb0ef41Sopenharmony_ci auto if_zero = __ MakeDeferredLabel(); 63091cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kFloat64); 63101cb0ef41Sopenharmony_ci 63111cb0ef41Sopenharmony_ci Node* const zero = __ Float64Constant(0.0); 63121cb0ef41Sopenharmony_ci Node* const two_52 = __ Float64Constant(4503599627370496.0E0); 63131cb0ef41Sopenharmony_ci 63141cb0ef41Sopenharmony_ci Node* check0 = __ Float64LessThan(zero, input); 63151cb0ef41Sopenharmony_ci __ GotoIfNot(check0, &if_not_positive); 63161cb0ef41Sopenharmony_ci { 63171cb0ef41Sopenharmony_ci Node* check1 = __ Float64LessThanOrEqual(two_52, input); 63181cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_greater_than_two_52); 63191cb0ef41Sopenharmony_ci { 63201cb0ef41Sopenharmony_ci Node* const one = __ Float64Constant(1.0); 63211cb0ef41Sopenharmony_ci Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); 63221cb0ef41Sopenharmony_ci __ GotoIfNot(__ Float64LessThan(input, temp1), &done, temp1); 63231cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Sub(temp1, one)); 63241cb0ef41Sopenharmony_ci } 63251cb0ef41Sopenharmony_ci 63261cb0ef41Sopenharmony_ci __ Bind(&if_greater_than_two_52); 63271cb0ef41Sopenharmony_ci __ Goto(&done, input); 63281cb0ef41Sopenharmony_ci } 63291cb0ef41Sopenharmony_ci 63301cb0ef41Sopenharmony_ci __ Bind(&if_not_positive); 63311cb0ef41Sopenharmony_ci { 63321cb0ef41Sopenharmony_ci Node* check1 = __ Float64Equal(input, zero); 63331cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_zero); 63341cb0ef41Sopenharmony_ci 63351cb0ef41Sopenharmony_ci Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); 63361cb0ef41Sopenharmony_ci Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); 63371cb0ef41Sopenharmony_ci __ GotoIf(check2, &if_less_than_minus_two_52); 63381cb0ef41Sopenharmony_ci 63391cb0ef41Sopenharmony_ci { 63401cb0ef41Sopenharmony_ci Node* const minus_zero = __ Float64Constant(-0.0); 63411cb0ef41Sopenharmony_ci Node* temp1 = __ Float64Sub(minus_zero, input); 63421cb0ef41Sopenharmony_ci Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); 63431cb0ef41Sopenharmony_ci Node* check3 = __ Float64LessThan(temp2, temp1); 63441cb0ef41Sopenharmony_ci __ GotoIf(check3, &if_temp2_lt_temp1); 63451cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Sub(minus_zero, temp2)); 63461cb0ef41Sopenharmony_ci 63471cb0ef41Sopenharmony_ci __ Bind(&if_temp2_lt_temp1); 63481cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2)); 63491cb0ef41Sopenharmony_ci } 63501cb0ef41Sopenharmony_ci __ Bind(&if_less_than_minus_two_52); 63511cb0ef41Sopenharmony_ci __ Goto(&done, input); 63521cb0ef41Sopenharmony_ci 63531cb0ef41Sopenharmony_ci __ Bind(&if_zero); 63541cb0ef41Sopenharmony_ci __ Goto(&done, input); 63551cb0ef41Sopenharmony_ci } 63561cb0ef41Sopenharmony_ci __ Bind(&done); 63571cb0ef41Sopenharmony_ci return done.PhiAt(0); 63581cb0ef41Sopenharmony_ci} 63591cb0ef41Sopenharmony_ci 63601cb0ef41Sopenharmony_ciMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) { 63611cb0ef41Sopenharmony_ci // Nothing to be done if a fast hardware instruction is available. 63621cb0ef41Sopenharmony_ci if (machine()->Float64RoundDown().IsSupported()) { 63631cb0ef41Sopenharmony_ci return Nothing<Node*>(); 63641cb0ef41Sopenharmony_ci } 63651cb0ef41Sopenharmony_ci 63661cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 63671cb0ef41Sopenharmony_ci return Just(BuildFloat64RoundDown(input)); 63681cb0ef41Sopenharmony_ci} 63691cb0ef41Sopenharmony_ci 63701cb0ef41Sopenharmony_ciMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) { 63711cb0ef41Sopenharmony_ci // Nothing to be done if a fast hardware instruction is available. 63721cb0ef41Sopenharmony_ci if (machine()->Float64RoundTiesEven().IsSupported()) { 63731cb0ef41Sopenharmony_ci return Nothing<Node*>(); 63741cb0ef41Sopenharmony_ci } 63751cb0ef41Sopenharmony_ci 63761cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 63771cb0ef41Sopenharmony_ci 63781cb0ef41Sopenharmony_ci // Generate case for round ties to even: 63791cb0ef41Sopenharmony_ci // 63801cb0ef41Sopenharmony_ci // let value = floor(input) in 63811cb0ef41Sopenharmony_ci // let temp1 = input - value in 63821cb0ef41Sopenharmony_ci // if temp1 < 0.5 then 63831cb0ef41Sopenharmony_ci // value 63841cb0ef41Sopenharmony_ci // else if 0.5 < temp1 then 63851cb0ef41Sopenharmony_ci // value + 1.0 63861cb0ef41Sopenharmony_ci // else 63871cb0ef41Sopenharmony_ci // let temp2 = value % 2.0 in 63881cb0ef41Sopenharmony_ci // if temp2 == 0.0 then 63891cb0ef41Sopenharmony_ci // value 63901cb0ef41Sopenharmony_ci // else 63911cb0ef41Sopenharmony_ci // value + 1.0 63921cb0ef41Sopenharmony_ci 63931cb0ef41Sopenharmony_ci auto if_is_half = __ MakeLabel(); 63941cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kFloat64); 63951cb0ef41Sopenharmony_ci 63961cb0ef41Sopenharmony_ci Node* value = BuildFloat64RoundDown(input); 63971cb0ef41Sopenharmony_ci Node* temp1 = __ Float64Sub(input, value); 63981cb0ef41Sopenharmony_ci 63991cb0ef41Sopenharmony_ci Node* const half = __ Float64Constant(0.5); 64001cb0ef41Sopenharmony_ci Node* check0 = __ Float64LessThan(temp1, half); 64011cb0ef41Sopenharmony_ci __ GotoIf(check0, &done, value); 64021cb0ef41Sopenharmony_ci 64031cb0ef41Sopenharmony_ci Node* const one = __ Float64Constant(1.0); 64041cb0ef41Sopenharmony_ci Node* check1 = __ Float64LessThan(half, temp1); 64051cb0ef41Sopenharmony_ci __ GotoIfNot(check1, &if_is_half); 64061cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Add(value, one)); 64071cb0ef41Sopenharmony_ci 64081cb0ef41Sopenharmony_ci __ Bind(&if_is_half); 64091cb0ef41Sopenharmony_ci Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0)); 64101cb0ef41Sopenharmony_ci Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0)); 64111cb0ef41Sopenharmony_ci __ GotoIf(check2, &done, value); 64121cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Add(value, one)); 64131cb0ef41Sopenharmony_ci 64141cb0ef41Sopenharmony_ci __ Bind(&done); 64151cb0ef41Sopenharmony_ci return Just(done.PhiAt(0)); 64161cb0ef41Sopenharmony_ci} 64171cb0ef41Sopenharmony_ci 64181cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildFloat64RoundTruncate(Node* input) { 64191cb0ef41Sopenharmony_ci if (machine()->Float64RoundTruncate().IsSupported()) { 64201cb0ef41Sopenharmony_ci return __ Float64RoundTruncate(input); 64211cb0ef41Sopenharmony_ci } 64221cb0ef41Sopenharmony_ci // General case for trunc. 64231cb0ef41Sopenharmony_ci // 64241cb0ef41Sopenharmony_ci // if 0.0 < input then 64251cb0ef41Sopenharmony_ci // if 2^52 <= input then 64261cb0ef41Sopenharmony_ci // input 64271cb0ef41Sopenharmony_ci // else 64281cb0ef41Sopenharmony_ci // let temp1 = (2^52 + input) - 2^52 in 64291cb0ef41Sopenharmony_ci // if input < temp1 then 64301cb0ef41Sopenharmony_ci // temp1 - 1 64311cb0ef41Sopenharmony_ci // else 64321cb0ef41Sopenharmony_ci // temp1 64331cb0ef41Sopenharmony_ci // else 64341cb0ef41Sopenharmony_ci // if input == 0 then 64351cb0ef41Sopenharmony_ci // input 64361cb0ef41Sopenharmony_ci // else 64371cb0ef41Sopenharmony_ci // if input <= -2^52 then 64381cb0ef41Sopenharmony_ci // input 64391cb0ef41Sopenharmony_ci // else 64401cb0ef41Sopenharmony_ci // let temp1 = -0 - input in 64411cb0ef41Sopenharmony_ci // let temp2 = (2^52 + temp1) - 2^52 in 64421cb0ef41Sopenharmony_ci // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in 64431cb0ef41Sopenharmony_ci // -0 - temp3 64441cb0ef41Sopenharmony_ci // 64451cb0ef41Sopenharmony_ci // Note: We do not use the Diamond helper class here, because it really hurts 64461cb0ef41Sopenharmony_ci // readability with nested diamonds. 64471cb0ef41Sopenharmony_ci 64481cb0ef41Sopenharmony_ci auto if_not_positive = __ MakeDeferredLabel(); 64491cb0ef41Sopenharmony_ci auto if_greater_than_two_52 = __ MakeDeferredLabel(); 64501cb0ef41Sopenharmony_ci auto if_less_than_minus_two_52 = __ MakeDeferredLabel(); 64511cb0ef41Sopenharmony_ci auto if_zero = __ MakeDeferredLabel(); 64521cb0ef41Sopenharmony_ci auto done_temp3 = __ MakeLabel(MachineRepresentation::kFloat64); 64531cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineRepresentation::kFloat64); 64541cb0ef41Sopenharmony_ci 64551cb0ef41Sopenharmony_ci Node* const zero = __ Float64Constant(0.0); 64561cb0ef41Sopenharmony_ci Node* const two_52 = __ Float64Constant(4503599627370496.0E0); 64571cb0ef41Sopenharmony_ci Node* const one = __ Float64Constant(1.0); 64581cb0ef41Sopenharmony_ci 64591cb0ef41Sopenharmony_ci Node* check0 = __ Float64LessThan(zero, input); 64601cb0ef41Sopenharmony_ci __ GotoIfNot(check0, &if_not_positive); 64611cb0ef41Sopenharmony_ci { 64621cb0ef41Sopenharmony_ci Node* check1 = __ Float64LessThanOrEqual(two_52, input); 64631cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_greater_than_two_52); 64641cb0ef41Sopenharmony_ci { 64651cb0ef41Sopenharmony_ci Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); 64661cb0ef41Sopenharmony_ci __ GotoIfNot(__ Float64LessThan(input, temp1), &done, temp1); 64671cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Sub(temp1, one)); 64681cb0ef41Sopenharmony_ci } 64691cb0ef41Sopenharmony_ci 64701cb0ef41Sopenharmony_ci __ Bind(&if_greater_than_two_52); 64711cb0ef41Sopenharmony_ci __ Goto(&done, input); 64721cb0ef41Sopenharmony_ci } 64731cb0ef41Sopenharmony_ci 64741cb0ef41Sopenharmony_ci __ Bind(&if_not_positive); 64751cb0ef41Sopenharmony_ci { 64761cb0ef41Sopenharmony_ci Node* check1 = __ Float64Equal(input, zero); 64771cb0ef41Sopenharmony_ci __ GotoIf(check1, &if_zero); 64781cb0ef41Sopenharmony_ci 64791cb0ef41Sopenharmony_ci Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); 64801cb0ef41Sopenharmony_ci Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); 64811cb0ef41Sopenharmony_ci __ GotoIf(check2, &if_less_than_minus_two_52); 64821cb0ef41Sopenharmony_ci 64831cb0ef41Sopenharmony_ci { 64841cb0ef41Sopenharmony_ci Node* const minus_zero = __ Float64Constant(-0.0); 64851cb0ef41Sopenharmony_ci Node* temp1 = __ Float64Sub(minus_zero, input); 64861cb0ef41Sopenharmony_ci Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); 64871cb0ef41Sopenharmony_ci Node* check3 = __ Float64LessThan(temp1, temp2); 64881cb0ef41Sopenharmony_ci __ GotoIfNot(check3, &done_temp3, temp2); 64891cb0ef41Sopenharmony_ci __ Goto(&done_temp3, __ Float64Sub(temp2, one)); 64901cb0ef41Sopenharmony_ci 64911cb0ef41Sopenharmony_ci __ Bind(&done_temp3); 64921cb0ef41Sopenharmony_ci Node* temp3 = done_temp3.PhiAt(0); 64931cb0ef41Sopenharmony_ci __ Goto(&done, __ Float64Sub(minus_zero, temp3)); 64941cb0ef41Sopenharmony_ci } 64951cb0ef41Sopenharmony_ci __ Bind(&if_less_than_minus_two_52); 64961cb0ef41Sopenharmony_ci __ Goto(&done, input); 64971cb0ef41Sopenharmony_ci 64981cb0ef41Sopenharmony_ci __ Bind(&if_zero); 64991cb0ef41Sopenharmony_ci __ Goto(&done, input); 65001cb0ef41Sopenharmony_ci } 65011cb0ef41Sopenharmony_ci __ Bind(&done); 65021cb0ef41Sopenharmony_ci return done.PhiAt(0); 65031cb0ef41Sopenharmony_ci} 65041cb0ef41Sopenharmony_ci 65051cb0ef41Sopenharmony_ciMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) { 65061cb0ef41Sopenharmony_ci // Nothing to be done if a fast hardware instruction is available. 65071cb0ef41Sopenharmony_ci if (machine()->Float64RoundTruncate().IsSupported()) { 65081cb0ef41Sopenharmony_ci return Nothing<Node*>(); 65091cb0ef41Sopenharmony_ci } 65101cb0ef41Sopenharmony_ci 65111cb0ef41Sopenharmony_ci Node* const input = node->InputAt(0); 65121cb0ef41Sopenharmony_ci return Just(BuildFloat64RoundTruncate(input)); 65131cb0ef41Sopenharmony_ci} 65141cb0ef41Sopenharmony_ci 65151cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerFindOrderedHashMapEntry(Node* node) { 65161cb0ef41Sopenharmony_ci Node* table = NodeProperties::GetValueInput(node, 0); 65171cb0ef41Sopenharmony_ci Node* key = NodeProperties::GetValueInput(node, 1); 65181cb0ef41Sopenharmony_ci 65191cb0ef41Sopenharmony_ci { 65201cb0ef41Sopenharmony_ci Callable const callable = 65211cb0ef41Sopenharmony_ci Builtins::CallableFor(isolate(), Builtin::kFindOrderedHashMapEntry); 65221cb0ef41Sopenharmony_ci Operator::Properties const properties = node->op()->properties(); 65231cb0ef41Sopenharmony_ci CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; 65241cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetStubCallDescriptor( 65251cb0ef41Sopenharmony_ci graph()->zone(), callable.descriptor(), 65261cb0ef41Sopenharmony_ci callable.descriptor().GetStackParameterCount(), flags, properties); 65271cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ HeapConstant(callable.code()), table, 65281cb0ef41Sopenharmony_ci key, __ NoContextConstant()); 65291cb0ef41Sopenharmony_ci } 65301cb0ef41Sopenharmony_ci} 65311cb0ef41Sopenharmony_ci 65321cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::ComputeUnseededHash(Node* value) { 65331cb0ef41Sopenharmony_ci // See v8::internal::ComputeUnseededHash() 65341cb0ef41Sopenharmony_ci value = __ Int32Add(__ Word32Xor(value, __ Int32Constant(0xFFFFFFFF)), 65351cb0ef41Sopenharmony_ci __ Word32Shl(value, __ Int32Constant(15))); 65361cb0ef41Sopenharmony_ci value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(12))); 65371cb0ef41Sopenharmony_ci value = __ Int32Add(value, __ Word32Shl(value, __ Int32Constant(2))); 65381cb0ef41Sopenharmony_ci value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(4))); 65391cb0ef41Sopenharmony_ci value = __ Int32Mul(value, __ Int32Constant(2057)); 65401cb0ef41Sopenharmony_ci value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(16))); 65411cb0ef41Sopenharmony_ci value = __ Word32And(value, __ Int32Constant(0x3FFFFFFF)); 65421cb0ef41Sopenharmony_ci return value; 65431cb0ef41Sopenharmony_ci} 65441cb0ef41Sopenharmony_ci 65451cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerFindOrderedHashMapEntryForInt32Key( 65461cb0ef41Sopenharmony_ci Node* node) { 65471cb0ef41Sopenharmony_ci Node* table = NodeProperties::GetValueInput(node, 0); 65481cb0ef41Sopenharmony_ci Node* key = NodeProperties::GetValueInput(node, 1); 65491cb0ef41Sopenharmony_ci 65501cb0ef41Sopenharmony_ci // Compute the integer hash code. 65511cb0ef41Sopenharmony_ci Node* hash = ChangeUint32ToUintPtr(ComputeUnseededHash(key)); 65521cb0ef41Sopenharmony_ci 65531cb0ef41Sopenharmony_ci Node* number_of_buckets = ChangeSmiToIntPtr(__ LoadField( 65541cb0ef41Sopenharmony_ci AccessBuilder::ForOrderedHashMapOrSetNumberOfBuckets(), table)); 65551cb0ef41Sopenharmony_ci hash = __ WordAnd(hash, __ IntSub(number_of_buckets, __ IntPtrConstant(1))); 65561cb0ef41Sopenharmony_ci Node* first_entry = ChangeSmiToIntPtr(__ Load( 65571cb0ef41Sopenharmony_ci MachineType::TaggedSigned(), table, 65581cb0ef41Sopenharmony_ci __ IntAdd(__ WordShl(hash, __ IntPtrConstant(kTaggedSizeLog2)), 65591cb0ef41Sopenharmony_ci __ IntPtrConstant(OrderedHashMap::HashTableStartOffset() - 65601cb0ef41Sopenharmony_ci kHeapObjectTag)))); 65611cb0ef41Sopenharmony_ci 65621cb0ef41Sopenharmony_ci auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation()); 65631cb0ef41Sopenharmony_ci auto done = __ MakeLabel(MachineType::PointerRepresentation()); 65641cb0ef41Sopenharmony_ci __ Goto(&loop, first_entry); 65651cb0ef41Sopenharmony_ci __ Bind(&loop); 65661cb0ef41Sopenharmony_ci { 65671cb0ef41Sopenharmony_ci Node* entry = loop.PhiAt(0); 65681cb0ef41Sopenharmony_ci Node* check = 65691cb0ef41Sopenharmony_ci __ IntPtrEqual(entry, __ IntPtrConstant(OrderedHashMap::kNotFound)); 65701cb0ef41Sopenharmony_ci __ GotoIf(check, &done, entry); 65711cb0ef41Sopenharmony_ci entry = __ IntAdd( 65721cb0ef41Sopenharmony_ci __ IntMul(entry, __ IntPtrConstant(OrderedHashMap::kEntrySize)), 65731cb0ef41Sopenharmony_ci number_of_buckets); 65741cb0ef41Sopenharmony_ci 65751cb0ef41Sopenharmony_ci Node* candidate_key = __ Load( 65761cb0ef41Sopenharmony_ci MachineType::AnyTagged(), table, 65771cb0ef41Sopenharmony_ci __ IntAdd(__ WordShl(entry, __ IntPtrConstant(kTaggedSizeLog2)), 65781cb0ef41Sopenharmony_ci __ IntPtrConstant(OrderedHashMap::HashTableStartOffset() - 65791cb0ef41Sopenharmony_ci kHeapObjectTag))); 65801cb0ef41Sopenharmony_ci 65811cb0ef41Sopenharmony_ci auto if_match = __ MakeLabel(); 65821cb0ef41Sopenharmony_ci auto if_notmatch = __ MakeLabel(); 65831cb0ef41Sopenharmony_ci auto if_notsmi = __ MakeDeferredLabel(); 65841cb0ef41Sopenharmony_ci __ GotoIfNot(ObjectIsSmi(candidate_key), &if_notsmi); 65851cb0ef41Sopenharmony_ci __ Branch(__ Word32Equal(ChangeSmiToInt32(candidate_key), key), &if_match, 65861cb0ef41Sopenharmony_ci &if_notmatch); 65871cb0ef41Sopenharmony_ci 65881cb0ef41Sopenharmony_ci __ Bind(&if_notsmi); 65891cb0ef41Sopenharmony_ci __ GotoIfNot( 65901cb0ef41Sopenharmony_ci __ TaggedEqual(__ LoadField(AccessBuilder::ForMap(), candidate_key), 65911cb0ef41Sopenharmony_ci __ HeapNumberMapConstant()), 65921cb0ef41Sopenharmony_ci &if_notmatch); 65931cb0ef41Sopenharmony_ci __ Branch(__ Float64Equal(__ LoadField(AccessBuilder::ForHeapNumberValue(), 65941cb0ef41Sopenharmony_ci candidate_key), 65951cb0ef41Sopenharmony_ci __ ChangeInt32ToFloat64(key)), 65961cb0ef41Sopenharmony_ci &if_match, &if_notmatch); 65971cb0ef41Sopenharmony_ci 65981cb0ef41Sopenharmony_ci __ Bind(&if_match); 65991cb0ef41Sopenharmony_ci __ Goto(&done, entry); 66001cb0ef41Sopenharmony_ci 66011cb0ef41Sopenharmony_ci __ Bind(&if_notmatch); 66021cb0ef41Sopenharmony_ci { 66031cb0ef41Sopenharmony_ci Node* next_entry = ChangeSmiToIntPtr(__ Load( 66041cb0ef41Sopenharmony_ci MachineType::TaggedSigned(), table, 66051cb0ef41Sopenharmony_ci __ IntAdd( 66061cb0ef41Sopenharmony_ci __ WordShl(entry, __ IntPtrConstant(kTaggedSizeLog2)), 66071cb0ef41Sopenharmony_ci __ IntPtrConstant(OrderedHashMap::HashTableStartOffset() + 66081cb0ef41Sopenharmony_ci OrderedHashMap::kChainOffset * kTaggedSize - 66091cb0ef41Sopenharmony_ci kHeapObjectTag)))); 66101cb0ef41Sopenharmony_ci __ Goto(&loop, next_entry); 66111cb0ef41Sopenharmony_ci } 66121cb0ef41Sopenharmony_ci } 66131cb0ef41Sopenharmony_ci 66141cb0ef41Sopenharmony_ci __ Bind(&done); 66151cb0ef41Sopenharmony_ci return done.PhiAt(0); 66161cb0ef41Sopenharmony_ci} 66171cb0ef41Sopenharmony_ci 66181cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::LowerDateNow(Node* node) { 66191cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; 66201cb0ef41Sopenharmony_ci Runtime::FunctionId id = Runtime::kDateCurrentTime; 66211cb0ef41Sopenharmony_ci auto call_descriptor = Linkage::GetRuntimeCallDescriptor( 66221cb0ef41Sopenharmony_ci graph()->zone(), id, 0, properties, CallDescriptor::kNoFlags); 66231cb0ef41Sopenharmony_ci return __ Call(call_descriptor, __ CEntryStubConstant(1), 66241cb0ef41Sopenharmony_ci __ ExternalConstant(ExternalReference::Create(id)), 66251cb0ef41Sopenharmony_ci __ Int32Constant(0), __ NoContextConstant()); 66261cb0ef41Sopenharmony_ci} 66271cb0ef41Sopenharmony_ci 66281cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::TruncateWordToInt32(Node* value) { 66291cb0ef41Sopenharmony_ci if (machine()->Is64()) { 66301cb0ef41Sopenharmony_ci return __ TruncateInt64ToInt32(value); 66311cb0ef41Sopenharmony_ci } 66321cb0ef41Sopenharmony_ci return value; 66331cb0ef41Sopenharmony_ci} 66341cb0ef41Sopenharmony_ci 66351cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildIsStrongReference(Node* value) { 66361cb0ef41Sopenharmony_ci return __ Word32Equal( 66371cb0ef41Sopenharmony_ci __ Word32And( 66381cb0ef41Sopenharmony_ci TruncateWordToInt32(__ BitcastTaggedToWordForTagAndSmiBits(value)), 66391cb0ef41Sopenharmony_ci __ Int32Constant(kHeapObjectTagMask)), 66401cb0ef41Sopenharmony_ci __ Int32Constant(kHeapObjectTag)); 66411cb0ef41Sopenharmony_ci} 66421cb0ef41Sopenharmony_ci 66431cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::MakeWeakForComparison(Node* heap_object) { 66441cb0ef41Sopenharmony_ci // TODO(gsathya): Specialize this for pointer compression. 66451cb0ef41Sopenharmony_ci return __ BitcastWordToTagged( 66461cb0ef41Sopenharmony_ci __ WordOr(__ BitcastTaggedToWord(heap_object), 66471cb0ef41Sopenharmony_ci __ IntPtrConstant(kWeakHeapObjectTag))); 66481cb0ef41Sopenharmony_ci} 66491cb0ef41Sopenharmony_ci 66501cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildStrongReferenceFromWeakReference( 66511cb0ef41Sopenharmony_ci Node* maybe_object) { 66521cb0ef41Sopenharmony_ci return __ BitcastWordToTagged( 66531cb0ef41Sopenharmony_ci __ WordAnd(__ BitcastMaybeObjectToWord(maybe_object), 66541cb0ef41Sopenharmony_ci __ IntPtrConstant(~kWeakHeapObjectMask))); 66551cb0ef41Sopenharmony_ci} 66561cb0ef41Sopenharmony_ci 66571cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildIsWeakReferenceTo(Node* maybe_object, 66581cb0ef41Sopenharmony_ci Node* value) { 66591cb0ef41Sopenharmony_ci if (COMPRESS_POINTERS_BOOL) { 66601cb0ef41Sopenharmony_ci return __ Word32Equal( 66611cb0ef41Sopenharmony_ci __ Word32And( 66621cb0ef41Sopenharmony_ci TruncateWordToInt32(__ BitcastMaybeObjectToWord(maybe_object)), 66631cb0ef41Sopenharmony_ci __ Uint32Constant(~static_cast<uint32_t>(kWeakHeapObjectMask))), 66641cb0ef41Sopenharmony_ci TruncateWordToInt32(__ BitcastTaggedToWord(value))); 66651cb0ef41Sopenharmony_ci } else { 66661cb0ef41Sopenharmony_ci return __ WordEqual(__ WordAnd(__ BitcastMaybeObjectToWord(maybe_object), 66671cb0ef41Sopenharmony_ci __ IntPtrConstant(~kWeakHeapObjectMask)), 66681cb0ef41Sopenharmony_ci __ BitcastTaggedToWord(value)); 66691cb0ef41Sopenharmony_ci } 66701cb0ef41Sopenharmony_ci} 66711cb0ef41Sopenharmony_ci 66721cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildIsClearedWeakReference(Node* maybe_object) { 66731cb0ef41Sopenharmony_ci return __ Word32Equal( 66741cb0ef41Sopenharmony_ci TruncateWordToInt32(__ BitcastMaybeObjectToWord(maybe_object)), 66751cb0ef41Sopenharmony_ci __ Int32Constant(kClearedWeakHeapObjectLower32)); 66761cb0ef41Sopenharmony_ci} 66771cb0ef41Sopenharmony_ci 66781cb0ef41Sopenharmony_ci// Pass {bitfield} = {digit} = nullptr to construct the canoncial 0n BigInt. 66791cb0ef41Sopenharmony_ciNode* EffectControlLinearizer::BuildAllocateBigInt(Node* bitfield, 66801cb0ef41Sopenharmony_ci Node* digit) { 66811cb0ef41Sopenharmony_ci DCHECK(machine()->Is64()); 66821cb0ef41Sopenharmony_ci DCHECK_EQ(bitfield == nullptr, digit == nullptr); 66831cb0ef41Sopenharmony_ci static constexpr auto zero_bitfield = 66841cb0ef41Sopenharmony_ci BigInt::SignBits::update(BigInt::LengthBits::encode(0), false); 66851cb0ef41Sopenharmony_ci 66861cb0ef41Sopenharmony_ci Node* map = __ HeapConstant(factory()->bigint_map()); 66871cb0ef41Sopenharmony_ci 66881cb0ef41Sopenharmony_ci Node* result = __ Allocate(AllocationType::kYoung, 66891cb0ef41Sopenharmony_ci __ IntPtrConstant(BigInt::SizeFor(digit ? 1 : 0))); 66901cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForMap(), result, map); 66911cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForBigIntBitfield(), result, 66921cb0ef41Sopenharmony_ci bitfield ? bitfield : __ Int32Constant(zero_bitfield)); 66931cb0ef41Sopenharmony_ci 66941cb0ef41Sopenharmony_ci // BigInts have no padding on 64 bit architectures with pointer compression. 66951cb0ef41Sopenharmony_ci if (BigInt::HasOptionalPadding()) { 66961cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForBigIntOptionalPadding(), result, 66971cb0ef41Sopenharmony_ci __ IntPtrConstant(0)); 66981cb0ef41Sopenharmony_ci } 66991cb0ef41Sopenharmony_ci if (digit) { 67001cb0ef41Sopenharmony_ci __ StoreField(AccessBuilder::ForBigIntLeastSignificantDigit64(), result, 67011cb0ef41Sopenharmony_ci digit); 67021cb0ef41Sopenharmony_ci } 67031cb0ef41Sopenharmony_ci return result; 67041cb0ef41Sopenharmony_ci} 67051cb0ef41Sopenharmony_ci 67061cb0ef41Sopenharmony_ci#undef __ 67071cb0ef41Sopenharmony_ci 67081cb0ef41Sopenharmony_civoid LinearizeEffectControl(JSGraph* graph, Schedule* schedule, Zone* temp_zone, 67091cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, 67101cb0ef41Sopenharmony_ci NodeOriginTable* node_origins, 67111cb0ef41Sopenharmony_ci JSHeapBroker* broker) { 67121cb0ef41Sopenharmony_ci JSGraphAssembler graph_assembler_(graph, temp_zone); 67131cb0ef41Sopenharmony_ci EffectControlLinearizer linearizer(graph, schedule, &graph_assembler_, 67141cb0ef41Sopenharmony_ci temp_zone, source_positions, node_origins, 67151cb0ef41Sopenharmony_ci MaintainSchedule::kDiscard, broker); 67161cb0ef41Sopenharmony_ci linearizer.Run(); 67171cb0ef41Sopenharmony_ci} 67181cb0ef41Sopenharmony_ci 67191cb0ef41Sopenharmony_ci} // namespace compiler 67201cb0ef41Sopenharmony_ci} // namespace internal 67211cb0ef41Sopenharmony_ci} // namespace v8 6722