LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 111 114 97.4 %
Date: 2019-01-20 Functions: 2354 2512 93.7 %

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

Generated by: LCOV version 1.10