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.
- package/CHANGELOG.md +132 -1597
- package/README.md +11 -16
- package/bin/node +0 -0
- package/include/node/common.gypi +1 -1
- package/include/node/config.gypi +251 -248
- package/include/node/cppgc/common.h +0 -1
- package/include/node/node.h +96 -10
- package/include/node/node_version.h +3 -3
- package/include/node/v8-callbacks.h +19 -5
- package/include/node/v8-context.h +12 -8
- package/include/node/v8-date.h +5 -0
- package/include/node/v8-embedder-heap.h +8 -3
- package/include/node/v8-exception.h +1 -1
- package/include/node/v8-function.h +8 -0
- package/include/node/v8-initialization.h +23 -49
- package/include/node/v8-internal.h +312 -123
- package/include/node/v8-isolate.h +26 -42
- package/include/node/v8-local-handle.h +5 -5
- package/include/node/v8-locker.h +0 -11
- package/include/node/v8-maybe.h +24 -1
- package/include/node/v8-message.h +2 -4
- package/include/node/v8-microtask-queue.h +1 -1
- package/include/node/v8-object.h +8 -15
- package/include/node/v8-persistent-handle.h +0 -2
- package/include/node/v8-platform.h +54 -25
- package/include/node/v8-primitive.h +8 -8
- package/include/node/v8-profiler.h +84 -22
- package/include/node/v8-regexp.h +2 -1
- package/include/node/v8-script.h +62 -6
- package/include/node/v8-template.h +13 -76
- package/include/node/v8-value-serializer.h +46 -23
- package/include/node/v8-version.h +3 -3
- package/include/node/v8-wasm.h +5 -62
- package/include/node/v8-weak-callback-info.h +0 -7
- package/include/node/v8config.h +247 -13
- package/package.json +1 -1
- package/share/doc/node/gdbinit +9 -1
- package/share/man/man1/node.1 +13 -6
- 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
|
|
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
|
-
|
|
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
|
-
//
|
|
250
|
-
|
|
251
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
#
|
|
280
|
-
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
//
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
//
|
|
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
|
-
//
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
|
|
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
|
-
|
|
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
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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
|
|
358
|
-
static const int
|
|
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 =
|
|
369
|
-
static const int kBuiltinTier0TableSize =
|
|
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
|
|
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 =
|
|
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
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
-
|
|
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
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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 =
|
|
844
|
+
constexpr int kGarbageCollectionReasonMaxValue = 27;
|
|
656
845
|
|
|
657
846
|
} // namespace internal
|
|
658
847
|
|