LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 114 117 97.4 %
Date: 2019-04-17 Functions: 2872 3411 84.2 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_COMPILER_CODE_ASSEMBLER_H_
       6             : #define V8_COMPILER_CODE_ASSEMBLER_H_
       7             : 
       8             : #include <map>
       9             : #include <memory>
      10             : #include <initializer_list>
      11             : 
      12             : // Clients of this interface shouldn't depend on lots of compiler internals.
      13             : // Do not include anything from src/compiler here!
      14             : #include "src/allocation.h"
      15             : #include "src/base/macros.h"
      16             : #include "src/builtins/builtins.h"
      17             : #include "src/code-factory.h"
      18             : #include "src/globals.h"
      19             : #include "src/heap/heap.h"
      20             : #include "src/machine-type.h"
      21             : #include "src/objects.h"
      22             : #include "src/objects/arguments.h"
      23             : #include "src/objects/data-handler.h"
      24             : #include "src/objects/heap-number.h"
      25             : #include "src/objects/js-array-buffer.h"
      26             : #include "src/objects/js-collection.h"
      27             : #include "src/objects/js-proxy.h"
      28             : #include "src/objects/map.h"
      29             : #include "src/objects/maybe-object.h"
      30             : #include "src/objects/oddball.h"
      31             : #include "src/runtime/runtime.h"
      32             : #include "src/source-position.h"
      33             : #include "src/type-traits.h"
      34             : #include "src/zone/zone-containers.h"
      35             : 
      36             : namespace v8 {
      37             : namespace internal {
      38             : 
      39             : // Forward declarations.
      40             : class AsmWasmData;
      41             : class AsyncGeneratorRequest;
      42             : struct AssemblerOptions;
      43             : class BigInt;
      44             : class CallInterfaceDescriptor;
      45             : class Callable;
      46             : class Factory;
      47             : class FinalizationGroupCleanupJobTask;
      48             : class InterpreterData;
      49             : class Isolate;
      50             : class JSAsyncFunctionObject;
      51             : class JSAsyncGeneratorObject;
      52             : class JSCollator;
      53             : class JSCollection;
      54             : class JSDateTimeFormat;
      55             : class JSListFormat;
      56             : class JSLocale;
      57             : class JSNumberFormat;
      58             : class JSPluralRules;
      59             : class JSRegExpStringIterator;
      60             : class JSRelativeTimeFormat;
      61             : class JSSegmentIterator;
      62             : class JSSegmenter;
      63             : class JSV8BreakIterator;
      64             : class JSWeakCollection;
      65             : class JSFinalizationGroup;
      66             : class JSFinalizationGroupCleanupIterator;
      67             : class JSWeakMap;
      68             : class JSWeakRef;
      69             : class JSWeakSet;
      70             : class MaybeObject;
      71             : class PromiseCapability;
      72             : class PromiseFulfillReactionJobTask;
      73             : class PromiseReaction;
      74             : class PromiseReactionJobTask;
      75             : class PromiseRejectReactionJobTask;
      76             : class WasmDebugInfo;
      77             : class WeakCell;
      78             : class Zone;
      79             : 
      80             : template <typename T>
      81             : class Signature;
      82             : 
      83             : struct UntaggedT {};
      84             : 
      85             : struct IntegralT : UntaggedT {};
      86             : 
      87             : struct WordT : IntegralT {
      88             :   static const MachineRepresentation kMachineRepresentation =
      89             :       (kSystemPointerSize == 4) ? MachineRepresentation::kWord32
      90             :                                 : MachineRepresentation::kWord64;
      91             : };
      92             : 
      93             : struct RawPtrT : WordT {
      94             :   static constexpr MachineType kMachineType = MachineType::Pointer();
      95             : };
      96             : 
      97             : template <class To>
      98             : struct RawPtr : RawPtrT {};
      99             : 
     100             : struct Word32T : IntegralT {
     101             :   static const MachineRepresentation kMachineRepresentation =
     102             :       MachineRepresentation::kWord32;
     103             : };
     104             : struct Int32T : Word32T {
     105             :   static constexpr MachineType kMachineType = MachineType::Int32();
     106             : };
     107             : struct Uint32T : Word32T {
     108             :   static constexpr MachineType kMachineType = MachineType::Uint32();
     109             : };
     110             : struct Int16T : Int32T {
     111             :   static constexpr MachineType kMachineType = MachineType::Int16();
     112             : };
     113             : struct Uint16T : Uint32T {
     114             :   static constexpr MachineType kMachineType = MachineType::Uint16();
     115             : };
     116             : struct Int8T : Int16T {
     117             :   static constexpr MachineType kMachineType = MachineType::Int8();
     118             : };
     119             : struct Uint8T : Uint16T {
     120             :   static constexpr MachineType kMachineType = MachineType::Uint8();
     121             : };
     122             : 
     123             : struct Word64T : IntegralT {
     124             :   static const MachineRepresentation kMachineRepresentation =
     125             :       MachineRepresentation::kWord64;
     126             : };
     127             : struct Int64T : Word64T {
     128             :   static constexpr MachineType kMachineType = MachineType::Int64();
     129             : };
     130             : struct Uint64T : Word64T {
     131             :   static constexpr MachineType kMachineType = MachineType::Uint64();
     132             : };
     133             : 
     134             : struct IntPtrT : WordT {
     135             :   static constexpr MachineType kMachineType = MachineType::IntPtr();
     136             : };
     137             : struct UintPtrT : WordT {
     138             :   static constexpr MachineType kMachineType = MachineType::UintPtr();
     139             : };
     140             : 
     141             : struct Float32T : UntaggedT {
     142             :   static const MachineRepresentation kMachineRepresentation =
     143             :       MachineRepresentation::kFloat32;
     144             :   static constexpr MachineType kMachineType = MachineType::Float32();
     145             : };
     146             : 
     147             : struct Float64T : UntaggedT {
     148             :   static const MachineRepresentation kMachineRepresentation =
     149             :       MachineRepresentation::kFloat64;
     150             :   static constexpr MachineType kMachineType = MachineType::Float64();
     151             : };
     152             : 
     153             : // Result of a comparison operation.
     154             : struct BoolT : Word32T {};
     155             : 
     156             : // Value type of a Turbofan node with two results.
     157             : template <class T1, class T2>
     158             : struct PairT {};
     159             : 
     160             : inline constexpr MachineType CommonMachineType(MachineType type1,
     161             :                                                MachineType type2) {
     162             :   return (type1 == type2) ? type1
     163             :                           : ((type1.IsTagged() && type2.IsTagged())
     164             :                                  ? MachineType::AnyTagged()
     165             :                                  : MachineType::None());
     166             : }
     167             : 
     168             : template <class Type, class Enable = void>
     169             : struct MachineTypeOf {
     170             :   static constexpr MachineType value = Type::kMachineType;
     171             : };
     172             : 
     173             : template <class Type, class Enable>
     174             : constexpr MachineType MachineTypeOf<Type, Enable>::value;
     175             : 
     176             : template <>
     177             : struct MachineTypeOf<Object> {
     178             :   static constexpr MachineType value = MachineType::AnyTagged();
     179             : };
     180             : template <>
     181             : struct MachineTypeOf<MaybeObject> {
     182             :   static constexpr MachineType value = MachineType::AnyTagged();
     183             : };
     184             : template <>
     185             : struct MachineTypeOf<Smi> {
     186             :   static constexpr MachineType value = MachineType::TaggedSigned();
     187             : };
     188             : template <class HeapObjectSubtype>
     189             : struct MachineTypeOf<HeapObjectSubtype,
     190             :                      typename std::enable_if<std::is_base_of<
     191             :                          HeapObject, HeapObjectSubtype>::value>::type> {
     192             :   static constexpr MachineType value = MachineType::TaggedPointer();
     193             : };
     194             : 
     195             : template <class HeapObjectSubtype>
     196             : constexpr MachineType MachineTypeOf<
     197             :     HeapObjectSubtype, typename std::enable_if<std::is_base_of<
     198             :                            HeapObject, HeapObjectSubtype>::value>::type>::value;
     199             : 
     200             : template <class Type, class Enable = void>
     201             : struct MachineRepresentationOf {
     202             :   static const MachineRepresentation value = Type::kMachineRepresentation;
     203             : };
     204             : template <class T>
     205             : struct MachineRepresentationOf<
     206             :     T, typename std::enable_if<std::is_base_of<Object, T>::value>::type> {
     207             :   static const MachineRepresentation value =
     208             :       MachineTypeOf<T>::value.representation();
     209             : };
     210             : template <class T>
     211             : struct MachineRepresentationOf<
     212             :     T, typename std::enable_if<std::is_base_of<MaybeObject, T>::value>::type> {
     213             :   static const MachineRepresentation value =
     214             :       MachineTypeOf<T>::value.representation();
     215             : };
     216             : 
     217             : template <class T>
     218             : struct is_valid_type_tag {
     219             :   static const bool value = std::is_base_of<Object, T>::value ||
     220             :                             std::is_base_of<UntaggedT, T>::value ||
     221             :                             std::is_base_of<MaybeObject, T>::value ||
     222             :                             std::is_same<ExternalReference, T>::value;
     223             :   static const bool is_tagged = std::is_base_of<Object, T>::value ||
     224             :                                 std::is_base_of<MaybeObject, T>::value;
     225             : };
     226             : 
     227             : template <class T1, class T2>
     228             : struct is_valid_type_tag<PairT<T1, T2>> {
     229             :   static const bool value =
     230             :       is_valid_type_tag<T1>::value && is_valid_type_tag<T2>::value;
     231             :   static const bool is_tagged = false;
     232             : };
     233             : 
     234             : template <class T1, class T2>
     235             : struct UnionT;
     236             : 
     237             : template <class T1, class T2>
     238             : struct is_valid_type_tag<UnionT<T1, T2>> {
     239             :   static const bool is_tagged =
     240             :       is_valid_type_tag<T1>::is_tagged && is_valid_type_tag<T2>::is_tagged;
     241             :   static const bool value = is_tagged;
     242             : };
     243             : 
     244             : template <class T1, class T2>
     245             : struct UnionT {
     246             :   static constexpr MachineType kMachineType =
     247             :       CommonMachineType(MachineTypeOf<T1>::value, MachineTypeOf<T2>::value);
     248             :   static const MachineRepresentation kMachineRepresentation =
     249             :       kMachineType.representation();
     250             :   static_assert(kMachineRepresentation != MachineRepresentation::kNone,
     251             :                 "no common representation");
     252             :   static_assert(is_valid_type_tag<T1>::is_tagged &&
     253             :                     is_valid_type_tag<T2>::is_tagged,
     254             :                 "union types are only possible for tagged values");
     255             : };
     256             : 
     257             : using Number = UnionT<Smi, HeapNumber>;
     258             : using Numeric = UnionT<Number, BigInt>;
     259             : 
     260             : // A pointer to a builtin function, used by Torque's function pointers.
     261             : using BuiltinPtr = Smi;
     262             : 
     263             : class int31_t {
     264             :  public:
     265             :   int31_t() : value_(0) {}
     266       70560 :   int31_t(int value) : value_(value) {  // NOLINT(runtime/explicit)
     267             :     DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
     268             :   }
     269             :   int31_t& operator=(int value) {
     270             :     DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
     271             :     value_ = value;
     272             :     return *this;
     273             :   }
     274             :   int32_t value() const { return value_; }
     275       70900 :   operator int32_t() const { return value_; }
     276             : 
     277             :  private:
     278             :   int32_t value_;
     279             : };
     280             : 
     281             : #define ENUM_ELEMENT(Name) k##Name,
     282             : #define ENUM_STRUCT_ELEMENT(NAME, Name, name) k##Name,
     283             : enum class ObjectType {
     284             :   kObject,
     285             :   OBJECT_TYPE_LIST(ENUM_ELEMENT) HEAP_OBJECT_TYPE_LIST(ENUM_ELEMENT)
     286             :       STRUCT_LIST(ENUM_STRUCT_ELEMENT)
     287             : };
     288             : #undef ENUM_ELEMENT
     289             : #undef ENUM_STRUCT_ELEMENT
     290             : 
     291             : enum class CheckBounds { kAlways, kDebugOnly };
     292             : inline bool NeedsBoundsCheck(CheckBounds check_bounds) {
     293      111120 :   switch (check_bounds) {
     294             :     case CheckBounds::kAlways:
     295             :       return true;
     296             :     case CheckBounds::kDebugOnly:
     297             :       return DEBUG_BOOL;
     298             :   }
     299             : }
     300             : 
     301             : class AccessCheckNeeded;
     302             : class BigIntWrapper;
     303             : class ClassBoilerplate;
     304             : class BooleanWrapper;
     305             : class CompilationCacheTable;
     306             : class Constructor;
     307             : class Filler;
     308             : class FunctionTemplateRareData;
     309             : class InternalizedString;
     310             : class JSArgumentsObject;
     311             : class JSArrayBufferView;
     312             : class JSContextExtensionObject;
     313             : class JSError;
     314             : class JSSloppyArgumentsObject;
     315             : class MapCache;
     316             : class MutableHeapNumber;
     317             : class NativeContext;
     318             : class NumberWrapper;
     319             : class ScriptWrapper;
     320             : class SloppyArgumentsElements;
     321             : class StringWrapper;
     322             : class SymbolWrapper;
     323             : class Undetectable;
     324             : class UniqueName;
     325             : class WasmExceptionObject;
     326             : class WasmExceptionTag;
     327             : class WasmExportedFunctionData;
     328             : class WasmGlobalObject;
     329             : class WasmMemoryObject;
     330             : class WasmModuleObject;
     331             : class WasmTableObject;
     332             : 
     333             : template <class T>
     334             : struct ObjectTypeOf {};
     335             : 
     336             : #define OBJECT_TYPE_CASE(Name)                           \
     337             :   template <>                                            \
     338             :   struct ObjectTypeOf<Name> {                            \
     339             :     static const ObjectType value = ObjectType::k##Name; \
     340             :   };
     341             : #define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name)        \
     342             :   template <>                                            \
     343             :   struct ObjectTypeOf<Name> {                            \
     344             :     static const ObjectType value = ObjectType::k##Name; \
     345             :   };
     346             : #define OBJECT_TYPE_TEMPLATE_CASE(Name)                  \
     347             :   template <class... Args>                               \
     348             :   struct ObjectTypeOf<Name<Args...>> {                   \
     349             :     static const ObjectType value = ObjectType::k##Name; \
     350             :   };
     351             : OBJECT_TYPE_CASE(Object)
     352             : OBJECT_TYPE_LIST(OBJECT_TYPE_CASE)
     353             : HEAP_OBJECT_ORDINARY_TYPE_LIST(OBJECT_TYPE_CASE)
     354             : STRUCT_LIST(OBJECT_TYPE_STRUCT_CASE)
     355             : HEAP_OBJECT_TEMPLATE_TYPE_LIST(OBJECT_TYPE_TEMPLATE_CASE)
     356             : #undef OBJECT_TYPE_CASE
     357             : #undef OBJECT_TYPE_STRUCT_CASE
     358             : #undef OBJECT_TYPE_TEMPLATE_CASE
     359             : 
     360             : // {raw_value} must be a tagged Object.
     361             : // {raw_type} must be a tagged Smi.
     362             : // {raw_location} must be a tagged String.
     363             : // Returns a tagged Smi.
     364             : Address CheckObjectType(Address raw_value, Address raw_type,
     365             :                         Address raw_location);
     366             : 
     367             : namespace compiler {
     368             : 
     369             : class CallDescriptor;
     370             : class CodeAssemblerLabel;
     371             : class CodeAssemblerVariable;
     372             : template <class T>
     373             : class TypedCodeAssemblerVariable;
     374             : class CodeAssemblerState;
     375             : class Node;
     376             : class RawMachineAssembler;
     377             : class RawMachineLabel;
     378             : class SourcePositionTable;
     379             : 
     380             : using CodeAssemblerVariableList = ZoneVector<CodeAssemblerVariable*>;
     381             : 
     382             : using CodeAssemblerCallback = std::function<void()>;
     383             : 
     384             : template <class T, class U>
     385             : struct is_subtype {
     386             :   static const bool value = std::is_base_of<U, T>::value;
     387             : };
     388             : template <class T1, class T2, class U>
     389             : struct is_subtype<UnionT<T1, T2>, U> {
     390             :   static const bool value =
     391             :       is_subtype<T1, U>::value && is_subtype<T2, U>::value;
     392             : };
     393             : template <class T, class U1, class U2>
     394             : struct is_subtype<T, UnionT<U1, U2>> {
     395             :   static const bool value =
     396             :       is_subtype<T, U1>::value || is_subtype<T, U2>::value;
     397             : };
     398             : template <class T1, class T2, class U1, class U2>
     399             : struct is_subtype<UnionT<T1, T2>, UnionT<U1, U2>> {
     400             :   static const bool value =
     401             :       (is_subtype<T1, U1>::value || is_subtype<T1, U2>::value) &&
     402             :       (is_subtype<T2, U1>::value || is_subtype<T2, U2>::value);
     403             : };
     404             : 
     405             : template <class T, class U>
     406             : struct types_have_common_values {
     407             :   static const bool value = is_subtype<T, U>::value || is_subtype<U, T>::value;
     408             : };
     409             : template <class U>
     410             : struct types_have_common_values<Uint32T, U> {
     411             :   static const bool value = types_have_common_values<Word32T, U>::value;
     412             : };
     413             : template <class U>
     414             : struct types_have_common_values<Int32T, U> {
     415             :   static const bool value = types_have_common_values<Word32T, U>::value;
     416             : };
     417             : template <class U>
     418             : struct types_have_common_values<Uint64T, U> {
     419             :   static const bool value = types_have_common_values<Word64T, U>::value;
     420             : };
     421             : template <class U>
     422             : struct types_have_common_values<Int64T, U> {
     423             :   static const bool value = types_have_common_values<Word64T, U>::value;
     424             : };
     425             : template <class U>
     426             : struct types_have_common_values<IntPtrT, U> {
     427             :   static const bool value = types_have_common_values<WordT, U>::value;
     428             : };
     429             : template <class U>
     430             : struct types_have_common_values<UintPtrT, U> {
     431             :   static const bool value = types_have_common_values<WordT, U>::value;
     432             : };
     433             : template <class T1, class T2, class U>
     434             : struct types_have_common_values<UnionT<T1, T2>, U> {
     435             :   static const bool value = types_have_common_values<T1, U>::value ||
     436             :                             types_have_common_values<T2, U>::value;
     437             : };
     438             : 
     439             : template <class T, class U1, class U2>
     440             : struct types_have_common_values<T, UnionT<U1, U2>> {
     441             :   static const bool value = types_have_common_values<T, U1>::value ||
     442             :                             types_have_common_values<T, U2>::value;
     443             : };
     444             : template <class T1, class T2, class U1, class U2>
     445             : struct types_have_common_values<UnionT<T1, T2>, UnionT<U1, U2>> {
     446             :   static const bool value = types_have_common_values<T1, U1>::value ||
     447             :                             types_have_common_values<T1, U2>::value ||
     448             :                             types_have_common_values<T2, U1>::value ||
     449             :                             types_have_common_values<T2, U2>::value;
     450             : };
     451             : 
     452             : template <class T>
     453             : struct types_have_common_values<T, MaybeObject> {
     454             :   static const bool value = types_have_common_values<T, Object>::value;
     455             : };
     456             : 
     457             : template <class T>
     458             : struct types_have_common_values<MaybeObject, T> {
     459             :   static const bool value = types_have_common_values<Object, T>::value;
     460             : };
     461             : 
     462             : // TNode<T> is an SSA value with the static type tag T, which is one of the
     463             : // following:
     464             : //   - a subclass of internal::Object represents a tagged type
     465             : //   - a subclass of internal::UntaggedT represents an untagged type
     466             : //   - ExternalReference
     467             : //   - PairT<T1, T2> for an operation returning two values, with types T1
     468             : //     and T2
     469             : //   - UnionT<T1, T2> represents either a value of type T1 or of type T2.
     470             : template <class T>
     471             : class TNode {
     472             :  public:
     473             :   static_assert(is_valid_type_tag<T>::value, "invalid type tag");
     474             : 
     475             :   template <class U,
     476             :             typename std::enable_if<is_subtype<U, T>::value, int>::type = 0>
     477     4951243 :   TNode(const TNode<U>& other) : node_(other) {}
     478     1004480 :   TNode() : node_(nullptr) {}
     479             : 
     480             :   TNode operator=(TNode other) {
     481             :     DCHECK_NOT_NULL(other.node_);
     482     3972548 :     node_ = other.node_;
     483             :     return *this;
     484             :   }
     485             : 
     486    14628706 :   operator compiler::Node*() const { return node_; }
     487             : 
     488             :   static TNode UncheckedCast(compiler::Node* node) { return TNode(node); }
     489             : 
     490             :  protected:
     491     3316702 :   explicit TNode(compiler::Node* node) : node_(node) {}
     492             : 
     493             :  private:
     494             :   compiler::Node* node_;
     495             : };
     496             : 
     497             : // SloppyTNode<T> is a variant of TNode<T> and allows implicit casts from
     498             : // Node*. It is intended for function arguments as long as some call sites
     499             : // still use untyped Node* arguments.
     500             : // TODO(tebbi): Delete this class once transition is finished.
     501             : template <class T>
     502             : class SloppyTNode : public TNode<T> {
     503             :  public:
     504             :   SloppyTNode(compiler::Node* node)  // NOLINT(runtime/explicit)
     505             :       : TNode<T>(node) {}
     506             :   template <class U, typename std::enable_if<is_subtype<U, T>::value,
     507             :                                              int>::type = 0>
     508             :   SloppyTNode(const TNode<U>& other)  // NOLINT(runtime/explicit)
     509     1802138 :       : TNode<T>(other) {}
     510             : };
     511             : 
     512             : template <class... Types>
     513             : class CodeAssemblerParameterizedLabel;
     514             : 
     515             : // This macro alias allows to use PairT<T1, T2> as a macro argument.
     516             : #define PAIR_TYPE(T1, T2) PairT<T1, T2>
     517             : 
     518             : #define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)          \
     519             :   V(Float32Equal, BoolT, Float32T, Float32T)              \
     520             :   V(Float32LessThan, BoolT, Float32T, Float32T)           \
     521             :   V(Float32LessThanOrEqual, BoolT, Float32T, Float32T)    \
     522             :   V(Float32GreaterThan, BoolT, Float32T, Float32T)        \
     523             :   V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
     524             :   V(Float64Equal, BoolT, Float64T, Float64T)              \
     525             :   V(Float64NotEqual, BoolT, Float64T, Float64T)           \
     526             :   V(Float64LessThan, BoolT, Float64T, Float64T)           \
     527             :   V(Float64LessThanOrEqual, BoolT, Float64T, Float64T)    \
     528             :   V(Float64GreaterThan, BoolT, Float64T, Float64T)        \
     529             :   V(Float64GreaterThanOrEqual, BoolT, Float64T, Float64T) \
     530             :   /* Use Word32Equal if you need Int32Equal */            \
     531             :   V(Int32GreaterThan, BoolT, Word32T, Word32T)            \
     532             :   V(Int32GreaterThanOrEqual, BoolT, Word32T, Word32T)     \
     533             :   V(Int32LessThan, BoolT, Word32T, Word32T)               \
     534             :   V(Int32LessThanOrEqual, BoolT, Word32T, Word32T)        \
     535             :   /* Use WordEqual if you need IntPtrEqual */             \
     536             :   V(IntPtrLessThan, BoolT, WordT, WordT)                  \
     537             :   V(IntPtrLessThanOrEqual, BoolT, WordT, WordT)           \
     538             :   V(IntPtrGreaterThan, BoolT, WordT, WordT)               \
     539             :   V(IntPtrGreaterThanOrEqual, BoolT, WordT, WordT)        \
     540             :   /* Use Word32Equal if you need Uint32Equal */           \
     541             :   V(Uint32LessThan, BoolT, Word32T, Word32T)              \
     542             :   V(Uint32LessThanOrEqual, BoolT, Word32T, Word32T)       \
     543             :   V(Uint32GreaterThan, BoolT, Word32T, Word32T)           \
     544             :   V(Uint32GreaterThanOrEqual, BoolT, Word32T, Word32T)    \
     545             :   /* Use WordEqual if you need UintPtrEqual */            \
     546             :   V(UintPtrLessThan, BoolT, WordT, WordT)                 \
     547             :   V(UintPtrLessThanOrEqual, BoolT, WordT, WordT)          \
     548             :   V(UintPtrGreaterThan, BoolT, WordT, WordT)              \
     549             :   V(UintPtrGreaterThanOrEqual, BoolT, WordT, WordT)
     550             : 
     551             : #define CODE_ASSEMBLER_BINARY_OP_LIST(V)                                \
     552             :   CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)                              \
     553             :   V(Float64Add, Float64T, Float64T, Float64T)                           \
     554             :   V(Float64Sub, Float64T, Float64T, Float64T)                           \
     555             :   V(Float64Mul, Float64T, Float64T, Float64T)                           \
     556             :   V(Float64Div, Float64T, Float64T, Float64T)                           \
     557             :   V(Float64Mod, Float64T, Float64T, Float64T)                           \
     558             :   V(Float64Atan2, Float64T, Float64T, Float64T)                         \
     559             :   V(Float64Pow, Float64T, Float64T, Float64T)                           \
     560             :   V(Float64Max, Float64T, Float64T, Float64T)                           \
     561             :   V(Float64Min, Float64T, Float64T, Float64T)                           \
     562             :   V(Float64InsertLowWord32, Float64T, Float64T, Word32T)                \
     563             :   V(Float64InsertHighWord32, Float64T, Float64T, Word32T)               \
     564             :   V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
     565             :   V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
     566             :   V(Int32Add, Word32T, Word32T, Word32T)                                \
     567             :   V(Int32AddWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
     568             :   V(Int32Sub, Word32T, Word32T, Word32T)                                \
     569             :   V(Int32SubWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
     570             :   V(Int32Mul, Word32T, Word32T, Word32T)                                \
     571             :   V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
     572             :   V(Int32Div, Int32T, Int32T, Int32T)                                   \
     573             :   V(Int32Mod, Int32T, Int32T, Int32T)                                   \
     574             :   V(WordRor, WordT, WordT, IntegralT)                                   \
     575             :   V(Word32Ror, Word32T, Word32T, Word32T)                               \
     576             :   V(Word64Ror, Word64T, Word64T, Word64T)
     577             : 
     578             : TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
     579             : 
     580             : #define CODE_ASSEMBLER_UNARY_OP_LIST(V)                        \
     581             :   V(Float64Abs, Float64T, Float64T)                            \
     582             :   V(Float64Acos, Float64T, Float64T)                           \
     583             :   V(Float64Acosh, Float64T, Float64T)                          \
     584             :   V(Float64Asin, Float64T, Float64T)                           \
     585             :   V(Float64Asinh, Float64T, Float64T)                          \
     586             :   V(Float64Atan, Float64T, Float64T)                           \
     587             :   V(Float64Atanh, Float64T, Float64T)                          \
     588             :   V(Float64Cos, Float64T, Float64T)                            \
     589             :   V(Float64Cosh, Float64T, Float64T)                           \
     590             :   V(Float64Exp, Float64T, Float64T)                            \
     591             :   V(Float64Expm1, Float64T, Float64T)                          \
     592             :   V(Float64Log, Float64T, Float64T)                            \
     593             :   V(Float64Log1p, Float64T, Float64T)                          \
     594             :   V(Float64Log2, Float64T, Float64T)                           \
     595             :   V(Float64Log10, Float64T, Float64T)                          \
     596             :   V(Float64Cbrt, Float64T, Float64T)                           \
     597             :   V(Float64Neg, Float64T, Float64T)                            \
     598             :   V(Float64Sin, Float64T, Float64T)                            \
     599             :   V(Float64Sinh, Float64T, Float64T)                           \
     600             :   V(Float64Sqrt, Float64T, Float64T)                           \
     601             :   V(Float64Tan, Float64T, Float64T)                            \
     602             :   V(Float64Tanh, Float64T, Float64T)                           \
     603             :   V(Float64ExtractLowWord32, Word32T, Float64T)                \
     604             :   V(Float64ExtractHighWord32, Word32T, Float64T)               \
     605             :   V(BitcastTaggedToWord, IntPtrT, Object)                      \
     606             :   V(BitcastMaybeObjectToWord, IntPtrT, MaybeObject)            \
     607             :   V(BitcastWordToTagged, Object, WordT)                        \
     608             :   V(BitcastWordToTaggedSigned, Smi, WordT)                     \
     609             :   V(TruncateFloat64ToFloat32, Float32T, Float64T)              \
     610             :   V(TruncateFloat64ToWord32, Word32T, Float64T)                \
     611             :   V(TruncateInt64ToInt32, Int32T, Int64T)                      \
     612             :   V(ChangeFloat32ToFloat64, Float64T, Float32T)                \
     613             :   V(ChangeFloat64ToUint32, Uint32T, Float64T)                  \
     614             :   V(ChangeFloat64ToUint64, Uint64T, Float64T)                  \
     615             :   V(ChangeInt32ToFloat64, Float64T, Int32T)                    \
     616             :   V(ChangeInt32ToInt64, Int64T, Int32T)                        \
     617             :   V(ChangeUint32ToFloat64, Float64T, Word32T)                  \
     618             :   V(ChangeUint32ToUint64, Uint64T, Word32T)                    \
     619             :   V(BitcastInt32ToFloat32, Float32T, Word32T)                  \
     620             :   V(BitcastFloat32ToInt32, Word32T, Float32T)                  \
     621             :   V(RoundFloat64ToInt32, Int32T, Float64T)                     \
     622             :   V(RoundInt32ToFloat32, Int32T, Float32T)                     \
     623             :   V(Float64SilenceNaN, Float64T, Float64T)                     \
     624             :   V(Float64RoundDown, Float64T, Float64T)                      \
     625             :   V(Float64RoundUp, Float64T, Float64T)                        \
     626             :   V(Float64RoundTiesEven, Float64T, Float64T)                  \
     627             :   V(Float64RoundTruncate, Float64T, Float64T)                  \
     628             :   V(Word32Clz, Int32T, Word32T)                                \
     629             :   V(Word32BitwiseNot, Word32T, Word32T)                        \
     630             :   V(WordNot, WordT, WordT)                                     \
     631             :   V(Int32AbsWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T)    \
     632             :   V(Int64AbsWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T)    \
     633             :   V(IntPtrAbsWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT) \
     634             :   V(Word32BinaryNot, BoolT, Word32T)
     635             : 
     636             : // A "public" interface used by components outside of compiler directory to
     637             : // create code objects with TurboFan's backend. This class is mostly a thin
     638             : // shim around the RawMachineAssembler, and its primary job is to ensure that
     639             : // the innards of the RawMachineAssembler and other compiler implementation
     640             : // details don't leak outside of the the compiler directory..
     641             : //
     642             : // V8 components that need to generate low-level code using this interface
     643             : // should include this header--and this header only--from the compiler
     644             : // directory (this is actually enforced). Since all interesting data
     645             : // structures are forward declared, it's not possible for clients to peek
     646             : // inside the compiler internals.
     647             : //
     648             : // In addition to providing isolation between TurboFan and code generation
     649             : // clients, CodeAssembler also provides an abstraction for creating variables
     650             : // and enhanced Label functionality to merge variable values along paths where
     651             : // they have differing values, including loops.
     652             : //
     653             : // The CodeAssembler itself is stateless (and instances are expected to be
     654             : // temporary-scoped and short-lived); all its state is encapsulated into
     655             : // a CodeAssemblerState instance.
     656     1318992 : class V8_EXPORT_PRIVATE CodeAssembler {
     657             :  public:
     658     1318992 :   explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
     659             :   ~CodeAssembler();
     660             : 
     661             :   static Handle<Code> GenerateCode(CodeAssemblerState* state,
     662             :                                    const AssemblerOptions& options);
     663             : 
     664             :   bool Is64() const;
     665             :   bool IsFloat64RoundUpSupported() const;
     666             :   bool IsFloat64RoundDownSupported() const;
     667             :   bool IsFloat64RoundTiesEvenSupported() const;
     668             :   bool IsFloat64RoundTruncateSupported() const;
     669             :   bool IsInt32AbsWithOverflowSupported() const;
     670             :   bool IsInt64AbsWithOverflowSupported() const;
     671             :   bool IsIntPtrAbsWithOverflowSupported() const;
     672             : 
     673             :   // Shortened aliases for use in CodeAssembler subclasses.
     674             :   using Label = CodeAssemblerLabel;
     675             :   using Variable = CodeAssemblerVariable;
     676             :   template <class T>
     677             :   using TVariable = TypedCodeAssemblerVariable<T>;
     678             :   using VariableList = CodeAssemblerVariableList;
     679             : 
     680             :   // ===========================================================================
     681             :   // Base Assembler
     682             :   // ===========================================================================
     683             : 
     684             :   template <class PreviousType, bool FromTyped>
     685             :   class CheckedNode {
     686             :    public:
     687             : #ifdef DEBUG
     688             :     CheckedNode(Node* node, CodeAssembler* code_assembler, const char* location)
     689             :         : node_(node), code_assembler_(code_assembler), location_(location) {}
     690             : #else
     691             :     CheckedNode(compiler::Node* node, CodeAssembler*, const char*)
     692             :         : node_(node) {}
     693             : #endif
     694             : 
     695             :     template <class A>
     696             :     operator TNode<A>() {
     697             :       static_assert(
     698             :           !std::is_same<A, MaybeObject>::value,
     699             :           "Can't cast to MaybeObject, use explicit conversion functions. ");
     700             : 
     701             :       static_assert(types_have_common_values<A, PreviousType>::value,
     702             :                     "Incompatible types: this cast can never succeed.");
     703             :       static_assert(std::is_convertible<TNode<A>, TNode<Object>>::value,
     704             :                     "Coercion to untagged values cannot be "
     705             :                     "checked.");
     706             :       static_assert(
     707             :           !FromTyped ||
     708             :               !std::is_convertible<TNode<PreviousType>, TNode<A>>::value,
     709             :           "Unnecessary CAST: types are convertible.");
     710             : #ifdef DEBUG
     711             :       if (FLAG_debug_code) {
     712             :         if (std::is_same<PreviousType, MaybeObject>::value) {
     713             :           code_assembler_->GenerateCheckMaybeObjectIsObject(node_, location_);
     714             :         }
     715             :         Node* function = code_assembler_->ExternalConstant(
     716             :             ExternalReference::check_object_type());
     717             :         code_assembler_->CallCFunction(
     718             :             function, MachineType::AnyTagged(),
     719             :             std::make_pair(MachineType::AnyTagged(), node_),
     720             :             std::make_pair(MachineType::TaggedSigned(),
     721             :                            code_assembler_->SmiConstant(
     722             :                                static_cast<int>(ObjectTypeOf<A>::value))),
     723             :             std::make_pair(MachineType::AnyTagged(),
     724             :                            code_assembler_->StringConstant(location_)));
     725             :       }
     726             : #endif
     727        3416 :       return TNode<A>::UncheckedCast(node_);
     728             :     }
     729             : 
     730             :     template <class A>
     731             :     operator SloppyTNode<A>() {
     732             :       return implicit_cast<TNode<A>>(*this);
     733             :     }
     734             : 
     735             :     Node* node() const { return node_; }
     736             : 
     737             :    private:
     738             :     Node* node_;
     739             : #ifdef DEBUG
     740             :     CodeAssembler* code_assembler_;
     741             :     const char* location_;
     742             : #endif
     743             :   };
     744             : 
     745             :   template <class T>
     746             :   TNode<T> UncheckedCast(Node* value) {
     747             :     return TNode<T>::UncheckedCast(value);
     748             :   }
     749             :   template <class T, class U>
     750             :   TNode<T> UncheckedCast(TNode<U> value) {
     751             :     static_assert(types_have_common_values<T, U>::value,
     752             :                   "Incompatible types: this cast can never succeed.");
     753             :     return TNode<T>::UncheckedCast(value);
     754             :   }
     755             : 
     756             :   // ReinterpretCast<T>(v) has the power to cast even when the type of v is
     757             :   // unrelated to T. Use with care.
     758             :   template <class T>
     759             :   TNode<T> ReinterpretCast(Node* value) {
     760             :     return TNode<T>::UncheckedCast(value);
     761             :   }
     762             : 
     763             :   CheckedNode<Object, false> Cast(Node* value, const char* location = "") {
     764             :     return {value, this, location};
     765             :   }
     766             : 
     767             :   template <class T>
     768             :   CheckedNode<T, true> Cast(TNode<T> value, const char* location = "") {
     769             :     return {value, this, location};
     770             :   }
     771             : 
     772             : #ifdef DEBUG
     773             : #define STRINGIFY(x) #x
     774             : #define TO_STRING_LITERAL(x) STRINGIFY(x)
     775             : #define CAST(x) \
     776             :   Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
     777             : #define TORQUE_CAST(x) \
     778             :   ca_.Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
     779             : #else
     780             : #define CAST(x) Cast(x)
     781             : #define TORQUE_CAST(x) ca_.Cast(x)
     782             : #endif
     783             : 
     784             : #ifdef DEBUG
     785             :   void GenerateCheckMaybeObjectIsObject(Node* node, const char* location);
     786             : #endif
     787             : 
     788             :   // Constants.
     789             :   TNode<Int32T> Int32Constant(int32_t value);
     790             :   TNode<Int64T> Int64Constant(int64_t value);
     791             :   TNode<IntPtrT> IntPtrConstant(intptr_t value);
     792             :   TNode<Uint32T> Uint32Constant(uint32_t value) {
     793       31360 :     return Unsigned(Int32Constant(bit_cast<int32_t>(value)));
     794             :   }
     795             :   TNode<UintPtrT> UintPtrConstant(uintptr_t value) {
     796        5608 :     return Unsigned(IntPtrConstant(bit_cast<intptr_t>(value)));
     797             :   }
     798             :   TNode<Number> NumberConstant(double value);
     799             :   TNode<Smi> SmiConstant(Smi value);
     800             :   TNode<Smi> SmiConstant(int value);
     801             :   template <typename E,
     802             :             typename = typename std::enable_if<std::is_enum<E>::value>::type>
     803             :   TNode<Smi> SmiConstant(E value) {
     804             :     STATIC_ASSERT(sizeof(E) <= sizeof(int));
     805       50996 :     return SmiConstant(static_cast<int>(value));
     806             :   }
     807             :   TNode<HeapObject> UntypedHeapConstant(Handle<HeapObject> object);
     808             :   template <class Type>
     809             :   TNode<Type> HeapConstant(Handle<Type> object) {
     810      144770 :     return UncheckedCast<Type>(UntypedHeapConstant(object));
     811             :   }
     812             :   TNode<String> StringConstant(const char* str);
     813             :   TNode<Oddball> BooleanConstant(bool value);
     814             :   TNode<ExternalReference> ExternalConstant(ExternalReference address);
     815             :   TNode<Float64T> Float64Constant(double value);
     816             :   TNode<HeapNumber> NaNConstant();
     817             :   TNode<BoolT> Int32TrueConstant() {
     818       19360 :     return ReinterpretCast<BoolT>(Int32Constant(1));
     819             :   }
     820             :   TNode<BoolT> Int32FalseConstant() {
     821       17440 :     return ReinterpretCast<BoolT>(Int32Constant(0));
     822             :   }
     823       11516 :   TNode<BoolT> BoolConstant(bool value) {
     824       23032 :     return value ? Int32TrueConstant() : Int32FalseConstant();
     825             :   }
     826             : 
     827             :   // TODO(jkummerow): The style guide wants pointers for output parameters.
     828             :   // https://google.github.io/styleguide/cppguide.html#Output_Parameters
     829             :   bool ToInt32Constant(Node* node, int32_t& out_value);
     830             :   bool ToInt64Constant(Node* node, int64_t& out_value);
     831             :   bool ToSmiConstant(Node* node, Smi* out_value);
     832             :   bool ToIntPtrConstant(Node* node, intptr_t& out_value);
     833             : 
     834             :   bool IsUndefinedConstant(TNode<Object> node);
     835             :   bool IsNullConstant(TNode<Object> node);
     836             : 
     837             :   TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
     838             :   TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
     839             :   TNode<Uint32T> Unsigned(TNode<Word32T> x) {
     840             :     return UncheckedCast<Uint32T>(x);
     841             :   }
     842             :   TNode<UintPtrT> Unsigned(TNode<WordT> x) {
     843             :     return UncheckedCast<UintPtrT>(x);
     844             :   }
     845             : 
     846             :   static constexpr int kTargetParameterIndex = -1;
     847             : 
     848             :   Node* Parameter(int value);
     849             : 
     850             :   TNode<Context> GetJSContextParameter();
     851             :   void Return(SloppyTNode<Object> value);
     852             :   void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2);
     853             :   void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2,
     854             :               SloppyTNode<Object> value3);
     855             :   void PopAndReturn(Node* pop, Node* value);
     856             : 
     857             :   void ReturnIf(Node* condition, Node* value);
     858             : 
     859             :   void ReturnRaw(Node* value);
     860             : 
     861             :   void DebugAbort(Node* message);
     862             :   void DebugBreak();
     863             :   void Unreachable();
     864      271640 :   void Comment(const char* msg) {
     865      271640 :     if (!FLAG_code_comments) return;
     866           8 :     Comment(std::string(msg));
     867             :   }
     868             :   void Comment(std::string msg);
     869             :   template <class... Args>
     870        4420 :   void Comment(Args&&... args) {
     871        8840 :     if (!FLAG_code_comments) return;
     872           0 :     std::ostringstream s;
     873           0 :     USE((s << std::forward<Args>(args))...);
     874           0 :     Comment(s.str());
     875             :   }
     876             : 
     877             :   void SetSourcePosition(const char* file, int line);
     878             : 
     879             :   void Bind(Label* label);
     880             : #if DEBUG
     881             :   void Bind(Label* label, AssemblerDebugInfo debug_info);
     882             : #endif  // DEBUG
     883             :   void Goto(Label* label);
     884             :   void GotoIf(SloppyTNode<IntegralT> condition, Label* true_label);
     885             :   void GotoIfNot(SloppyTNode<IntegralT> condition, Label* false_label);
     886             :   void Branch(SloppyTNode<IntegralT> condition, Label* true_label,
     887             :               Label* false_label);
     888             : 
     889             :   template <class T>
     890             :   TNode<T> Uninitialized() {
     891             :     return {};
     892             :   }
     893             : 
     894             :   template <class... T>
     895             :   void Bind(CodeAssemblerParameterizedLabel<T...>* label, TNode<T>*... phis) {
     896     1186612 :     Bind(label->plain_label());
     897     1186840 :     label->CreatePhis(phis...);
     898             :   }
     899             :   template <class... T, class... Args>
     900       72268 :   void Branch(TNode<BoolT> condition,
     901             :               CodeAssemblerParameterizedLabel<T...>* if_true,
     902             :               CodeAssemblerParameterizedLabel<T...>* if_false, Args... args) {
     903       72268 :     if_true->AddInputs(args...);
     904       72268 :     if_false->AddInputs(args...);
     905       72268 :     Branch(condition, if_true->plain_label(), if_false->plain_label());
     906       72268 :   }
     907             : 
     908             :   template <class... T, class... Args>
     909             :   void Goto(CodeAssemblerParameterizedLabel<T...>* label, Args... args) {
     910     1124224 :     label->AddInputs(args...);
     911     1124224 :     Goto(label->plain_label());
     912             :   }
     913             : 
     914             :   void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
     915             :               const std::function<void()>& false_body);
     916             :   void Branch(TNode<BoolT> condition, Label* true_label,
     917             :               const std::function<void()>& false_body);
     918             :   void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
     919             :               Label* false_label);
     920             : 
     921             :   void Switch(Node* index, Label* default_label, const int32_t* case_values,
     922             :               Label** case_labels, size_t case_count);
     923             : 
     924             :   // Access to the frame pointer
     925             :   Node* LoadFramePointer();
     926             :   Node* LoadParentFramePointer();
     927             : 
     928             :   // Access to the stack pointer
     929             :   Node* LoadStackPointer();
     930             : 
     931             :   // Poison |value| on speculative paths.
     932             :   TNode<Object> TaggedPoisonOnSpeculation(SloppyTNode<Object> value);
     933             :   TNode<WordT> WordPoisonOnSpeculation(SloppyTNode<WordT> value);
     934             : 
     935             :   // Load raw memory location.
     936             :   Node* Load(MachineType rep, Node* base,
     937             :              LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
     938             :   template <class Type>
     939             :   TNode<Type> Load(MachineType rep, TNode<RawPtr<Type>> base) {
     940             :     DCHECK(
     941             :         IsSubtype(rep.representation(), MachineRepresentationOf<Type>::value));
     942             :     return UncheckedCast<Type>(Load(rep, static_cast<Node*>(base)));
     943             :   }
     944             :   Node* Load(MachineType rep, Node* base, Node* offset,
     945             :              LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
     946             :   Node* AtomicLoad(MachineType rep, Node* base, Node* offset);
     947             :   // Load uncompressed tagged value from (most likely off JS heap) memory
     948             :   // location.
     949             :   Node* LoadFullTagged(
     950             :       Node* base, LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
     951             :   Node* LoadFullTagged(
     952             :       Node* base, Node* offset,
     953             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
     954             : 
     955             :   // Load a value from the root array.
     956             :   TNode<Object> LoadRoot(RootIndex root_index);
     957             : 
     958             :   // Store value to raw memory location.
     959             :   Node* Store(Node* base, Node* value);
     960             :   Node* Store(Node* base, Node* offset, Node* value);
     961             :   Node* StoreEphemeronKey(Node* base, Node* offset, Node* value);
     962             :   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
     963             :   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
     964             :                             Node* value);
     965             :   // Stores uncompressed tagged value to (most likely off JS heap) memory
     966             :   // location without write barrier.
     967             :   Node* StoreFullTaggedNoWriteBarrier(Node* base, Node* tagged_value);
     968             :   Node* StoreFullTaggedNoWriteBarrier(Node* base, Node* offset,
     969             :                                       Node* tagged_value);
     970             : 
     971             :   // Optimized memory operations that map to Turbofan simplified nodes.
     972             :   TNode<HeapObject> OptimizedAllocate(TNode<IntPtrT> size,
     973             :                                       AllocationType allocation);
     974             :   void OptimizedStoreField(MachineRepresentation rep, TNode<HeapObject> object,
     975             :                            int offset, Node* value,
     976             :                            WriteBarrierKind write_barrier);
     977             :   void OptimizedStoreMap(TNode<HeapObject> object, TNode<Map>);
     978             :   // {value_high} is used for 64-bit stores on 32-bit platforms, must be
     979             :   // nullptr in other cases.
     980             :   Node* AtomicStore(MachineRepresentation rep, Node* base, Node* offset,
     981             :                     Node* value, Node* value_high = nullptr);
     982             : 
     983             :   // Exchange value at raw memory location
     984             :   Node* AtomicExchange(MachineType type, Node* base, Node* offset, Node* value,
     985             :                        Node* value_high = nullptr);
     986             : 
     987             :   // Compare and Exchange value at raw memory location
     988             :   Node* AtomicCompareExchange(MachineType type, Node* base, Node* offset,
     989             :                               Node* old_value, Node* new_value,
     990             :                               Node* old_value_high = nullptr,
     991             :                               Node* new_value_high = nullptr);
     992             : 
     993             :   Node* AtomicAdd(MachineType type, Node* base, Node* offset, Node* value,
     994             :                   Node* value_high = nullptr);
     995             : 
     996             :   Node* AtomicSub(MachineType type, Node* base, Node* offset, Node* value,
     997             :                   Node* value_high = nullptr);
     998             : 
     999             :   Node* AtomicAnd(MachineType type, Node* base, Node* offset, Node* value,
    1000             :                   Node* value_high = nullptr);
    1001             : 
    1002             :   Node* AtomicOr(MachineType type, Node* base, Node* offset, Node* value,
    1003             :                  Node* value_high = nullptr);
    1004             : 
    1005             :   Node* AtomicXor(MachineType type, Node* base, Node* offset, Node* value,
    1006             :                   Node* value_high = nullptr);
    1007             : 
    1008             :   // Store a value to the root array.
    1009             :   Node* StoreRoot(RootIndex root_index, Node* value);
    1010             : 
    1011             : // Basic arithmetic operations.
    1012             : #define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
    1013             :   TNode<ResType> name(SloppyTNode<Arg1Type> a, SloppyTNode<Arg2Type> b);
    1014             :   CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
    1015             : #undef DECLARE_CODE_ASSEMBLER_BINARY_OP
    1016             : 
    1017             :   TNode<IntPtrT> WordShr(TNode<IntPtrT> left, TNode<IntegralT> right) {
    1018             :     return UncheckedCast<IntPtrT>(
    1019        4948 :         WordShr(static_cast<Node*>(left), static_cast<Node*>(right)));
    1020             :   }
    1021             :   TNode<IntPtrT> WordSar(TNode<IntPtrT> left, TNode<IntegralT> right) {
    1022             :     return UncheckedCast<IntPtrT>(
    1023         168 :         WordSar(static_cast<Node*>(left), static_cast<Node*>(right)));
    1024             :   }
    1025             : 
    1026             :   TNode<IntPtrT> WordAnd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
    1027             :     return UncheckedCast<IntPtrT>(
    1028      233092 :         WordAnd(static_cast<Node*>(left), static_cast<Node*>(right)));
    1029             :   }
    1030             : 
    1031             :   template <class Left, class Right,
    1032             :             class = typename std::enable_if<
    1033             :                 std::is_base_of<Object, Left>::value &&
    1034             :                 std::is_base_of<Object, Right>::value>::type>
    1035             :   TNode<BoolT> WordEqual(TNode<Left> left, TNode<Right> right) {
    1036             :     return WordEqual(ReinterpretCast<WordT>(left),
    1037      198124 :                      ReinterpretCast<WordT>(right));
    1038             :   }
    1039             :   TNode<BoolT> WordEqual(TNode<Object> left, Node* right) {
    1040             :     return WordEqual(ReinterpretCast<WordT>(left),
    1041       10664 :                      ReinterpretCast<WordT>(right));
    1042             :   }
    1043             :   TNode<BoolT> WordEqual(Node* left, TNode<Object> right) {
    1044             :     return WordEqual(ReinterpretCast<WordT>(left),
    1045       34748 :                      ReinterpretCast<WordT>(right));
    1046             :   }
    1047             :   template <class Left, class Right,
    1048             :             class = typename std::enable_if<
    1049             :                 std::is_base_of<Object, Left>::value &&
    1050             :                 std::is_base_of<Object, Right>::value>::type>
    1051             :   TNode<BoolT> WordNotEqual(TNode<Left> left, TNode<Right> right) {
    1052             :     return WordNotEqual(ReinterpretCast<WordT>(left),
    1053        7372 :                         ReinterpretCast<WordT>(right));
    1054             :   }
    1055             :   TNode<BoolT> WordNotEqual(TNode<Object> left, Node* right) {
    1056             :     return WordNotEqual(ReinterpretCast<WordT>(left),
    1057         280 :                         ReinterpretCast<WordT>(right));
    1058             :   }
    1059             :   TNode<BoolT> WordNotEqual(Node* left, TNode<Object> right) {
    1060             :     return WordNotEqual(ReinterpretCast<WordT>(left),
    1061        1796 :                         ReinterpretCast<WordT>(right));
    1062             :   }
    1063             : 
    1064             :   TNode<BoolT> IntPtrEqual(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1065             :   TNode<BoolT> WordEqual(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1066             :   TNode<BoolT> WordNotEqual(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1067             :   TNode<BoolT> Word32Equal(SloppyTNode<Word32T> left,
    1068             :                            SloppyTNode<Word32T> right);
    1069             :   TNode<BoolT> Word32NotEqual(SloppyTNode<Word32T> left,
    1070             :                               SloppyTNode<Word32T> right);
    1071             :   TNode<BoolT> Word64Equal(SloppyTNode<Word64T> left,
    1072             :                            SloppyTNode<Word64T> right);
    1073             :   TNode<BoolT> Word64NotEqual(SloppyTNode<Word64T> left,
    1074             :                               SloppyTNode<Word64T> right);
    1075             : 
    1076             :   TNode<Int32T> Int32Add(TNode<Int32T> left, TNode<Int32T> right) {
    1077             :     return Signed(
    1078        1688 :         Int32Add(static_cast<Node*>(left), static_cast<Node*>(right)));
    1079             :   }
    1080             : 
    1081             :   TNode<Uint32T> Uint32Add(TNode<Uint32T> left, TNode<Uint32T> right) {
    1082             :     return Unsigned(
    1083        2408 :         Int32Add(static_cast<Node*>(left), static_cast<Node*>(right)));
    1084             :   }
    1085             : 
    1086             :   TNode<WordT> IntPtrAdd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1087             :   TNode<IntPtrT> IntPtrDiv(TNode<IntPtrT> left, TNode<IntPtrT> right);
    1088             :   TNode<WordT> IntPtrSub(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1089             :   TNode<WordT> IntPtrMul(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1090             :   TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
    1091             :     return Signed(
    1092      393608 :         IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
    1093             :   }
    1094             :   TNode<IntPtrT> IntPtrSub(TNode<IntPtrT> left, TNode<IntPtrT> right) {
    1095             :     return Signed(
    1096       93900 :         IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
    1097             :   }
    1098             :   TNode<IntPtrT> IntPtrMul(TNode<IntPtrT> left, TNode<IntPtrT> right) {
    1099             :     return Signed(
    1100       25148 :         IntPtrMul(static_cast<Node*>(left), static_cast<Node*>(right)));
    1101             :   }
    1102             :   TNode<UintPtrT> UintPtrAdd(TNode<UintPtrT> left, TNode<UintPtrT> right) {
    1103             :     return Unsigned(
    1104        6888 :         IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
    1105             :   }
    1106             :   TNode<UintPtrT> UintPtrSub(TNode<UintPtrT> left, TNode<UintPtrT> right) {
    1107             :     return Unsigned(
    1108         224 :         IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
    1109             :   }
    1110             :   TNode<RawPtrT> RawPtrAdd(TNode<RawPtrT> left, TNode<IntPtrT> right) {
    1111         560 :     return ReinterpretCast<RawPtrT>(IntPtrAdd(left, right));
    1112             :   }
    1113             :   TNode<RawPtrT> RawPtrAdd(TNode<IntPtrT> left, TNode<RawPtrT> right) {
    1114             :     return ReinterpretCast<RawPtrT>(IntPtrAdd(left, right));
    1115             :   }
    1116             : 
    1117             :   TNode<WordT> WordShl(SloppyTNode<WordT> value, int shift);
    1118             :   TNode<WordT> WordShr(SloppyTNode<WordT> value, int shift);
    1119             :   TNode<WordT> WordSar(SloppyTNode<WordT> value, int shift);
    1120             :   TNode<IntPtrT> WordShr(TNode<IntPtrT> value, int shift) {
    1121        4824 :     return UncheckedCast<IntPtrT>(WordShr(static_cast<Node*>(value), shift));
    1122             :   }
    1123             :   TNode<IntPtrT> WordSar(TNode<IntPtrT> value, int shift) {
    1124        3038 :     return UncheckedCast<IntPtrT>(WordSar(static_cast<Node*>(value), shift));
    1125             :   }
    1126             :   TNode<Word32T> Word32Shr(SloppyTNode<Word32T> value, int shift);
    1127             : 
    1128             :   TNode<WordT> WordOr(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1129             :   TNode<WordT> WordAnd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1130             :   TNode<WordT> WordXor(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
    1131             :   TNode<WordT> WordShl(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
    1132             :   TNode<WordT> WordShr(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
    1133             :   TNode<WordT> WordSar(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
    1134             :   TNode<Word32T> Word32Or(SloppyTNode<Word32T> left,
    1135             :                           SloppyTNode<Word32T> right);
    1136             :   TNode<Word32T> Word32And(SloppyTNode<Word32T> left,
    1137             :                            SloppyTNode<Word32T> right);
    1138             :   TNode<Word32T> Word32Xor(SloppyTNode<Word32T> left,
    1139             :                            SloppyTNode<Word32T> right);
    1140             :   TNode<Word32T> Word32Shl(SloppyTNode<Word32T> left,
    1141             :                            SloppyTNode<Word32T> right);
    1142             :   TNode<Word32T> Word32Shr(SloppyTNode<Word32T> left,
    1143             :                            SloppyTNode<Word32T> right);
    1144             :   TNode<Word32T> Word32Sar(SloppyTNode<Word32T> left,
    1145             :                            SloppyTNode<Word32T> right);
    1146             :   TNode<Word64T> Word64Or(SloppyTNode<Word64T> left,
    1147             :                           SloppyTNode<Word64T> right);
    1148             :   TNode<Word64T> Word64And(SloppyTNode<Word64T> left,
    1149             :                            SloppyTNode<Word64T> right);
    1150             :   TNode<Word64T> Word64Xor(SloppyTNode<Word64T> left,
    1151             :                            SloppyTNode<Word64T> right);
    1152             :   TNode<Word64T> Word64Shl(SloppyTNode<Word64T> left,
    1153             :                            SloppyTNode<Word64T> right);
    1154             :   TNode<Word64T> Word64Shr(SloppyTNode<Word64T> left,
    1155             :                            SloppyTNode<Word64T> right);
    1156             :   TNode<Word64T> Word64Sar(SloppyTNode<Word64T> left,
    1157             :                            SloppyTNode<Word64T> right);
    1158             : 
    1159             : // Unary
    1160             : #define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
    1161             :   TNode<ResType> name(SloppyTNode<ArgType> a);
    1162             :   CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
    1163             : #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
    1164             : 
    1165             :   // Changes a double to an inptr_t for pointer arithmetic outside of Smi range.
    1166             :   // Assumes that the double can be exactly represented as an int.
    1167             :   TNode<UintPtrT> ChangeFloat64ToUintPtr(SloppyTNode<Float64T> value);
    1168             :   // Same in the opposite direction.
    1169             :   TNode<Float64T> ChangeUintPtrToFloat64(TNode<UintPtrT> value);
    1170             : 
    1171             :   // Changes an intptr_t to a double, e.g. for storing an element index
    1172             :   // outside Smi range in a HeapNumber. Lossless on 32-bit,
    1173             :   // rounds on 64-bit (which doesn't affect valid element indices).
    1174             :   Node* RoundIntPtrToFloat64(Node* value);
    1175             :   // No-op on 32-bit, otherwise zero extend.
    1176             :   TNode<UintPtrT> ChangeUint32ToWord(SloppyTNode<Word32T> value);
    1177             :   // No-op on 32-bit, otherwise sign extend.
    1178             :   TNode<IntPtrT> ChangeInt32ToIntPtr(SloppyTNode<Word32T> value);
    1179             : 
    1180             :   // No-op that guarantees that the value is kept alive till this point even
    1181             :   // if GC happens.
    1182             :   Node* Retain(Node* value);
    1183             : 
    1184             :   // Projections
    1185             :   Node* Projection(int index, Node* value);
    1186             : 
    1187             :   // Pointer compression and decompression.
    1188             :   Node* ChangeTaggedToCompressed(Node* tagged);
    1189             :   Node* ChangeCompressedToTagged(Node* compressed);
    1190             : 
    1191             :   template <int index, class T1, class T2>
    1192             :   TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
    1193             :   Projection(TNode<PairT<T1, T2>> value) {
    1194             :     return UncheckedCast<
    1195       15472 :         typename std::tuple_element<index, std::tuple<T1, T2>>::type>(
    1196             :         Projection(index, value));
    1197             :   }
    1198             : 
    1199             :   // Calls
    1200             :   template <class... TArgs>
    1201             :   TNode<Object> CallRuntime(Runtime::FunctionId function,
    1202             :                             SloppyTNode<Object> context, TArgs... args) {
    1203             :     return CallRuntimeImpl(function, context,
    1204      140852 :                            {implicit_cast<SloppyTNode<Object>>(args)...});
    1205             :   }
    1206             : 
    1207             :   template <class... TArgs>
    1208             :   TNode<Object> CallRuntimeWithCEntry(Runtime::FunctionId function,
    1209             :                                       TNode<Code> centry,
    1210             :                                       SloppyTNode<Object> context,
    1211             :                                       TArgs... args) {
    1212         448 :     return CallRuntimeWithCEntryImpl(function, centry, context, {args...});
    1213             :   }
    1214             : 
    1215             :   template <class... TArgs>
    1216        7848 :   void TailCallRuntime(Runtime::FunctionId function,
    1217             :                        SloppyTNode<Object> context, TArgs... args) {
    1218             :     int argc = static_cast<int>(sizeof...(args));
    1219        7848 :     TNode<Int32T> arity = Int32Constant(argc);
    1220             :     return TailCallRuntimeImpl(function, arity, context,
    1221       10704 :                                {implicit_cast<SloppyTNode<Object>>(args)...});
    1222             :   }
    1223             : 
    1224             :   template <class... TArgs>
    1225             :   void TailCallRuntime(Runtime::FunctionId function, TNode<Int32T> arity,
    1226             :                        SloppyTNode<Object> context, TArgs... args) {
    1227             :     return TailCallRuntimeImpl(function, arity, context,
    1228         112 :                                {implicit_cast<SloppyTNode<Object>>(args)...});
    1229             :   }
    1230             : 
    1231             :   template <class... TArgs>
    1232        1064 :   void TailCallRuntimeWithCEntry(Runtime::FunctionId function,
    1233             :                                  TNode<Code> centry, TNode<Object> context,
    1234             :                                  TArgs... args) {
    1235             :     int argc = sizeof...(args);
    1236        1064 :     TNode<Int32T> arity = Int32Constant(argc);
    1237             :     return TailCallRuntimeWithCEntryImpl(
    1238             :         function, arity, centry, context,
    1239        1344 :         {implicit_cast<SloppyTNode<Object>>(args)...});
    1240             :   }
    1241             : 
    1242             :   //
    1243             :   // If context passed to CallStub is nullptr, it won't be passed to the stub.
    1244             :   //
    1245             : 
    1246             :   template <class T = Object, class... TArgs>
    1247      105020 :   TNode<T> CallStub(Callable const& callable, SloppyTNode<Object> context,
    1248             :                     TArgs... args) {
    1249             :     TNode<Code> target = HeapConstant(callable.code());
    1250      210040 :     return CallStub<T>(callable.descriptor(), target, context, args...);
    1251             :   }
    1252             : 
    1253             :   template <class T = Object, class... TArgs>
    1254      107540 :   TNode<T> CallStub(const CallInterfaceDescriptor& descriptor,
    1255             :                     SloppyTNode<Code> target, SloppyTNode<Object> context,
    1256             :                     TArgs... args) {
    1257             :     return UncheckedCast<T>(CallStubR(StubCallMode::kCallCodeObject, descriptor,
    1258      107540 :                                       1, target, context, args...));
    1259             :   }
    1260             : 
    1261             :   template <class... TArgs>
    1262             :   Node* CallStubR(StubCallMode call_mode,
    1263             :                   const CallInterfaceDescriptor& descriptor, size_t result_size,
    1264             :                   SloppyTNode<Object> target, SloppyTNode<Object> context,
    1265             :                   TArgs... args) {
    1266             :     return CallStubRImpl(call_mode, descriptor, result_size, target, context,
    1267      109698 :                          {args...});
    1268             :   }
    1269             : 
    1270             :   Node* CallStubN(StubCallMode call_mode,
    1271             :                   const CallInterfaceDescriptor& descriptor, size_t result_size,
    1272             :                   int input_count, Node* const* inputs);
    1273             : 
    1274             :   template <class T = Object, class... TArgs>
    1275        1816 :   TNode<T> CallBuiltinPointer(const CallInterfaceDescriptor& descriptor,
    1276             :                               TNode<BuiltinPtr> target, TNode<Object> context,
    1277             :                               TArgs... args) {
    1278             :     return UncheckedCast<T>(CallStubR(StubCallMode::kCallBuiltinPointer,
    1279        1816 :                                       descriptor, 1, target, context, args...));
    1280             :   }
    1281             : 
    1282             :   template <class... TArgs>
    1283        5320 :   void TailCallStub(Callable const& callable, SloppyTNode<Object> context,
    1284             :                     TArgs... args) {
    1285             :     TNode<Code> target = HeapConstant(callable.code());
    1286        5320 :     return TailCallStub(callable.descriptor(), target, context, args...);
    1287             :   }
    1288             : 
    1289             :   template <class... TArgs>
    1290             :   void TailCallStub(const CallInterfaceDescriptor& descriptor,
    1291             :                     SloppyTNode<Code> target, SloppyTNode<Object> context,
    1292             :                     TArgs... args) {
    1293        7504 :     return TailCallStubImpl(descriptor, target, context, {args...});
    1294             :   }
    1295             : 
    1296             :   template <class... TArgs>
    1297             :   Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
    1298             :                                  Node* target, TArgs... args);
    1299             : 
    1300             :   template <class... TArgs>
    1301             :   Node* TailCallStubThenBytecodeDispatch(
    1302             :       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
    1303             :       TArgs... args) {
    1304             :     return TailCallStubThenBytecodeDispatchImpl(descriptor, target, context,
    1305        2184 :                                                 {args...});
    1306             :   }
    1307             : 
    1308             :   // Tailcalls to the given code object with JSCall linkage. The JS arguments
    1309             :   // (including receiver) are supposed to be already on the stack.
    1310             :   // This is a building block for implementing trampoline stubs that are
    1311             :   // installed instead of code objects with JSCall linkage.
    1312             :   // Note that no arguments adaption is going on here - all the JavaScript
    1313             :   // arguments are left on the stack unmodified. Therefore, this tail call can
    1314             :   // only be used after arguments adaptation has been performed already.
    1315             :   TNode<Object> TailCallJSCode(TNode<Code> code, TNode<Context> context,
    1316             :                                TNode<JSFunction> function,
    1317             :                                TNode<Object> new_target,
    1318             :                                TNode<Int32T> arg_count);
    1319             : 
    1320             :   template <class... TArgs>
    1321       15248 :   Node* CallJS(Callable const& callable, Node* context, Node* function,
    1322             :                Node* receiver, TArgs... args) {
    1323             :     int argc = static_cast<int>(sizeof...(args));
    1324       30496 :     Node* arity = Int32Constant(argc);
    1325       30496 :     return CallStub(callable, context, function, arity, receiver, args...);
    1326             :   }
    1327             : 
    1328             :   template <class... TArgs>
    1329        1176 :   Node* ConstructJSWithTarget(Callable const& callable, Node* context,
    1330             :                               Node* target, Node* new_target, TArgs... args) {
    1331             :     int argc = static_cast<int>(sizeof...(args));
    1332        2352 :     Node* arity = Int32Constant(argc);
    1333        2352 :     Node* receiver = LoadRoot(RootIndex::kUndefinedValue);
    1334             : 
    1335             :     // Construct(target, new_target, arity, receiver, arguments...)
    1336             :     return CallStub(callable, context, target, new_target, arity, receiver,
    1337        2352 :                     args...);
    1338             :   }
    1339             :   template <class... TArgs>
    1340             :   Node* ConstructJS(Callable const& callable, Node* context, Node* new_target,
    1341             :                     TArgs... args) {
    1342             :     return ConstructJSWithTarget(callable, context, new_target, new_target,
    1343         112 :                                  args...);
    1344             :   }
    1345             : 
    1346             :   Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
    1347             :                        Node* const* inputs);
    1348             : 
    1349             :   // Type representing C function argument with type info.
    1350             :   using CFunctionArg = std::pair<MachineType, Node*>;
    1351             : 
    1352             :   // Call to a C function.
    1353             :   template <class... CArgs>
    1354       10788 :   Node* CallCFunction(Node* function, MachineType return_type, CArgs... cargs) {
    1355             :     static_assert(v8::internal::conjunction<
    1356             :                       std::is_convertible<CArgs, CFunctionArg>...>::value,
    1357             :                   "invalid argument types");
    1358       14004 :     return CallCFunction(function, return_type, {cargs...});
    1359             :   }
    1360             : 
    1361             :   // Call to a C function, while saving/restoring caller registers.
    1362             :   template <class... CArgs>
    1363         224 :   Node* CallCFunctionWithCallerSavedRegisters(Node* function,
    1364             :                                               MachineType return_type,
    1365             :                                               SaveFPRegsMode mode,
    1366             :                                               CArgs... cargs) {
    1367             :     static_assert(v8::internal::conjunction<
    1368             :                       std::is_convertible<CArgs, CFunctionArg>...>::value,
    1369             :                   "invalid argument types");
    1370             :     return CallCFunctionWithCallerSavedRegisters(function, return_type, mode,
    1371         452 :                                                  {cargs...});
    1372             :   }
    1373             : 
    1374             :   // Exception handling support.
    1375             :   void GotoIfException(Node* node, Label* if_exception,
    1376             :                        Variable* exception_var = nullptr);
    1377             : 
    1378             :   // Helpers which delegate to RawMachineAssembler.
    1379             :   Factory* factory() const;
    1380             :   Isolate* isolate() const;
    1381             :   Zone* zone() const;
    1382             : 
    1383     6127108 :   CodeAssemblerState* state() { return state_; }
    1384             : 
    1385             :   void BreakOnNode(int node_id);
    1386             : 
    1387             :   bool UnalignedLoadSupported(MachineRepresentation rep) const;
    1388             :   bool UnalignedStoreSupported(MachineRepresentation rep) const;
    1389             : 
    1390             :   bool IsExceptionHandlerActive() const;
    1391             : 
    1392             :  protected:
    1393             :   void RegisterCallGenerationCallbacks(
    1394             :       const CodeAssemblerCallback& call_prologue,
    1395             :       const CodeAssemblerCallback& call_epilogue);
    1396             :   void UnregisterCallGenerationCallbacks();
    1397             : 
    1398             :   bool Word32ShiftIsSafe() const;
    1399             :   PoisoningMitigationLevel poisoning_level() const;
    1400             : 
    1401             :   bool IsJSFunctionCall() const;
    1402             : 
    1403             :  private:
    1404             :   void HandleException(Node* result);
    1405             : 
    1406             :   Node* CallCFunction(Node* function, MachineType return_type,
    1407             :                       std::initializer_list<CFunctionArg> args);
    1408             : 
    1409             :   Node* CallCFunctionWithCallerSavedRegisters(
    1410             :       Node* function, MachineType return_type, SaveFPRegsMode mode,
    1411             :       std::initializer_list<CFunctionArg> args);
    1412             : 
    1413             :   TNode<Object> CallRuntimeImpl(Runtime::FunctionId function,
    1414             :                                 TNode<Object> context,
    1415             :                                 std::initializer_list<TNode<Object>> args);
    1416             : 
    1417             :   TNode<Object> CallRuntimeWithCEntryImpl(
    1418             :       Runtime::FunctionId function, TNode<Code> centry, TNode<Object> context,
    1419             :       std::initializer_list<TNode<Object>> args);
    1420             : 
    1421             :   void TailCallRuntimeImpl(Runtime::FunctionId function, TNode<Int32T> arity,
    1422             :                            TNode<Object> context,
    1423             :                            std::initializer_list<TNode<Object>> args);
    1424             : 
    1425             :   void TailCallRuntimeWithCEntryImpl(Runtime::FunctionId function,
    1426             :                                      TNode<Int32T> arity, TNode<Code> centry,
    1427             :                                      TNode<Object> context,
    1428             :                                      std::initializer_list<TNode<Object>> args);
    1429             : 
    1430             :   void TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
    1431             :                         TNode<Code> target, TNode<Object> context,
    1432             :                         std::initializer_list<Node*> args);
    1433             : 
    1434             :   Node* TailCallStubThenBytecodeDispatchImpl(
    1435             :       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
    1436             :       std::initializer_list<Node*> args);
    1437             : 
    1438             :   Node* CallStubRImpl(StubCallMode call_mode,
    1439             :                       const CallInterfaceDescriptor& descriptor,
    1440             :                       size_t result_size, Node* target,
    1441             :                       SloppyTNode<Object> context,
    1442             :                       std::initializer_list<Node*> args);
    1443             : 
    1444             :   // These two don't have definitions and are here only for catching use cases
    1445             :   // where the cast is not necessary.
    1446             :   TNode<Int32T> Signed(TNode<Int32T> x);
    1447             :   TNode<Uint32T> Unsigned(TNode<Uint32T> x);
    1448             : 
    1449             :   RawMachineAssembler* raw_assembler() const;
    1450             : 
    1451             :   // Calls respective callback registered in the state.
    1452             :   void CallPrologue();
    1453             :   void CallEpilogue();
    1454             : 
    1455             :   CodeAssemblerState* state_;
    1456             : 
    1457             :   DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
    1458             : };
    1459             : 
    1460             : class V8_EXPORT_PRIVATE CodeAssemblerVariable {
    1461             :  public:
    1462             :   explicit CodeAssemblerVariable(CodeAssembler* assembler,
    1463             :                                  MachineRepresentation rep);
    1464             :   CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
    1465             :                         Node* initial_value);
    1466             : #if DEBUG
    1467             :   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
    1468             :                         MachineRepresentation rep);
    1469             :   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
    1470             :                         MachineRepresentation rep, Node* initial_value);
    1471             : #endif  // DEBUG
    1472             : 
    1473             :   ~CodeAssemblerVariable();
    1474             :   void Bind(Node* value);
    1475             :   Node* value() const;
    1476             :   MachineRepresentation rep() const;
    1477             :   bool IsBound() const;
    1478             : 
    1479             :  private:
    1480             :   class Impl;
    1481             :   friend class CodeAssemblerLabel;
    1482             :   friend class CodeAssemblerState;
    1483             :   friend std::ostream& operator<<(std::ostream&, const Impl&);
    1484             :   friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
    1485             :   struct ImplComparator {
    1486             :     bool operator()(const CodeAssemblerVariable::Impl* a,
    1487             :                     const CodeAssemblerVariable::Impl* b) const;
    1488             :   };
    1489             :   Impl* impl_;
    1490             :   CodeAssemblerState* state_;
    1491             :   DISALLOW_COPY_AND_ASSIGN(CodeAssemblerVariable);
    1492             : };
    1493             : 
    1494             : std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
    1495             : std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
    1496             : 
    1497             : template <class T>
    1498      170492 : class TypedCodeAssemblerVariable : public CodeAssemblerVariable {
    1499             :  public:
    1500             :   TypedCodeAssemblerVariable(TNode<T> initial_value, CodeAssembler* assembler)
    1501             :       : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value,
    1502       52900 :                               initial_value) {}
    1503             :   explicit TypedCodeAssemblerVariable(CodeAssembler* assembler)
    1504      122476 :       : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value) {}
    1505             : #if DEBUG
    1506             :   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
    1507             :                              CodeAssembler* assembler)
    1508             :       : CodeAssemblerVariable(assembler, debug_info,
    1509             :                               MachineRepresentationOf<T>::value) {}
    1510             :   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
    1511             :                              TNode<T> initial_value, CodeAssembler* assembler)
    1512             :       : CodeAssemblerVariable(assembler, debug_info,
    1513             :                               MachineRepresentationOf<T>::value,
    1514             :                               initial_value) {}
    1515             : #endif  // DEBUG
    1516             : 
    1517             :   TNode<T> value() const {
    1518      273784 :     return TNode<T>::UncheckedCast(CodeAssemblerVariable::value());
    1519             :   }
    1520             : 
    1521      361864 :   void operator=(TNode<T> value) { Bind(value); }
    1522             :   void operator=(const TypedCodeAssemblerVariable<T>& variable) {
    1523          56 :     Bind(variable.value());
    1524             :   }
    1525             : 
    1526             :  private:
    1527             :   using CodeAssemblerVariable::Bind;
    1528             : };
    1529             : 
    1530             : class V8_EXPORT_PRIVATE CodeAssemblerLabel {
    1531             :  public:
    1532             :   enum Type { kDeferred, kNonDeferred };
    1533             : 
    1534             :   explicit CodeAssemblerLabel(
    1535             :       CodeAssembler* assembler,
    1536             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1537     2736579 :       : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
    1538             :   CodeAssemblerLabel(
    1539             :       CodeAssembler* assembler,
    1540             :       const CodeAssemblerVariableList& merged_variables,
    1541             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1542             :       : CodeAssemblerLabel(assembler, merged_variables.size(),
    1543       36896 :                            &(merged_variables[0]), type) {}
    1544             :   CodeAssemblerLabel(
    1545             :       CodeAssembler* assembler, size_t count,
    1546             :       CodeAssemblerVariable* const* vars,
    1547             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
    1548             :   CodeAssemblerLabel(
    1549             :       CodeAssembler* assembler,
    1550             :       std::initializer_list<CodeAssemblerVariable*> vars,
    1551             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1552       16316 :       : CodeAssemblerLabel(assembler, vars.size(), vars.begin(), type) {}
    1553             :   CodeAssemblerLabel(
    1554             :       CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
    1555             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1556       72532 :       : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
    1557             :   ~CodeAssemblerLabel();
    1558             : 
    1559             :   inline bool is_bound() const { return bound_; }
    1560             :   inline bool is_used() const { return merge_count_ != 0; }
    1561             : 
    1562             :  private:
    1563             :   friend class CodeAssembler;
    1564             : 
    1565             :   void Bind();
    1566             : #if DEBUG
    1567             :   void Bind(AssemblerDebugInfo debug_info);
    1568             : #endif  // DEBUG
    1569             :   void UpdateVariablesAfterBind();
    1570             :   void MergeVariables();
    1571             : 
    1572             :   bool bound_;
    1573             :   size_t merge_count_;
    1574             :   CodeAssemblerState* state_;
    1575             :   RawMachineLabel* label_;
    1576             :   // Map of variables that need to be merged to their phi nodes (or placeholders
    1577             :   // for those phis).
    1578             :   std::map<CodeAssemblerVariable::Impl*, Node*,
    1579             :            CodeAssemblerVariable::ImplComparator>
    1580             :       variable_phis_;
    1581             :   // Map of variables to the list of value nodes that have been added from each
    1582             :   // merge path in their order of merging.
    1583             :   std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>,
    1584             :            CodeAssemblerVariable::ImplComparator>
    1585             :       variable_merges_;
    1586             : 
    1587             :   // Cannot be copied because the destructor explicitly call the destructor of
    1588             :   // the underlying {RawMachineLabel}, hence only one pointer can point to it.
    1589             :   DISALLOW_COPY_AND_ASSIGN(CodeAssemblerLabel);
    1590             : };
    1591             : 
    1592     2484184 : class CodeAssemblerParameterizedLabelBase {
    1593             :  public:
    1594             :   bool is_used() const { return plain_label_.is_used(); }
    1595     1242092 :   explicit CodeAssemblerParameterizedLabelBase(CodeAssembler* assembler,
    1596             :                                                size_t arity,
    1597             :                                                CodeAssemblerLabel::Type type)
    1598             :       : state_(assembler->state()),
    1599             :         phi_inputs_(arity),
    1600     3726276 :         plain_label_(assembler, type) {}
    1601             : 
    1602             :  protected:
    1603       80016 :   CodeAssemblerLabel* plain_label() { return &plain_label_; }
    1604             :   void AddInputs(std::vector<Node*> inputs);
    1605             :   Node* CreatePhi(MachineRepresentation rep, const std::vector<Node*>& inputs);
    1606             :   const std::vector<Node*>& CreatePhis(
    1607             :       std::vector<MachineRepresentation> representations);
    1608             : 
    1609             :  private:
    1610             :   CodeAssemblerState* state_;
    1611             :   std::vector<std::vector<Node*>> phi_inputs_;
    1612             :   std::vector<Node*> phi_nodes_;
    1613             :   CodeAssemblerLabel plain_label_;
    1614             : };
    1615             : 
    1616             : template <class... Types>
    1617      272456 : class CodeAssemblerParameterizedLabel
    1618             :     : public CodeAssemblerParameterizedLabelBase {
    1619             :  public:
    1620             :   static constexpr size_t kArity = sizeof...(Types);
    1621             :   explicit CodeAssemblerParameterizedLabel(CodeAssembler* assembler,
    1622             :                                            CodeAssemblerLabel::Type type)
    1623      272788 :       : CodeAssemblerParameterizedLabelBase(assembler, kArity, type) {}
    1624             : 
    1625             :  private:
    1626             :   friend class CodeAssembler;
    1627             : 
    1628     1276280 :   void AddInputs(TNode<Types>... inputs) {
    1629     7033776 :     CodeAssemblerParameterizedLabelBase::AddInputs(
    1630             :         std::vector<Node*>{inputs...});
    1631     1276280 :   }
    1632     1186840 :   void CreatePhis(TNode<Types>*... results) {
    1633             :     const std::vector<Node*>& phi_nodes =
    1634     2373680 :         CodeAssemblerParameterizedLabelBase::CreatePhis(
    1635     1186840 :             {MachineRepresentationOf<Types>::value...});
    1636             :     auto it = phi_nodes.begin();
    1637             :     USE(it);
    1638     3976484 :     ITERATE_PACK(AssignPhi(results, *(it++)));
    1639     1186840 :   }
    1640             :   template <class T>
    1641             :   static void AssignPhi(TNode<T>* result, Node* phi) {
    1642     3976484 :     if (phi != nullptr) *result = TNode<T>::UncheckedCast(phi);
    1643             :   }
    1644             : };
    1645             : 
    1646             : using CodeAssemblerExceptionHandlerLabel =
    1647             :     CodeAssemblerParameterizedLabel<Object>;
    1648             : 
    1649      137502 : class V8_EXPORT_PRIVATE CodeAssemblerState {
    1650             :  public:
    1651             :   // Create with CallStub linkage.
    1652             :   // |result_size| specifies the number of results returned by the stub.
    1653             :   // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
    1654             :   CodeAssemblerState(Isolate* isolate, Zone* zone,
    1655             :                      const CallInterfaceDescriptor& descriptor, Code::Kind kind,
    1656             :                      const char* name, PoisoningMitigationLevel poisoning_level,
    1657             :                      int32_t builtin_index = Builtins::kNoBuiltinId);
    1658             : 
    1659             :   // Create with JSCall linkage.
    1660             :   CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
    1661             :                      Code::Kind kind, const char* name,
    1662             :                      PoisoningMitigationLevel poisoning_level,
    1663             :                      int32_t builtin_index = Builtins::kNoBuiltinId);
    1664             : 
    1665             :   ~CodeAssemblerState();
    1666             : 
    1667             :   const char* name() const { return name_; }
    1668             :   int parameter_count() const;
    1669             : 
    1670             : #if DEBUG
    1671             :   void PrintCurrentBlock(std::ostream& os);
    1672             : #endif  // DEBUG
    1673             :   bool InsideBlock();
    1674             :   void SetInitialDebugInformation(const char* msg, const char* file, int line);
    1675             : 
    1676             :  private:
    1677             :   friend class CodeAssembler;
    1678             :   friend class CodeAssemblerLabel;
    1679             :   friend class CodeAssemblerVariable;
    1680             :   friend class CodeAssemblerTester;
    1681             :   friend class CodeAssemblerParameterizedLabelBase;
    1682             :   friend class CodeAssemblerScopedExceptionHandler;
    1683             : 
    1684             :   CodeAssemblerState(Isolate* isolate, Zone* zone,
    1685             :                      CallDescriptor* call_descriptor, Code::Kind kind,
    1686             :                      const char* name, PoisoningMitigationLevel poisoning_level,
    1687             :                      int32_t builtin_index);
    1688             : 
    1689             :   void PushExceptionHandler(CodeAssemblerExceptionHandlerLabel* label);
    1690             :   void PopExceptionHandler();
    1691             : 
    1692             :   std::unique_ptr<RawMachineAssembler> raw_assembler_;
    1693             :   Code::Kind kind_;
    1694             :   const char* name_;
    1695             :   int32_t builtin_index_;
    1696             :   bool code_generated_;
    1697             :   ZoneSet<CodeAssemblerVariable::Impl*, CodeAssemblerVariable::ImplComparator>
    1698             :       variables_;
    1699             :   CodeAssemblerCallback call_prologue_;
    1700             :   CodeAssemblerCallback call_epilogue_;
    1701             :   std::vector<CodeAssemblerExceptionHandlerLabel*> exception_handler_labels_;
    1702             :   using VariableId = uint32_t;
    1703             :   VariableId next_variable_id_ = 0;
    1704             : 
    1705      615070 :   VariableId NextVariableId() { return next_variable_id_++; }
    1706             : 
    1707             :   DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState);
    1708             : };
    1709             : 
    1710             : class V8_EXPORT_PRIVATE CodeAssemblerScopedExceptionHandler {
    1711             :  public:
    1712             :   CodeAssemblerScopedExceptionHandler(
    1713             :       CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label);
    1714             : 
    1715             :   // Use this constructor for compatability/ports of old CSA code only. New code
    1716             :   // should use the CodeAssemblerExceptionHandlerLabel version.
    1717             :   CodeAssemblerScopedExceptionHandler(
    1718             :       CodeAssembler* assembler, CodeAssemblerLabel* label,
    1719             :       TypedCodeAssemblerVariable<Object>* exception);
    1720             : 
    1721             :   ~CodeAssemblerScopedExceptionHandler();
    1722             : 
    1723             :  private:
    1724             :   bool has_handler_;
    1725             :   CodeAssembler* assembler_;
    1726             :   CodeAssemblerLabel* compatibility_label_;
    1727             :   std::unique_ptr<CodeAssemblerExceptionHandlerLabel> label_;
    1728             :   TypedCodeAssemblerVariable<Object>* exception_;
    1729             : };
    1730             : 
    1731             : }  // namespace compiler
    1732             : 
    1733             : #if defined(V8_HOST_ARCH_32_BIT)
    1734             : using BInt = Smi;
    1735             : #elif defined(V8_HOST_ARCH_64_BIT)
    1736             : using BInt = IntPtrT;
    1737             : #else
    1738             : #error Unknown architecture.
    1739             : #endif
    1740             : 
    1741             : }  // namespace internal
    1742             : }  // namespace v8
    1743             : 
    1744             : #endif  // V8_COMPILER_CODE_ASSEMBLER_H_

Generated by: LCOV version 1.10