LCOV - code coverage report
Current view: top level - src/compiler - code-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 51 52 98.1 %
Date: 2017-10-20 Functions: 45 45 100.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_COMPILER_CODE_ASSEMBLER_H_
       6             : #define V8_COMPILER_CODE_ASSEMBLER_H_
       7             : 
       8             : #include <map>
       9             : #include <memory>
      10             : 
      11             : // Clients of this interface shouldn't depend on lots of compiler internals.
      12             : // Do not include anything from src/compiler here!
      13             : #include "src/allocation.h"
      14             : #include "src/base/template-utils.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/runtime/runtime.h"
      21             : #include "src/zone/zone-containers.h"
      22             : 
      23             : namespace v8 {
      24             : namespace internal {
      25             : 
      26             : class Callable;
      27             : class CallInterfaceDescriptor;
      28             : class Isolate;
      29             : class Factory;
      30             : class Zone;
      31             : 
      32             : struct UntaggedT {};
      33             : 
      34             : struct IntegralT : UntaggedT {};
      35             : 
      36             : struct WordT : IntegralT {
      37             :   static const MachineRepresentation kMachineRepresentation =
      38             :       (kPointerSize == 4) ? MachineRepresentation::kWord32
      39             :                           : MachineRepresentation::kWord64;
      40             : };
      41             : 
      42             : struct RawPtrT : WordT {};
      43             : 
      44             : template <class To>
      45             : struct RawPtr : RawPtrT {};
      46             : 
      47             : struct Word32T : IntegralT {
      48             :   static const MachineRepresentation kMachineRepresentation =
      49             :       MachineRepresentation::kWord32;
      50             : };
      51             : struct Int32T : Word32T {
      52             :   static constexpr MachineType kMachineType = MachineType::Int32();
      53             : };
      54             : struct Uint32T : Word32T {
      55             :   static constexpr MachineType kMachineType = MachineType::Uint32();
      56             : };
      57             : 
      58             : struct Word64T : IntegralT {
      59             :   static const MachineRepresentation kMachineRepresentation =
      60             :       MachineRepresentation::kWord64;
      61             : };
      62             : struct Int64T : Word64T {
      63             :   static constexpr MachineType kMachineType = MachineType::Int64();
      64             : };
      65             : struct Uint64T : Word64T {
      66             :   static constexpr MachineType kMachineType = MachineType::Uint64();
      67             : };
      68             : 
      69             : struct IntPtrT : WordT {
      70             :   static constexpr MachineType kMachineType = MachineType::IntPtr();
      71             : };
      72             : struct UintPtrT : WordT {
      73             :   static constexpr MachineType kMachineType = MachineType::UintPtr();
      74             : };
      75             : 
      76             : struct Float32T : UntaggedT {
      77             :   static const MachineRepresentation kMachineRepresentation =
      78             :       MachineRepresentation::kFloat32;
      79             :   static constexpr MachineType kMachineType = MachineType::Float32();
      80             : };
      81             : 
      82             : struct Float64T : UntaggedT {
      83             :   static const MachineRepresentation kMachineRepresentation =
      84             :       MachineRepresentation::kFloat64;
      85             :   static constexpr MachineType kMachineType = MachineType::Float64();
      86             : };
      87             : 
      88             : // Result of a comparison operation.
      89             : struct BoolT : Word32T {};
      90             : 
      91             : // Value type of a Turbofan node with two results.
      92             : template <class T1, class T2>
      93             : struct PairT {};
      94             : 
      95             : inline constexpr MachineType CommonMachineType(MachineType type1,
      96             :                                                MachineType type2) {
      97             :   return (type1 == type2) ? type1
      98             :                           : ((type1.IsTagged() && type2.IsTagged())
      99             :                                  ? MachineType::AnyTagged()
     100             :                                  : MachineType::None());
     101             : }
     102             : 
     103             : template <class Type, class Enable = void>
     104             : struct MachineTypeOf {
     105             :   static constexpr MachineType value = Type::kMachineType;
     106             : };
     107             : 
     108             : template <class Type, class Enable>
     109             : constexpr MachineType MachineTypeOf<Type, Enable>::value;
     110             : 
     111             : template <>
     112             : struct MachineTypeOf<Object> {
     113             :   static constexpr MachineType value = MachineType::AnyTagged();
     114             : };
     115             : template <>
     116             : struct MachineTypeOf<Smi> {
     117             :   static constexpr MachineType value = MachineType::TaggedSigned();
     118             : };
     119             : template <class HeapObjectSubtype>
     120             : struct MachineTypeOf<HeapObjectSubtype,
     121             :                      typename std::enable_if<std::is_base_of<
     122             :                          HeapObject, HeapObjectSubtype>::value>::type> {
     123             :   static constexpr MachineType value = MachineType::TaggedPointer();
     124             : };
     125             : 
     126             : template <class HeapObjectSubtype>
     127             : constexpr MachineType MachineTypeOf<
     128             :     HeapObjectSubtype, typename std::enable_if<std::is_base_of<
     129             :                            HeapObject, HeapObjectSubtype>::value>::type>::value;
     130             : 
     131             : template <class Type, class Enable = void>
     132             : struct MachineRepresentationOf {
     133             :   static const MachineRepresentation value = Type::kMachineRepresentation;
     134             : };
     135             : template <class T>
     136             : struct MachineRepresentationOf<
     137             :     T, typename std::enable_if<std::is_base_of<Object, T>::value>::type> {
     138             :   static const MachineRepresentation value =
     139             :       MachineTypeOf<T>::value.representation();
     140             : };
     141             : 
     142             : template <class T>
     143             : struct is_valid_type_tag {
     144             :   static const bool value = std::is_base_of<Object, T>::value ||
     145             :                             std::is_base_of<UntaggedT, T>::value ||
     146             :                             std::is_same<ExternalReference, T>::value;
     147             :   static const bool is_tagged = std::is_base_of<Object, T>::value;
     148             : };
     149             : 
     150             : template <class T1, class T2>
     151             : struct is_valid_type_tag<PairT<T1, T2>> {
     152             :   static const bool value =
     153             :       is_valid_type_tag<T1>::value && is_valid_type_tag<T2>::value;
     154             :   static const bool is_tagged = false;
     155             : };
     156             : 
     157             : template <class T1, class T2>
     158             : struct UnionT;
     159             : 
     160             : template <class T1, class T2>
     161             : struct is_valid_type_tag<UnionT<T1, T2>> {
     162             :   static const bool is_tagged =
     163             :       is_valid_type_tag<T1>::is_tagged && is_valid_type_tag<T2>::is_tagged;
     164             :   static const bool value = is_tagged;
     165             : };
     166             : 
     167             : template <class T1, class T2>
     168             : struct UnionT {
     169             :   static constexpr MachineType kMachineType =
     170             :       CommonMachineType(MachineTypeOf<T1>::value, MachineTypeOf<T2>::value);
     171             :   static const MachineRepresentation kMachineRepresentation =
     172             :       kMachineType.representation();
     173             :   static_assert(kMachineRepresentation != MachineRepresentation::kNone,
     174             :                 "no common representation");
     175             :   static_assert(is_valid_type_tag<T1>::is_tagged &&
     176             :                     is_valid_type_tag<T2>::is_tagged,
     177             :                 "union types are only possible for tagged values");
     178             : };
     179             : 
     180             : using Number = UnionT<Smi, HeapNumber>;
     181             : using Numeric = UnionT<Number, BigInt>;
     182             : 
     183             : #define ENUM_ELEMENT(Name) k##Name,
     184             : #define ENUM_STRUCT_ELEMENT(NAME, Name, name) k##Name,
     185             : enum class ObjectType {
     186             :   kObject,
     187             :   OBJECT_TYPE_LIST(ENUM_ELEMENT) HEAP_OBJECT_TYPE_LIST(ENUM_ELEMENT)
     188             :       STRUCT_LIST(ENUM_STRUCT_ELEMENT)
     189             : };
     190             : #undef ENUM_ELEMENT
     191             : #undef ENUM_STRUCT_ELEMENT
     192             : 
     193             : class AccessCheckNeeded;
     194             : class CompilationCacheTable;
     195             : class Constructor;
     196             : class Filler;
     197             : class InternalizedString;
     198             : class JSArgumentsObject;
     199             : class JSContextExtensionObject;
     200             : class JSError;
     201             : class JSSloppyArgumentsObject;
     202             : class MapCache;
     203             : class MutableHeapNumber;
     204             : class NativeContext;
     205             : class SloppyArgumentsElements;
     206             : class StringWrapper;
     207             : class Undetectable;
     208             : class UniqueName;
     209             : class WasmMemoryObject;
     210             : class WasmModuleObject;
     211             : class WasmTableObject;
     212             : 
     213             : template <class T>
     214             : struct ObjectTypeOf {};
     215             : 
     216             : #define OBJECT_TYPE_CASE(Name)                           \
     217             :   template <>                                            \
     218             :   struct ObjectTypeOf<Name> {                            \
     219             :     static const ObjectType value = ObjectType::k##Name; \
     220             :   };
     221             : #define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name)        \
     222             :   template <>                                            \
     223             :   struct ObjectTypeOf<Name> {                            \
     224             :     static const ObjectType value = ObjectType::k##Name; \
     225             :   };
     226             : #define OBJECT_TYPE_TEMPLATE_CASE(Name)                  \
     227             :   template <class... Args>                               \
     228             :   struct ObjectTypeOf<Name<Args...>> {                   \
     229             :     static const ObjectType value = ObjectType::k##Name; \
     230             :   };
     231             : OBJECT_TYPE_CASE(Object)
     232             : OBJECT_TYPE_LIST(OBJECT_TYPE_CASE)
     233             : HEAP_OBJECT_ORDINARY_TYPE_LIST(OBJECT_TYPE_CASE)
     234             : STRUCT_LIST(OBJECT_TYPE_STRUCT_CASE)
     235             : HEAP_OBJECT_TEMPLATE_TYPE_LIST(OBJECT_TYPE_TEMPLATE_CASE)
     236             : #undef OBJECT_TYPE_CASE
     237             : #undef OBJECT_TYPE_STRUCT_CASE
     238             : #undef OBJECT_TYPE_TEMPLATE_CASE
     239             : 
     240             : Smi* CheckObjectType(Object* value, Smi* type, String* location);
     241             : 
     242             : namespace compiler {
     243             : 
     244             : class CallDescriptor;
     245             : class CodeAssemblerLabel;
     246             : class CodeAssemblerVariable;
     247             : template <class T>
     248             : class TypedCodeAssemblerVariable;
     249             : class CodeAssemblerState;
     250             : class Node;
     251             : class RawMachineAssembler;
     252             : class RawMachineLabel;
     253             : 
     254             : typedef ZoneList<CodeAssemblerVariable*> CodeAssemblerVariableList;
     255             : 
     256             : typedef std::function<void()> CodeAssemblerCallback;
     257             : 
     258             : template <class T, class U>
     259             : struct is_subtype {
     260             :   static const bool value = std::is_base_of<U, T>::value;
     261             : };
     262             : template <class T1, class T2, class U>
     263             : struct is_subtype<UnionT<T1, T2>, U> {
     264             :   static const bool value =
     265             :       is_subtype<T1, U>::value && is_subtype<T2, U>::value;
     266             : };
     267             : template <class T, class U1, class U2>
     268             : struct is_subtype<T, UnionT<U1, U2>> {
     269             :   static const bool value =
     270             :       is_subtype<T, U1>::value || is_subtype<T, U2>::value;
     271             : };
     272             : template <class T1, class T2, class U1, class U2>
     273             : struct is_subtype<UnionT<T1, T2>, UnionT<U1, U2>> {
     274             :   static const bool value =
     275             :       (is_subtype<T1, U1>::value || is_subtype<T1, U2>::value) &&
     276             :       (is_subtype<T2, U1>::value || is_subtype<T2, U2>::value);
     277             : };
     278             : 
     279             : template <class T, class U>
     280             : struct types_have_common_values {
     281             :   static const bool value = is_subtype<T, U>::value || is_subtype<U, T>::value;
     282             : };
     283             : template <class U>
     284             : struct types_have_common_values<Uint32T, U> {
     285             :   static const bool value = types_have_common_values<Word32T, U>::value;
     286             : };
     287             : template <class U>
     288             : struct types_have_common_values<Int32T, U> {
     289             :   static const bool value = types_have_common_values<Word32T, U>::value;
     290             : };
     291             : template <class U>
     292             : struct types_have_common_values<Uint64T, U> {
     293             :   static const bool value = types_have_common_values<Word64T, U>::value;
     294             : };
     295             : template <class U>
     296             : struct types_have_common_values<Int64T, U> {
     297             :   static const bool value = types_have_common_values<Word64T, U>::value;
     298             : };
     299             : template <class U>
     300             : struct types_have_common_values<IntPtrT, U> {
     301             :   static const bool value = types_have_common_values<WordT, U>::value;
     302             : };
     303             : template <class U>
     304             : struct types_have_common_values<UintPtrT, U> {
     305             :   static const bool value = types_have_common_values<WordT, U>::value;
     306             : };
     307             : template <class T1, class T2, class U>
     308             : struct types_have_common_values<UnionT<T1, T2>, U> {
     309             :   static const bool value = types_have_common_values<T1, U>::value ||
     310             :                             types_have_common_values<T2, U>::value;
     311             : };
     312             : 
     313             : template <class T, class U1, class U2>
     314             : struct types_have_common_values<T, UnionT<U1, U2>> {
     315             :   static const bool value = types_have_common_values<T, U1>::value ||
     316             :                             types_have_common_values<T, U2>::value;
     317             : };
     318             : template <class T1, class T2, class U1, class U2>
     319             : struct types_have_common_values<UnionT<T1, T2>, UnionT<U1, U2>> {
     320             :   static const bool value = types_have_common_values<T1, U1>::value ||
     321             :                             types_have_common_values<T1, U2>::value ||
     322             :                             types_have_common_values<T2, U1>::value ||
     323             :                             types_have_common_values<T2, U2>::value;
     324             : };
     325             : 
     326             : // TNode<T> is an SSA value with the static type tag T, which is one of the
     327             : // following:
     328             : //   - a subclass of internal::Object represents a tagged type
     329             : //   - a subclass of internal::UntaggedT represents an untagged type
     330             : //   - ExternalReference
     331             : //   - PairT<T1, T2> for an operation returning two values, with types T1
     332             : //     and T2
     333             : //   - UnionT<T1, T2> represents either a value of type T1 or of type T2.
     334             : template <class T>
     335             : class TNode {
     336             :  public:
     337             :   static_assert(is_valid_type_tag<T>::value, "invalid type tag");
     338             : 
     339             :   template <class U,
     340             :             typename std::enable_if<is_subtype<U, T>::value, int>::type = 0>
     341     1847519 :   TNode(const TNode<U>& other) : node_(other) {}
     342        1988 :   TNode() : node_(nullptr) {}
     343             : 
     344             :   TNode operator=(TNode other) {
     345             :     DCHECK_NULL(node_);
     346        1988 :     node_ = other.node_;
     347             :     return *this;
     348             :   }
     349             : 
     350     6453494 :   operator compiler::Node*() const { return node_; }
     351             : 
     352             :   static TNode UncheckedCast(compiler::Node* node) { return TNode(node); }
     353             : 
     354             :  protected:
     355     2355166 :   explicit TNode(compiler::Node* node) : node_(node) {}
     356             : 
     357             :  private:
     358             :   compiler::Node* node_;
     359             : };
     360             : 
     361             : // SloppyTNode<T> is a variant of TNode<T> and allows implicit casts from
     362             : // Node*. It is intended for function arguments as long as some call sites
     363             : // still use untyped Node* arguments.
     364             : // TODO(tebbi): Delete this class once transition is finished.
     365             : template <class T>
     366             : class SloppyTNode : public TNode<T> {
     367             :  public:
     368             :   SloppyTNode(compiler::Node* node)  // NOLINT(runtime/explicit)
     369             :       : TNode<T>(node) {}
     370             :   template <class U, typename std::enable_if<is_subtype<U, T>::value,
     371             :                                              int>::type = 0>
     372             :   SloppyTNode(const TNode<U>& other)  // NOLINT(runtime/explicit)
     373      515719 :       : TNode<T>(other) {}
     374             : };
     375             : 
     376             : // This macro alias allows to use PairT<T1, T2> as a macro argument.
     377             : #define PAIR_TYPE(T1, T2) PairT<T1, T2>
     378             : 
     379             : #define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)          \
     380             :   V(Float32Equal, BoolT, Float32T, Float32T)              \
     381             :   V(Float32LessThan, BoolT, Float32T, Float32T)           \
     382             :   V(Float32LessThanOrEqual, BoolT, Float32T, Float32T)    \
     383             :   V(Float32GreaterThan, BoolT, Float32T, Float32T)        \
     384             :   V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
     385             :   V(Float64Equal, BoolT, Float64T, Float64T)              \
     386             :   V(Float64LessThan, BoolT, Float64T, Float64T)           \
     387             :   V(Float64LessThanOrEqual, BoolT, Float64T, Float64T)    \
     388             :   V(Float64GreaterThan, BoolT, Float64T, Float64T)        \
     389             :   V(Float64GreaterThanOrEqual, BoolT, Float64T, Float64T) \
     390             :   V(Int32GreaterThan, BoolT, Word32T, Word32T)            \
     391             :   V(Int32GreaterThanOrEqual, BoolT, Word32T, Word32T)     \
     392             :   V(Int32LessThan, BoolT, Word32T, Word32T)               \
     393             :   V(Int32LessThanOrEqual, BoolT, Word32T, Word32T)        \
     394             :   V(IntPtrLessThan, BoolT, WordT, WordT)                  \
     395             :   V(IntPtrLessThanOrEqual, BoolT, WordT, WordT)           \
     396             :   V(IntPtrGreaterThan, BoolT, WordT, WordT)               \
     397             :   V(IntPtrGreaterThanOrEqual, BoolT, WordT, WordT)        \
     398             :   V(IntPtrEqual, BoolT, WordT, WordT)                     \
     399             :   V(Uint32LessThan, BoolT, Word32T, Word32T)              \
     400             :   V(Uint32LessThanOrEqual, BoolT, Word32T, Word32T)       \
     401             :   V(Uint32GreaterThanOrEqual, BoolT, Word32T, Word32T)    \
     402             :   V(UintPtrLessThan, BoolT, WordT, WordT)                 \
     403             :   V(UintPtrLessThanOrEqual, BoolT, WordT, WordT)          \
     404             :   V(UintPtrGreaterThan, BoolT, WordT, WordT)              \
     405             :   V(UintPtrGreaterThanOrEqual, BoolT, WordT, WordT)       \
     406             :   V(WordEqual, BoolT, WordT, WordT)                       \
     407             :   V(WordNotEqual, BoolT, WordT, WordT)                    \
     408             :   V(Word32Equal, BoolT, Word32T, Word32T)                 \
     409             :   V(Word32NotEqual, BoolT, Word32T, Word32T)              \
     410             :   V(Word64Equal, BoolT, Word64T, Word64T)                 \
     411             :   V(Word64NotEqual, BoolT, Word64T, Word64T)
     412             : 
     413             : #define CODE_ASSEMBLER_BINARY_OP_LIST(V)                                \
     414             :   CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)                              \
     415             :   V(Float64Add, Float64T, Float64T, Float64T)                           \
     416             :   V(Float64Sub, Float64T, Float64T, Float64T)                           \
     417             :   V(Float64Mul, Float64T, Float64T, Float64T)                           \
     418             :   V(Float64Div, Float64T, Float64T, Float64T)                           \
     419             :   V(Float64Mod, Float64T, Float64T, Float64T)                           \
     420             :   V(Float64Atan2, Float64T, Float64T, Float64T)                         \
     421             :   V(Float64Pow, Float64T, Float64T, Float64T)                           \
     422             :   V(Float64Max, Float64T, Float64T, Float64T)                           \
     423             :   V(Float64Min, Float64T, Float64T, Float64T)                           \
     424             :   V(Float64InsertLowWord32, Float64T, Float64T, Word32T)                \
     425             :   V(Float64InsertHighWord32, Float64T, Float64T, Word32T)               \
     426             :   V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
     427             :   V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
     428             :   V(Int32Add, Word32T, Word32T, Word32T)                                \
     429             :   V(Int32AddWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
     430             :   V(Int32Sub, Word32T, Word32T, Word32T)                                \
     431             :   V(Int32Mul, Word32T, Word32T, Word32T)                                \
     432             :   V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
     433             :   V(Int32Div, Int32T, Int32T, Int32T)                                   \
     434             :   V(Int32Mod, Int32T, Int32T, Int32T)                                   \
     435             :   V(WordRor, WordT, WordT, IntegralT)                                   \
     436             :   V(Word32Ror, Word32T, Word32T, Word32T)                               \
     437             :   V(Word64Ror, Word64T, Word64T, Word64T)
     438             : 
     439             : TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
     440             : 
     441             : #define CODE_ASSEMBLER_UNARY_OP_LIST(V)                        \
     442             :   V(Float64Abs, Float64T, Float64T)                            \
     443             :   V(Float64Acos, Float64T, Float64T)                           \
     444             :   V(Float64Acosh, Float64T, Float64T)                          \
     445             :   V(Float64Asin, Float64T, Float64T)                           \
     446             :   V(Float64Asinh, Float64T, Float64T)                          \
     447             :   V(Float64Atan, Float64T, Float64T)                           \
     448             :   V(Float64Atanh, Float64T, Float64T)                          \
     449             :   V(Float64Cos, Float64T, Float64T)                            \
     450             :   V(Float64Cosh, Float64T, Float64T)                           \
     451             :   V(Float64Exp, Float64T, Float64T)                            \
     452             :   V(Float64Expm1, Float64T, Float64T)                          \
     453             :   V(Float64Log, Float64T, Float64T)                            \
     454             :   V(Float64Log1p, Float64T, Float64T)                          \
     455             :   V(Float64Log2, Float64T, Float64T)                           \
     456             :   V(Float64Log10, Float64T, Float64T)                          \
     457             :   V(Float64Cbrt, Float64T, Float64T)                           \
     458             :   V(Float64Neg, Float64T, Float64T)                            \
     459             :   V(Float64Sin, Float64T, Float64T)                            \
     460             :   V(Float64Sinh, Float64T, Float64T)                           \
     461             :   V(Float64Sqrt, Float64T, Float64T)                           \
     462             :   V(Float64Tan, Float64T, Float64T)                            \
     463             :   V(Float64Tanh, Float64T, Float64T)                           \
     464             :   V(Float64ExtractLowWord32, Word32T, Float64T)                \
     465             :   V(Float64ExtractHighWord32, Word32T, Float64T)               \
     466             :   V(BitcastTaggedToWord, IntPtrT, Object)                      \
     467             :   V(BitcastWordToTagged, Object, WordT)                        \
     468             :   V(BitcastWordToTaggedSigned, Smi, WordT)                     \
     469             :   V(TruncateFloat64ToFloat32, Float32T, Float64T)              \
     470             :   V(TruncateFloat64ToWord32, Word32T, Float64T)                \
     471             :   V(TruncateInt64ToInt32, Int32T, Int64T)                      \
     472             :   V(ChangeFloat32ToFloat64, Float64T, Float32T)                \
     473             :   V(ChangeFloat64ToUint32, Uint32T, Float64T)                  \
     474             :   V(ChangeFloat64ToUint64, Uint64T, Float64T)                  \
     475             :   V(ChangeInt32ToFloat64, Float64T, Int32T)                    \
     476             :   V(ChangeInt32ToInt64, Int64T, Int32T)                        \
     477             :   V(ChangeUint32ToFloat64, Float64T, Word32T)                  \
     478             :   V(ChangeUint32ToUint64, Uint64T, Word32T)                    \
     479             :   V(RoundFloat64ToInt32, Int32T, Float64T)                     \
     480             :   V(RoundInt32ToFloat32, Int32T, Float32T)                     \
     481             :   V(Float64SilenceNaN, Float64T, Float64T)                     \
     482             :   V(Float64RoundDown, Float64T, Float64T)                      \
     483             :   V(Float64RoundUp, Float64T, Float64T)                        \
     484             :   V(Float64RoundTiesEven, Float64T, Float64T)                  \
     485             :   V(Float64RoundTruncate, Float64T, Float64T)                  \
     486             :   V(Word32Clz, Int32T, Word32T)                                \
     487             :   V(Word32Not, Word32T, Word32T)                               \
     488             :   V(Int32AbsWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T)    \
     489             :   V(Int64AbsWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T)    \
     490             :   V(IntPtrAbsWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT) \
     491             :   V(Word32BinaryNot, Word32T, Word32T)
     492             : 
     493             : // A "public" interface used by components outside of compiler directory to
     494             : // create code objects with TurboFan's backend. This class is mostly a thin
     495             : // shim around the RawMachineAssembler, and its primary job is to ensure that
     496             : // the innards of the RawMachineAssembler and other compiler implementation
     497             : // details don't leak outside of the the compiler directory..
     498             : //
     499             : // V8 components that need to generate low-level code using this interface
     500             : // should include this header--and this header only--from the compiler
     501             : // directory (this is actually enforced). Since all interesting data
     502             : // structures are forward declared, it's not possible for clients to peek
     503             : // inside the compiler internals.
     504             : //
     505             : // In addition to providing isolation between TurboFan and code generation
     506             : // clients, CodeAssembler also provides an abstraction for creating variables
     507             : // and enhanced Label functionality to merge variable values along paths where
     508             : // they have differing values, including loops.
     509             : //
     510             : // The CodeAssembler itself is stateless (and instances are expected to be
     511             : // temporary-scoped and short-lived); all its state is encapsulated into
     512             : // a CodeAssemblerState instance.
     513             : class V8_EXPORT_PRIVATE CodeAssembler {
     514             :  public:
     515       58506 :   explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
     516             :   ~CodeAssembler();
     517             : 
     518             :   static Handle<Code> GenerateCode(CodeAssemblerState* state);
     519             : 
     520             :   bool Is64() const;
     521             :   bool IsFloat64RoundUpSupported() const;
     522             :   bool IsFloat64RoundDownSupported() const;
     523             :   bool IsFloat64RoundTiesEvenSupported() const;
     524             :   bool IsFloat64RoundTruncateSupported() const;
     525             :   bool IsInt32AbsWithOverflowSupported() const;
     526             :   bool IsInt64AbsWithOverflowSupported() const;
     527             :   bool IsIntPtrAbsWithOverflowSupported() const;
     528             : 
     529             :   // Shortened aliases for use in CodeAssembler subclasses.
     530             :   using Label = CodeAssemblerLabel;
     531             :   using Variable = CodeAssemblerVariable;
     532             :   template <class T>
     533             :   using TVariable = TypedCodeAssemblerVariable<T>;
     534             :   using VariableList = CodeAssemblerVariableList;
     535             : 
     536             :   // ===========================================================================
     537             :   // Base Assembler
     538             :   // ===========================================================================
     539             : 
     540             :   template <class PreviousType>
     541             :   class CheckedNode {
     542             :    public:
     543             : #ifdef DEBUG
     544             :     CheckedNode(Node* node, CodeAssembler* code_assembler, const char* location)
     545             :         : node_(node), code_assembler_(code_assembler), location_(location) {}
     546             : #else
     547             :     CheckedNode(compiler::Node* node, CodeAssembler*, const char*)
     548             :         : node_(node) {}
     549             : #endif
     550             : 
     551             :     template <class A>
     552             :     operator TNode<A>() {
     553             :       static_assert(types_have_common_values<A, PreviousType>::value,
     554             :                     "Incompatible types: this cast can never succeed.");
     555             :       static_assert(std::is_convertible<TNode<A>, TNode<Object>>::value,
     556             :                     "Coercion to untagged values cannot be "
     557             :                     "checked.");
     558             : #ifdef DEBUG
     559             :       if (FLAG_debug_code) {
     560             :         Node* function = code_assembler_->ExternalConstant(
     561             :             ExternalReference::check_object_type(code_assembler_->isolate()));
     562             :         code_assembler_->CallCFunction3(
     563             :             MachineType::AnyTagged(), MachineType::AnyTagged(),
     564             :             MachineType::TaggedSigned(), MachineType::AnyTagged(), function,
     565             :             node_,
     566             :             code_assembler_->SmiConstant(
     567             :                 static_cast<int>(ObjectTypeOf<A>::value)),
     568             :             code_assembler_->StringConstant(location_));
     569             :       }
     570             : #endif
     571             :       return TNode<A>::UncheckedCast(node_);
     572             :     }
     573             : 
     574             :     template <class A>
     575             :     operator SloppyTNode<A>() {
     576             :       return base::implicit_cast<TNode<A>>(*this);
     577             :     }
     578             : 
     579             :     Node* node() const { return node_; }
     580             : 
     581             :    private:
     582             :     Node* node_;
     583             : #ifdef DEBUG
     584             :     CodeAssembler* code_assembler_;
     585             :     const char* location_;
     586             : #endif
     587             :   };
     588             : 
     589             :   template <class T>
     590             :   TNode<T> UncheckedCast(Node* value) {
     591             :     return TNode<T>::UncheckedCast(value);
     592             :   }
     593             :   template <class T, class U>
     594             :   TNode<T> UncheckedCast(TNode<U> value) {
     595             :     static_assert(types_have_common_values<T, U>::value,
     596             :                   "Incompatible types: this cast can never succeed.");
     597             :     return TNode<T>::UncheckedCast(value);
     598             :   }
     599             : 
     600             :   // ReinterpretCast<T>(v) has the power to cast even when the type of v is
     601             :   // unrelated to T. Use with care.
     602             :   template <class T>
     603             :   TNode<T> ReinterpretCast(Node* value) {
     604             :     return TNode<T>::UncheckedCast(value);
     605             :   }
     606             : 
     607             :   CheckedNode<Object> Cast(Node* value, const char* location) {
     608             :     return CheckedNode<Object>(value, this, location);
     609             :   }
     610             : 
     611             :   template <class T>
     612             :   CheckedNode<T> Cast(TNode<T> value, const char* location) {
     613             :     return CheckedNode<T>(value, this, location);
     614             :   }
     615             : 
     616             : #ifdef DEBUG
     617             : #define STRINGIFY(x) #x
     618             : #define TO_STRING_LITERAL(x) STRINGIFY(x)
     619             : #define CAST(x) \
     620             :   Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
     621             : #else
     622             : #define CAST(x) Cast(x, "")
     623             : #endif
     624             : 
     625             :   // Constants.
     626             :   TNode<Int32T> Int32Constant(int32_t value);
     627             :   TNode<Int64T> Int64Constant(int64_t value);
     628             :   TNode<IntPtrT> IntPtrConstant(intptr_t value);
     629             :   TNode<Number> NumberConstant(double value);
     630             :   TNode<Smi> SmiConstant(Smi* value);
     631             :   TNode<Smi> SmiConstant(int value);
     632             :   TNode<HeapObject> UntypedHeapConstant(Handle<HeapObject> object);
     633             :   template <class Type>
     634             :   TNode<Type> HeapConstant(Handle<Type> object) {
     635       59283 :     return UncheckedCast<Type>(UntypedHeapConstant(object));
     636             :   }
     637             :   TNode<String> StringConstant(const char* str);
     638             :   TNode<Oddball> BooleanConstant(bool value);
     639             :   TNode<ExternalReference> ExternalConstant(ExternalReference address);
     640             :   TNode<Float64T> Float64Constant(double value);
     641             :   TNode<HeapNumber> NaNConstant();
     642             : 
     643             :   bool ToInt32Constant(Node* node, int32_t& out_value);
     644             :   bool ToInt64Constant(Node* node, int64_t& out_value);
     645             :   bool ToSmiConstant(Node* node, Smi*& out_value);
     646             :   bool ToIntPtrConstant(Node* node, intptr_t& out_value);
     647             : 
     648             :   TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
     649             :   TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
     650             :   TNode<Uint32T> Unsigned(TNode<Word32T> x) {
     651             :     return UncheckedCast<Uint32T>(x);
     652             :   }
     653             :   TNode<UintPtrT> Unsigned(TNode<WordT> x) {
     654             :     return UncheckedCast<UintPtrT>(x);
     655             :   }
     656             : 
     657             :   Node* Parameter(int value);
     658             : 
     659             :   TNode<Context> GetJSContextParameter();
     660             :   void Return(SloppyTNode<Object> value);
     661             :   void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2);
     662             :   void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2,
     663             :               SloppyTNode<Object> value3);
     664             :   void PopAndReturn(Node* pop, Node* value);
     665             : 
     666             :   void ReturnIf(Node* condition, Node* value);
     667             : 
     668             :   void DebugAbort(Node* message);
     669             :   void DebugBreak();
     670             :   void Unreachable();
     671             :   void Comment(const char* format, ...);
     672             : 
     673             :   void Bind(Label* label);
     674             : #if DEBUG
     675             :   void Bind(Label* label, AssemblerDebugInfo debug_info);
     676             : #endif  // DEBUG
     677             :   void Goto(Label* label);
     678             :   void GotoIf(SloppyTNode<IntegralT> condition, Label* true_label);
     679             :   void GotoIfNot(SloppyTNode<IntegralT> condition, Label* false_label);
     680             :   void Branch(SloppyTNode<IntegralT> condition, Label* true_label,
     681             :               Label* false_label);
     682             : 
     683             :   void Switch(Node* index, Label* default_label, const int32_t* case_values,
     684             :               Label** case_labels, size_t case_count);
     685             : 
     686             :   // Access to the frame pointer
     687             :   Node* LoadFramePointer();
     688             :   Node* LoadParentFramePointer();
     689             : 
     690             :   // Access to the stack pointer
     691             :   Node* LoadStackPointer();
     692             : 
     693             :   // Load raw memory location.
     694             :   Node* Load(MachineType rep, Node* base);
     695             :   template <class Type>
     696             :   TNode<Type> Load(MachineType rep, TNode<RawPtr<Type>> base) {
     697             :     DCHECK(
     698             :         IsSubtype(rep.representation(), MachineRepresentationOf<Type>::value));
     699        2573 :     return UncheckedCast<Type>(Load(rep, static_cast<Node*>(base)));
     700             :   }
     701             :   Node* Load(MachineType rep, Node* base, Node* offset);
     702             :   Node* AtomicLoad(MachineType rep, Node* base, Node* offset);
     703             : 
     704             :   // Load a value from the root array.
     705             :   TNode<Object> LoadRoot(Heap::RootListIndex root_index);
     706             : 
     707             :   // Store value to raw memory location.
     708             :   Node* Store(Node* base, Node* value);
     709             :   Node* Store(Node* base, Node* offset, Node* value);
     710             :   Node* StoreWithMapWriteBarrier(Node* base, Node* offset, Node* value);
     711             :   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
     712             :   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
     713             :                             Node* value);
     714             :   Node* AtomicStore(MachineRepresentation rep, Node* base, Node* offset,
     715             :                     Node* value);
     716             : 
     717             :   // Exchange value at raw memory location
     718             :   Node* AtomicExchange(MachineType type, Node* base, Node* offset, Node* value);
     719             : 
     720             :   // Compare and Exchange value at raw memory location
     721             :   Node* AtomicCompareExchange(MachineType type, Node* base, Node* offset,
     722             :                               Node* old_value, Node* new_value);
     723             : 
     724             :   Node* AtomicAdd(MachineType type, Node* base, Node* offset, Node* value);
     725             : 
     726             :   Node* AtomicSub(MachineType type, Node* base, Node* offset, Node* value);
     727             : 
     728             :   Node* AtomicAnd(MachineType type, Node* base, Node* offset, Node* value);
     729             : 
     730             :   Node* AtomicOr(MachineType type, Node* base, Node* offset, Node* value);
     731             : 
     732             :   Node* AtomicXor(MachineType type, Node* base, Node* offset, Node* value);
     733             : 
     734             :   // Store a value to the root array.
     735             :   Node* StoreRoot(Heap::RootListIndex root_index, Node* value);
     736             : 
     737             : // Basic arithmetic operations.
     738             : #define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
     739             :   TNode<ResType> name(SloppyTNode<Arg1Type> a, SloppyTNode<Arg2Type> b);
     740             :   CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
     741             : #undef DECLARE_CODE_ASSEMBLER_BINARY_OP
     742             : 
     743             :   TNode<IntPtrT> WordShr(TNode<IntPtrT> left, TNode<IntegralT> right) {
     744             :     return UncheckedCast<IntPtrT>(
     745         471 :         WordShr(static_cast<Node*>(left), static_cast<Node*>(right)));
     746             :   }
     747             : 
     748             :   TNode<IntPtrT> WordAnd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
     749             :     return UncheckedCast<IntPtrT>(
     750       76939 :         WordAnd(static_cast<Node*>(left), static_cast<Node*>(right)));
     751             :   }
     752             : 
     753             :   template <class Left, class Right,
     754             :             class = typename std::enable_if<
     755             :                 std::is_base_of<Object, Left>::value &&
     756             :                 std::is_base_of<Object, Right>::value>::type>
     757             :   TNode<BoolT> WordEqual(TNode<Left> left, TNode<Right> right) {
     758             :     return WordEqual(ReinterpretCast<WordT>(left),
     759       72658 :                      ReinterpretCast<WordT>(right));
     760             :   }
     761             :   TNode<BoolT> WordEqual(TNode<Object> left, Node* right) {
     762             :     return WordEqual(ReinterpretCast<WordT>(left),
     763        1643 :                      ReinterpretCast<WordT>(right));
     764             :   }
     765             :   TNode<BoolT> WordEqual(Node* left, TNode<Object> right) {
     766             :     return WordEqual(ReinterpretCast<WordT>(left),
     767       21662 :                      ReinterpretCast<WordT>(right));
     768             :   }
     769             :   template <class Left, class Right,
     770             :             class = typename std::enable_if<
     771             :                 std::is_base_of<Object, Left>::value &&
     772             :                 std::is_base_of<Object, Right>::value>::type>
     773             :   TNode<BoolT> WordNotEqual(TNode<Left> left, TNode<Right> right) {
     774             :     return WordNotEqual(ReinterpretCast<WordT>(left),
     775        1469 :                         ReinterpretCast<WordT>(right));
     776             :   }
     777             :   TNode<BoolT> WordNotEqual(TNode<Object> left, Node* right) {
     778             :     return WordNotEqual(ReinterpretCast<WordT>(left),
     779             :                         ReinterpretCast<WordT>(right));
     780             :   }
     781             :   TNode<BoolT> WordNotEqual(Node* left, TNode<Object> right) {
     782             :     return WordNotEqual(ReinterpretCast<WordT>(left),
     783        2449 :                         ReinterpretCast<WordT>(right));
     784             :   }
     785             : 
     786             :   TNode<Int32T> Int32Add(TNode<Int32T> left, TNode<Int32T> right) {
     787             :     return Signed(
     788           6 :         Int32Add(static_cast<Node*>(left), static_cast<Node*>(right)));
     789             :   }
     790             : 
     791             :   TNode<WordT> IntPtrAdd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
     792             :   TNode<WordT> IntPtrSub(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
     793             :   TNode<WordT> IntPtrMul(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
     794             :   TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
     795             :     return Signed(
     796        9486 :         IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
     797             :   }
     798             :   TNode<IntPtrT> IntPtrSub(TNode<IntPtrT> left, TNode<IntPtrT> right) {
     799             :     return Signed(
     800        7101 :         IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
     801             :   }
     802             :   TNode<IntPtrT> IntPtrMul(TNode<IntPtrT> left, TNode<IntPtrT> right) {
     803             :     return Signed(
     804             :         IntPtrMul(static_cast<Node*>(left), static_cast<Node*>(right)));
     805             :   }
     806             : 
     807             :   TNode<WordT> WordShl(SloppyTNode<WordT> value, int shift);
     808             :   TNode<WordT> WordShr(SloppyTNode<WordT> value, int shift);
     809             :   TNode<IntPtrT> WordShr(TNode<IntPtrT> value, int shift) {
     810        1184 :     return UncheckedCast<IntPtrT>(WordShr(static_cast<Node*>(value), shift));
     811             :   }
     812             :   TNode<Word32T> Word32Shr(SloppyTNode<Word32T> value, int shift);
     813             : 
     814             :   TNode<WordT> WordOr(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
     815             :   TNode<WordT> WordAnd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
     816             :   TNode<WordT> WordXor(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
     817             :   TNode<WordT> WordShl(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
     818             :   TNode<WordT> WordShr(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
     819             :   TNode<WordT> WordSar(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
     820             :   TNode<Word32T> Word32Or(SloppyTNode<Word32T> left,
     821             :                           SloppyTNode<Word32T> right);
     822             :   TNode<Word32T> Word32And(SloppyTNode<Word32T> left,
     823             :                            SloppyTNode<Word32T> right);
     824             :   TNode<Word32T> Word32Xor(SloppyTNode<Word32T> left,
     825             :                            SloppyTNode<Word32T> right);
     826             :   TNode<Word32T> Word32Shl(SloppyTNode<Word32T> left,
     827             :                            SloppyTNode<Word32T> right);
     828             :   TNode<Word32T> Word32Shr(SloppyTNode<Word32T> left,
     829             :                            SloppyTNode<Word32T> right);
     830             :   TNode<Word32T> Word32Sar(SloppyTNode<Word32T> left,
     831             :                            SloppyTNode<Word32T> right);
     832             :   TNode<Word64T> Word64Or(SloppyTNode<Word64T> left,
     833             :                           SloppyTNode<Word64T> right);
     834             :   TNode<Word64T> Word64And(SloppyTNode<Word64T> left,
     835             :                            SloppyTNode<Word64T> right);
     836             :   TNode<Word64T> Word64Xor(SloppyTNode<Word64T> left,
     837             :                            SloppyTNode<Word64T> right);
     838             :   TNode<Word64T> Word64Shl(SloppyTNode<Word64T> left,
     839             :                            SloppyTNode<Word64T> right);
     840             :   TNode<Word64T> Word64Shr(SloppyTNode<Word64T> left,
     841             :                            SloppyTNode<Word64T> right);
     842             :   TNode<Word64T> Word64Sar(SloppyTNode<Word64T> left,
     843             :                            SloppyTNode<Word64T> right);
     844             : 
     845             : // Unary
     846             : #define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
     847             :   TNode<ResType> name(SloppyTNode<ArgType> a);
     848             :   CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
     849             : #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
     850             : 
     851             :   // Changes a double to an inptr_t for pointer arithmetic outside of Smi range.
     852             :   // Assumes that the double can be exactly represented as an int.
     853             :   TNode<UintPtrT> ChangeFloat64ToUintPtr(SloppyTNode<Float64T> value);
     854             : 
     855             :   // Changes an intptr_t to a double, e.g. for storing an element index
     856             :   // outside Smi range in a HeapNumber. Lossless on 32-bit,
     857             :   // rounds on 64-bit (which doesn't affect valid element indices).
     858             :   Node* RoundIntPtrToFloat64(Node* value);
     859             :   // No-op on 32-bit, otherwise zero extend.
     860             :   TNode<UintPtrT> ChangeUint32ToWord(SloppyTNode<Word32T> value);
     861             :   // No-op on 32-bit, otherwise sign extend.
     862             :   TNode<IntPtrT> ChangeInt32ToIntPtr(SloppyTNode<Word32T> value);
     863             : 
     864             :   // No-op that guarantees that the value is kept alive till this point even
     865             :   // if GC happens.
     866             :   Node* Retain(Node* value);
     867             : 
     868             :   // Projections
     869             :   Node* Projection(int index, Node* value);
     870             : 
     871             :   template <int index, class T1, class T2>
     872             :   TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
     873             :   Projection(TNode<PairT<T1, T2>> value) {
     874             :     return UncheckedCast<
     875             :         typename std::tuple_element<index, std::tuple<T1, T2>>::type>(
     876           0 :         Projection(index, value));
     877             :   }
     878             : 
     879             :   // Calls
     880             :   template <class... TArgs>
     881             :   TNode<Object> CallRuntimeImpl(Runtime::FunctionId function,
     882             :                                 SloppyTNode<Object> context, TArgs... args);
     883             :   template <class... TArgs>
     884          93 :   TNode<Object> CallRuntime(Runtime::FunctionId function,
     885             :                             SloppyTNode<Object> context, TArgs... args) {
     886             :     return CallRuntimeImpl(function, context,
     887       76193 :                            base::implicit_cast<SloppyTNode<Object>>(args)...);
     888             :   }
     889             : 
     890             :   template <class... TArgs>
     891             :   TNode<Object> TailCallRuntimeImpl(Runtime::FunctionId function,
     892             :                                     SloppyTNode<Object> context, TArgs... args);
     893             :   template <class... TArgs>
     894         880 :   TNode<Object> TailCallRuntime(Runtime::FunctionId function,
     895             :                                 SloppyTNode<Object> context, TArgs... args) {
     896             :     return TailCallRuntimeImpl(
     897        9408 :         function, context, base::implicit_cast<SloppyTNode<Object>>(args)...);
     898             :   }
     899             : 
     900             :   template <class... TArgs>
     901       43162 :   Node* CallStub(Callable const& callable, Node* context, TArgs... args) {
     902             :     Node* target = HeapConstant(callable.code());
     903             :     return CallStub(callable.descriptor(), target, context,
     904       43162 :                     base::implicit_cast<Node*>(args)...);
     905             :   }
     906             : 
     907             :   template <class... TArgs>
     908             :   Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
     909             :                  Node* context, TArgs... args) {
     910             :     return CallStubR(descriptor, 1, target, context,
     911       44743 :                      base::implicit_cast<Node*>(args)...);
     912             :   }
     913             : 
     914             :   template <class... TArgs>
     915             :   Node* CallStubR(const CallInterfaceDescriptor& descriptor, size_t result_size,
     916             :                   Node* target, Node* context, TArgs... args);
     917             : 
     918             :   Node* CallStubN(const CallInterfaceDescriptor& descriptor, size_t result_size,
     919             :                   int input_count, Node* const* inputs);
     920             : 
     921             :   template <class... TArgs>
     922        2449 :   Node* TailCallStub(Callable const& callable, Node* context, TArgs... args) {
     923             :     Node* target = HeapConstant(callable.code());
     924        2449 :     return TailCallStub(callable.descriptor(), target, context, args...);
     925             :   }
     926             : 
     927             :   template <class... TArgs>
     928             :   Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
     929             :                      Node* context, TArgs... args) {
     930             :     return TailCallStubImpl(descriptor, target, context,
     931        2883 :                             base::implicit_cast<Node*>(args)...);
     932             :   }
     933             :   template <class... TArgs>
     934             :   Node* TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
     935             :                          Node* target, Node* context, TArgs... args);
     936             : 
     937             :   template <class... TArgs>
     938             :   Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
     939             :                                  Node* target, TArgs... args);
     940             : 
     941             :   template <class... TArgs>
     942             :   Node* TailCallStubThenBytecodeDispatch(
     943             :       const CallInterfaceDescriptor& descriptor, Node* context, Node* target,
     944             :       TArgs... args);
     945             : 
     946             :   template <class... TArgs>
     947        9541 :   Node* CallJS(Callable const& callable, Node* context, Node* function,
     948             :                Node* receiver, TArgs... args) {
     949             :     int argc = static_cast<int>(sizeof...(args));
     950       19082 :     Node* arity = Int32Constant(argc);
     951        9541 :     return CallStub(callable, context, function, arity, receiver, args...);
     952             :   }
     953             : 
     954             :   template <class... TArgs>
     955         322 :   Node* ConstructJS(Callable const& callable, Node* context, Node* new_target,
     956             :                     TArgs... args) {
     957             :     int argc = static_cast<int>(sizeof...(args));
     958         644 :     Node* arity = Int32Constant(argc);
     959         644 :     Node* receiver = LoadRoot(Heap::kUndefinedValueRootIndex);
     960             : 
     961             :     // Construct(target, new_target, arity, receiver, arguments...)
     962             :     return CallStub(callable, context, new_target, new_target, arity, receiver,
     963         322 :                     args...);
     964             :   }
     965             : 
     966             :   Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
     967             :                        Node* const* inputs);
     968             : 
     969             :   // Call to a C function with one argument.
     970             :   Node* CallCFunction1(MachineType return_type, MachineType arg0_type,
     971             :                        Node* function, Node* arg0);
     972             : 
     973             :   // Call to a C function with one argument, while saving/restoring caller
     974             :   // registers except the register used for return value.
     975             :   Node* CallCFunction1WithCallerSavedRegisters(MachineType return_type,
     976             :                                                MachineType arg0_type,
     977             :                                                Node* function, Node* arg0,
     978             :                                                SaveFPRegsMode mode);
     979             : 
     980             :   // Call to a C function with two arguments.
     981             :   Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
     982             :                        MachineType arg1_type, Node* function, Node* arg0,
     983             :                        Node* arg1);
     984             : 
     985             :   // Call to a C function with three arguments.
     986             :   Node* CallCFunction3(MachineType return_type, MachineType arg0_type,
     987             :                        MachineType arg1_type, MachineType arg2_type,
     988             :                        Node* function, Node* arg0, Node* arg1, Node* arg2);
     989             : 
     990             :   // Call to a C function with three arguments, while saving/restoring caller
     991             :   // registers except the register used for return value.
     992             :   Node* CallCFunction3WithCallerSavedRegisters(
     993             :       MachineType return_type, MachineType arg0_type, MachineType arg1_type,
     994             :       MachineType arg2_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
     995             :       SaveFPRegsMode mode);
     996             : 
     997             :   // Call to a C function with six arguments.
     998             :   Node* CallCFunction6(MachineType return_type, MachineType arg0_type,
     999             :                        MachineType arg1_type, MachineType arg2_type,
    1000             :                        MachineType arg3_type, MachineType arg4_type,
    1001             :                        MachineType arg5_type, Node* function, Node* arg0,
    1002             :                        Node* arg1, Node* arg2, Node* arg3, Node* arg4,
    1003             :                        Node* arg5);
    1004             : 
    1005             :   // Call to a C function with nine arguments.
    1006             :   Node* CallCFunction9(MachineType return_type, MachineType arg0_type,
    1007             :                        MachineType arg1_type, MachineType arg2_type,
    1008             :                        MachineType arg3_type, MachineType arg4_type,
    1009             :                        MachineType arg5_type, MachineType arg6_type,
    1010             :                        MachineType arg7_type, MachineType arg8_type,
    1011             :                        Node* function, Node* arg0, Node* arg1, Node* arg2,
    1012             :                        Node* arg3, Node* arg4, Node* arg5, Node* arg6,
    1013             :                        Node* arg7, Node* arg8);
    1014             : 
    1015             :   // Exception handling support.
    1016             :   void GotoIfException(Node* node, Label* if_exception,
    1017             :                        Variable* exception_var = nullptr);
    1018             : 
    1019             :   // Helpers which delegate to RawMachineAssembler.
    1020             :   Factory* factory() const;
    1021             :   Isolate* isolate() const;
    1022             :   Zone* zone() const;
    1023             : 
    1024     1434632 :   CodeAssemblerState* state() { return state_; }
    1025             : 
    1026             :   void BreakOnNode(int node_id);
    1027             : 
    1028             :   bool UnalignedLoadSupported(MachineRepresentation rep) const;
    1029             :   bool UnalignedStoreSupported(MachineRepresentation rep) const;
    1030             : 
    1031             :  protected:
    1032             :   void RegisterCallGenerationCallbacks(
    1033             :       const CodeAssemblerCallback& call_prologue,
    1034             :       const CodeAssemblerCallback& call_epilogue);
    1035             :   void UnregisterCallGenerationCallbacks();
    1036             : 
    1037             :  private:
    1038             :   RawMachineAssembler* raw_assembler() const;
    1039             : 
    1040             :   // Calls respective callback registered in the state.
    1041             :   void CallPrologue();
    1042             :   void CallEpilogue();
    1043             : 
    1044             :   CodeAssemblerState* state_;
    1045             : 
    1046             :   DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
    1047             : };
    1048             : 
    1049             : class CodeAssemblerVariable {
    1050             :  public:
    1051             :   explicit CodeAssemblerVariable(CodeAssembler* assembler,
    1052             :                                  MachineRepresentation rep);
    1053             :   CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
    1054             :                         Node* initial_value);
    1055             : #if DEBUG
    1056             :   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
    1057             :                         MachineRepresentation rep);
    1058             :   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
    1059             :                         MachineRepresentation rep, Node* initial_value);
    1060             : #endif  // DEBUG
    1061             : 
    1062             :   ~CodeAssemblerVariable();
    1063             :   void Bind(Node* value);
    1064             :   Node* value() const;
    1065             :   MachineRepresentation rep() const;
    1066             :   bool IsBound() const;
    1067             : 
    1068             :  private:
    1069             :   class Impl;
    1070             :   friend class CodeAssemblerLabel;
    1071             :   friend class CodeAssemblerState;
    1072             :   friend std::ostream& operator<<(std::ostream&, const Impl&);
    1073             :   friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
    1074             :   Impl* impl_;
    1075             :   CodeAssemblerState* state_;
    1076             :   DISALLOW_COPY_AND_ASSIGN(CodeAssemblerVariable);
    1077             : };
    1078             : 
    1079             : std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
    1080             : std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
    1081             : 
    1082             : template <class T>
    1083        7155 : class TypedCodeAssemblerVariable : public CodeAssemblerVariable {
    1084             :  public:
    1085             :   TypedCodeAssemblerVariable(TNode<T> initial_value, CodeAssembler* assembler)
    1086             :       : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value,
    1087        1178 :                               initial_value) {}
    1088             :   explicit TypedCodeAssemblerVariable(CodeAssembler* assembler)
    1089        5977 :       : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value) {}
    1090             : #if DEBUG
    1091             :   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
    1092             :                              CodeAssembler* assembler)
    1093             :       : CodeAssemblerVariable(assembler, debug_info,
    1094             :                               MachineRepresentationOf<T>::value) {}
    1095             :   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
    1096             :                              TNode<T> initial_value, CodeAssembler* assembler)
    1097             :       : CodeAssemblerVariable(assembler, debug_info,
    1098             :                               MachineRepresentationOf<T>::value,
    1099             :                               initial_value) {}
    1100             : #endif  // DEBUG
    1101             : 
    1102             :   template <class U, class = typename std::enable_if<
    1103             :                          std::is_convertible<TNode<T>, TNode<U>>::value>::type>
    1104             :   operator TNode<U>() const {
    1105        7356 :     return TNode<T>::UncheckedCast(value());
    1106             :   }
    1107             :   template <class U, class = typename std::enable_if<
    1108             :                          std::is_convertible<TNode<T>, TNode<U>>::value>::type>
    1109             :   operator SloppyTNode<U>() const {
    1110         372 :     return value();
    1111             :   }
    1112        1395 :   operator Node*() const { return value(); }
    1113             : 
    1114       16176 :   void operator=(TNode<T> value) { Bind(value); }
    1115             : 
    1116             :  private:
    1117             :   using CodeAssemblerVariable::Bind;
    1118             :   using CodeAssemblerVariable::value;
    1119             : };
    1120             : 
    1121        8928 : class CodeAssemblerLabel {
    1122             :  public:
    1123             :   enum Type { kDeferred, kNonDeferred };
    1124             : 
    1125             :   explicit CodeAssemblerLabel(
    1126             :       CodeAssembler* assembler,
    1127             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1128      654174 :       : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
    1129             :   CodeAssemblerLabel(
    1130             :       CodeAssembler* assembler,
    1131       21066 :       const CodeAssemblerVariableList& merged_variables,
    1132             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1133             :       : CodeAssemblerLabel(assembler, merged_variables.length(),
    1134       21066 :                            &(merged_variables[0]), type) {}
    1135             :   CodeAssemblerLabel(
    1136             :       CodeAssembler* assembler, size_t count,
    1137             :       CodeAssemblerVariable* const* vars,
    1138             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
    1139             :   CodeAssemblerLabel(
    1140             :       CodeAssembler* assembler,
    1141             :       std::initializer_list<CodeAssemblerVariable*> vars,
    1142             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1143        5626 :       : CodeAssemblerLabel(assembler, vars.size(), vars.begin(), type) {}
    1144             :   CodeAssemblerLabel(
    1145             :       CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
    1146             :       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
    1147       65717 :       : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
    1148             :   ~CodeAssemblerLabel();
    1149             : 
    1150             :   inline bool is_bound() const { return bound_; }
    1151             : 
    1152             :  private:
    1153             :   friend class CodeAssembler;
    1154             : 
    1155             :   void Bind();
    1156             : #if DEBUG
    1157             :   void Bind(AssemblerDebugInfo debug_info);
    1158             : #endif  // DEBUG
    1159             :   void UpdateVariablesAfterBind();
    1160             :   void MergeVariables();
    1161             : 
    1162             :   bool bound_;
    1163             :   size_t merge_count_;
    1164             :   CodeAssemblerState* state_;
    1165             :   RawMachineLabel* label_;
    1166             :   // Map of variables that need to be merged to their phi nodes (or placeholders
    1167             :   // for those phis).
    1168             :   std::map<CodeAssemblerVariable::Impl*, Node*> variable_phis_;
    1169             :   // Map of variables to the list of value nodes that have been added from each
    1170             :   // merge path in their order of merging.
    1171             :   std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>> variable_merges_;
    1172             : };
    1173             : 
    1174             : class V8_EXPORT_PRIVATE CodeAssemblerState {
    1175             :  public:
    1176             :   // Create with CallStub linkage.
    1177             :   // |result_size| specifies the number of results returned by the stub.
    1178             :   // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
    1179             :   CodeAssemblerState(Isolate* isolate, Zone* zone,
    1180             :                      const CallInterfaceDescriptor& descriptor, Code::Kind kind,
    1181             :                      const char* name, size_t result_size = 1);
    1182             : 
    1183             :   // Create with JSCall linkage.
    1184             :   CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
    1185             :                      Code::Kind kind, const char* name);
    1186             : 
    1187             :   ~CodeAssemblerState();
    1188             : 
    1189             :   const char* name() const { return name_; }
    1190             :   int parameter_count() const;
    1191             : 
    1192             : #if DEBUG
    1193             :   void PrintCurrentBlock(std::ostream& os);
    1194             : #endif  // DEBUG
    1195             :   void SetInitialDebugInformation(const char* msg, const char* file, int line);
    1196             : 
    1197             :  private:
    1198             :   friend class CodeAssembler;
    1199             :   friend class CodeAssemblerLabel;
    1200             :   friend class CodeAssemblerVariable;
    1201             :   friend class CodeAssemblerTester;
    1202             : 
    1203             :   CodeAssemblerState(Isolate* isolate, Zone* zone,
    1204             :                      CallDescriptor* call_descriptor, Code::Kind kind,
    1205             :                      const char* name);
    1206             : 
    1207             :   std::unique_ptr<RawMachineAssembler> raw_assembler_;
    1208             :   Code::Kind kind_;
    1209             :   const char* name_;
    1210             :   bool code_generated_;
    1211             :   ZoneSet<CodeAssemblerVariable::Impl*> variables_;
    1212             :   CodeAssemblerCallback call_prologue_;
    1213             :   CodeAssemblerCallback call_epilogue_;
    1214             : 
    1215             :   DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState);
    1216             : };
    1217             : 
    1218             : }  // namespace compiler
    1219             : }  // namespace internal
    1220             : }  // namespace v8
    1221             : 
    1222             : #endif  // V8_COMPILER_CODE_ASSEMBLER_H_

Generated by: LCOV version 1.10