LCOV - code coverage report
Current view: top level - src - utils.h (source / functions) Hit Total Coverage
Test: app.info Lines: 125 129 96.9 %
Date: 2019-02-19 Functions: 58 61 95.1 %

          Line data    Source code
       1             : // Copyright 2012 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_UTILS_H_
       6             : #define V8_UTILS_H_
       7             : 
       8             : #include <limits.h>
       9             : #include <stdlib.h>
      10             : #include <string.h>
      11             : #include <cmath>
      12             : #include <string>
      13             : #include <type_traits>
      14             : 
      15             : #include "include/v8.h"
      16             : #include "src/allocation.h"
      17             : #include "src/base/bits.h"
      18             : #include "src/base/compiler-specific.h"
      19             : #include "src/base/logging.h"
      20             : #include "src/base/macros.h"
      21             : #include "src/base/platform/platform.h"
      22             : #include "src/base/v8-fallthrough.h"
      23             : #include "src/globals.h"
      24             : #include "src/third_party/siphash/halfsiphash.h"
      25             : #include "src/vector.h"
      26             : 
      27             : #if defined(V8_OS_AIX)
      28             : #include <fenv.h>  // NOLINT(build/c++11)
      29             : #endif
      30             : 
      31             : namespace v8 {
      32             : namespace internal {
      33             : 
      34             : // ----------------------------------------------------------------------------
      35             : // General helper functions
      36             : 
      37             : // Returns the value (0 .. 15) of a hexadecimal character c.
      38             : // If c is not a legal hexadecimal character, returns a value < 0.
      39             : inline int HexValue(uc32 c) {
      40    66387700 :   c -= '0';
      41    66387700 :   if (static_cast<unsigned>(c) <= 9) return c;
      42     8076213 :   c = (c | 0x20) - ('a' - '0');  // detect 0x11..0x16 and 0x31..0x36.
      43     8076213 :   if (static_cast<unsigned>(c) <= 5) return c + 10;
      44             :   return -1;
      45             : }
      46             : 
      47             : inline char HexCharOfValue(int value) {
      48             :   DCHECK(0 <= value && value <= 16);
      49     8201226 :   if (value < 10) return value + '0';
      50      533385 :   return value - 10 + 'A';
      51             : }
      52             : 
      53       37097 : inline int BoolToInt(bool b) { return b ? 1 : 0; }
      54             : 
      55             : // Same as strcmp, but can handle NULL arguments.
      56             : inline bool CStringEquals(const char* s1, const char* s2) {
      57             :   return (s1 == s2) || (s1 != nullptr && s2 != nullptr && strcmp(s1, s2) == 0);
      58             : }
      59             : 
      60             : // Checks if value is in range [lower_limit, higher_limit] using a single
      61             : // branch.
      62             : template <typename T, typename U>
      63  2321788435 : inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) {
      64             : #if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
      65             :   DCHECK(lower_limit <= higher_limit);
      66             : #endif
      67             :   STATIC_ASSERT(sizeof(U) <= sizeof(T));
      68             :   typedef typename std::make_unsigned<T>::type unsigned_T;
      69             :   // Use static_cast to support enum classes.
      70             :   return static_cast<unsigned_T>(static_cast<unsigned_T>(value) -
      71             :                                  static_cast<unsigned_T>(lower_limit)) <=
      72             :          static_cast<unsigned_T>(static_cast<unsigned_T>(higher_limit) -
      73  8325415023 :                                  static_cast<unsigned_T>(lower_limit));
      74             : }
      75             : 
      76             : // Checks if [index, index+length) is in range [0, max). Note that this check
      77             : // works even if {index+length} would wrap around.
      78             : inline constexpr bool IsInBounds(size_t index, size_t length, size_t max) {
      79     6372875 :   return length <= max && index <= (max - length);
      80             : }
      81             : 
      82             : // X must be a power of 2.  Returns the number of trailing zeros.
      83             : template <typename T,
      84             :           typename = typename std::enable_if<std::is_integral<T>::value>::type>
      85       21298 : inline int WhichPowerOf2(T x) {
      86             :   DCHECK(base::bits::IsPowerOfTwo(x));
      87             :   int bits = 0;
      88             : #ifdef DEBUG
      89             :   const T original_x = x;
      90             : #endif
      91             :   constexpr int max_bits = sizeof(T) * 8;
      92             :   static_assert(max_bits <= 64, "integral types are not bigger than 64 bits");
      93             : // Avoid shifting by more than the bit width of x to avoid compiler warnings.
      94             : #define CHECK_BIGGER(s)                                      \
      95             :   if (max_bits > s && x >= T{1} << (max_bits > s ? s : 0)) { \
      96             :     bits += s;                                               \
      97             :     x >>= max_bits > s ? s : 0;                              \
      98             :   }
      99       18530 :   CHECK_BIGGER(32)
     100       21298 :   CHECK_BIGGER(16)
     101       21298 :   CHECK_BIGGER(8)
     102       21298 :   CHECK_BIGGER(4)
     103             : #undef CHECK_BIGGER
     104       21298 :   switch (x) {
     105           0 :     default: UNREACHABLE();
     106             :     case 8:
     107        8975 :       bits++;
     108             :       V8_FALLTHROUGH;
     109             :     case 4:
     110        9416 :       bits++;
     111             :       V8_FALLTHROUGH;
     112             :     case 2:
     113       13114 :       bits++;
     114             :       V8_FALLTHROUGH;
     115             :     case 1: break;
     116             :   }
     117             :   DCHECK_EQ(T{1} << bits, original_x);
     118       21298 :   return bits;
     119             : }
     120             : 
     121             : inline int MostSignificantBit(uint32_t x) {
     122             :   static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
     123             :   int nibble = 0;
     124             :   if (x & 0xffff0000) {
     125             :     nibble += 16;
     126             :     x >>= 16;
     127             :   }
     128             :   if (x & 0xff00) {
     129             :     nibble += 8;
     130             :     x >>= 8;
     131             :   }
     132             :   if (x & 0xf0) {
     133             :     nibble += 4;
     134             :     x >>= 4;
     135             :   }
     136             :   return nibble + msb4[x];
     137             : }
     138             : 
     139             : template <typename T>
     140       23952 : static T ArithmeticShiftRight(T x, int shift) {
     141             :   DCHECK_LE(0, shift);
     142       24324 :   if (x < 0) {
     143             :     // Right shift of signed values is implementation defined. Simulate a
     144             :     // true arithmetic right shift by adding leading sign bits.
     145             :     using UnsignedT = typename std::make_unsigned<T>::type;
     146        5610 :     UnsignedT mask = ~(static_cast<UnsignedT>(~0) >> shift);
     147        5610 :     return (static_cast<UnsignedT>(x) >> shift) | mask;
     148             :   } else {
     149       18714 :     return x >> shift;
     150             :   }
     151             : }
     152             : 
     153             : template <typename T>
     154             : int Compare(const T& a, const T& b) {
     155        3935 :   if (a == b)
     156             :     return 0;
     157        3935 :   else if (a < b)
     158             :     return -1;
     159             :   else
     160             :     return 1;
     161             : }
     162             : 
     163             : // Compare function to compare the object pointer value of two
     164             : // handlified objects. The handles are passed as pointers to the
     165             : // handles.
     166             : template<typename T> class Handle;  // Forward declaration.
     167             : template <typename T>
     168             : int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
     169             :   return Compare<T*>(*(*a), *(*b));
     170             : }
     171             : 
     172             : // Returns the maximum of the two parameters.
     173             : template <typename T>
     174      247386 : constexpr T Max(T a, T b) {
     175   167009079 :   return a < b ? b : a;
     176             : }
     177             : 
     178             : 
     179             : // Returns the minimum of the two parameters.
     180             : template <typename T>
     181     7007018 : constexpr T Min(T a, T b) {
     182   324071167 :   return a < b ? a : b;
     183             : }
     184             : 
     185             : // Returns the maximum of the two parameters according to JavaScript semantics.
     186             : template <typename T>
     187      435048 : T JSMax(T x, T y) {
     188      435048 :   if (std::isnan(x)) return x;
     189      425764 :   if (std::isnan(y)) return y;
     190      833416 :   if (std::signbit(x) < std::signbit(y)) return x;
     191      314612 :   return x > y ? x : y;
     192             : }
     193             : 
     194             : // Returns the maximum of the two parameters according to JavaScript semantics.
     195             : template <typename T>
     196      435048 : T JSMin(T x, T y) {
     197      435048 :   if (std::isnan(x)) return x;
     198      425764 :   if (std::isnan(y)) return y;
     199      833416 :   if (std::signbit(x) < std::signbit(y)) return y;
     200      314612 :   return x > y ? y : x;
     201             : }
     202             : 
     203             : // Returns the absolute value of its argument.
     204             : template <typename T,
     205             :           typename = typename std::enable_if<std::is_signed<T>::value>::type>
     206             : typename std::make_unsigned<T>::type Abs(T a) {
     207             :   // This is a branch-free implementation of the absolute value function and is
     208             :   // described in Warren's "Hacker's Delight", chapter 2. It avoids undefined
     209             :   // behavior with the arithmetic negation operation on signed values as well.
     210             :   typedef typename std::make_unsigned<T>::type unsignedT;
     211        5281 :   unsignedT x = static_cast<unsignedT>(a);
     212        5281 :   unsignedT y = static_cast<unsignedT>(a >> (sizeof(T) * 8 - 1));
     213        5281 :   return (x ^ y) - y;
     214             : }
     215             : 
     216             : // Returns the negative absolute value of its argument.
     217             : template <typename T,
     218             :           typename = typename std::enable_if<std::is_signed<T>::value>::type>
     219             : T Nabs(T a) {
     220             :   return a < 0 ? a : -a;
     221             : }
     222             : 
     223             : // Floor(-0.0) == 0.0
     224             : inline double Floor(double x) {
     225             : #if V8_CC_MSVC
     226             :   if (x == 0) return x;  // Fix for issue 3477.
     227             : #endif
     228      144304 :   return std::floor(x);
     229             : }
     230             : 
     231             : inline double Modulo(double x, double y) {
     232             : #if defined(V8_OS_WIN)
     233             :   // Workaround MS fmod bugs. ECMA-262 says:
     234             :   // dividend is finite and divisor is an infinity => result equals dividend
     235             :   // dividend is a zero and divisor is nonzero finite => result equals dividend
     236             :   if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
     237             :       !(x == 0 && (y != 0 && std::isfinite(y)))) {
     238             :     double result = fmod(x, y);
     239             :     // Workaround MS bug in VS CRT in some OS versions, https://crbug.com/915045
     240             :     // fmod(-17, +/-1) should equal -0.0 but now returns 0.0.
     241             :     if (x < 0 && result == 0) result = -0.0;
     242             :     x = result;
     243             :   }
     244             :   return x;
     245             : #elif defined(V8_OS_AIX)
     246             :   // AIX raises an underflow exception for (Number.MIN_VALUE % Number.MAX_VALUE)
     247             :   feclearexcept(FE_ALL_EXCEPT);
     248             :   double result = std::fmod(x, y);
     249             :   int exception = fetestexcept(FE_UNDERFLOW);
     250             :   return (exception ? x : result);
     251             : #else
     252      724270 :   return std::fmod(x, y);
     253             : #endif
     254             : }
     255             : 
     256             : template <typename T>
     257        9378 : T SaturateAdd(T a, T b) {
     258             :   if (std::is_signed<T>::value) {
     259        9378 :     if (a > 0 && b > 0) {
     260        2310 :       if (a > std::numeric_limits<T>::max() - b) {
     261             :         return std::numeric_limits<T>::max();
     262             :       }
     263        7068 :     } else if (a < 0 && b < 0) {
     264        1653 :       if (a < std::numeric_limits<T>::min() - b) {
     265             :         return std::numeric_limits<T>::min();
     266             :       }
     267             :     }
     268             :   } else {
     269             :     CHECK(std::is_unsigned<T>::value);
     270        9369 :     if (a > std::numeric_limits<T>::max() - b) {
     271             :       return std::numeric_limits<T>::max();
     272             :     }
     273             :   }
     274       12784 :   return a + b;
     275             : }
     276             : 
     277             : template <typename T>
     278        9440 : T SaturateSub(T a, T b) {
     279             :   if (std::is_signed<T>::value) {
     280        9440 :     if (a >= 0 && b < 0) {
     281        2244 :       if (a > std::numeric_limits<T>::max() + b) {
     282             :         return std::numeric_limits<T>::max();
     283             :       }
     284        7196 :     } else if (a < 0 && b > 0) {
     285        1841 :       if (a < std::numeric_limits<T>::min() + b) {
     286             :         return std::numeric_limits<T>::min();
     287             :       }
     288             :     }
     289             :   } else {
     290             :     CHECK(std::is_unsigned<T>::value);
     291        9369 :     if (a < b) {
     292             :       return static_cast<T>(0);
     293             :     }
     294             :   }
     295       12617 :   return a - b;
     296             : }
     297             : 
     298             : // ----------------------------------------------------------------------------
     299             : // BitField is a help template for encoding and decode bitfield with
     300             : // unsigned content.
     301             : 
     302             : template<class T, int shift, int size, class U>
     303             : class BitFieldBase {
     304             :  public:
     305             :   typedef T FieldType;
     306             : 
     307             :   // A type U mask of bit field.  To use all bits of a type U of x bits
     308             :   // in a bitfield without compiler warnings we have to compute 2^x
     309             :   // without using a shift count of x in the computation.
     310             :   static const U kOne = static_cast<U>(1U);
     311             :   static const U kMask = ((kOne << shift) << size) - (kOne << shift);
     312             :   static const U kShift = shift;
     313             :   static const U kSize = size;
     314             :   static const U kNext = kShift + kSize;
     315             :   static const U kNumValues = kOne << size;
     316             : 
     317             :   // Value for the field with all bits set.
     318             :   static const T kMax = static_cast<T>(kNumValues - 1);
     319             : 
     320             :   // Tells whether the provided value fits into the bit field.
     321             :   static constexpr bool is_valid(T value) {
     322    76071812 :     return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
     323             :   }
     324             : 
     325             :   // Returns a type U with the bit field value encoded.
     326       37051 :   static constexpr U encode(T value) {
     327             : #if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
     328             :     DCHECK(is_valid(value));
     329             : #endif
     330  5316312506 :     return static_cast<U>(value) << shift;
     331             :   }
     332             : 
     333             :   // Returns a type U with the bit field value updated.
     334        5779 :   static constexpr U update(U previous, T value) {
     335  5579673011 :     return (previous & ~kMask) | encode(value);
     336             :   }
     337             : 
     338             :   // Extracts the bit field from the value.
     339    25214494 :   static constexpr T decode(U value) {
     340 48348578601 :     return static_cast<T>((value & kMask) >> shift);
     341             :   }
     342             : 
     343             :   STATIC_ASSERT((kNext - 1) / 8 < sizeof(U));
     344             : };
     345             : 
     346             : template <class T, int shift, int size>
     347             : class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
     348             : 
     349             : 
     350             : template <class T, int shift, int size>
     351             : class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
     352             : 
     353             : 
     354             : template<class T, int shift, int size>
     355             : class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
     356             : 
     357             : 
     358             : template<class T, int shift, int size>
     359             : class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
     360             : 
     361             : // Helper macros for defining a contiguous sequence of bit fields. Example:
     362             : // (backslashes at the ends of respective lines of this multi-line macro
     363             : // definition are omitted here to please the compiler)
     364             : //
     365             : // #define MAP_BIT_FIELD1(V, _)
     366             : //   V(IsAbcBit, bool, 1, _)
     367             : //   V(IsBcdBit, bool, 1, _)
     368             : //   V(CdeBits, int, 5, _)
     369             : //   V(DefBits, MutableMode, 1, _)
     370             : //
     371             : // DEFINE_BIT_FIELDS(MAP_BIT_FIELD1)
     372             : // or
     373             : // DEFINE_BIT_FIELDS_64(MAP_BIT_FIELD1)
     374             : //
     375             : #define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \
     376             :   k##Name##Start, k##Name##End = k##Name##Start + Size - 1,
     377             : 
     378             : #define DEFINE_BIT_RANGES(LIST_MACRO)                               \
     379             :   struct LIST_MACRO##_Ranges {                                      \
     380             :     enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) kBitsCount }; \
     381             :   };
     382             : 
     383             : #define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \
     384             :   typedef BitField<Type, RangesName::k##Name##Start, Size> Name;
     385             : 
     386             : #define DEFINE_BIT_FIELD_64_TYPE(Name, Type, Size, RangesName) \
     387             :   typedef BitField64<Type, RangesName::k##Name##Start, Size> Name;
     388             : 
     389             : #define DEFINE_BIT_FIELDS(LIST_MACRO) \
     390             :   DEFINE_BIT_RANGES(LIST_MACRO)       \
     391             :   LIST_MACRO(DEFINE_BIT_FIELD_TYPE, LIST_MACRO##_Ranges)
     392             : 
     393             : #define DEFINE_BIT_FIELDS_64(LIST_MACRO) \
     394             :   DEFINE_BIT_RANGES(LIST_MACRO)          \
     395             :   LIST_MACRO(DEFINE_BIT_FIELD_64_TYPE, LIST_MACRO##_Ranges)
     396             : 
     397             : // ----------------------------------------------------------------------------
     398             : // BitSetComputer is a help template for encoding and decoding information for
     399             : // a variable number of items in an array.
     400             : //
     401             : // To encode boolean data in a smi array you would use:
     402             : // typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer;
     403             : //
     404             : template <class T, int kBitsPerItem, int kBitsPerWord, class U>
     405             : class BitSetComputer {
     406             :  public:
     407             :   static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
     408             :   static const int kMask = (1 << kBitsPerItem) - 1;
     409             : 
     410             :   // The number of array elements required to embed T information for each item.
     411             :   static int word_count(int items) {
     412     7033896 :     if (items == 0) return 0;
     413     7022375 :     return (items - 1) / kItemsPerWord + 1;
     414             :   }
     415             : 
     416             :   // The array index to look at for item.
     417             :   static int index(int base_index, int item) {
     418    75924991 :     return base_index + item / kItemsPerWord;
     419             :   }
     420             : 
     421             :   // Extract T data for a given item from data.
     422             :   static T decode(U data, int item) {
     423    47852368 :     return static_cast<T>((data >> shift(item)) & kMask);
     424             :   }
     425             : 
     426             :   // Return the encoding for a store of value for item in previous.
     427             :   static U encode(U previous, int item, T value) {
     428             :     int shift_value = shift(item);
     429    28076793 :     int set_bits = (static_cast<int>(value) << shift_value);
     430    28076793 :     return (previous & ~(kMask << shift_value)) | set_bits;
     431             :   }
     432             : 
     433    75924991 :   static int shift(int item) { return (item % kItemsPerWord) * kBitsPerItem; }
     434             : };
     435             : 
     436             : // Helper macros for defining a contiguous sequence of field offset constants.
     437             : // Example: (backslashes at the ends of respective lines of this multi-line
     438             : // macro definition are omitted here to please the compiler)
     439             : //
     440             : // #define MAP_FIELDS(V)
     441             : //   V(kField1Offset, kTaggedSize)
     442             : //   V(kField2Offset, kIntSize)
     443             : //   V(kField3Offset, kIntSize)
     444             : //   V(kField4Offset, kSystemPointerSize)
     445             : //   V(kSize, 0)
     446             : //
     447             : // DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS)
     448             : //
     449             : #define DEFINE_ONE_FIELD_OFFSET(Name, Size) Name, Name##End = Name + (Size)-1,
     450             : 
     451             : #define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO) \
     452             :   enum {                                                       \
     453             :     LIST_MACRO##_StartOffset = StartOffset - 1,                \
     454             :     LIST_MACRO(DEFINE_ONE_FIELD_OFFSET)                        \
     455             :   };
     456             : 
     457             : // Size of the field defined by DEFINE_FIELD_OFFSET_CONSTANTS
     458             : #define FIELD_SIZE(Name) (Name##End + 1 - Name)
     459             : 
     460             : // ----------------------------------------------------------------------------
     461             : // Hash function.
     462             : 
     463             : static const uint64_t kZeroHashSeed = 0;
     464             : 
     465             : // Thomas Wang, Integer Hash Functions.
     466             : // http://www.concentric.net/~Ttwang/tech/inthash.htm`
     467             : inline uint32_t ComputeUnseededHash(uint32_t key) {
     468             :   uint32_t hash = key;
     469    92295942 :   hash = ~hash + (hash << 15);  // hash = (hash << 15) - hash - 1;
     470    92295942 :   hash = hash ^ (hash >> 12);
     471    92295942 :   hash = hash + (hash << 2);
     472    92295942 :   hash = hash ^ (hash >> 4);
     473    92295942 :   hash = hash * 2057;  // hash = (hash + (hash << 3)) + (hash << 11);
     474    92295942 :   hash = hash ^ (hash >> 16);
     475    92295942 :   return hash & 0x3fffffff;
     476             : }
     477             : 
     478             : inline uint32_t ComputeLongHash(uint64_t key) {
     479             :   uint64_t hash = key;
     480   150201314 :   hash = ~hash + (hash << 18);  // hash = (hash << 18) - hash - 1;
     481   150201314 :   hash = hash ^ (hash >> 31);
     482   150201314 :   hash = hash * 21;  // hash = (hash + (hash << 2)) + (hash << 4);
     483   150201314 :   hash = hash ^ (hash >> 11);
     484   150201314 :   hash = hash + (hash << 6);
     485   150201314 :   hash = hash ^ (hash >> 22);
     486   150201314 :   return static_cast<uint32_t>(hash & 0x3fffffff);
     487             : }
     488             : 
     489             : inline uint32_t ComputeSeededHash(uint32_t key, uint64_t seed) {
     490             : #ifdef V8_USE_SIPHASH
     491             :   return halfsiphash(key, seed);
     492             : #else
     493   146170020 :   return ComputeLongHash(static_cast<uint64_t>(key) ^ seed);
     494             : #endif  // V8_USE_SIPHASH
     495             : }
     496             : 
     497             : inline uint32_t ComputePointerHash(void* ptr) {
     498             :   return ComputeUnseededHash(
     499       21309 :       static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)));
     500             : }
     501             : 
     502             : inline uint32_t ComputeAddressHash(Address address) {
     503    10545187 :   return ComputeUnseededHash(static_cast<uint32_t>(address & 0xFFFFFFFFul));
     504             : }
     505             : 
     506             : // ----------------------------------------------------------------------------
     507             : // Miscellaneous
     508             : 
     509             : // Memory offset for lower and higher bits in a 64 bit integer.
     510             : #if defined(V8_TARGET_LITTLE_ENDIAN)
     511             : static const int kInt64LowerHalfMemoryOffset = 0;
     512             : static const int kInt64UpperHalfMemoryOffset = 4;
     513             : #elif defined(V8_TARGET_BIG_ENDIAN)
     514             : static const int kInt64LowerHalfMemoryOffset = 4;
     515             : static const int kInt64UpperHalfMemoryOffset = 0;
     516             : #endif  // V8_TARGET_LITTLE_ENDIAN
     517             : 
     518             : // A static resource holds a static instance that can be reserved in
     519             : // a local scope using an instance of Access.  Attempts to re-reserve
     520             : // the instance will cause an error.
     521             : template <typename T>
     522             : class StaticResource {
     523             :  public:
     524       61049 :   StaticResource() : is_reserved_(false)  {}
     525             : 
     526             :  private:
     527             :   template <typename S> friend class Access;
     528             :   T instance_;
     529             :   bool is_reserved_;
     530             : };
     531             : 
     532             : 
     533             : // Locally scoped access to a static resource.
     534             : template <typename T>
     535             : class Access {
     536             :  public:
     537             :   explicit Access(StaticResource<T>* resource)
     538             :     : resource_(resource)
     539          10 :     , instance_(&resource->instance_) {
     540             :     DCHECK(!resource->is_reserved_);
     541          10 :     resource->is_reserved_ = true;
     542             :   }
     543             : 
     544             :   ~Access() {
     545          10 :     resource_->is_reserved_ = false;
     546             :     resource_ = nullptr;
     547             :     instance_ = nullptr;
     548             :   }
     549             : 
     550             :   T* value()  { return instance_; }
     551             :   T* operator -> ()  { return instance_; }
     552             : 
     553             :  private:
     554             :   StaticResource<T>* resource_;
     555             :   T* instance_;
     556             : };
     557             : 
     558             : // A pointer that can only be set once and doesn't allow NULL values.
     559             : template<typename T>
     560             : class SetOncePointer {
     561             :  public:
     562             :   SetOncePointer() = default;
     563             : 
     564     7515956 :   bool is_set() const { return pointer_ != nullptr; }
     565             : 
     566             :   T* get() const {
     567             :     DCHECK_NOT_NULL(pointer_);
     568     9407224 :     return pointer_;
     569             :   }
     570             : 
     571             :   void set(T* value) {
     572             :     DCHECK(pointer_ == nullptr && value != nullptr);
     573     1332363 :     pointer_ = value;
     574             :   }
     575             : 
     576             :   T* operator=(T* value) {
     577             :     set(value);
     578             :     return value;
     579             :   }
     580             : 
     581       70851 :   bool operator==(std::nullptr_t) const { return pointer_ == nullptr; }
     582             :   bool operator!=(std::nullptr_t) const { return pointer_ != nullptr; }
     583             : 
     584             :  private:
     585             :   T* pointer_ = nullptr;
     586             : };
     587             : 
     588             : 
     589             : template <typename T, int kSize>
     590             : class EmbeddedVector : public Vector<T> {
     591             :  public:
     592  1448768331 :   EmbeddedVector() : Vector<T>(buffer_, kSize) { }
     593             : 
     594   238302144 :   explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
     595   238302880 :     for (int i = 0; i < kSize; ++i) {
     596   238302880 :       buffer_[i] = initial_value;
     597             :     }
     598             :   }
     599             : 
     600             :   // When copying, make underlying Vector to reference our buffer.
     601             :   EmbeddedVector(const EmbeddedVector& rhs) V8_NOEXCEPT : Vector<T>(rhs) {
     602             :     MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
     603             :     this->set_start(buffer_);
     604             :   }
     605             : 
     606             :   EmbeddedVector& operator=(const EmbeddedVector& rhs) V8_NOEXCEPT {
     607             :     if (this == &rhs) return *this;
     608             :     Vector<T>::operator=(rhs);
     609             :     MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
     610             :     this->set_start(buffer_);
     611             :     return *this;
     612             :   }
     613             : 
     614             :  private:
     615             :   T buffer_[kSize];
     616             : };
     617             : 
     618             : // Compare 8bit/16bit chars to 8bit/16bit chars.
     619             : template <typename lchar, typename rchar>
     620             : inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
     621             :                                 size_t chars) {
     622      816324 :   const lchar* limit = lhs + chars;
     623             :   if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
     624             :     // memcmp compares byte-by-byte, yielding wrong results for two-byte
     625             :     // strings on little-endian systems.
     626   149469658 :     return memcmp(lhs, rhs, chars);
     627             :   }
     628     3875880 :   while (lhs < limit) {
     629     3077822 :     int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
     630     3077822 :     if (r != 0) return r;
     631     3059556 :     ++lhs;
     632     3059556 :     ++rhs;
     633             :   }
     634             :   return 0;
     635             : }
     636             : 
     637             : template <typename lchar, typename rchar>
     638             : inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
     639             :   DCHECK_LE(sizeof(lchar), 2);
     640             :   DCHECK_LE(sizeof(rchar), 2);
     641             :   if (sizeof(lchar) == 1) {
     642             :     if (sizeof(rchar) == 1) {
     643             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
     644             :                                   reinterpret_cast<const uint8_t*>(rhs),
     645             :                                   chars);
     646             :     } else {
     647             :       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
     648             :                                   reinterpret_cast<const uint16_t*>(rhs),
     649             :                                   chars);
     650             :     }
     651             :   } else {
     652             :     if (sizeof(rchar) == 1) {
     653             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
     654             :                                   reinterpret_cast<const uint8_t*>(rhs),
     655             :                                   chars);
     656             :     } else {
     657             :       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
     658             :                                   reinterpret_cast<const uint16_t*>(rhs),
     659             :                                   chars);
     660             :     }
     661             :   }
     662             : }
     663             : 
     664             : 
     665             : // Calculate 10^exponent.
     666             : inline int TenToThe(int exponent) {
     667             :   DCHECK_LE(exponent, 9);
     668             :   DCHECK_GE(exponent, 1);
     669             :   int answer = 10;
     670             :   for (int i = 1; i < exponent; i++) answer *= 10;
     671             :   return answer;
     672             : }
     673             : 
     674             : 
     675             : template<typename ElementType, int NumElements>
     676             : class EmbeddedContainer {
     677             :  public:
     678             :   EmbeddedContainer() : elems_() { }
     679             : 
     680             :   int length() const { return NumElements; }
     681             :   const ElementType& operator[](int i) const {
     682             :     DCHECK(i < length());
     683             :     return elems_[i];
     684             :   }
     685             :   ElementType& operator[](int i) {
     686             :     DCHECK(i < length());
     687             :     return elems_[i];
     688             :   }
     689             : 
     690             :  private:
     691             :   ElementType elems_[NumElements];
     692             : };
     693             : 
     694             : 
     695             : template<typename ElementType>
     696             : class EmbeddedContainer<ElementType, 0> {
     697             :  public:
     698             :   int length() const { return 0; }
     699             :   const ElementType& operator[](int i) const {
     700             :     UNREACHABLE();
     701             :     static ElementType t = 0;
     702             :     return t;
     703             :   }
     704             :   ElementType& operator[](int i) {
     705             :     UNREACHABLE();
     706             :     static ElementType t = 0;
     707             :     return t;
     708             :   }
     709             : };
     710             : 
     711             : 
     712             : // Helper class for building result strings in a character buffer. The
     713             : // purpose of the class is to use safe operations that checks the
     714             : // buffer bounds on all operations in debug mode.
     715             : // This simple base class does not allow formatted output.
     716             : class SimpleStringBuilder {
     717             :  public:
     718             :   // Create a string builder with a buffer of the given size. The
     719             :   // buffer is allocated through NewArray<char> and must be
     720             :   // deallocated by the caller of Finalize().
     721             :   explicit SimpleStringBuilder(int size);
     722             : 
     723             :   SimpleStringBuilder(char* buffer, int size)
     724     2264220 :       : buffer_(buffer, size), position_(0) { }
     725             : 
     726     1142049 :   ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
     727             : 
     728             :   int size() const { return buffer_.length(); }
     729             : 
     730             :   // Get the current position in the builder.
     731             :   int position() const {
     732             :     DCHECK(!is_finalized());
     733             :     return position_;
     734             :   }
     735             : 
     736             :   // Reset the position.
     737           0 :   void Reset() { position_ = 0; }
     738             : 
     739             :   // Add a single character to the builder. It is not allowed to add
     740             :   // 0-characters; use the Finalize() method to terminate the string
     741             :   // instead.
     742             :   void AddCharacter(char c) {
     743             :     DCHECK_NE(c, '\0');
     744             :     DCHECK(!is_finalized() && position_ < buffer_.length());
     745     4232632 :     buffer_[position_++] = c;
     746             :   }
     747             : 
     748             :   // Add an entire string to the builder. Uses strlen() internally to
     749             :   // compute the length of the input string.
     750             :   void AddString(const char* s);
     751             : 
     752             :   // Add the first 'n' characters of the given 0-terminated string 's' to the
     753             :   // builder. The input string must have enough characters.
     754             :   void AddSubstring(const char* s, int n);
     755             : 
     756             :   // Add character padding to the builder. If count is non-positive,
     757             :   // nothing is added to the builder.
     758             :   void AddPadding(char c, int count);
     759             : 
     760             :   // Add the decimal representation of the value.
     761             :   void AddDecimalInteger(int value);
     762             : 
     763             :   // Finalize the string by 0-terminating it and returning the buffer.
     764             :   char* Finalize();
     765             : 
     766             :  protected:
     767             :   Vector<char> buffer_;
     768             :   int position_;
     769             : 
     770             :   bool is_finalized() const { return position_ < 0; }
     771             : 
     772             :  private:
     773             :   DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
     774             : };
     775             : 
     776             : // Bit field extraction.
     777             : inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
     778             :   return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
     779             : }
     780             : 
     781             : inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
     782             :   return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
     783             : }
     784             : 
     785             : inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
     786             :   return (x << (31 - msb)) >> (lsb + 31 - msb);
     787             : }
     788             : 
     789             : inline int signed_bitextract_64(int msb, int lsb, int x) {
     790             :   // TODO(jbramley): This is broken for big bitfields.
     791             :   return (x << (63 - msb)) >> (lsb + 63 - msb);
     792             : }
     793             : 
     794             : // Check number width.
     795             : inline bool is_intn(int64_t x, unsigned n) {
     796             :   DCHECK((0 < n) && (n < 64));
     797             :   int64_t limit = static_cast<int64_t>(1) << (n - 1);
     798    66850015 :   return (-limit <= x) && (x < limit);
     799             : }
     800             : 
     801             : inline bool is_uintn(int64_t x, unsigned n) {
     802             :   DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
     803    19648963 :   return !(x >> n);
     804             : }
     805             : 
     806             : template <class T>
     807             : inline T truncate_to_intn(T x, unsigned n) {
     808             :   DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
     809             :   return (x & ((static_cast<T>(1) << n) - 1));
     810             : }
     811             : 
     812             : #define INT_1_TO_63_LIST(V)                                                    \
     813             : V(1)  V(2)  V(3)  V(4)  V(5)  V(6)  V(7)  V(8)                                 \
     814             : V(9)  V(10) V(11) V(12) V(13) V(14) V(15) V(16)                                \
     815             : V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24)                                \
     816             : V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32)                                \
     817             : V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40)                                \
     818             : V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48)                                \
     819             : V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56)                                \
     820             : V(57) V(58) V(59) V(60) V(61) V(62) V(63)
     821             : 
     822             : #define DECLARE_IS_INT_N(N)                                                    \
     823             : inline bool is_int##N(int64_t x) { return is_intn(x, N); }
     824             : #define DECLARE_IS_UINT_N(N)                                                   \
     825             : template <class T>                                                             \
     826             : inline bool is_uint##N(T x) { return is_uintn(x, N); }
     827             : #define DECLARE_TRUNCATE_TO_INT_N(N)                                           \
     828             : template <class T>                                                             \
     829             : inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
     830             : INT_1_TO_63_LIST(DECLARE_IS_INT_N)
     831     5026933 : INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
     832             : INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
     833             : #undef DECLARE_IS_INT_N
     834             : #undef DECLARE_IS_UINT_N
     835             : #undef DECLARE_TRUNCATE_TO_INT_N
     836             : 
     837             : // clang-format off
     838             : #define INT_0_TO_127_LIST(V)                                          \
     839             : V(0)   V(1)   V(2)   V(3)   V(4)   V(5)   V(6)   V(7)   V(8)   V(9)   \
     840             : V(10)  V(11)  V(12)  V(13)  V(14)  V(15)  V(16)  V(17)  V(18)  V(19)  \
     841             : V(20)  V(21)  V(22)  V(23)  V(24)  V(25)  V(26)  V(27)  V(28)  V(29)  \
     842             : V(30)  V(31)  V(32)  V(33)  V(34)  V(35)  V(36)  V(37)  V(38)  V(39)  \
     843             : V(40)  V(41)  V(42)  V(43)  V(44)  V(45)  V(46)  V(47)  V(48)  V(49)  \
     844             : V(50)  V(51)  V(52)  V(53)  V(54)  V(55)  V(56)  V(57)  V(58)  V(59)  \
     845             : V(60)  V(61)  V(62)  V(63)  V(64)  V(65)  V(66)  V(67)  V(68)  V(69)  \
     846             : V(70)  V(71)  V(72)  V(73)  V(74)  V(75)  V(76)  V(77)  V(78)  V(79)  \
     847             : V(80)  V(81)  V(82)  V(83)  V(84)  V(85)  V(86)  V(87)  V(88)  V(89)  \
     848             : V(90)  V(91)  V(92)  V(93)  V(94)  V(95)  V(96)  V(97)  V(98)  V(99)  \
     849             : V(100) V(101) V(102) V(103) V(104) V(105) V(106) V(107) V(108) V(109) \
     850             : V(110) V(111) V(112) V(113) V(114) V(115) V(116) V(117) V(118) V(119) \
     851             : V(120) V(121) V(122) V(123) V(124) V(125) V(126) V(127)
     852             : // clang-format on
     853             : 
     854             : class FeedbackSlot {
     855             :  public:
     856   301882499 :   FeedbackSlot() : id_(kInvalidSlot) {}
     857     2140155 :   explicit FeedbackSlot(int id) : id_(id) {}
     858             : 
     859     1499935 :   int ToInt() const { return id_; }
     860             : 
     861             :   static FeedbackSlot Invalid() { return FeedbackSlot(); }
     862     4165025 :   bool IsInvalid() const { return id_ == kInvalidSlot; }
     863             : 
     864          15 :   bool operator==(FeedbackSlot that) const { return this->id_ == that.id_; }
     865             :   bool operator!=(FeedbackSlot that) const { return !(*this == that); }
     866             : 
     867           0 :   friend size_t hash_value(FeedbackSlot slot) { return slot.ToInt(); }
     868             :   friend std::ostream& operator<<(std::ostream& os, FeedbackSlot);
     869             : 
     870             :  private:
     871             :   static const int kInvalidSlot = -1;
     872             : 
     873             :   int id_;
     874             : };
     875             : 
     876             : 
     877             : class BailoutId {
     878             :  public:
     879     7189515 :   explicit BailoutId(int id) : id_(id) { }
     880     3890209 :   int ToInt() const { return id_; }
     881             : 
     882             :   static BailoutId None() { return BailoutId(kNoneId); }
     883             :   static BailoutId ScriptContext() { return BailoutId(kScriptContextId); }
     884             :   static BailoutId FunctionContext() { return BailoutId(kFunctionContextId); }
     885             :   static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
     886             :   static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
     887             :   static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
     888             :   static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
     889             : 
     890             :   // Special bailout id support for deopting into the {JSConstructStub} stub.
     891             :   // The following hard-coded deoptimization points are supported by the stub:
     892             :   //  - {ConstructStubCreate} maps to {construct_stub_create_deopt_pc_offset}.
     893             :   //  - {ConstructStubInvoke} maps to {construct_stub_invoke_deopt_pc_offset}.
     894             :   static BailoutId ConstructStubCreate() { return BailoutId(1); }
     895             :   static BailoutId ConstructStubInvoke() { return BailoutId(2); }
     896             :   bool IsValidForConstructStub() const {
     897             :     return id_ == ConstructStubCreate().ToInt() ||
     898             :            id_ == ConstructStubInvoke().ToInt();
     899             :   }
     900             : 
     901     9396134 :   bool IsNone() const { return id_ == kNoneId; }
     902           2 :   bool operator==(const BailoutId& other) const { return id_ == other.id_; }
     903             :   bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
     904             :   friend size_t hash_value(BailoutId);
     905             :   V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream&, BailoutId);
     906             : 
     907             :  private:
     908             :   friend class Builtins;
     909             : 
     910             :   static const int kNoneId = -1;
     911             : 
     912             :   // Using 0 could disguise errors.
     913             :   static const int kScriptContextId = 1;
     914             :   static const int kFunctionContextId = 2;
     915             :   static const int kFunctionEntryId = 3;
     916             : 
     917             :   // This AST id identifies the point after the declarations have been visited.
     918             :   // We need it to capture the environment effects of declarations that emit
     919             :   // code (function declarations).
     920             :   static const int kDeclarationsId = 4;
     921             : 
     922             :   // Every FunctionState starts with this id.
     923             :   static const int kFirstUsableId = 5;
     924             : 
     925             :   // Every compiled stub starts with this id.
     926             :   static const int kStubEntryId = 6;
     927             : 
     928             :   // Builtin continuations bailout ids start here. If you need to add a
     929             :   // non-builtin BailoutId, add it before this id so that this Id has the
     930             :   // highest number.
     931             :   static const int kFirstBuiltinContinuationId = 7;
     932             : 
     933             :   int id_;
     934             : };
     935             : 
     936             : 
     937             : // ----------------------------------------------------------------------------
     938             : // I/O support.
     939             : 
     940             : // Our version of printf().
     941             : V8_EXPORT_PRIVATE void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
     942             : void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
     943             : 
     944             : // Prepends the current process ID to the output.
     945             : void PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...);
     946             : 
     947             : // Prepends the current process ID and given isolate pointer to the output.
     948             : void PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...);
     949             : 
     950             : // Safe formatting print. Ensures that str is always null-terminated.
     951             : // Returns the number of chars written, or -1 if output was truncated.
     952             : int PRINTF_FORMAT(2, 3) SNPrintF(Vector<char> str, const char* format, ...);
     953             : V8_EXPORT_PRIVATE int PRINTF_FORMAT(2, 0)
     954             :     VSNPrintF(Vector<char> str, const char* format, va_list args);
     955             : 
     956             : void StrNCpy(Vector<char> dest, const char* src, size_t n);
     957             : 
     958             : // Our version of fflush.
     959             : void Flush(FILE* out);
     960             : 
     961             : inline void Flush() {
     962             :   Flush(stdout);
     963             : }
     964             : 
     965             : 
     966             : // Read a line of characters after printing the prompt to stdout. The resulting
     967             : // char* needs to be disposed off with DeleteArray by the caller.
     968             : char* ReadLine(const char* prompt);
     969             : 
     970             : 
     971             : // Append size chars from str to the file given by filename.
     972             : // The file is overwritten. Returns the number of chars written.
     973             : int AppendChars(const char* filename,
     974             :                 const char* str,
     975             :                 int size,
     976             :                 bool verbose = true);
     977             : 
     978             : 
     979             : // Write size chars from str to the file given by filename.
     980             : // The file is overwritten. Returns the number of chars written.
     981             : int WriteChars(const char* filename,
     982             :                const char* str,
     983             :                int size,
     984             :                bool verbose = true);
     985             : 
     986             : 
     987             : // Write size bytes to the file given by filename.
     988             : // The file is overwritten. Returns the number of bytes written.
     989             : int WriteBytes(const char* filename,
     990             :                const byte* bytes,
     991             :                int size,
     992             :                bool verbose = true);
     993             : 
     994             : 
     995             : // Write the C code
     996             : // const char* <varname> = "<str>";
     997             : // const int <varname>_len = <len>;
     998             : // to the file given by filename. Only the first len chars are written.
     999             : int WriteAsCFile(const char* filename, const char* varname,
    1000             :                  const char* str, int size, bool verbose = true);
    1001             : 
    1002             : 
    1003             : // Simple support to read a file into std::string.
    1004             : // On return, *exits tells whether the file existed.
    1005             : V8_EXPORT_PRIVATE std::string ReadFile(const char* filename, bool* exists,
    1006             :                                        bool verbose = true);
    1007             : std::string ReadFile(FILE* file, bool* exists, bool verbose = true);
    1008             : 
    1009             : class StringBuilder : public SimpleStringBuilder {
    1010             :  public:
    1011             :   explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
    1012             :   StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
    1013             : 
    1014             :   // Add formatted contents to the builder just like printf().
    1015             :   void PRINTF_FORMAT(2, 3) AddFormatted(const char* format, ...);
    1016             : 
    1017             :   // Add formatted contents like printf based on a va_list.
    1018             :   void PRINTF_FORMAT(2, 0) AddFormattedList(const char* format, va_list list);
    1019             : 
    1020             :  private:
    1021             :   DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
    1022             : };
    1023             : 
    1024             : 
    1025             : bool DoubleToBoolean(double d);
    1026             : 
    1027             : template <typename Char>
    1028             : bool TryAddIndexChar(uint32_t* index, Char c);
    1029             : 
    1030             : template <typename Stream>
    1031             : bool StringToArrayIndex(Stream* stream, uint32_t* index);
    1032             : 
    1033             : // Returns the current stack top. Works correctly with ASAN and SafeStack.
    1034             : // GetCurrentStackPosition() should not be inlined, because it works on stack
    1035             : // frames if it were inlined into a function with a huge stack frame it would
    1036             : // return an address significantly above the actual current stack position.
    1037             : V8_NOINLINE uintptr_t GetCurrentStackPosition();
    1038             : 
    1039             : static inline uint16_t ByteReverse16(uint16_t value) {
    1040             : #if V8_HAS_BUILTIN_BSWAP16
    1041             :       return __builtin_bswap16(value);
    1042             : #else
    1043             :       return value << 8 | (value >> 8 & 0x00FF);
    1044             : #endif
    1045             : }
    1046             : 
    1047             : static inline uint32_t ByteReverse32(uint32_t value) {
    1048             : #if V8_HAS_BUILTIN_BSWAP32
    1049             :       return __builtin_bswap32(value);
    1050             : #else
    1051             :       return value << 24 |
    1052             :              ((value << 8) & 0x00FF0000) |
    1053             :              ((value >> 8) & 0x0000FF00) |
    1054             :              ((value >> 24) & 0x00000FF);
    1055             : #endif
    1056             : }
    1057             : 
    1058             : static inline uint64_t ByteReverse64(uint64_t value) {
    1059             : #if V8_HAS_BUILTIN_BSWAP64
    1060             :       return __builtin_bswap64(value);
    1061             : #else
    1062             :       size_t bits_of_v = sizeof(value) * kBitsPerByte;
    1063             :       return value << (bits_of_v - 8) |
    1064             :              ((value << (bits_of_v - 24)) & 0x00FF000000000000) |
    1065             :              ((value << (bits_of_v - 40)) & 0x0000FF0000000000) |
    1066             :              ((value << (bits_of_v - 56)) & 0x000000FF00000000) |
    1067             :              ((value >> (bits_of_v - 56)) & 0x00000000FF000000) |
    1068             :              ((value >> (bits_of_v - 40)) & 0x0000000000FF0000) |
    1069             :              ((value >> (bits_of_v - 24)) & 0x000000000000FF00) |
    1070             :              ((value >> (bits_of_v - 8)) & 0x00000000000000FF);
    1071             : #endif
    1072             : }
    1073             : 
    1074             : template <typename V>
    1075             : static inline V ByteReverse(V value) {
    1076             :   size_t size_of_v = sizeof(value);
    1077             :   switch (size_of_v) {
    1078             :     case 1:
    1079             :       return value;
    1080             :     case 2:
    1081             :       return static_cast<V>(ByteReverse16(static_cast<uint16_t>(value)));
    1082             :     case 4:
    1083             :       return static_cast<V>(ByteReverse32(static_cast<uint32_t>(value)));
    1084             :     case 8:
    1085             :       return static_cast<V>(ByteReverse64(static_cast<uint64_t>(value)));
    1086             :     default:
    1087             :       UNREACHABLE();
    1088             :   }
    1089             : }
    1090             : 
    1091             : V8_EXPORT_PRIVATE bool PassesFilter(Vector<const char> name,
    1092             :                                     Vector<const char> filter);
    1093             : 
    1094             : // Zap the specified area with a specific byte pattern. This currently defaults
    1095             : // to int3 on x64 and ia32. On other architectures this will produce unspecified
    1096             : // instruction sequences.
    1097             : // TODO(jgruber): Better support for other architectures.
    1098             : V8_INLINE void ZapCode(Address addr, size_t size_in_bytes) {
    1099             :   static constexpr int kZapByte = 0xCC;
    1100           0 :   std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes);
    1101             : }
    1102             : 
    1103             : }  // namespace internal
    1104             : }  // namespace v8
    1105             : 
    1106             : #endif  // V8_UTILS_H_

Generated by: LCOV version 1.10