LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 202 207 97.6 %
Date: 2019-02-19 Functions: 12272 12919 95.0 %

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

Generated by: LCOV version 1.10