Skip to content

Commit 5dd670b

Browse files
jasnelladuh95
authored andcommitted
src: initial enablement of IsolateGroups
This lays the initial groundwork for enabling the use of IsolateGroups. Every isolate in V8 is created within a group. When pointer compression is enabled, all isolates within a single group are limited to a 4 GB shared pointer cage. By default, all isolates in the process share the same group, which means that when running with pointer compression, the entire process would be limited to a single 4 GB shared pointer cage. But, we can create as many IsolateGroups as we want, limited only by the amount of virtual memory available on the machine. PR-URL: #60254 Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Michaël Zasso <[email protected]>
1 parent 11ebb04 commit 5dd670b

File tree

8 files changed

+62
-4
lines changed

8 files changed

+62
-4
lines changed

common.gypi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@
443443
['v8_enable_pointer_compression == 1', {
444444
'defines': ['V8_COMPRESS_POINTERS'],
445445
}],
446+
['v8_enable_pointer_compression == 1 and v8_enable_pointer_compression_shared_cage != 1', {
447+
'defines': ['V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES'],
448+
}],
446449
['v8_enable_pointer_compression_shared_cage == 1', {
447450
'defines': ['V8_COMPRESS_POINTERS_IN_SHARED_CAGE'],
448451
}],

configure.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,12 @@
646646
default=None,
647647
help='[Experimental] Enable V8 pointer compression (limits max heap to 4GB and breaks ABI compatibility)')
648648

649+
parser.add_argument('--experimental-pointer-compression-shared-cage',
650+
action='store_true',
651+
dest='pointer_compression_shared_cage',
652+
default=None,
653+
help='[Experimental] Use V8 pointer compression with shared cage (requires --experimental-enable-pointer-compression)')
654+
649655
parser.add_argument('--v8-options',
650656
action='store',
651657
dest='v8_options',
@@ -1789,7 +1795,10 @@ def configure_v8(o, configs):
17891795
# Note that enabling pointer compression without enabling sandbox is unsupported by V8,
17901796
# so this can be broken at any time.
17911797
o['variables']['v8_enable_sandbox'] = 0
1792-
o['variables']['v8_enable_pointer_compression_shared_cage'] = 1 if options.enable_pointer_compression else 0
1798+
# We set v8_enable_pointer_compression_shared_cage to 0 always, even when
1799+
# pointer compression is enabled so that we don't accidentally enable shared
1800+
# cage mode when pointer compression is on.
1801+
o['variables']['v8_enable_pointer_compression_shared_cage'] = 1 if options.pointer_compression_shared_cage else 0
17931802
o['variables']['v8_enable_external_code_space'] = 1 if options.enable_pointer_compression else 0
17941803
o['variables']['v8_enable_31bit_smis_on_64bit_arch'] = 1 if options.enable_pointer_compression else 0
17951804
o['variables']['v8_enable_extensible_ro_snapshot'] = 0

src/api/embed_helpers.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "debug_utils-inl.h"
22
#include "env-inl.h"
33
#include "node.h"
4+
#include "node_internals.h"
45
#include "node_snapshot_builder.h"
56

67
using v8::Context;
@@ -127,7 +128,7 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
127128
if (flags & Flags::kIsForSnapshotting) {
128129
// The isolate must be registered before the SnapshotCreator initializes the
129130
// isolate, so that the memory reducer can be initialized.
130-
isolate = impl_->isolate = Isolate::Allocate();
131+
isolate = impl_->isolate = Isolate::Allocate(GetOrCreateIsolateGroup());
131132
platform->RegisterIsolate(isolate, loop);
132133

133134
impl_->snapshot_creator.emplace(isolate, params);

src/api/environment.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ using v8::Function;
3737
using v8::FunctionCallbackInfo;
3838
using v8::HandleScope;
3939
using v8::Isolate;
40+
using v8::IsolateGroup;
4041
using v8::Just;
4142
using v8::JustVoid;
4243
using v8::Local;
@@ -304,14 +305,26 @@ void SetIsolateUpForNode(v8::Isolate* isolate) {
304305
SetIsolateUpForNode(isolate, settings);
305306
}
306307

308+
//
309+
IsolateGroup GetOrCreateIsolateGroup() {
310+
// When pointer compression is disabled, we cannot create new groups,
311+
// in which case we'll always return the default.
312+
if (IsolateGroup::CanCreateNewGroups()) {
313+
return IsolateGroup::Create();
314+
}
315+
316+
return IsolateGroup::GetDefault();
317+
}
318+
307319
// TODO(joyeecheung): we may want to expose this, but then we need to be
308320
// careful about what we override in the params.
309321
Isolate* NewIsolate(Isolate::CreateParams* params,
310322
uv_loop_t* event_loop,
311323
MultiIsolatePlatform* platform,
312324
const SnapshotData* snapshot_data,
313325
const IsolateSettings& settings) {
314-
Isolate* isolate = Isolate::Allocate();
326+
IsolateGroup group = GetOrCreateIsolateGroup();
327+
Isolate* isolate = Isolate::Allocate(group);
315328
if (isolate == nullptr) return nullptr;
316329

317330
if (snapshot_data != nullptr) {

src/node_internals.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ extern uint64_t node_start_time;
5656
// Forward declaration
5757
class Environment;
5858

59+
static constexpr uint64_t kMaxPointerCompressionHeap = uint64_t{1}
60+
<< 32; // 4 GiB
61+
5962
// Convert a struct sockaddr to a { address: '1.2.3.4', port: 1234 } JS object.
6063
// Sets address and port properties on the info object and returns it.
6164
// If |info| is omitted, a new object is returned.
@@ -342,6 +345,20 @@ void TraceEnvVar(Environment* env,
342345
v8::Local<v8::String> key);
343346

344347
void DefineZlibConstants(v8::Local<v8::Object> target);
348+
349+
// If creating new v8::IsolateGroup instance is supported, this returns a
350+
// new instance. Otherwise, it returns the default instance.
351+
//
352+
// An IsolateGroup is a collection of Isolates that share the same underlying
353+
// pointer cage when pointer compression is enabled. When pointer compression is
354+
// disabled, there is a default IsolateGroup that is used for all isolates, and
355+
// when pointer compression is enabled, all isolates in the app share the
356+
// same pointer cage by default that is limited a maximum of 4GB, not counting
357+
// array buffers and off-heap storage. Multiple IsolateGroups can be used to
358+
// work around the 4GB limit, but each group reserves a range of virtual memory
359+
// addresses, so this should be used with care.
360+
v8::IsolateGroup GetOrCreateIsolateGroup();
361+
345362
v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params,
346363
uv_loop_t* event_loop,
347364
MultiIsolatePlatform* platform,

src/node_options.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,15 @@ void PerIsolateOptions::HandleMaxOldSpaceSizePercentage(
128128
}
129129

130130
// Get available memory in bytes
131+
#ifdef V8_COMPRESS_POINTERS
132+
// When pointer compression is enabled, V8 uses a 4 GiB heap limit.
133+
// We'll use the smaller of that or the total system memory as
134+
// reported by uv.
135+
uint64_t total_memory =
136+
std::min(uv_get_total_memory(), kMaxPointerCompressionHeap); // 4 GiB
137+
#else
131138
uint64_t total_memory = uv_get_total_memory();
139+
#endif
132140
uint64_t constrained_memory = uv_get_constrained_memory();
133141

134142
// Use constrained memory if available, otherwise use total memory

test/parallel/test-max-old-space-size-percentage.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ assert(
122122
);
123123

124124
// Validate heap sizes against system memory
125-
const totalMemoryMB = Math.floor(os.totalmem() / 1024 / 1024);
125+
// When pointer compression is enabled, the maximum total memory is 4 GB
126+
const totalmem = Math.floor(os.totalmem() / 1024 / 1024);
127+
const totalMemoryMB = process.config.variables.v8_enable_pointer_compression ?
128+
Math.min(4096, totalmem) :
129+
totalmem;
126130
const uint64Max = 2 ** 64 - 1;
127131
const constrainedMemory = process.constrainedMemory();
128132
const constrainedMemoryMB = Math.floor(constrainedMemory / 1024 / 1024);

tools/v8_gypfiles/features.gypi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@
355355
['v8_enable_pointer_compression==1', {
356356
'defines': ['V8_COMPRESS_POINTERS'],
357357
}],
358+
['v8_enable_pointer_compression==1 and v8_enable_pointer_compression_shared_cage!=1', {
359+
'defines': ['V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES'],
360+
}],
358361
['v8_enable_pointer_compression_shared_cage==1', {
359362
'defines': ['V8_COMPRESS_POINTERS_IN_SHARED_CAGE'],
360363
}],

0 commit comments

Comments
 (0)