node-linux-arm64 18.10.0 → 19.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +132 -1597
  2. package/README.md +11 -16
  3. package/bin/node +0 -0
  4. package/include/node/common.gypi +1 -1
  5. package/include/node/config.gypi +251 -248
  6. package/include/node/cppgc/common.h +0 -1
  7. package/include/node/node.h +96 -10
  8. package/include/node/node_version.h +3 -3
  9. package/include/node/v8-callbacks.h +19 -5
  10. package/include/node/v8-context.h +12 -8
  11. package/include/node/v8-date.h +5 -0
  12. package/include/node/v8-embedder-heap.h +8 -3
  13. package/include/node/v8-exception.h +1 -1
  14. package/include/node/v8-function.h +8 -0
  15. package/include/node/v8-initialization.h +23 -49
  16. package/include/node/v8-internal.h +312 -123
  17. package/include/node/v8-isolate.h +26 -42
  18. package/include/node/v8-local-handle.h +5 -5
  19. package/include/node/v8-locker.h +0 -11
  20. package/include/node/v8-maybe.h +24 -1
  21. package/include/node/v8-message.h +2 -4
  22. package/include/node/v8-microtask-queue.h +1 -1
  23. package/include/node/v8-object.h +8 -15
  24. package/include/node/v8-persistent-handle.h +0 -2
  25. package/include/node/v8-platform.h +54 -25
  26. package/include/node/v8-primitive.h +8 -8
  27. package/include/node/v8-profiler.h +84 -22
  28. package/include/node/v8-regexp.h +2 -1
  29. package/include/node/v8-script.h +62 -6
  30. package/include/node/v8-template.h +13 -76
  31. package/include/node/v8-value-serializer.h +46 -23
  32. package/include/node/v8-version.h +3 -3
  33. package/include/node/v8-wasm.h +5 -62
  34. package/include/node/v8-weak-callback-info.h +0 -7
  35. package/include/node/v8config.h +247 -13
  36. package/package.json +1 -1
  37. package/share/doc/node/gdbinit +9 -1
  38. package/share/man/man1/node.1 +13 -6
  39. package/share/systemtap/tapset/node.stp +0 -146
@@ -8,6 +8,8 @@
8
8
  #include <stddef.h>
9
9
  #include <stdint.h>
10
10
  #include <string.h>
11
+
12
+ #include <atomic>
11
13
  #include <type_traits>
12
14
 
13
15
  #include "v8-version.h" // NOLINT(build/include_directory)
@@ -50,6 +52,7 @@ const int kHeapObjectTag = 1;
50
52
  const int kWeakHeapObjectTag = 3;
51
53
  const int kHeapObjectTagSize = 2;
52
54
  const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
55
+ const intptr_t kHeapObjectReferenceTagMask = 1 << (kHeapObjectTagSize - 1);
53
56
 
54
57
  // Tag information for fowarding pointers stored in object headers.
55
58
  // 0b00 at the lowest 2 bits in the header indicates that the map word is a
@@ -157,15 +160,7 @@ V8_INLINE static constexpr internal::Address IntToSmi(int value) {
157
160
  * Sandbox related types, constants, and functions.
158
161
  */
159
162
  constexpr bool SandboxIsEnabled() {
160
- #ifdef V8_SANDBOX
161
- return true;
162
- #else
163
- return false;
164
- #endif
165
- }
166
-
167
- constexpr bool SandboxedExternalPointersAreEnabled() {
168
- #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
163
+ #ifdef V8_ENABLE_SANDBOX
169
164
  return true;
170
165
  #else
171
166
  return false;
@@ -176,19 +171,18 @@ constexpr bool SandboxedExternalPointersAreEnabled() {
176
171
  // for example by storing them as offset rather than as raw pointers.
177
172
  using SandboxedPointer_t = Address;
178
173
 
179
- // ExternalPointers point to objects located outside the sandbox. When sandboxed
180
- // external pointers are enabled, these are stored in an external pointer table
181
- // and referenced from HeapObjects through indices.
182
- #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
183
- using ExternalPointer_t = uint32_t;
184
- #else
185
- using ExternalPointer_t = Address;
186
- #endif
187
-
188
- #ifdef V8_SANDBOX_IS_AVAILABLE
174
+ #ifdef V8_ENABLE_SANDBOX
189
175
 
190
176
  // Size of the sandbox, excluding the guard regions surrounding it.
177
+ #ifdef V8_TARGET_OS_ANDROID
178
+ // On Android, most 64-bit devices seem to be configured with only 39 bits of
179
+ // virtual address space for userspace. As such, limit the sandbox to 128GB (a
180
+ // quarter of the total available address space).
181
+ constexpr size_t kSandboxSizeLog2 = 37; // 128 GB
182
+ #else
183
+ // Everywhere else use a 1TB sandbox.
191
184
  constexpr size_t kSandboxSizeLog2 = 40; // 1 TB
185
+ #endif // V8_OS_ANDROID
192
186
  constexpr size_t kSandboxSize = 1ULL << kSandboxSizeLog2;
193
187
 
194
188
  // Required alignment of the sandbox. For simplicity, we require the
@@ -213,20 +207,6 @@ static_assert((kSandboxGuardRegionSize % kSandboxAlignment) == 0,
213
207
  "The size of the guard regions around the sandbox must be a "
214
208
  "multiple of its required alignment.");
215
209
 
216
- // Minimum size of the sandbox, excluding the guard regions surrounding it. If
217
- // the virtual memory reservation for the sandbox fails, its size is currently
218
- // halved until either the reservation succeeds or the minimum size is reached.
219
- // A minimum of 32GB allows the 4GB pointer compression region as well as the
220
- // ArrayBuffer partition and two 10GB Wasm memory cages to fit into the
221
- // sandbox. 32GB should also be the minimum possible size of the userspace
222
- // address space as there are some machine configurations with only 36 virtual
223
- // address bits.
224
- constexpr size_t kSandboxMinimumSize = 32ULL * GB;
225
-
226
- static_assert(kSandboxMinimumSize <= kSandboxSize,
227
- "The minimal size of the sandbox must be smaller or equal to the "
228
- "regular size.");
229
-
230
210
  // On OSes where reserving virtual memory is too expensive to reserve the
231
211
  // entire address space backing the sandbox, notably Windows pre 8.1, we create
232
212
  // a partially reserved sandbox that doesn't actually reserve most of the
@@ -239,82 +219,253 @@ static_assert(kSandboxMinimumSize <= kSandboxSize,
239
219
  // well as the ArrayBuffer partition.
240
220
  constexpr size_t kSandboxMinimumReservationSize = 8ULL * GB;
241
221
 
242
- static_assert(kSandboxMinimumSize > kPtrComprCageReservationSize,
243
- "The sandbox must be larger than the pointer compression cage "
244
- "contained within it.");
245
222
  static_assert(kSandboxMinimumReservationSize > kPtrComprCageReservationSize,
246
223
  "The minimum reservation size for a sandbox must be larger than "
247
224
  "the pointer compression cage contained within it.");
248
225
 
249
- // For now, even if the sandbox is enabled, we still allow backing stores to be
250
- // allocated outside of it as fallback. This will simplify the initial rollout.
251
- // However, if sandboxed pointers are also enabled, we must always place
252
- // backing stores inside the sandbox as they will be referenced though them.
253
- #ifdef V8_SANDBOXED_POINTERS
254
- constexpr bool kAllowBackingStoresOutsideSandbox = false;
255
- #else
256
- constexpr bool kAllowBackingStoresOutsideSandbox = true;
257
- #endif // V8_SANDBOXED_POINTERS
226
+ #endif // V8_ENABLE_SANDBOX
227
+
228
+ #ifdef V8_COMPRESS_POINTERS
258
229
 
259
230
  // The size of the virtual memory reservation for an external pointer table.
260
231
  // This determines the maximum number of entries in a table. Using a maximum
261
232
  // size allows omitting bounds checks on table accesses if the indices are
262
233
  // guaranteed (e.g. through shifting) to be below the maximum index. This
263
234
  // value must be a power of two.
264
- static const size_t kExternalPointerTableReservationSize = 128 * MB;
235
+ static const size_t kExternalPointerTableReservationSize = 512 * MB;
265
236
 
266
237
  // The maximum number of entries in an external pointer table.
267
- static const size_t kMaxSandboxedExternalPointers =
238
+ static const size_t kMaxExternalPointers =
268
239
  kExternalPointerTableReservationSize / kApiSystemPointerSize;
269
240
 
270
241
  // The external pointer table indices stored in HeapObjects as external
271
242
  // pointers are shifted to the left by this amount to guarantee that they are
272
243
  // smaller than the maximum table size.
273
- static const uint32_t kExternalPointerIndexShift = 8;
274
- static_assert((1 << (32 - kExternalPointerIndexShift)) ==
275
- kMaxSandboxedExternalPointers,
244
+ static const uint32_t kExternalPointerIndexShift = 6;
245
+ static_assert((1 << (32 - kExternalPointerIndexShift)) == kMaxExternalPointers,
276
246
  "kExternalPointerTableReservationSize and "
277
247
  "kExternalPointerIndexShift don't match");
278
248
 
279
- #endif // V8_SANDBOX_IS_AVAILABLE
280
-
281
- // If sandboxed external pointers are enabled, these tag values will be ORed
282
- // with the external pointers in the external pointer table to prevent use of
283
- // pointers of the wrong type. When a pointer is loaded, it is ANDed with the
284
- // inverse of the expected type's tag. The tags are constructed in a way that
285
- // guarantees that a failed type check will result in one or more of the top
286
- // bits of the pointer to be set, rendering the pointer inacessible. Besides
287
- // the type tag bits (48 through 62), the tags also have the GC mark bit (63)
288
- // set, so that the mark bit is automatically set when a pointer is written
289
- // into the external pointer table (in which case it is clearly alive) and is
290
- // cleared when the pointer is loaded. The exception to this is the free entry
291
- // tag, which doesn't have the mark bit set, as the entry is not alive. This
249
+ #else // !V8_COMPRESS_POINTERS
250
+
251
+ // Needed for the V8.SandboxedExternalPointersCount histogram.
252
+ static const size_t kMaxExternalPointers = 0;
253
+
254
+ #endif // V8_COMPRESS_POINTERS
255
+
256
+ // A ExternalPointerHandle represents a (opaque) reference to an external
257
+ // pointer that can be stored inside the sandbox. A ExternalPointerHandle has
258
+ // meaning only in combination with an (active) Isolate as it references an
259
+ // external pointer stored in the currently active Isolate's
260
+ // ExternalPointerTable. Internally, an ExternalPointerHandles is simply an
261
+ // index into an ExternalPointerTable that is shifted to the left to guarantee
262
+ // that it is smaller than the size of the table.
263
+ using ExternalPointerHandle = uint32_t;
264
+
265
+ // ExternalPointers point to objects located outside the sandbox. When
266
+ // sandboxed external pointers are enabled, these are stored on heap as
267
+ // ExternalPointerHandles, otherwise they are simply raw pointers.
268
+ #ifdef V8_ENABLE_SANDBOX
269
+ using ExternalPointer_t = ExternalPointerHandle;
270
+ #else
271
+ using ExternalPointer_t = Address;
272
+ #endif
273
+
274
+ // When the sandbox is enabled, external pointers are stored in an external
275
+ // pointer table and are referenced from HeapObjects through an index (a
276
+ // "handle"). When stored in the table, the pointers are tagged with per-type
277
+ // tags to prevent type confusion attacks between different external objects.
278
+ // Besides type information bits, these tags also contain the GC marking bit
279
+ // which indicates whether the pointer table entry is currently alive. When a
280
+ // pointer is written into the table, the tag is ORed into the top bits. When
281
+ // that pointer is later loaded from the table, it is ANDed with the inverse of
282
+ // the expected tag. If the expected and actual type differ, this will leave
283
+ // some of the top bits of the pointer set, rendering the pointer inaccessible.
284
+ // The AND operation also removes the GC marking bit from the pointer.
285
+ //
286
+ // The tags are constructed such that UNTAG(TAG(0, T1), T2) != 0 for any two
287
+ // (distinct) tags T1 and T2. In practice, this is achieved by generating tags
288
+ // that all have the same number of zeroes and ones but different bit patterns.
289
+ // With N type tag bits, this allows for (N choose N/2) possible type tags.
290
+ // Besides the type tag bits, the tags also have the GC marking bit set so that
291
+ // the marking bit is automatically set when a pointer is written into the
292
+ // external pointer table (in which case it is clearly alive) and is cleared
293
+ // when the pointer is loaded. The exception to this is the free entry tag,
294
+ // which doesn't have the mark bit set, as the entry is not alive. This
292
295
  // construction allows performing the type check and removing GC marking bits
293
- // (the MSB) from the pointer at the same time.
294
- // Note: this scheme assumes a 48-bit address space and will likely break if
295
- // more virtual address bits are used.
296
- constexpr uint64_t kExternalPointerTagMask = 0xffff000000000000;
296
+ // from the pointer in one efficient operation (bitwise AND). The number of
297
+ // available bits is limited in the following way: on x64, bits [47, 64) are
298
+ // generally available for tagging (userspace has 47 address bits available).
299
+ // On Arm64, userspace typically has a 40 or 48 bit address space. However, due
300
+ // to top-byte ignore (TBI) and memory tagging (MTE), the top byte is unusable
301
+ // for type checks as type-check failures would go unnoticed or collide with
302
+ // MTE bits. Some bits of the top byte can, however, still be used for the GC
303
+ // marking bit. The bits available for the type tags are therefore limited to
304
+ // [48, 56), i.e. (8 choose 4) = 70 different types.
305
+ // The following options exist to increase the number of possible types:
306
+ // - Using multiple ExternalPointerTables since tags can safely be reused
307
+ // across different tables
308
+ // - Using "extended" type checks, where additional type information is stored
309
+ // either in an adjacent pointer table entry or at the pointed-to location
310
+ // - Using a different tagging scheme, for example based on XOR which would
311
+ // allow for 2**8 different tags but require a separate operation to remove
312
+ // the marking bit
313
+ //
314
+ // The external pointer sandboxing mechanism ensures that every access to an
315
+ // external pointer field will result in a valid pointer of the expected type
316
+ // even in the presence of an attacker able to corrupt memory inside the
317
+ // sandbox. However, if any data related to the external object is stored
318
+ // inside the sandbox it may still be corrupted and so must be validated before
319
+ // use or moved into the external object. Further, an attacker will always be
320
+ // able to substitute different external pointers of the same type for each
321
+ // other. Therefore, code using external pointers must be written in a
322
+ // "substitution-safe" way, i.e. it must always be possible to substitute
323
+ // external pointers of the same type without causing memory corruption outside
324
+ // of the sandbox. Generally this is achieved by referencing any group of
325
+ // related external objects through a single external pointer.
326
+ //
327
+ // Currently we use bit 62 for the marking bit which should always be unused as
328
+ // it's part of the non-canonical address range. When Arm's top-byte ignore
329
+ // (TBI) is enabled, this bit will be part of the ignored byte, and we assume
330
+ // that the Embedder is not using this byte (really only this one bit) for any
331
+ // other purpose. This bit also does not collide with the memory tagging
332
+ // extension (MTE) which would use bits [56, 60).
333
+ constexpr uint64_t kExternalPointerMarkBit = 1ULL << 62;
334
+ constexpr uint64_t kExternalPointerTagMask = 0x40ff000000000000;
297
335
  constexpr uint64_t kExternalPointerTagShift = 48;
298
- #define MAKE_TAG(v) (static_cast<uint64_t>(v) << kExternalPointerTagShift)
336
+
337
+ // All possible 8-bit type tags.
338
+ // These are sorted so that tags can be grouped together and it can efficiently
339
+ // be checked if a tag belongs to a given group. See for example the
340
+ // IsSharedExternalPointerType routine.
341
+ constexpr uint64_t kAllExternalPointerTypeTags[] = {
342
+ 0b00001111, 0b00010111, 0b00011011, 0b00011101, 0b00011110, 0b00100111,
343
+ 0b00101011, 0b00101101, 0b00101110, 0b00110011, 0b00110101, 0b00110110,
344
+ 0b00111001, 0b00111010, 0b00111100, 0b01000111, 0b01001011, 0b01001101,
345
+ 0b01001110, 0b01010011, 0b01010101, 0b01010110, 0b01011001, 0b01011010,
346
+ 0b01011100, 0b01100011, 0b01100101, 0b01100110, 0b01101001, 0b01101010,
347
+ 0b01101100, 0b01110001, 0b01110010, 0b01110100, 0b01111000, 0b10000111,
348
+ 0b10001011, 0b10001101, 0b10001110, 0b10010011, 0b10010101, 0b10010110,
349
+ 0b10011001, 0b10011010, 0b10011100, 0b10100011, 0b10100101, 0b10100110,
350
+ 0b10101001, 0b10101010, 0b10101100, 0b10110001, 0b10110010, 0b10110100,
351
+ 0b10111000, 0b11000011, 0b11000101, 0b11000110, 0b11001001, 0b11001010,
352
+ 0b11001100, 0b11010001, 0b11010010, 0b11010100, 0b11011000, 0b11100001,
353
+ 0b11100010, 0b11100100, 0b11101000, 0b11110000};
354
+
299
355
  // clang-format off
356
+ // New entries should be added with state "sandboxed".
357
+ // When adding new tags, please ensure that the code using these tags is
358
+ // "substitution-safe", i.e. still operate safely if external pointers of the
359
+ // same type are swapped by an attacker. See comment above for more details.
360
+ #define TAG(i) (kAllExternalPointerTypeTags[i])
361
+
362
+ // Shared external pointers are owned by the shared Isolate and stored in the
363
+ // shared external pointer table associated with that Isolate, where they can
364
+ // be accessed from multiple threads at the same time. The objects referenced
365
+ // in this way must therefore always be thread-safe.
366
+ #define SHARED_EXTERNAL_POINTER_TAGS(V) \
367
+ V(kFirstSharedTag, sandboxed, TAG(0)) \
368
+ V(kWaiterQueueNodeTag, sandboxed, TAG(0)) \
369
+ V(kExternalStringResourceTag, sandboxed, TAG(1)) \
370
+ V(kExternalStringResourceDataTag, sandboxed, TAG(2)) \
371
+ V(kLastSharedTag, sandboxed, TAG(2))
372
+
373
+ // External pointers using these tags are kept in a per-Isolate external
374
+ // pointer table and can only be accessed when this Isolate is active.
375
+ #define PER_ISOLATE_EXTERNAL_POINTER_TAGS(V) \
376
+ V(kForeignForeignAddressTag, sandboxed, TAG(10)) \
377
+ V(kNativeContextMicrotaskQueueTag, sandboxed, TAG(11)) \
378
+ V(kEmbedderDataSlotPayloadTag, sandboxed, TAG(12)) \
379
+ V(kExternalObjectValueTag, sandboxed, TAG(13)) \
380
+ V(kCallHandlerInfoCallbackTag, sandboxed, TAG(14)) \
381
+ V(kAccessorInfoGetterTag, sandboxed, TAG(15)) \
382
+ V(kAccessorInfoSetterTag, sandboxed, TAG(16)) \
383
+ V(kWasmInternalFunctionCallTargetTag, sandboxed, TAG(17)) \
384
+ V(kWasmTypeInfoNativeTypeTag, sandboxed, TAG(18)) \
385
+ V(kWasmExportedFunctionDataSignatureTag, sandboxed, TAG(19)) \
386
+ V(kWasmContinuationJmpbufTag, sandboxed, TAG(20))
387
+
388
+ // All external pointer tags.
389
+ #define ALL_EXTERNAL_POINTER_TAGS(V) \
390
+ SHARED_EXTERNAL_POINTER_TAGS(V) \
391
+ PER_ISOLATE_EXTERNAL_POINTER_TAGS(V)
392
+
393
+ // When the sandbox is enabled, external pointers marked as "sandboxed" above
394
+ // use the external pointer table (i.e. are sandboxed). This allows a gradual
395
+ // rollout of external pointer sandboxing. If the sandbox is off, no external
396
+ // pointers are sandboxed.
397
+ //
398
+ // Sandboxed external pointer tags are available when compressing pointers even
399
+ // when the sandbox is off. Some tags (e.g. kWaiterQueueNodeTag) are used
400
+ // manually with the external pointer table even when the sandbox is off to ease
401
+ // alignment requirements.
402
+ #define sandboxed(X) (X << kExternalPointerTagShift) | kExternalPointerMarkBit
403
+ #define unsandboxed(X) kUnsandboxedExternalPointerTag
404
+ #if defined(V8_COMPRESS_POINTERS)
405
+ #define EXTERNAL_POINTER_TAG_ENUM(Name, State, Bits) Name = State(Bits),
406
+ #else
407
+ #define EXTERNAL_POINTER_TAG_ENUM(Name, State, Bits) Name = unsandboxed(Bits),
408
+ #endif
409
+
410
+ #define MAKE_TAG(HasMarkBit, TypeTag) \
411
+ ((static_cast<uint64_t>(TypeTag) << kExternalPointerTagShift) | \
412
+ (HasMarkBit ? kExternalPointerMarkBit : 0))
300
413
  enum ExternalPointerTag : uint64_t {
301
- kExternalPointerNullTag = MAKE_TAG(0b0000000000000000),
302
- kExternalPointerFreeEntryTag = MAKE_TAG(0b0111111110000000),
303
- kExternalStringResourceTag = MAKE_TAG(0b1000000011111111),
304
- kExternalStringResourceDataTag = MAKE_TAG(0b1000000101111111),
305
- kForeignForeignAddressTag = MAKE_TAG(0b1000000110111111),
306
- kNativeContextMicrotaskQueueTag = MAKE_TAG(0b1000000111011111),
307
- kEmbedderDataSlotPayloadTag = MAKE_TAG(0b1000000111101111),
308
- kCodeEntryPointTag = MAKE_TAG(0b1000000111110111),
309
- kExternalObjectValueTag = MAKE_TAG(0b1000000111111011),
414
+ // Empty tag value. Mostly used as placeholder.
415
+ kExternalPointerNullTag = MAKE_TAG(0, 0b00000000),
416
+ // Tag to use for unsandboxed external pointers, which are still stored as
417
+ // raw pointers on the heap.
418
+ kUnsandboxedExternalPointerTag = MAKE_TAG(0, 0b00000000),
419
+ // External pointer tag that will match any external pointer. Use with care!
420
+ kAnyExternalPointerTag = MAKE_TAG(1, 0b11111111),
421
+ // The free entry tag has all type bits set so every type check with a
422
+ // different type fails. It also doesn't have the mark bit set as free
423
+ // entries are (by definition) not alive.
424
+ kExternalPointerFreeEntryTag = MAKE_TAG(0, 0b11111111),
425
+ // Evacuation entries are used during external pointer table compaction.
426
+ kExternalPointerEvacuationEntryTag = MAKE_TAG(1, 0b11100111),
427
+
428
+ ALL_EXTERNAL_POINTER_TAGS(EXTERNAL_POINTER_TAG_ENUM)
310
429
  };
311
- // clang-format on
430
+
312
431
  #undef MAKE_TAG
432
+ #undef unsandboxed
433
+ #undef sandboxed
434
+ #undef TAG
435
+ #undef EXTERNAL_POINTER_TAG_ENUM
436
+
437
+ // clang-format on
438
+
439
+ // True if the external pointer is sandboxed and so must be referenced through
440
+ // an external pointer table.
441
+ V8_INLINE static constexpr bool IsSandboxedExternalPointerType(
442
+ ExternalPointerTag tag) {
443
+ return tag != kUnsandboxedExternalPointerTag;
444
+ }
313
445
 
314
- // Converts encoded external pointer to address.
315
- V8_EXPORT Address DecodeExternalPointerImpl(const Isolate* isolate,
316
- ExternalPointer_t pointer,
317
- ExternalPointerTag tag);
446
+ // True if the external pointer must be accessed from the shared isolate's
447
+ // external pointer table.
448
+ V8_INLINE static constexpr bool IsSharedExternalPointerType(
449
+ ExternalPointerTag tag) {
450
+ return tag >= kFirstSharedTag && tag <= kLastSharedTag;
451
+ }
452
+
453
+ // Sanity checks.
454
+ #define CHECK_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
455
+ static_assert(!IsSandboxedExternalPointerType(Tag) || \
456
+ IsSharedExternalPointerType(Tag));
457
+ #define CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
458
+ static_assert(!IsSandboxedExternalPointerType(Tag) || \
459
+ !IsSharedExternalPointerType(Tag));
460
+
461
+ SHARED_EXTERNAL_POINTER_TAGS(CHECK_SHARED_EXTERNAL_POINTER_TAGS)
462
+ PER_ISOLATE_EXTERNAL_POINTER_TAGS(CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS)
463
+
464
+ #undef CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS
465
+ #undef CHECK_SHARED_EXTERNAL_POINTER_TAGS
466
+
467
+ #undef SHARED_EXTERNAL_POINTER_TAGS
468
+ #undef EXTERNAL_POINTER_TAGS
318
469
 
319
470
  // {obj} must be the raw tagged pointer representation of a HeapObject
320
471
  // that's guaranteed to never be in ReadOnlySpace.
@@ -324,9 +475,6 @@ V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
324
475
  // mode based on the current context and the closure. This returns true if the
325
476
  // language mode is strict.
326
477
  V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate);
327
-
328
- V8_EXPORT bool CanHaveInternalField(int instance_type);
329
-
330
478
  /**
331
479
  * This class exports constants and functionality from within v8 that
332
480
  * is necessary to implement inline functions in the v8 api. Don't
@@ -354,8 +502,10 @@ class Internals {
354
502
  static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
355
503
  static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
356
504
  static const int kEmbedderDataSlotSize = kApiSystemPointerSize;
357
- #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
358
- static const int kEmbedderDataSlotRawPayloadOffset = kApiTaggedSize;
505
+ #ifdef V8_ENABLE_SANDBOX
506
+ static const int kEmbedderDataSlotExternalPointerOffset = kApiTaggedSize;
507
+ #else
508
+ static const int kEmbedderDataSlotExternalPointerOffset = 0;
359
509
  #endif
360
510
  static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize;
361
511
  static const int kStringRepresentationAndEncodingMask = 0x0f;
@@ -365,15 +515,21 @@ class Internals {
365
515
 
366
516
  static const uint32_t kNumIsolateDataSlots = 4;
367
517
  static const int kStackGuardSize = 7 * kApiSystemPointerSize;
368
- static const int kBuiltinTier0EntryTableSize = 10 * kApiSystemPointerSize;
369
- static const int kBuiltinTier0TableSize = 10 * kApiSystemPointerSize;
518
+ static const int kBuiltinTier0EntryTableSize = 7 * kApiSystemPointerSize;
519
+ static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize;
520
+
521
+ // ExternalPointerTable layout guarantees.
522
+ static const int kExternalPointerTableBufferOffset = 0;
523
+ static const int kExternalPointerTableSize = 4 * kApiSystemPointerSize;
370
524
 
371
525
  // IsolateData layout guarantees.
372
526
  static const int kIsolateCageBaseOffset = 0;
373
527
  static const int kIsolateStackGuardOffset =
374
528
  kIsolateCageBaseOffset + kApiSystemPointerSize;
375
- static const int kBuiltinTier0EntryTableOffset =
529
+ static const int kVariousBooleanFlagsOffset =
376
530
  kIsolateStackGuardOffset + kStackGuardSize;
531
+ static const int kBuiltinTier0EntryTableOffset =
532
+ kVariousBooleanFlagsOffset + kApiSystemPointerSize;
377
533
  static const int kBuiltinTier0TableOffset =
378
534
  kBuiltinTier0EntryTableOffset + kBuiltinTier0EntryTableSize;
379
535
  static const int kIsolateEmbedderDataOffset =
@@ -386,14 +542,17 @@ class Internals {
386
542
  kIsolateFastCCallCallerPcOffset + kApiSystemPointerSize;
387
543
  static const int kIsolateLongTaskStatsCounterOffset =
388
544
  kIsolateFastApiCallTargetOffset + kApiSystemPointerSize;
545
+ #ifdef V8_COMPRESS_POINTERS
546
+ static const int kIsolateExternalPointerTableOffset =
547
+ kIsolateLongTaskStatsCounterOffset + kApiSizetSize;
548
+ static const int kIsolateSharedExternalPointerTableAddressOffset =
549
+ kIsolateExternalPointerTableOffset + kExternalPointerTableSize;
550
+ static const int kIsolateRootsOffset =
551
+ kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
552
+ #else
389
553
  static const int kIsolateRootsOffset =
390
554
  kIsolateLongTaskStatsCounterOffset + kApiSizetSize;
391
-
392
- static const int kExternalPointerTableBufferOffset = 0;
393
- static const int kExternalPointerTableCapacityOffset =
394
- kExternalPointerTableBufferOffset + kApiSystemPointerSize;
395
- static const int kExternalPointerTableFreelistHeadOffset =
396
- kExternalPointerTableCapacityOffset + kApiInt32Size;
555
+ #endif
397
556
 
398
557
  static const int kUndefinedValueRootIndex = 4;
399
558
  static const int kTheHoleValueRootIndex = 5;
@@ -404,9 +563,8 @@ class Internals {
404
563
 
405
564
  static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize;
406
565
  static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
407
- static const int kNodeStateMask = 0x7;
566
+ static const int kNodeStateMask = 0x3;
408
567
  static const int kNodeStateIsWeakValue = 2;
409
- static const int kNodeStateIsPendingValue = 3;
410
568
 
411
569
  static const int kFirstNonstringType = 0x80;
412
570
  static const int kOddballType = 0x83;
@@ -481,6 +639,18 @@ class Internals {
481
639
  return representation == kExternalTwoByteRepresentationTag;
482
640
  }
483
641
 
642
+ V8_INLINE static constexpr bool CanHaveInternalField(int instance_type) {
643
+ static_assert(kJSObjectType + 1 == kFirstJSApiObjectType);
644
+ static_assert(kJSObjectType < kLastJSApiObjectType);
645
+ static_assert(kFirstJSApiObjectType < kLastJSApiObjectType);
646
+ // Check for IsJSObject() || IsJSSpecialApiObject() || IsJSApiObject()
647
+ return instance_type == kJSSpecialApiObjectType ||
648
+ // inlined version of base::IsInRange
649
+ (static_cast<unsigned>(static_cast<unsigned>(instance_type) -
650
+ static_cast<unsigned>(kJSObjectType)) <=
651
+ static_cast<unsigned>(kLastJSApiObjectType - kJSObjectType));
652
+ }
653
+
484
654
  V8_INLINE static uint8_t GetNodeFlag(internal::Address* obj, int shift) {
485
655
  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
486
656
  return *addr & static_cast<uint8_t>(1U << shift);
@@ -532,6 +702,25 @@ class Internals {
532
702
  return reinterpret_cast<internal::Address*>(addr);
533
703
  }
534
704
 
705
+ #ifdef V8_ENABLE_SANDBOX
706
+ V8_INLINE static internal::Address* GetExternalPointerTableBase(
707
+ v8::Isolate* isolate) {
708
+ internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
709
+ kIsolateExternalPointerTableOffset +
710
+ kExternalPointerTableBufferOffset;
711
+ return *reinterpret_cast<internal::Address**>(addr);
712
+ }
713
+
714
+ V8_INLINE static internal::Address* GetSharedExternalPointerTableBase(
715
+ v8::Isolate* isolate) {
716
+ internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
717
+ kIsolateSharedExternalPointerTableAddressOffset;
718
+ addr = *reinterpret_cast<internal::Address*>(addr);
719
+ addr += kExternalPointerTableBufferOffset;
720
+ return *reinterpret_cast<internal::Address**>(addr);
721
+ }
722
+ #endif
723
+
535
724
  template <typename T>
536
725
  V8_INLINE static T ReadRawField(internal::Address heap_object_ptr,
537
726
  int offset) {
@@ -572,38 +761,38 @@ class Internals {
572
761
  #endif
573
762
  }
574
763
 
575
- V8_INLINE static internal::Isolate* GetIsolateForSandbox(
576
- internal::Address obj) {
577
- #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
578
- return internal::IsolateFromNeverReadOnlySpaceObject(obj);
764
+ V8_INLINE static v8::Isolate* GetIsolateForSandbox(internal::Address obj) {
765
+ #ifdef V8_ENABLE_SANDBOX
766
+ return reinterpret_cast<v8::Isolate*>(
767
+ internal::IsolateFromNeverReadOnlySpaceObject(obj));
579
768
  #else
580
769
  // Not used in non-sandbox mode.
581
770
  return nullptr;
582
771
  #endif
583
772
  }
584
773
 
585
- V8_INLINE static Address DecodeExternalPointer(
586
- const Isolate* isolate, ExternalPointer_t encoded_pointer,
587
- ExternalPointerTag tag) {
588
- #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
589
- return internal::DecodeExternalPointerImpl(isolate, encoded_pointer, tag);
590
- #else
591
- return encoded_pointer;
592
- #endif
593
- }
594
-
774
+ template <ExternalPointerTag tag>
595
775
  V8_INLINE static internal::Address ReadExternalPointerField(
596
- internal::Isolate* isolate, internal::Address heap_object_ptr, int offset,
597
- ExternalPointerTag tag) {
598
- #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
599
- internal::ExternalPointer_t encoded_value =
600
- ReadRawField<uint32_t>(heap_object_ptr, offset);
601
- // We currently have to treat zero as nullptr in embedder slots.
602
- return encoded_value ? DecodeExternalPointer(isolate, encoded_value, tag)
603
- : 0;
604
- #else
605
- return ReadRawField<Address>(heap_object_ptr, offset);
776
+ v8::Isolate* isolate, internal::Address heap_object_ptr, int offset) {
777
+ #ifdef V8_ENABLE_SANDBOX
778
+ if (IsSandboxedExternalPointerType(tag)) {
779
+ // See src/sandbox/external-pointer-table-inl.h. Logic duplicated here so
780
+ // it can be inlined and doesn't require an additional call.
781
+ internal::Address* table =
782
+ IsSharedExternalPointerType(tag)
783
+ ? GetSharedExternalPointerTableBase(isolate)
784
+ : GetExternalPointerTableBase(isolate);
785
+ internal::ExternalPointerHandle handle =
786
+ ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
787
+ uint32_t index = handle >> kExternalPointerIndexShift;
788
+ std::atomic<internal::Address>* ptr =
789
+ reinterpret_cast<std::atomic<internal::Address>*>(&table[index]);
790
+ internal::Address entry =
791
+ std::atomic_load_explicit(ptr, std::memory_order_relaxed);
792
+ return entry & ~tag;
793
+ }
606
794
  #endif
795
+ return ReadRawField<Address>(heap_object_ptr, offset);
607
796
  }
608
797
 
609
798
  #ifdef V8_COMPRESS_POINTERS
@@ -652,7 +841,7 @@ class BackingStoreBase {};
652
841
 
653
842
  // The maximum value in enum GarbageCollectionReason, defined in heap.h.
654
843
  // This is needed for histograms sampling garbage collection reasons.
655
- constexpr int kGarbageCollectionReasonMaxValue = 25;
844
+ constexpr int kGarbageCollectionReasonMaxValue = 27;
656
845
 
657
846
  } // namespace internal
658
847