11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_GRAPH_ASSEMBLER_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_GRAPH_ASSEMBLER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/codegen/tnode.h" 91cb0ef41Sopenharmony_ci#include "src/compiler/feedback-source.h" 101cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h" 111cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/simplified-operator.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_cinamespace v8 { 151cb0ef41Sopenharmony_cinamespace internal { 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ciclass JSGraph; 181cb0ef41Sopenharmony_ciclass Graph; 191cb0ef41Sopenharmony_ciclass Oddball; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci// TODO(jgruber): Currently this is too permissive, but at least it lets us 221cb0ef41Sopenharmony_ci// document which functions expect JS booleans. If a real Boolean type becomes 231cb0ef41Sopenharmony_ci// possible in the future, use that instead. 241cb0ef41Sopenharmony_ciusing Boolean = Oddball; 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace compiler { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ciclass Reducer; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \ 311cb0ef41Sopenharmony_ci V(BitcastFloat32ToInt32) \ 321cb0ef41Sopenharmony_ci V(BitcastFloat64ToInt64) \ 331cb0ef41Sopenharmony_ci V(BitcastInt32ToFloat32) \ 341cb0ef41Sopenharmony_ci V(BitcastWord32ToWord64) \ 351cb0ef41Sopenharmony_ci V(BitcastInt64ToFloat64) \ 361cb0ef41Sopenharmony_ci V(ChangeFloat32ToFloat64) \ 371cb0ef41Sopenharmony_ci V(ChangeFloat64ToInt32) \ 381cb0ef41Sopenharmony_ci V(ChangeFloat64ToInt64) \ 391cb0ef41Sopenharmony_ci V(ChangeFloat64ToUint32) \ 401cb0ef41Sopenharmony_ci V(ChangeInt32ToFloat64) \ 411cb0ef41Sopenharmony_ci V(ChangeInt32ToInt64) \ 421cb0ef41Sopenharmony_ci V(ChangeInt64ToFloat64) \ 431cb0ef41Sopenharmony_ci V(ChangeUint32ToFloat64) \ 441cb0ef41Sopenharmony_ci V(ChangeUint32ToUint64) \ 451cb0ef41Sopenharmony_ci V(Float64Abs) \ 461cb0ef41Sopenharmony_ci V(Float64ExtractHighWord32) \ 471cb0ef41Sopenharmony_ci V(Float64ExtractLowWord32) \ 481cb0ef41Sopenharmony_ci V(Float64SilenceNaN) \ 491cb0ef41Sopenharmony_ci V(RoundFloat64ToInt32) \ 501cb0ef41Sopenharmony_ci V(RoundInt32ToFloat32) \ 511cb0ef41Sopenharmony_ci V(TruncateFloat64ToFloat32) \ 521cb0ef41Sopenharmony_ci V(TruncateFloat64ToWord32) \ 531cb0ef41Sopenharmony_ci V(TruncateInt64ToInt32) \ 541cb0ef41Sopenharmony_ci V(Word32ReverseBytes) \ 551cb0ef41Sopenharmony_ci V(Word64ReverseBytes) 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci#define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \ 581cb0ef41Sopenharmony_ci V(Float64Add) \ 591cb0ef41Sopenharmony_ci V(Float64Div) \ 601cb0ef41Sopenharmony_ci V(Float64Equal) \ 611cb0ef41Sopenharmony_ci V(Float64InsertHighWord32) \ 621cb0ef41Sopenharmony_ci V(Float64InsertLowWord32) \ 631cb0ef41Sopenharmony_ci V(Float64LessThan) \ 641cb0ef41Sopenharmony_ci V(Float64LessThanOrEqual) \ 651cb0ef41Sopenharmony_ci V(Float64Mod) \ 661cb0ef41Sopenharmony_ci V(Float64Sub) \ 671cb0ef41Sopenharmony_ci V(Int32Add) \ 681cb0ef41Sopenharmony_ci V(Int32LessThan) \ 691cb0ef41Sopenharmony_ci V(Int32LessThanOrEqual) \ 701cb0ef41Sopenharmony_ci V(Int32Mul) \ 711cb0ef41Sopenharmony_ci V(Int32Sub) \ 721cb0ef41Sopenharmony_ci V(Int64Sub) \ 731cb0ef41Sopenharmony_ci V(IntAdd) \ 741cb0ef41Sopenharmony_ci V(IntLessThan) \ 751cb0ef41Sopenharmony_ci V(IntMul) \ 761cb0ef41Sopenharmony_ci V(IntSub) \ 771cb0ef41Sopenharmony_ci V(Uint32LessThan) \ 781cb0ef41Sopenharmony_ci V(Uint32LessThanOrEqual) \ 791cb0ef41Sopenharmony_ci V(Uint64LessThan) \ 801cb0ef41Sopenharmony_ci V(Uint64LessThanOrEqual) \ 811cb0ef41Sopenharmony_ci V(UintLessThan) \ 821cb0ef41Sopenharmony_ci V(Word32And) \ 831cb0ef41Sopenharmony_ci V(Word32Equal) \ 841cb0ef41Sopenharmony_ci V(Word32Or) \ 851cb0ef41Sopenharmony_ci V(Word32Sar) \ 861cb0ef41Sopenharmony_ci V(Word32SarShiftOutZeros) \ 871cb0ef41Sopenharmony_ci V(Word32Shl) \ 881cb0ef41Sopenharmony_ci V(Word32Shr) \ 891cb0ef41Sopenharmony_ci V(Word32Xor) \ 901cb0ef41Sopenharmony_ci V(Word64And) \ 911cb0ef41Sopenharmony_ci V(Word64Equal) \ 921cb0ef41Sopenharmony_ci V(Word64Or) \ 931cb0ef41Sopenharmony_ci V(Word64Sar) \ 941cb0ef41Sopenharmony_ci V(Word64SarShiftOutZeros) \ 951cb0ef41Sopenharmony_ci V(Word64Shl) \ 961cb0ef41Sopenharmony_ci V(Word64Shr) \ 971cb0ef41Sopenharmony_ci V(Word64Xor) \ 981cb0ef41Sopenharmony_ci V(WordAnd) \ 991cb0ef41Sopenharmony_ci V(WordEqual) \ 1001cb0ef41Sopenharmony_ci V(WordOr) \ 1011cb0ef41Sopenharmony_ci V(WordSar) \ 1021cb0ef41Sopenharmony_ci V(WordSarShiftOutZeros) \ 1031cb0ef41Sopenharmony_ci V(WordShl) \ 1041cb0ef41Sopenharmony_ci V(WordShr) \ 1051cb0ef41Sopenharmony_ci V(WordXor) 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci#define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V) \ 1081cb0ef41Sopenharmony_ci V(Int32AddWithOverflow) \ 1091cb0ef41Sopenharmony_ci V(Int32Div) \ 1101cb0ef41Sopenharmony_ci V(Int32Mod) \ 1111cb0ef41Sopenharmony_ci V(Int32MulWithOverflow) \ 1121cb0ef41Sopenharmony_ci V(Int32SubWithOverflow) \ 1131cb0ef41Sopenharmony_ci V(Int64Div) \ 1141cb0ef41Sopenharmony_ci V(Int64Mod) \ 1151cb0ef41Sopenharmony_ci V(Uint32Div) \ 1161cb0ef41Sopenharmony_ci V(Uint32Mod) \ 1171cb0ef41Sopenharmony_ci V(Uint64Div) \ 1181cb0ef41Sopenharmony_ci V(Uint64Mod) 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci#define JSGRAPH_SINGLETON_CONSTANT_LIST(V) \ 1211cb0ef41Sopenharmony_ci V(AllocateInOldGenerationStub, Code) \ 1221cb0ef41Sopenharmony_ci V(AllocateInYoungGenerationStub, Code) \ 1231cb0ef41Sopenharmony_ci V(AllocateRegularInOldGenerationStub, Code) \ 1241cb0ef41Sopenharmony_ci V(AllocateRegularInYoungGenerationStub, Code) \ 1251cb0ef41Sopenharmony_ci V(BigIntMap, Map) \ 1261cb0ef41Sopenharmony_ci V(BooleanMap, Map) \ 1271cb0ef41Sopenharmony_ci V(EmptyString, String) \ 1281cb0ef41Sopenharmony_ci V(False, Boolean) \ 1291cb0ef41Sopenharmony_ci V(FixedArrayMap, Map) \ 1301cb0ef41Sopenharmony_ci V(FixedDoubleArrayMap, Map) \ 1311cb0ef41Sopenharmony_ci V(WeakFixedArrayMap, Map) \ 1321cb0ef41Sopenharmony_ci V(HeapNumberMap, Map) \ 1331cb0ef41Sopenharmony_ci V(MinusOne, Number) \ 1341cb0ef41Sopenharmony_ci V(NaN, Number) \ 1351cb0ef41Sopenharmony_ci V(NoContext, Object) \ 1361cb0ef41Sopenharmony_ci V(Null, Oddball) \ 1371cb0ef41Sopenharmony_ci V(One, Number) \ 1381cb0ef41Sopenharmony_ci V(TheHole, Oddball) \ 1391cb0ef41Sopenharmony_ci V(ToNumberBuiltin, Code) \ 1401cb0ef41Sopenharmony_ci V(PlainPrimitiveToNumberBuiltin, Code) \ 1411cb0ef41Sopenharmony_ci V(True, Boolean) \ 1421cb0ef41Sopenharmony_ci V(Undefined, Oddball) \ 1431cb0ef41Sopenharmony_ci V(Zero, Number) 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ciclass GraphAssembler; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_cienum class GraphAssemblerLabelType { kDeferred, kNonDeferred, kLoop }; 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci// Label with statically known count of incoming branches and phis. 1501cb0ef41Sopenharmony_citemplate <size_t VarCount> 1511cb0ef41Sopenharmony_ciclass GraphAssemblerLabel { 1521cb0ef41Sopenharmony_ci public: 1531cb0ef41Sopenharmony_ci Node* PhiAt(size_t index); 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci template <typename T> 1561cb0ef41Sopenharmony_ci TNode<T> PhiAt(size_t index) { 1571cb0ef41Sopenharmony_ci // TODO(jgruber): Investigate issues on ptr compression bots and enable. 1581cb0ef41Sopenharmony_ci // DCHECK(IsMachineRepresentationOf<T>(representations_[index])); 1591cb0ef41Sopenharmony_ci return TNode<T>::UncheckedCast(PhiAt(index)); 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci GraphAssemblerLabel(GraphAssemblerLabelType type, int loop_nesting_level, 1631cb0ef41Sopenharmony_ci const std::array<MachineRepresentation, VarCount>& reps) 1641cb0ef41Sopenharmony_ci : type_(type), 1651cb0ef41Sopenharmony_ci loop_nesting_level_(loop_nesting_level), 1661cb0ef41Sopenharmony_ci representations_(reps) {} 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci ~GraphAssemblerLabel() { DCHECK(IsBound() || merged_count_ == 0); } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci private: 1711cb0ef41Sopenharmony_ci friend class GraphAssembler; 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci void SetBound() { 1741cb0ef41Sopenharmony_ci DCHECK(!IsBound()); 1751cb0ef41Sopenharmony_ci is_bound_ = true; 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci bool IsBound() const { return is_bound_; } 1781cb0ef41Sopenharmony_ci bool IsDeferred() const { 1791cb0ef41Sopenharmony_ci return type_ == GraphAssemblerLabelType::kDeferred; 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci bool IsLoop() const { return type_ == GraphAssemblerLabelType::kLoop; } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci bool is_bound_ = false; 1841cb0ef41Sopenharmony_ci const GraphAssemblerLabelType type_; 1851cb0ef41Sopenharmony_ci const int loop_nesting_level_; 1861cb0ef41Sopenharmony_ci size_t merged_count_ = 0; 1871cb0ef41Sopenharmony_ci Node* effect_; 1881cb0ef41Sopenharmony_ci Node* control_; 1891cb0ef41Sopenharmony_ci std::array<Node*, VarCount> bindings_; 1901cb0ef41Sopenharmony_ci const std::array<MachineRepresentation, VarCount> representations_; 1911cb0ef41Sopenharmony_ci}; 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ciusing NodeChangedCallback = std::function<void(Node*)>; 1941cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE GraphAssembler { 1951cb0ef41Sopenharmony_ci public: 1961cb0ef41Sopenharmony_ci // Constructs a GraphAssembler. If {schedule} is not null, the graph assembler 1971cb0ef41Sopenharmony_ci // will maintain the schedule as it updates blocks. 1981cb0ef41Sopenharmony_ci GraphAssembler( 1991cb0ef41Sopenharmony_ci MachineGraph* jsgraph, Zone* zone, 2001cb0ef41Sopenharmony_ci base::Optional<NodeChangedCallback> node_changed_callback = base::nullopt, 2011cb0ef41Sopenharmony_ci bool mark_loop_exits = false); 2021cb0ef41Sopenharmony_ci virtual ~GraphAssembler(); 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci void Reset(); 2051cb0ef41Sopenharmony_ci void InitializeEffectControl(Node* effect, Node* control); 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci // Create label. 2081cb0ef41Sopenharmony_ci template <typename... Reps> 2091cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Reps)> MakeLabelFor( 2101cb0ef41Sopenharmony_ci GraphAssemblerLabelType type, Reps... reps) { 2111cb0ef41Sopenharmony_ci std::array<MachineRepresentation, sizeof...(Reps)> reps_array = {reps...}; 2121cb0ef41Sopenharmony_ci return MakeLabel<sizeof...(Reps)>(reps_array, type); 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci // As above, but with an std::array of machine representations. 2161cb0ef41Sopenharmony_ci template <int VarCount> 2171cb0ef41Sopenharmony_ci GraphAssemblerLabel<VarCount> MakeLabel( 2181cb0ef41Sopenharmony_ci std::array<MachineRepresentation, VarCount> reps_array, 2191cb0ef41Sopenharmony_ci GraphAssemblerLabelType type) { 2201cb0ef41Sopenharmony_ci return GraphAssemblerLabel<VarCount>(type, loop_nesting_level_, reps_array); 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci // Convenience wrapper for creating non-deferred labels. 2241cb0ef41Sopenharmony_ci template <typename... Reps> 2251cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Reps)> MakeLabel(Reps... reps) { 2261cb0ef41Sopenharmony_ci return MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, reps...); 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci // Convenience wrapper for creating loop labels. 2301cb0ef41Sopenharmony_ci template <typename... Reps> 2311cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Reps)> MakeLoopLabel(Reps... reps) { 2321cb0ef41Sopenharmony_ci return MakeLabelFor(GraphAssemblerLabelType::kLoop, reps...); 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci // Convenience wrapper for creating deferred labels. 2361cb0ef41Sopenharmony_ci template <typename... Reps> 2371cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Reps)> MakeDeferredLabel(Reps... reps) { 2381cb0ef41Sopenharmony_ci return MakeLabelFor(GraphAssemblerLabelType::kDeferred, reps...); 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci // Value creation. 2421cb0ef41Sopenharmony_ci Node* IntPtrConstant(intptr_t value); 2431cb0ef41Sopenharmony_ci Node* UintPtrConstant(uintptr_t value); 2441cb0ef41Sopenharmony_ci Node* Int32Constant(int32_t value); 2451cb0ef41Sopenharmony_ci Node* Uint32Constant(uint32_t value); 2461cb0ef41Sopenharmony_ci Node* Int64Constant(int64_t value); 2471cb0ef41Sopenharmony_ci Node* Uint64Constant(uint64_t value); 2481cb0ef41Sopenharmony_ci Node* UniqueIntPtrConstant(intptr_t value); 2491cb0ef41Sopenharmony_ci Node* Float64Constant(double value); 2501cb0ef41Sopenharmony_ci Node* Projection(int index, Node* value); 2511cb0ef41Sopenharmony_ci Node* ExternalConstant(ExternalReference ref); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci Node* Parameter(int index); 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci Node* LoadFramePointer(); 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci Node* LoadHeapNumberValue(Node* heap_number); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci#define PURE_UNOP_DECL(Name) Node* Name(Node* input); 2601cb0ef41Sopenharmony_ci PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL) 2611cb0ef41Sopenharmony_ci#undef PURE_UNOP_DECL 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci#define BINOP_DECL(Name) Node* Name(Node* left, Node* right); 2641cb0ef41Sopenharmony_ci PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL) 2651cb0ef41Sopenharmony_ci CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL) 2661cb0ef41Sopenharmony_ci#undef BINOP_DECL 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING 2691cb0ef41Sopenharmony_ci Node* PackMapWord(TNode<Map> map); 2701cb0ef41Sopenharmony_ci TNode<Map> UnpackMapWord(Node* map_word); 2711cb0ef41Sopenharmony_ci#endif 2721cb0ef41Sopenharmony_ci TNode<Map> LoadMap(Node* object); 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci Node* DebugBreak(); 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci // Unreachable nodes are similar to Goto in that they reset effect/control to 2771cb0ef41Sopenharmony_ci // nullptr and it's thus not possible to append other nodes without first 2781cb0ef41Sopenharmony_ci // binding a new label. 2791cb0ef41Sopenharmony_ci // The block_updater_successor label is a crutch to work around block updater 2801cb0ef41Sopenharmony_ci // weaknesses (see the related comment in ConnectUnreachableToEnd); if the 2811cb0ef41Sopenharmony_ci // block updater exists, we cannot connect unreachable to end, instead we 2821cb0ef41Sopenharmony_ci // must preserve the Goto pattern. 2831cb0ef41Sopenharmony_ci Node* Unreachable(GraphAssemblerLabel<0u>* block_updater_successor = nullptr); 2841cb0ef41Sopenharmony_ci // This special variant doesn't connect the Unreachable node to end, and does 2851cb0ef41Sopenharmony_ci // not reset current effect/control. Intended only for special use-cases like 2861cb0ef41Sopenharmony_ci // lowering DeadValue. 2871cb0ef41Sopenharmony_ci Node* UnreachableWithoutConnectToEnd(); 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci Node* IntPtrEqual(Node* left, Node* right); 2901cb0ef41Sopenharmony_ci Node* TaggedEqual(Node* left, Node* right); 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci Node* SmiSub(Node* left, Node* right); 2931cb0ef41Sopenharmony_ci Node* SmiLessThan(Node* left, Node* right); 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci Node* Float64RoundDown(Node* value); 2961cb0ef41Sopenharmony_ci Node* Float64RoundTruncate(Node* value); 2971cb0ef41Sopenharmony_ci Node* TruncateFloat64ToInt64(Node* value, TruncateKind kind); 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci Node* BitcastWordToTagged(Node* value); 3001cb0ef41Sopenharmony_ci Node* BitcastWordToTaggedSigned(Node* value); 3011cb0ef41Sopenharmony_ci Node* BitcastTaggedToWord(Node* value); 3021cb0ef41Sopenharmony_ci Node* BitcastTaggedToWordForTagAndSmiBits(Node* value); 3031cb0ef41Sopenharmony_ci Node* BitcastMaybeObjectToWord(Node* value); 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci Node* TypeGuard(Type type, Node* value); 3061cb0ef41Sopenharmony_ci Node* Checkpoint(FrameState frame_state); 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci TNode<RawPtrT> StackSlot(int size, int alignment); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value); 3111cb0ef41Sopenharmony_ci Node* Store(StoreRepresentation rep, Node* object, int offset, Node* value); 3121cb0ef41Sopenharmony_ci Node* Load(MachineType type, Node* object, Node* offset); 3131cb0ef41Sopenharmony_ci Node* Load(MachineType type, Node* object, int offset); 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci Node* StoreUnaligned(MachineRepresentation rep, Node* object, Node* offset, 3161cb0ef41Sopenharmony_ci Node* value); 3171cb0ef41Sopenharmony_ci Node* LoadUnaligned(MachineType type, Node* object, Node* offset); 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci Node* ProtectedStore(MachineRepresentation rep, Node* object, Node* offset, 3201cb0ef41Sopenharmony_ci Node* value); 3211cb0ef41Sopenharmony_ci Node* ProtectedLoad(MachineType type, Node* object, Node* offset); 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci Node* Retain(Node* buffer); 3241cb0ef41Sopenharmony_ci Node* UnsafePointerAdd(Node* base, Node* external); 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci Node* DeoptimizeIf(DeoptimizeReason reason, FeedbackSource const& feedback, 3271cb0ef41Sopenharmony_ci Node* condition, Node* frame_state); 3281cb0ef41Sopenharmony_ci Node* DeoptimizeIfNot(DeoptimizeReason reason, FeedbackSource const& feedback, 3291cb0ef41Sopenharmony_ci Node* condition, Node* frame_state); 3301cb0ef41Sopenharmony_ci TNode<Object> Call(const CallDescriptor* call_descriptor, int inputs_size, 3311cb0ef41Sopenharmony_ci Node** inputs); 3321cb0ef41Sopenharmony_ci TNode<Object> Call(const Operator* op, int inputs_size, Node** inputs); 3331cb0ef41Sopenharmony_ci template <typename... Args> 3341cb0ef41Sopenharmony_ci TNode<Object> Call(const CallDescriptor* call_descriptor, Node* first_arg, 3351cb0ef41Sopenharmony_ci Args... args); 3361cb0ef41Sopenharmony_ci template <typename... Args> 3371cb0ef41Sopenharmony_ci TNode<Object> Call(const Operator* op, Node* first_arg, Args... args); 3381cb0ef41Sopenharmony_ci void TailCall(const CallDescriptor* call_descriptor, int inputs_size, 3391cb0ef41Sopenharmony_ci Node** inputs); 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci // Basic control operations. 3421cb0ef41Sopenharmony_ci template <size_t VarCount> 3431cb0ef41Sopenharmony_ci void Bind(GraphAssemblerLabel<VarCount>* label); 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci template <typename... Vars> 3461cb0ef41Sopenharmony_ci void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...); 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci // Branch hints are inferred from if_true/if_false deferred states. 3491cb0ef41Sopenharmony_ci void BranchWithCriticalSafetyCheck(Node* condition, 3501cb0ef41Sopenharmony_ci GraphAssemblerLabel<0u>* if_true, 3511cb0ef41Sopenharmony_ci GraphAssemblerLabel<0u>* if_false); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci // Branch hints are inferred from if_true/if_false deferred states. 3541cb0ef41Sopenharmony_ci template <typename... Vars> 3551cb0ef41Sopenharmony_ci void Branch(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* if_true, 3561cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_false, Vars...); 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci template <typename... Vars> 3591cb0ef41Sopenharmony_ci void BranchWithHint(Node* condition, 3601cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_true, 3611cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_false, 3621cb0ef41Sopenharmony_ci BranchHint hint, Vars...); 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci // Control helpers. 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci // {GotoIf(c, l, h)} is equivalent to {BranchWithHint(c, l, templ, h); 3671cb0ef41Sopenharmony_ci // Bind(templ)}. 3681cb0ef41Sopenharmony_ci template <typename... Vars> 3691cb0ef41Sopenharmony_ci void GotoIf(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label, 3701cb0ef41Sopenharmony_ci BranchHint hint, Vars...); 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci // {GotoIfNot(c, l, h)} is equivalent to {BranchWithHint(c, templ, l, h); 3731cb0ef41Sopenharmony_ci // Bind(templ)}. 3741cb0ef41Sopenharmony_ci // The branch hint refers to the expected outcome of the provided condition, 3751cb0ef41Sopenharmony_ci // so {GotoIfNot(..., BranchHint::kTrue)} means "optimize for the case where 3761cb0ef41Sopenharmony_ci // the branch is *not* taken". 3771cb0ef41Sopenharmony_ci template <typename... Vars> 3781cb0ef41Sopenharmony_ci void GotoIfNot(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label, 3791cb0ef41Sopenharmony_ci BranchHint hint, Vars...); 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}. 3821cb0ef41Sopenharmony_ci template <typename... Vars> 3831cb0ef41Sopenharmony_ci void GotoIf(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label, 3841cb0ef41Sopenharmony_ci Vars...); 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ci // {GotoIfNot(c, l)} is equivalent to {Branch(c, templ, l);Bind(templ)}. 3871cb0ef41Sopenharmony_ci template <typename... Vars> 3881cb0ef41Sopenharmony_ci void GotoIfNot(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label, 3891cb0ef41Sopenharmony_ci Vars...); 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci bool HasActiveBlock() const { 3921cb0ef41Sopenharmony_ci // This is false if the current block has been terminated (e.g. by a Goto or 3931cb0ef41Sopenharmony_ci // Unreachable). In that case, a new label must be bound before we can 3941cb0ef41Sopenharmony_ci // continue emitting nodes. 3951cb0ef41Sopenharmony_ci return control() != nullptr; 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci // Updates current effect and control based on outputs of {node}. 3991cb0ef41Sopenharmony_ci V8_INLINE void UpdateEffectControlWith(Node* node) { 4001cb0ef41Sopenharmony_ci if (node->op()->EffectOutputCount() > 0) { 4011cb0ef41Sopenharmony_ci effect_ = node; 4021cb0ef41Sopenharmony_ci } 4031cb0ef41Sopenharmony_ci if (node->op()->ControlOutputCount() > 0) { 4041cb0ef41Sopenharmony_ci control_ = node; 4051cb0ef41Sopenharmony_ci } 4061cb0ef41Sopenharmony_ci } 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci // Adds {node} to the current position and updates assembler's current effect 4091cb0ef41Sopenharmony_ci // and control. 4101cb0ef41Sopenharmony_ci Node* AddNode(Node* node); 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci template <typename T> 4131cb0ef41Sopenharmony_ci TNode<T> AddNode(Node* node) { 4141cb0ef41Sopenharmony_ci return TNode<T>::UncheckedCast(AddNode(node)); 4151cb0ef41Sopenharmony_ci } 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci void ConnectUnreachableToEnd(); 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci // Add an inline reducers such that nodes added to the graph will be run 4201cb0ef41Sopenharmony_ci // through the reducers and possibly further lowered. Each reducer should 4211cb0ef41Sopenharmony_ci // operate on independent node types since once a reducer changes a node we 4221cb0ef41Sopenharmony_ci // no longer run any other reducers on that node. The reducers should also 4231cb0ef41Sopenharmony_ci // only generate new nodes that wouldn't be further reduced, as new nodes 4241cb0ef41Sopenharmony_ci // generated by a reducer won't be passed through the reducers again. 4251cb0ef41Sopenharmony_ci void AddInlineReducer(Reducer* reducer) { 4261cb0ef41Sopenharmony_ci inline_reducers_.push_back(reducer); 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci Control control() const { return Control(control_); } 4301cb0ef41Sopenharmony_ci Effect effect() const { return Effect(effect_); } 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci protected: 4331cb0ef41Sopenharmony_ci template <typename... Vars> 4341cb0ef41Sopenharmony_ci void MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars... vars); 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ci V8_INLINE Node* AddClonedNode(Node* node); 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci MachineGraph* mcgraph() const { return mcgraph_; } 4391cb0ef41Sopenharmony_ci Graph* graph() const { return mcgraph_->graph(); } 4401cb0ef41Sopenharmony_ci Zone* temp_zone() const { return temp_zone_; } 4411cb0ef41Sopenharmony_ci CommonOperatorBuilder* common() const { return mcgraph()->common(); } 4421cb0ef41Sopenharmony_ci MachineOperatorBuilder* machine() const { return mcgraph()->machine(); } 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci // Updates machinery for creating {LoopExit,LoopExitEffect,LoopExitValue} 4451cb0ef41Sopenharmony_ci // nodes on loop exits (which are necessary for loop peeling). 4461cb0ef41Sopenharmony_ci // 4471cb0ef41Sopenharmony_ci // All labels created while a LoopScope is live are considered to be inside 4481cb0ef41Sopenharmony_ci // the loop. 4491cb0ef41Sopenharmony_ci template <MachineRepresentation... Reps> 4501cb0ef41Sopenharmony_ci class V8_NODISCARD LoopScope final { 4511cb0ef41Sopenharmony_ci private: 4521cb0ef41Sopenharmony_ci // The internal scope is only here to increment the graph assembler's 4531cb0ef41Sopenharmony_ci // nesting level prior to `loop_header_label` creation below. 4541cb0ef41Sopenharmony_ci class V8_NODISCARD LoopScopeInternal { 4551cb0ef41Sopenharmony_ci public: 4561cb0ef41Sopenharmony_ci explicit LoopScopeInternal(GraphAssembler* gasm) 4571cb0ef41Sopenharmony_ci : previous_loop_nesting_level_(gasm->loop_nesting_level_), 4581cb0ef41Sopenharmony_ci gasm_(gasm) { 4591cb0ef41Sopenharmony_ci gasm->loop_nesting_level_++; 4601cb0ef41Sopenharmony_ci } 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci ~LoopScopeInternal() { 4631cb0ef41Sopenharmony_ci gasm_->loop_nesting_level_--; 4641cb0ef41Sopenharmony_ci DCHECK_EQ(gasm_->loop_nesting_level_, previous_loop_nesting_level_); 4651cb0ef41Sopenharmony_ci } 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci private: 4681cb0ef41Sopenharmony_ci const int previous_loop_nesting_level_; 4691cb0ef41Sopenharmony_ci GraphAssembler* const gasm_; 4701cb0ef41Sopenharmony_ci }; 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci public: 4731cb0ef41Sopenharmony_ci explicit LoopScope(GraphAssembler* gasm) 4741cb0ef41Sopenharmony_ci : internal_scope_(gasm), 4751cb0ef41Sopenharmony_ci gasm_(gasm), 4761cb0ef41Sopenharmony_ci loop_header_label_(gasm->MakeLoopLabel(Reps...)) { 4771cb0ef41Sopenharmony_ci // This feature may only be used if it has been enabled. 4781cb0ef41Sopenharmony_ci DCHECK(gasm_->mark_loop_exits_); 4791cb0ef41Sopenharmony_ci gasm->loop_headers_.push_back(&loop_header_label_.control_); 4801cb0ef41Sopenharmony_ci DCHECK_EQ(static_cast<int>(gasm_->loop_headers_.size()), 4811cb0ef41Sopenharmony_ci gasm_->loop_nesting_level_); 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci ~LoopScope() { 4851cb0ef41Sopenharmony_ci DCHECK_EQ(static_cast<int>(gasm_->loop_headers_.size()), 4861cb0ef41Sopenharmony_ci gasm_->loop_nesting_level_); 4871cb0ef41Sopenharmony_ci gasm_->loop_headers_.pop_back(); 4881cb0ef41Sopenharmony_ci } 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Reps)>* loop_header_label() { 4911cb0ef41Sopenharmony_ci return &loop_header_label_; 4921cb0ef41Sopenharmony_ci } 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci private: 4951cb0ef41Sopenharmony_ci const LoopScopeInternal internal_scope_; 4961cb0ef41Sopenharmony_ci GraphAssembler* const gasm_; 4971cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Reps)> loop_header_label_; 4981cb0ef41Sopenharmony_ci }; 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci // Upon destruction, restores effect and control to the state at construction. 5011cb0ef41Sopenharmony_ci class V8_NODISCARD RestoreEffectControlScope { 5021cb0ef41Sopenharmony_ci public: 5031cb0ef41Sopenharmony_ci explicit RestoreEffectControlScope(GraphAssembler* gasm) 5041cb0ef41Sopenharmony_ci : gasm_(gasm), effect_(gasm->effect()), control_(gasm->control()) {} 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci ~RestoreEffectControlScope() { 5071cb0ef41Sopenharmony_ci gasm_->effect_ = effect_; 5081cb0ef41Sopenharmony_ci gasm_->control_ = control_; 5091cb0ef41Sopenharmony_ci } 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ci private: 5121cb0ef41Sopenharmony_ci GraphAssembler* const gasm_; 5131cb0ef41Sopenharmony_ci const Effect effect_; 5141cb0ef41Sopenharmony_ci const Control control_; 5151cb0ef41Sopenharmony_ci }; 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci private: 5181cb0ef41Sopenharmony_ci class BlockInlineReduction; 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_ci template <typename... Vars> 5211cb0ef41Sopenharmony_ci void BranchImpl(Node* condition, 5221cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_true, 5231cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_false, 5241cb0ef41Sopenharmony_ci BranchHint hint, Vars...); 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_ci Zone* temp_zone_; 5271cb0ef41Sopenharmony_ci MachineGraph* mcgraph_; 5281cb0ef41Sopenharmony_ci Node* effect_; 5291cb0ef41Sopenharmony_ci Node* control_; 5301cb0ef41Sopenharmony_ci // {node_changed_callback_} should be called when a node outside the 5311cb0ef41Sopenharmony_ci // subgraph created by the graph assembler changes. 5321cb0ef41Sopenharmony_ci base::Optional<NodeChangedCallback> node_changed_callback_; 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci // Inline reducers enable reductions to be performed to nodes as they are 5351cb0ef41Sopenharmony_ci // added to the graph with the graph assembler. 5361cb0ef41Sopenharmony_ci ZoneVector<Reducer*> inline_reducers_; 5371cb0ef41Sopenharmony_ci bool inline_reductions_blocked_; 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci // Track loop information in order to properly mark loop exits with 5401cb0ef41Sopenharmony_ci // {LoopExit,LoopExitEffect,LoopExitValue} nodes. The outermost level has 5411cb0ef41Sopenharmony_ci // a nesting level of 0. See also GraphAssembler::LoopScope. 5421cb0ef41Sopenharmony_ci int loop_nesting_level_ = 0; 5431cb0ef41Sopenharmony_ci ZoneVector<Node**> loop_headers_; 5441cb0ef41Sopenharmony_ci 5451cb0ef41Sopenharmony_ci // Feature configuration. As more features are added, this should be turned 5461cb0ef41Sopenharmony_ci // into a bitfield. 5471cb0ef41Sopenharmony_ci const bool mark_loop_exits_; 5481cb0ef41Sopenharmony_ci}; 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_citemplate <size_t VarCount> 5511cb0ef41Sopenharmony_ciNode* GraphAssemblerLabel<VarCount>::PhiAt(size_t index) { 5521cb0ef41Sopenharmony_ci DCHECK(IsBound()); 5531cb0ef41Sopenharmony_ci DCHECK_LT(index, VarCount); 5541cb0ef41Sopenharmony_ci return bindings_[index]; 5551cb0ef41Sopenharmony_ci} 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_citemplate <typename... Vars> 5581cb0ef41Sopenharmony_civoid GraphAssembler::MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label, 5591cb0ef41Sopenharmony_ci Vars... vars) { 5601cb0ef41Sopenharmony_ci RestoreEffectControlScope restore_effect_control_scope(this); 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ci const int merged_count = static_cast<int>(label->merged_count_); 5631cb0ef41Sopenharmony_ci static constexpr int kVarCount = sizeof...(vars); 5641cb0ef41Sopenharmony_ci std::array<Node*, kVarCount> var_array = {vars...}; 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ci const bool is_loop_exit = label->loop_nesting_level_ != loop_nesting_level_; 5671cb0ef41Sopenharmony_ci if (is_loop_exit) { 5681cb0ef41Sopenharmony_ci // This feature may only be used if it has been enabled. 5691cb0ef41Sopenharmony_ci USE(mark_loop_exits_); 5701cb0ef41Sopenharmony_ci DCHECK(mark_loop_exits_); 5711cb0ef41Sopenharmony_ci // Jumping from loops to loops not supported. 5721cb0ef41Sopenharmony_ci DCHECK(!label->IsLoop()); 5731cb0ef41Sopenharmony_ci // Currently only the simple case of jumping one level is supported. 5741cb0ef41Sopenharmony_ci DCHECK_EQ(label->loop_nesting_level_, loop_nesting_level_ - 1); 5751cb0ef41Sopenharmony_ci DCHECK(!loop_headers_.empty()); 5761cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(*loop_headers_.back()); 5771cb0ef41Sopenharmony_ci 5781cb0ef41Sopenharmony_ci // Mark this exit to enable loop peeling. 5791cb0ef41Sopenharmony_ci AddNode(graph()->NewNode(common()->LoopExit(), control(), 5801cb0ef41Sopenharmony_ci *loop_headers_.back())); 5811cb0ef41Sopenharmony_ci AddNode(graph()->NewNode(common()->LoopExitEffect(), effect(), control())); 5821cb0ef41Sopenharmony_ci for (size_t i = 0; i < kVarCount; i++) { 5831cb0ef41Sopenharmony_ci var_array[i] = AddNode(graph()->NewNode( 5841cb0ef41Sopenharmony_ci common()->LoopExitValue(MachineRepresentation::kTagged), var_array[i], 5851cb0ef41Sopenharmony_ci control())); 5861cb0ef41Sopenharmony_ci } 5871cb0ef41Sopenharmony_ci } 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci if (label->IsLoop()) { 5901cb0ef41Sopenharmony_ci if (merged_count == 0) { 5911cb0ef41Sopenharmony_ci DCHECK(!label->IsBound()); 5921cb0ef41Sopenharmony_ci label->control_ = 5931cb0ef41Sopenharmony_ci graph()->NewNode(common()->Loop(2), control(), control()); 5941cb0ef41Sopenharmony_ci label->effect_ = graph()->NewNode(common()->EffectPhi(2), effect(), 5951cb0ef41Sopenharmony_ci effect(), label->control_); 5961cb0ef41Sopenharmony_ci Node* terminate = graph()->NewNode(common()->Terminate(), label->effect_, 5971cb0ef41Sopenharmony_ci label->control_); 5981cb0ef41Sopenharmony_ci NodeProperties::MergeControlToEnd(graph(), common(), terminate); 5991cb0ef41Sopenharmony_ci for (size_t i = 0; i < kVarCount; i++) { 6001cb0ef41Sopenharmony_ci label->bindings_[i] = 6011cb0ef41Sopenharmony_ci graph()->NewNode(common()->Phi(label->representations_[i], 2), 6021cb0ef41Sopenharmony_ci var_array[i], var_array[i], label->control_); 6031cb0ef41Sopenharmony_ci } 6041cb0ef41Sopenharmony_ci } else { 6051cb0ef41Sopenharmony_ci DCHECK(label->IsBound()); 6061cb0ef41Sopenharmony_ci DCHECK_EQ(1, merged_count); 6071cb0ef41Sopenharmony_ci label->control_->ReplaceInput(1, control()); 6081cb0ef41Sopenharmony_ci label->effect_->ReplaceInput(1, effect()); 6091cb0ef41Sopenharmony_ci for (size_t i = 0; i < kVarCount; i++) { 6101cb0ef41Sopenharmony_ci label->bindings_[i]->ReplaceInput(1, var_array[i]); 6111cb0ef41Sopenharmony_ci CHECK(!NodeProperties::IsTyped(var_array[i])); // Unsupported. 6121cb0ef41Sopenharmony_ci } 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci } else { 6151cb0ef41Sopenharmony_ci DCHECK(!label->IsLoop()); 6161cb0ef41Sopenharmony_ci DCHECK(!label->IsBound()); 6171cb0ef41Sopenharmony_ci if (merged_count == 0) { 6181cb0ef41Sopenharmony_ci // Just set the control, effect and variables directly. 6191cb0ef41Sopenharmony_ci label->control_ = control(); 6201cb0ef41Sopenharmony_ci label->effect_ = effect(); 6211cb0ef41Sopenharmony_ci for (size_t i = 0; i < kVarCount; i++) { 6221cb0ef41Sopenharmony_ci label->bindings_[i] = var_array[i]; 6231cb0ef41Sopenharmony_ci } 6241cb0ef41Sopenharmony_ci } else if (merged_count == 1) { 6251cb0ef41Sopenharmony_ci // Create merge, effect phi and a phi for each variable. 6261cb0ef41Sopenharmony_ci label->control_ = 6271cb0ef41Sopenharmony_ci graph()->NewNode(common()->Merge(2), label->control_, control()); 6281cb0ef41Sopenharmony_ci label->effect_ = graph()->NewNode(common()->EffectPhi(2), label->effect_, 6291cb0ef41Sopenharmony_ci effect(), label->control_); 6301cb0ef41Sopenharmony_ci for (size_t i = 0; i < kVarCount; i++) { 6311cb0ef41Sopenharmony_ci label->bindings_[i] = graph()->NewNode( 6321cb0ef41Sopenharmony_ci common()->Phi(label->representations_[i], 2), label->bindings_[i], 6331cb0ef41Sopenharmony_ci var_array[i], label->control_); 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci } else { 6361cb0ef41Sopenharmony_ci // Append to the merge, effect phi and phis. 6371cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kMerge, label->control_->opcode()); 6381cb0ef41Sopenharmony_ci label->control_->AppendInput(graph()->zone(), control()); 6391cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(label->control_, 6401cb0ef41Sopenharmony_ci common()->Merge(merged_count + 1)); 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kEffectPhi, label->effect_->opcode()); 6431cb0ef41Sopenharmony_ci label->effect_->ReplaceInput(merged_count, effect()); 6441cb0ef41Sopenharmony_ci label->effect_->AppendInput(graph()->zone(), label->control_); 6451cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(label->effect_, 6461cb0ef41Sopenharmony_ci common()->EffectPhi(merged_count + 1)); 6471cb0ef41Sopenharmony_ci 6481cb0ef41Sopenharmony_ci for (size_t i = 0; i < kVarCount; i++) { 6491cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kPhi, label->bindings_[i]->opcode()); 6501cb0ef41Sopenharmony_ci label->bindings_[i]->ReplaceInput(merged_count, var_array[i]); 6511cb0ef41Sopenharmony_ci label->bindings_[i]->AppendInput(graph()->zone(), label->control_); 6521cb0ef41Sopenharmony_ci NodeProperties::ChangeOp( 6531cb0ef41Sopenharmony_ci label->bindings_[i], 6541cb0ef41Sopenharmony_ci common()->Phi(label->representations_[i], merged_count + 1)); 6551cb0ef41Sopenharmony_ci if (NodeProperties::IsTyped(label->bindings_[i])) { 6561cb0ef41Sopenharmony_ci CHECK(NodeProperties::IsTyped(var_array[i])); 6571cb0ef41Sopenharmony_ci Type old_type = NodeProperties::GetType(label->bindings_[i]); 6581cb0ef41Sopenharmony_ci Type new_type = Type::Union( 6591cb0ef41Sopenharmony_ci old_type, NodeProperties::GetType(var_array[i]), graph()->zone()); 6601cb0ef41Sopenharmony_ci NodeProperties::SetType(label->bindings_[i], new_type); 6611cb0ef41Sopenharmony_ci } 6621cb0ef41Sopenharmony_ci } 6631cb0ef41Sopenharmony_ci } 6641cb0ef41Sopenharmony_ci } 6651cb0ef41Sopenharmony_ci label->merged_count_++; 6661cb0ef41Sopenharmony_ci} 6671cb0ef41Sopenharmony_ci 6681cb0ef41Sopenharmony_citemplate <size_t VarCount> 6691cb0ef41Sopenharmony_civoid GraphAssembler::Bind(GraphAssemblerLabel<VarCount>* label) { 6701cb0ef41Sopenharmony_ci DCHECK_NULL(control()); 6711cb0ef41Sopenharmony_ci DCHECK_NULL(effect()); 6721cb0ef41Sopenharmony_ci DCHECK_LT(0, label->merged_count_); 6731cb0ef41Sopenharmony_ci DCHECK_EQ(label->loop_nesting_level_, loop_nesting_level_); 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_ci control_ = label->control_; 6761cb0ef41Sopenharmony_ci effect_ = label->effect_; 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ci label->SetBound(); 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ci if (label->merged_count_ > 1 || label->IsLoop()) { 6811cb0ef41Sopenharmony_ci AddNode(label->control_); 6821cb0ef41Sopenharmony_ci AddNode(label->effect_); 6831cb0ef41Sopenharmony_ci for (size_t i = 0; i < VarCount; i++) { 6841cb0ef41Sopenharmony_ci AddNode(label->bindings_[i]); 6851cb0ef41Sopenharmony_ci } 6861cb0ef41Sopenharmony_ci } else { 6871cb0ef41Sopenharmony_ci // If the basic block does not have a control node, insert a dummy 6881cb0ef41Sopenharmony_ci // Merge node, so that other passes have a control node to start from. 6891cb0ef41Sopenharmony_ci control_ = AddNode(graph()->NewNode(common()->Merge(1), control())); 6901cb0ef41Sopenharmony_ci } 6911cb0ef41Sopenharmony_ci} 6921cb0ef41Sopenharmony_ci 6931cb0ef41Sopenharmony_citemplate <typename... Vars> 6941cb0ef41Sopenharmony_civoid GraphAssembler::Branch(Node* condition, 6951cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_true, 6961cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_false, 6971cb0ef41Sopenharmony_ci Vars... vars) { 6981cb0ef41Sopenharmony_ci BranchHint hint = BranchHint::kNone; 6991cb0ef41Sopenharmony_ci if (if_true->IsDeferred() != if_false->IsDeferred()) { 7001cb0ef41Sopenharmony_ci hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse; 7011cb0ef41Sopenharmony_ci } 7021cb0ef41Sopenharmony_ci 7031cb0ef41Sopenharmony_ci BranchImpl(condition, if_true, if_false, hint, vars...); 7041cb0ef41Sopenharmony_ci} 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_citemplate <typename... Vars> 7071cb0ef41Sopenharmony_civoid GraphAssembler::BranchWithHint( 7081cb0ef41Sopenharmony_ci Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* if_true, 7091cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_false, BranchHint hint, 7101cb0ef41Sopenharmony_ci Vars... vars) { 7111cb0ef41Sopenharmony_ci BranchImpl(condition, if_true, if_false, hint, vars...); 7121cb0ef41Sopenharmony_ci} 7131cb0ef41Sopenharmony_ci 7141cb0ef41Sopenharmony_citemplate <typename... Vars> 7151cb0ef41Sopenharmony_civoid GraphAssembler::BranchImpl(Node* condition, 7161cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_true, 7171cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* if_false, 7181cb0ef41Sopenharmony_ci BranchHint hint, Vars... vars) { 7191cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(control()); 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci Node* branch = graph()->NewNode(common()->Branch(hint), condition, control()); 7221cb0ef41Sopenharmony_ci 7231cb0ef41Sopenharmony_ci control_ = graph()->NewNode(common()->IfTrue(), branch); 7241cb0ef41Sopenharmony_ci MergeState(if_true, vars...); 7251cb0ef41Sopenharmony_ci 7261cb0ef41Sopenharmony_ci control_ = graph()->NewNode(common()->IfFalse(), branch); 7271cb0ef41Sopenharmony_ci MergeState(if_false, vars...); 7281cb0ef41Sopenharmony_ci 7291cb0ef41Sopenharmony_ci control_ = nullptr; 7301cb0ef41Sopenharmony_ci effect_ = nullptr; 7311cb0ef41Sopenharmony_ci} 7321cb0ef41Sopenharmony_ci 7331cb0ef41Sopenharmony_citemplate <typename... Vars> 7341cb0ef41Sopenharmony_civoid GraphAssembler::Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, 7351cb0ef41Sopenharmony_ci Vars... vars) { 7361cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(control()); 7371cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(effect()); 7381cb0ef41Sopenharmony_ci MergeState(label, vars...); 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_ci control_ = nullptr; 7411cb0ef41Sopenharmony_ci effect_ = nullptr; 7421cb0ef41Sopenharmony_ci} 7431cb0ef41Sopenharmony_ci 7441cb0ef41Sopenharmony_citemplate <typename... Vars> 7451cb0ef41Sopenharmony_civoid GraphAssembler::GotoIf(Node* condition, 7461cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* label, 7471cb0ef41Sopenharmony_ci BranchHint hint, Vars... vars) { 7481cb0ef41Sopenharmony_ci Node* branch = graph()->NewNode(common()->Branch(hint), condition, control()); 7491cb0ef41Sopenharmony_ci 7501cb0ef41Sopenharmony_ci control_ = graph()->NewNode(common()->IfTrue(), branch); 7511cb0ef41Sopenharmony_ci MergeState(label, vars...); 7521cb0ef41Sopenharmony_ci 7531cb0ef41Sopenharmony_ci control_ = AddNode(graph()->NewNode(common()->IfFalse(), branch)); 7541cb0ef41Sopenharmony_ci} 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_citemplate <typename... Vars> 7571cb0ef41Sopenharmony_civoid GraphAssembler::GotoIfNot(Node* condition, 7581cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* label, 7591cb0ef41Sopenharmony_ci BranchHint hint, Vars... vars) { 7601cb0ef41Sopenharmony_ci Node* branch = graph()->NewNode(common()->Branch(hint), condition, control()); 7611cb0ef41Sopenharmony_ci 7621cb0ef41Sopenharmony_ci control_ = graph()->NewNode(common()->IfFalse(), branch); 7631cb0ef41Sopenharmony_ci MergeState(label, vars...); 7641cb0ef41Sopenharmony_ci 7651cb0ef41Sopenharmony_ci control_ = AddNode(graph()->NewNode(common()->IfTrue(), branch)); 7661cb0ef41Sopenharmony_ci} 7671cb0ef41Sopenharmony_ci 7681cb0ef41Sopenharmony_citemplate <typename... Vars> 7691cb0ef41Sopenharmony_civoid GraphAssembler::GotoIf(Node* condition, 7701cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* label, 7711cb0ef41Sopenharmony_ci Vars... vars) { 7721cb0ef41Sopenharmony_ci BranchHint hint = 7731cb0ef41Sopenharmony_ci label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone; 7741cb0ef41Sopenharmony_ci return GotoIf(condition, label, hint, vars...); 7751cb0ef41Sopenharmony_ci} 7761cb0ef41Sopenharmony_ci 7771cb0ef41Sopenharmony_citemplate <typename... Vars> 7781cb0ef41Sopenharmony_civoid GraphAssembler::GotoIfNot(Node* condition, 7791cb0ef41Sopenharmony_ci GraphAssemblerLabel<sizeof...(Vars)>* label, 7801cb0ef41Sopenharmony_ci Vars... vars) { 7811cb0ef41Sopenharmony_ci BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone; 7821cb0ef41Sopenharmony_ci return GotoIfNot(condition, label, hint, vars...); 7831cb0ef41Sopenharmony_ci} 7841cb0ef41Sopenharmony_ci 7851cb0ef41Sopenharmony_citemplate <typename... Args> 7861cb0ef41Sopenharmony_ciTNode<Object> GraphAssembler::Call(const CallDescriptor* call_descriptor, 7871cb0ef41Sopenharmony_ci Node* first_arg, Args... args) { 7881cb0ef41Sopenharmony_ci const Operator* op = common()->Call(call_descriptor); 7891cb0ef41Sopenharmony_ci return Call(op, first_arg, args...); 7901cb0ef41Sopenharmony_ci} 7911cb0ef41Sopenharmony_ci 7921cb0ef41Sopenharmony_citemplate <typename... Args> 7931cb0ef41Sopenharmony_ciTNode<Object> GraphAssembler::Call(const Operator* op, Node* first_arg, 7941cb0ef41Sopenharmony_ci Args... args) { 7951cb0ef41Sopenharmony_ci Node* args_array[] = {first_arg, args..., effect(), control()}; 7961cb0ef41Sopenharmony_ci int size = static_cast<int>(1 + sizeof...(args)) + op->EffectInputCount() + 7971cb0ef41Sopenharmony_ci op->ControlInputCount(); 7981cb0ef41Sopenharmony_ci return Call(op, size, args_array); 7991cb0ef41Sopenharmony_ci} 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE JSGraphAssembler : public GraphAssembler { 8021cb0ef41Sopenharmony_ci public: 8031cb0ef41Sopenharmony_ci // Constructs a JSGraphAssembler. If {schedule} is not null, the graph 8041cb0ef41Sopenharmony_ci // assembler will maintain the schedule as it updates blocks. 8051cb0ef41Sopenharmony_ci JSGraphAssembler( 8061cb0ef41Sopenharmony_ci JSGraph* jsgraph, Zone* zone, 8071cb0ef41Sopenharmony_ci base::Optional<NodeChangedCallback> node_changed_callback = base::nullopt, 8081cb0ef41Sopenharmony_ci bool mark_loop_exits = false) 8091cb0ef41Sopenharmony_ci : GraphAssembler(jsgraph, zone, node_changed_callback, mark_loop_exits), 8101cb0ef41Sopenharmony_ci jsgraph_(jsgraph) {} 8111cb0ef41Sopenharmony_ci 8121cb0ef41Sopenharmony_ci Node* SmiConstant(int32_t value); 8131cb0ef41Sopenharmony_ci TNode<HeapObject> HeapConstant(Handle<HeapObject> object); 8141cb0ef41Sopenharmony_ci TNode<Object> Constant(const ObjectRef& ref); 8151cb0ef41Sopenharmony_ci TNode<Number> NumberConstant(double value); 8161cb0ef41Sopenharmony_ci Node* CEntryStubConstant(int result_size); 8171cb0ef41Sopenharmony_ci 8181cb0ef41Sopenharmony_ci#define SINGLETON_CONST_DECL(Name, Type) TNode<Type> Name##Constant(); 8191cb0ef41Sopenharmony_ci JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL) 8201cb0ef41Sopenharmony_ci#undef SINGLETON_CONST_DECL 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci#define SINGLETON_CONST_TEST_DECL(Name, ...) \ 8231cb0ef41Sopenharmony_ci TNode<Boolean> Is##Name(TNode<Object> value); 8241cb0ef41Sopenharmony_ci JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_TEST_DECL) 8251cb0ef41Sopenharmony_ci#undef SINGLETON_CONST_TEST_DECL 8261cb0ef41Sopenharmony_ci 8271cb0ef41Sopenharmony_ci Node* Allocate(AllocationType allocation, Node* size); 8281cb0ef41Sopenharmony_ci Node* LoadField(FieldAccess const&, Node* object); 8291cb0ef41Sopenharmony_ci template <typename T> 8301cb0ef41Sopenharmony_ci TNode<T> LoadField(FieldAccess const& access, TNode<HeapObject> object) { 8311cb0ef41Sopenharmony_ci // TODO(jgruber): Investigate issues on ptr compression bots and enable. 8321cb0ef41Sopenharmony_ci // DCHECK(IsMachineRepresentationOf<T>( 8331cb0ef41Sopenharmony_ci // access.machine_type.representation())); 8341cb0ef41Sopenharmony_ci return TNode<T>::UncheckedCast(LoadField(access, object)); 8351cb0ef41Sopenharmony_ci } 8361cb0ef41Sopenharmony_ci Node* LoadElement(ElementAccess const&, Node* object, Node* index); 8371cb0ef41Sopenharmony_ci template <typename T> 8381cb0ef41Sopenharmony_ci TNode<T> LoadElement(ElementAccess const& access, TNode<HeapObject> object, 8391cb0ef41Sopenharmony_ci TNode<Number> index) { 8401cb0ef41Sopenharmony_ci // TODO(jgruber): Investigate issues on ptr compression bots and enable. 8411cb0ef41Sopenharmony_ci // DCHECK(IsMachineRepresentationOf<T>( 8421cb0ef41Sopenharmony_ci // access.machine_type.representation())); 8431cb0ef41Sopenharmony_ci return TNode<T>::UncheckedCast(LoadElement(access, object, index)); 8441cb0ef41Sopenharmony_ci } 8451cb0ef41Sopenharmony_ci Node* StoreField(FieldAccess const&, Node* object, Node* value); 8461cb0ef41Sopenharmony_ci Node* StoreElement(ElementAccess const&, Node* object, Node* index, 8471cb0ef41Sopenharmony_ci Node* value); 8481cb0ef41Sopenharmony_ci void TransitionAndStoreElement(MapRef double_map, MapRef fast_map, 8491cb0ef41Sopenharmony_ci TNode<HeapObject> object, TNode<Number> index, 8501cb0ef41Sopenharmony_ci TNode<Object> value); 8511cb0ef41Sopenharmony_ci TNode<Number> StringLength(TNode<String> string); 8521cb0ef41Sopenharmony_ci TNode<Boolean> ReferenceEqual(TNode<Object> lhs, TNode<Object> rhs); 8531cb0ef41Sopenharmony_ci TNode<Number> PlainPrimitiveToNumber(TNode<Object> value); 8541cb0ef41Sopenharmony_ci TNode<Number> NumberMin(TNode<Number> lhs, TNode<Number> rhs); 8551cb0ef41Sopenharmony_ci TNode<Number> NumberMax(TNode<Number> lhs, TNode<Number> rhs); 8561cb0ef41Sopenharmony_ci TNode<Boolean> NumberEqual(TNode<Number> lhs, TNode<Number> rhs); 8571cb0ef41Sopenharmony_ci TNode<Boolean> NumberLessThan(TNode<Number> lhs, TNode<Number> rhs); 8581cb0ef41Sopenharmony_ci TNode<Boolean> NumberLessThanOrEqual(TNode<Number> lhs, TNode<Number> rhs); 8591cb0ef41Sopenharmony_ci TNode<Number> NumberAdd(TNode<Number> lhs, TNode<Number> rhs); 8601cb0ef41Sopenharmony_ci TNode<Number> NumberSubtract(TNode<Number> lhs, TNode<Number> rhs); 8611cb0ef41Sopenharmony_ci TNode<String> StringSubstring(TNode<String> string, TNode<Number> from, 8621cb0ef41Sopenharmony_ci TNode<Number> to); 8631cb0ef41Sopenharmony_ci TNode<Boolean> ObjectIsCallable(TNode<Object> value); 8641cb0ef41Sopenharmony_ci TNode<Boolean> ObjectIsUndetectable(TNode<Object> value); 8651cb0ef41Sopenharmony_ci Node* CheckIf(Node* cond, DeoptimizeReason reason); 8661cb0ef41Sopenharmony_ci TNode<Boolean> NumberIsFloat64Hole(TNode<Number> value); 8671cb0ef41Sopenharmony_ci TNode<Boolean> ToBoolean(TNode<Object> value); 8681cb0ef41Sopenharmony_ci TNode<Object> ConvertTaggedHoleToUndefined(TNode<Object> value); 8691cb0ef41Sopenharmony_ci TNode<FixedArrayBase> MaybeGrowFastElements(ElementsKind kind, 8701cb0ef41Sopenharmony_ci const FeedbackSource& feedback, 8711cb0ef41Sopenharmony_ci TNode<JSArray> array, 8721cb0ef41Sopenharmony_ci TNode<FixedArrayBase> elements, 8731cb0ef41Sopenharmony_ci TNode<Number> new_length, 8741cb0ef41Sopenharmony_ci TNode<Number> old_length); 8751cb0ef41Sopenharmony_ci Node* StringCharCodeAt(TNode<String> string, TNode<Number> position); 8761cb0ef41Sopenharmony_ci 8771cb0ef41Sopenharmony_ci JSGraph* jsgraph() const { return jsgraph_; } 8781cb0ef41Sopenharmony_ci Isolate* isolate() const { return jsgraph()->isolate(); } 8791cb0ef41Sopenharmony_ci SimplifiedOperatorBuilder* simplified() const { 8801cb0ef41Sopenharmony_ci return jsgraph()->simplified(); 8811cb0ef41Sopenharmony_ci } 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_ci protected: 8841cb0ef41Sopenharmony_ci Operator const* PlainPrimitiveToNumberOperator(); 8851cb0ef41Sopenharmony_ci 8861cb0ef41Sopenharmony_ci private: 8871cb0ef41Sopenharmony_ci JSGraph* jsgraph_; 8881cb0ef41Sopenharmony_ci SetOncePointer<Operator const> to_number_operator_; 8891cb0ef41Sopenharmony_ci}; 8901cb0ef41Sopenharmony_ci 8911cb0ef41Sopenharmony_ci} // namespace compiler 8921cb0ef41Sopenharmony_ci} // namespace internal 8931cb0ef41Sopenharmony_ci} // namespace v8 8941cb0ef41Sopenharmony_ci 8951cb0ef41Sopenharmony_ci#endif // V8_COMPILER_GRAPH_ASSEMBLER_H_ 896