LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 210 215 97.7 %
Date: 2019-03-21 Functions: 13103 15478 84.7 %

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

Generated by: LCOV version 1.10