Turn audio into a shareable video. forked from nypublicradio/audiogram

v8-internal.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. // Copyright 2018 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. #ifndef INCLUDE_V8_INTERNAL_H_
  5. #define INCLUDE_V8_INTERNAL_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <string.h>
  9. #include <type_traits>
  10. #include "v8-version.h" // NOLINT(build/include)
  11. #include "v8config.h" // NOLINT(build/include)
  12. namespace v8 {
  13. class Context;
  14. class Data;
  15. class Isolate;
  16. namespace internal {
  17. class Isolate;
  18. typedef uintptr_t Address;
  19. static const Address kNullAddress = 0;
  20. /**
  21. * Configuration of tagging scheme.
  22. */
  23. const int kApiSystemPointerSize = sizeof(void*);
  24. const int kApiDoubleSize = sizeof(double);
  25. const int kApiInt32Size = sizeof(int32_t);
  26. const int kApiInt64Size = sizeof(int64_t);
  27. // Tag information for HeapObject.
  28. const int kHeapObjectTag = 1;
  29. const int kWeakHeapObjectTag = 3;
  30. const int kHeapObjectTagSize = 2;
  31. const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
  32. // Tag information for Smi.
  33. const int kSmiTag = 0;
  34. const int kSmiTagSize = 1;
  35. const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
  36. template <size_t tagged_ptr_size>
  37. struct SmiTagging;
  38. constexpr intptr_t kIntptrAllBitsSet = intptr_t{-1};
  39. constexpr uintptr_t kUintptrAllBitsSet =
  40. static_cast<uintptr_t>(kIntptrAllBitsSet);
  41. // Smi constants for systems where tagged pointer is a 32-bit value.
  42. template <>
  43. struct SmiTagging<4> {
  44. enum { kSmiShiftSize = 0, kSmiValueSize = 31 };
  45. static constexpr intptr_t kSmiMinValue =
  46. static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
  47. static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
  48. V8_INLINE static int SmiToInt(const internal::Address value) {
  49. int shift_bits = kSmiTagSize + kSmiShiftSize;
  50. // Shift down (requires >> to be sign extending).
  51. return static_cast<int>(static_cast<intptr_t>(value)) >> shift_bits;
  52. }
  53. V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
  54. // Is value in range [kSmiMinValue, kSmiMaxValue].
  55. // Use unsigned operations in order to avoid undefined behaviour in case of
  56. // signed integer overflow.
  57. return (static_cast<uintptr_t>(value) -
  58. static_cast<uintptr_t>(kSmiMinValue)) <=
  59. (static_cast<uintptr_t>(kSmiMaxValue) -
  60. static_cast<uintptr_t>(kSmiMinValue));
  61. }
  62. };
  63. // Smi constants for systems where tagged pointer is a 64-bit value.
  64. template <>
  65. struct SmiTagging<8> {
  66. enum { kSmiShiftSize = 31, kSmiValueSize = 32 };
  67. static constexpr intptr_t kSmiMinValue =
  68. static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
  69. static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
  70. V8_INLINE static int SmiToInt(const internal::Address value) {
  71. int shift_bits = kSmiTagSize + kSmiShiftSize;
  72. // Shift down and throw away top 32 bits.
  73. return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits);
  74. }
  75. V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
  76. // To be representable as a long smi, the value must be a 32-bit integer.
  77. return (value == static_cast<int32_t>(value));
  78. }
  79. };
  80. #ifdef V8_COMPRESS_POINTERS
  81. static_assert(
  82. kApiSystemPointerSize == kApiInt64Size,
  83. "Pointer compression can be enabled only for 64-bit architectures");
  84. const int kApiTaggedSize = kApiInt32Size;
  85. #else
  86. const int kApiTaggedSize = kApiSystemPointerSize;
  87. #endif
  88. #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH
  89. using PlatformSmiTagging = SmiTagging<kApiInt32Size>;
  90. #else
  91. using PlatformSmiTagging = SmiTagging<kApiTaggedSize>;
  92. #endif
  93. const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
  94. const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
  95. const int kSmiMinValue = static_cast<int>(PlatformSmiTagging::kSmiMinValue);
  96. const int kSmiMaxValue = static_cast<int>(PlatformSmiTagging::kSmiMaxValue);
  97. constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; }
  98. constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; }
  99. V8_INLINE static constexpr internal::Address IntToSmi(int value) {
  100. return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) |
  101. kSmiTag;
  102. }
  103. /**
  104. * This class exports constants and functionality from within v8 that
  105. * is necessary to implement inline functions in the v8 api. Don't
  106. * depend on functions and constants defined here.
  107. */
  108. class Internals {
  109. public:
  110. // These values match non-compiler-dependent values defined within
  111. // the implementation of v8.
  112. static const int kHeapObjectMapOffset = 0;
  113. static const int kMapInstanceTypeOffset = 1 * kApiTaggedSize + kApiInt32Size;
  114. static const int kStringResourceOffset =
  115. 1 * kApiTaggedSize + 2 * kApiInt32Size;
  116. static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
  117. static const int kForeignAddressOffset = kApiTaggedSize;
  118. static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
  119. static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
  120. static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
  121. static const int kEmbedderDataSlotSize = kApiSystemPointerSize;
  122. static const int kNativeContextEmbedderDataOffset = 7 * kApiTaggedSize;
  123. static const int kFullStringRepresentationMask = 0x0f;
  124. static const int kStringEncodingMask = 0x8;
  125. static const int kExternalTwoByteRepresentationTag = 0x02;
  126. static const int kExternalOneByteRepresentationTag = 0x0a;
  127. static const uint32_t kNumIsolateDataSlots = 4;
  128. static const int kIsolateEmbedderDataOffset = 0;
  129. static const int kExternalMemoryOffset =
  130. kNumIsolateDataSlots * kApiSystemPointerSize;
  131. static const int kExternalMemoryLimitOffset =
  132. kExternalMemoryOffset + kApiInt64Size;
  133. static const int kExternalMemoryAtLastMarkCompactOffset =
  134. kExternalMemoryLimitOffset + kApiInt64Size;
  135. static const int kIsolateRootsOffset =
  136. kExternalMemoryAtLastMarkCompactOffset + kApiInt64Size;
  137. static const int kUndefinedValueRootIndex = 4;
  138. static const int kTheHoleValueRootIndex = 5;
  139. static const int kNullValueRootIndex = 6;
  140. static const int kTrueValueRootIndex = 7;
  141. static const int kFalseValueRootIndex = 8;
  142. static const int kEmptyStringRootIndex = 9;
  143. static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize;
  144. static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
  145. static const int kNodeStateMask = 0x7;
  146. static const int kNodeStateIsWeakValue = 2;
  147. static const int kNodeStateIsPendingValue = 3;
  148. static const int kNodeIsIndependentShift = 3;
  149. static const int kNodeIsActiveShift = 4;
  150. static const int kFirstNonstringType = 0x40;
  151. static const int kOddballType = 0x43;
  152. static const int kForeignType = 0x47;
  153. static const int kJSSpecialApiObjectType = 0x410;
  154. static const int kJSApiObjectType = 0x420;
  155. static const int kJSObjectType = 0x421;
  156. static const int kUndefinedOddballKind = 5;
  157. static const int kNullOddballKind = 3;
  158. // Constants used by PropertyCallbackInfo to check if we should throw when an
  159. // error occurs.
  160. static const int kThrowOnError = 0;
  161. static const int kDontThrow = 1;
  162. static const int kInferShouldThrowMode = 2;
  163. // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
  164. // incremental GC once the external memory reaches this limit.
  165. static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024;
  166. V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
  167. V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
  168. #ifdef V8_ENABLE_CHECKS
  169. CheckInitializedImpl(isolate);
  170. #endif
  171. }
  172. V8_INLINE static bool HasHeapObjectTag(const internal::Address value) {
  173. return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
  174. }
  175. V8_INLINE static int SmiValue(const internal::Address value) {
  176. return PlatformSmiTagging::SmiToInt(value);
  177. }
  178. V8_INLINE static constexpr internal::Address IntToSmi(int value) {
  179. return internal::IntToSmi(value);
  180. }
  181. V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
  182. return PlatformSmiTagging::IsValidSmi(value);
  183. }
  184. V8_INLINE static int GetInstanceType(const internal::Address obj) {
  185. typedef internal::Address A;
  186. A map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
  187. return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
  188. }
  189. V8_INLINE static int GetOddballKind(const internal::Address obj) {
  190. return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset));
  191. }
  192. V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
  193. int representation = (instance_type & kFullStringRepresentationMask);
  194. return representation == kExternalTwoByteRepresentationTag;
  195. }
  196. V8_INLINE static uint8_t GetNodeFlag(internal::Address* obj, int shift) {
  197. uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
  198. return *addr & static_cast<uint8_t>(1U << shift);
  199. }
  200. V8_INLINE static void UpdateNodeFlag(internal::Address* obj, bool value,
  201. int shift) {
  202. uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
  203. uint8_t mask = static_cast<uint8_t>(1U << shift);
  204. *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
  205. }
  206. V8_INLINE static uint8_t GetNodeState(internal::Address* obj) {
  207. uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
  208. return *addr & kNodeStateMask;
  209. }
  210. V8_INLINE static void UpdateNodeState(internal::Address* obj, uint8_t value) {
  211. uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
  212. *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
  213. }
  214. V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
  215. void* data) {
  216. internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
  217. kIsolateEmbedderDataOffset +
  218. slot * kApiSystemPointerSize;
  219. *reinterpret_cast<void**>(addr) = data;
  220. }
  221. V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
  222. uint32_t slot) {
  223. internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
  224. kIsolateEmbedderDataOffset +
  225. slot * kApiSystemPointerSize;
  226. return *reinterpret_cast<void* const*>(addr);
  227. }
  228. V8_INLINE static internal::Address* GetRoot(v8::Isolate* isolate, int index) {
  229. internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
  230. kIsolateRootsOffset +
  231. index * kApiSystemPointerSize;
  232. return reinterpret_cast<internal::Address*>(addr);
  233. }
  234. template <typename T>
  235. V8_INLINE static T ReadRawField(internal::Address heap_object_ptr,
  236. int offset) {
  237. internal::Address addr = heap_object_ptr + offset - kHeapObjectTag;
  238. #ifdef V8_COMPRESS_POINTERS
  239. if (sizeof(T) > kApiTaggedSize) {
  240. // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
  241. // fields (external pointers, doubles and BigInt data) are only
  242. // kTaggedSize aligned so we have to use unaligned pointer friendly way of
  243. // accessing them in order to avoid undefined behavior in C++ code.
  244. T r;
  245. memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T));
  246. return r;
  247. }
  248. #endif
  249. return *reinterpret_cast<const T*>(addr);
  250. }
  251. V8_INLINE static internal::Address ReadTaggedPointerField(
  252. internal::Address heap_object_ptr, int offset) {
  253. #ifdef V8_COMPRESS_POINTERS
  254. int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
  255. internal::Address root = GetRootFromOnHeapAddress(heap_object_ptr);
  256. return root + static_cast<internal::Address>(static_cast<intptr_t>(value));
  257. #else
  258. return ReadRawField<internal::Address>(heap_object_ptr, offset);
  259. #endif
  260. }
  261. V8_INLINE static internal::Address ReadTaggedSignedField(
  262. internal::Address heap_object_ptr, int offset) {
  263. #ifdef V8_COMPRESS_POINTERS
  264. int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
  265. return static_cast<internal::Address>(static_cast<intptr_t>(value));
  266. #else
  267. return ReadRawField<internal::Address>(heap_object_ptr, offset);
  268. #endif
  269. }
  270. #ifdef V8_COMPRESS_POINTERS
  271. // See v8:7703 or src/ptr-compr.* for details about pointer compression.
  272. static constexpr size_t kPtrComprHeapReservationSize = size_t{1} << 32;
  273. static constexpr size_t kPtrComprIsolateRootBias =
  274. kPtrComprHeapReservationSize / 2;
  275. static constexpr size_t kPtrComprIsolateRootAlignment = size_t{1} << 32;
  276. V8_INLINE static internal::Address GetRootFromOnHeapAddress(
  277. internal::Address addr) {
  278. return (addr + kPtrComprIsolateRootBias) &
  279. -static_cast<intptr_t>(kPtrComprIsolateRootAlignment);
  280. }
  281. V8_INLINE static internal::Address DecompressTaggedAnyField(
  282. internal::Address heap_object_ptr, int32_t value) {
  283. internal::Address root_mask = static_cast<internal::Address>(
  284. -static_cast<intptr_t>(value & kSmiTagMask));
  285. internal::Address root_or_zero =
  286. root_mask & GetRootFromOnHeapAddress(heap_object_ptr);
  287. return root_or_zero +
  288. static_cast<internal::Address>(static_cast<intptr_t>(value));
  289. }
  290. #endif // V8_COMPRESS_POINTERS
  291. };
  292. // Only perform cast check for types derived from v8::Data since
  293. // other types do not implement the Cast method.
  294. template <bool PerformCheck>
  295. struct CastCheck {
  296. template <class T>
  297. static void Perform(T* data);
  298. };
  299. template <>
  300. template <class T>
  301. void CastCheck<true>::Perform(T* data) {
  302. T::Cast(data);
  303. }
  304. template <>
  305. template <class T>
  306. void CastCheck<false>::Perform(T* data) {}
  307. template <class T>
  308. V8_INLINE void PerformCastCheck(T* data) {
  309. CastCheck<std::is_base_of<Data, T>::value>::Perform(data);
  310. }
  311. // {obj} must be the raw tagged pointer representation of a HeapObject
  312. // that's guaranteed to never be in ReadOnlySpace.
  313. V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
  314. // Returns if we need to throw when an error occurs. This infers the language
  315. // mode based on the current context and the closure. This returns true if the
  316. // language mode is strict.
  317. V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate);
  318. } // namespace internal
  319. } // namespace v8
  320. #endif // INCLUDE_V8_INTERNAL_H_