Skip to content
This repository was archived by the owner on Aug 31, 2018. It is now read-only.

Commit 2f47b5b

Browse files
committed
src: prepare v8 platform for multi-isolate support
This splits the task queue used for asynchronous tasks scheduled by V8 in per-isolate queues, so that multiple threads can be supported. PR-URL: #89 Reviewed-By: Timothy Gu <[email protected]>
1 parent 53b718e commit 2f47b5b

File tree

10 files changed

+268
-93
lines changed

10 files changed

+268
-93
lines changed

src/env-inl.h

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,41 +38,9 @@
3838

3939
namespace node {
4040

41-
inline IsolateData::IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop,
42-
uint32_t* zero_fill_field) :
43-
44-
// Create string and private symbol properties as internalized one byte strings.
45-
//
46-
// Internalized because it makes property lookups a little faster and because
47-
// the string is created in the old space straight away. It's going to end up
48-
// in the old space sooner or later anyway but now it doesn't go through
49-
// v8::Eternal's new space handling first.
50-
//
51-
// One byte because our strings are ASCII and we can safely skip V8's UTF-8
52-
// decoding step. It's a one-time cost, but why pay it when you don't have to?
53-
#define V(PropertyName, StringValue) \
54-
PropertyName ## _( \
55-
isolate, \
56-
v8::Private::New( \
57-
isolate, \
58-
v8::String::NewFromOneByte( \
59-
isolate, \
60-
reinterpret_cast<const uint8_t*>(StringValue), \
61-
v8::NewStringType::kInternalized, \
62-
sizeof(StringValue) - 1).ToLocalChecked())),
63-
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
64-
#undef V
65-
#define V(PropertyName, StringValue) \
66-
PropertyName ## _( \
67-
isolate, \
68-
v8::String::NewFromOneByte( \
69-
isolate, \
70-
reinterpret_cast<const uint8_t*>(StringValue), \
71-
v8::NewStringType::kInternalized, \
72-
sizeof(StringValue) - 1).ToLocalChecked()),
73-
PER_ISOLATE_STRING_PROPERTIES(V)
74-
#undef V
75-
event_loop_(event_loop), zero_fill_field_(zero_fill_field) {}
41+
inline v8::Isolate* IsolateData::isolate() const {
42+
return isolate_;
43+
}
7644

7745
inline uv_loop_t* IsolateData::event_loop() const {
7846
return event_loop_;
@@ -82,6 +50,10 @@ inline uint32_t* IsolateData::zero_fill_field() const {
8250
return zero_fill_field_;
8351
}
8452

53+
inline MultiIsolatePlatform* IsolateData::platform() const {
54+
return platform_;
55+
}
56+
8557
inline Environment::AsyncHooks::AsyncHooks(v8::Isolate* isolate)
8658
: isolate_(isolate),
8759
fields_(isolate, kFieldsCount),

src/env.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "async-wrap.h"
33
#include "v8-profiler.h"
44
#include "req-wrap-inl.h"
5+
#include "node_platform.h"
56

67
#if defined(_MSC_VER)
78
#define getpid GetCurrentProcessId
@@ -17,10 +18,62 @@ namespace node {
1718
using v8::Context;
1819
using v8::FunctionTemplate;
1920
using v8::HandleScope;
21+
using v8::Isolate;
2022
using v8::Local;
2123
using v8::Message;
24+
using v8::Private;
2225
using v8::StackFrame;
2326
using v8::StackTrace;
27+
using v8::String;
28+
29+
IsolateData::IsolateData(Isolate* isolate,
30+
uv_loop_t* event_loop,
31+
MultiIsolatePlatform* platform,
32+
uint32_t* zero_fill_field) :
33+
34+
// Create string and private symbol properties as internalized one byte strings.
35+
//
36+
// Internalized because it makes property lookups a little faster and because
37+
// the string is created in the old space straight away. It's going to end up
38+
// in the old space sooner or later anyway but now it doesn't go through
39+
// v8::Eternal's new space handling first.
40+
//
41+
// One byte because our strings are ASCII and we can safely skip V8's UTF-8
42+
// decoding step. It's a one-time cost, but why pay it when you don't have to?
43+
#define V(PropertyName, StringValue) \
44+
PropertyName ## _( \
45+
isolate, \
46+
Private::New( \
47+
isolate, \
48+
String::NewFromOneByte( \
49+
isolate, \
50+
reinterpret_cast<const uint8_t*>(StringValue), \
51+
v8::NewStringType::kInternalized, \
52+
sizeof(StringValue) - 1).ToLocalChecked())),
53+
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
54+
#undef V
55+
#define V(PropertyName, StringValue) \
56+
PropertyName ## _( \
57+
isolate, \
58+
String::NewFromOneByte( \
59+
isolate, \
60+
reinterpret_cast<const uint8_t*>(StringValue), \
61+
v8::NewStringType::kInternalized, \
62+
sizeof(StringValue) - 1).ToLocalChecked()),
63+
PER_ISOLATE_STRING_PROPERTIES(V)
64+
#undef V
65+
isolate_(isolate),
66+
event_loop_(event_loop),
67+
zero_fill_field_(zero_fill_field),
68+
platform_(platform) {
69+
if (platform_ != nullptr)
70+
platform_->RegisterIsolate(this, event_loop);
71+
}
72+
73+
IsolateData::~IsolateData() {
74+
if (platform_ != nullptr)
75+
platform_->UnregisterIsolate(this);
76+
}
2477

2578
void Environment::Start(int argc,
2679
const char* const* argv,

src/env.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,13 @@ struct node_async_ids {
338338

339339
class IsolateData {
340340
public:
341-
inline IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop,
342-
uint32_t* zero_fill_field = nullptr);
341+
IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop,
342+
MultiIsolatePlatform* platform = nullptr,
343+
uint32_t* zero_fill_field = nullptr);
344+
~IsolateData();
343345
inline uv_loop_t* event_loop() const;
344346
inline uint32_t* zero_fill_field() const;
347+
inline MultiIsolatePlatform* platform() const;
345348

346349
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
347350
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
@@ -354,6 +357,7 @@ class IsolateData {
354357
#undef VP
355358

356359
std::unordered_map<nghttp2_rcbuf*, v8::Eternal<v8::String>> http2_static_strs;
360+
inline v8::Isolate* isolate() const;
357361

358362
private:
359363
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
@@ -366,8 +370,10 @@ class IsolateData {
366370
#undef VS
367371
#undef VP
368372

373+
v8::Isolate* const isolate_;
369374
uv_loop_t* const event_loop_;
370375
uint32_t* const zero_fill_field_;
376+
MultiIsolatePlatform* platform_;
371377

372378
DISALLOW_COPY_AND_ASSIGN(IsolateData);
373379
};

src/inspector_agent.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ class NodeInspectorClient : public V8InspectorClient {
489489
terminated_ = false;
490490
running_nested_loop_ = true;
491491
while (!terminated_ && channel_->waitForFrontendMessage()) {
492-
platform_->FlushForegroundTasksInternal();
492+
platform_->FlushForegroundTasks(env_->isolate());
493493
}
494494
terminated_ = false;
495495
running_nested_loop_ = false;

src/node.cc

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,10 @@ node::DebugOptions debug_options;
261261

262262
static struct {
263263
#if NODE_USE_V8_PLATFORM
264-
void Initialize(int thread_pool_size, uv_loop_t* loop) {
264+
void Initialize(int thread_pool_size) {
265265
tracing_agent_ =
266266
trace_enabled ? new tracing::Agent() : nullptr;
267-
platform_ = new NodePlatform(thread_pool_size, loop,
267+
platform_ = new NodePlatform(thread_pool_size,
268268
trace_enabled ? tracing_agent_->GetTracingController() : nullptr);
269269
V8::InitializePlatform(platform_);
270270
tracing::TraceEventHelper::SetTracingController(
@@ -279,8 +279,8 @@ static struct {
279279
tracing_agent_ = nullptr;
280280
}
281281

282-
void DrainVMTasks() {
283-
platform_->DrainBackgroundTasks();
282+
void DrainVMTasks(Isolate* isolate) {
283+
platform_->DrainBackgroundTasks(isolate);
284284
}
285285

286286
#if HAVE_INSPECTOR
@@ -305,12 +305,16 @@ static struct {
305305
tracing_agent_->Stop();
306306
}
307307

308+
NodePlatform* Platform() {
309+
return platform_;
310+
}
311+
308312
tracing::Agent* tracing_agent_;
309313
NodePlatform* platform_;
310314
#else // !NODE_USE_V8_PLATFORM
311-
void Initialize(int thread_pool_size, uv_loop_t* loop) {}
315+
void Initialize(int thread_pool_size) {}
312316
void Dispose() {}
313-
void DrainVMTasks() {}
317+
void DrainVMTasks(Isolate* isolate) {}
314318
bool StartInspector(Environment *env, const char* script_path,
315319
const node::DebugOptions& options) {
316320
env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
@@ -322,6 +326,10 @@ static struct {
322326
"so event tracing is not available.\n");
323327
}
324328
void StopTracingAgent() {}
329+
330+
NodePlatform* Platform() {
331+
return nullptr;
332+
}
325333
#endif // !NODE_USE_V8_PLATFORM
326334

327335
#if !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
@@ -4672,7 +4680,14 @@ int EmitExit(Environment* env) {
46724680

46734681

46744682
IsolateData* CreateIsolateData(Isolate* isolate, uv_loop_t* loop) {
4675-
return new IsolateData(isolate, loop);
4683+
return new IsolateData(isolate, loop, nullptr);
4684+
}
4685+
4686+
IsolateData* CreateIsolateData(
4687+
Isolate* isolate,
4688+
uv_loop_t* loop,
4689+
MultiIsolatePlatform* platform) {
4690+
return new IsolateData(isolate, loop, platform);
46764691
}
46774692

46784693

@@ -4753,7 +4768,7 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
47534768
do {
47544769
uv_run(env.event_loop(), UV_RUN_DEFAULT);
47554770

4756-
v8_platform.DrainVMTasks();
4771+
v8_platform.DrainVMTasks(isolate);
47574772

47584773
more = uv_loop_alive(env.event_loop());
47594774
if (more)
@@ -4777,7 +4792,7 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
47774792
RunAtExit(&env);
47784793
uv_key_delete(&thread_local_env);
47794794

4780-
v8_platform.DrainVMTasks();
4795+
v8_platform.DrainVMTasks(isolate);
47814796
WaitForInspectorDisconnect(&env);
47824797
#if defined(LEAK_SANITIZER)
47834798
__lsan_do_leak_check();
@@ -4820,7 +4835,11 @@ inline int Start(uv_loop_t* event_loop,
48204835
Locker locker(isolate);
48214836
Isolate::Scope isolate_scope(isolate);
48224837
HandleScope handle_scope(isolate);
4823-
IsolateData isolate_data(isolate, event_loop, allocator.zero_fill_field());
4838+
IsolateData isolate_data(
4839+
isolate,
4840+
event_loop,
4841+
v8_platform.Platform(),
4842+
allocator.zero_fill_field());
48244843
exit_code = Start(isolate, &isolate_data, argc, argv, exec_argc, exec_argv);
48254844
}
48264845

@@ -4867,7 +4886,7 @@ int Start(int argc, char** argv) {
48674886
V8::SetEntropySource(crypto::EntropySource);
48684887
#endif // HAVE_OPENSSL
48694888

4870-
v8_platform.Initialize(v8_thread_pool_size, uv_default_loop());
4889+
v8_platform.Initialize(v8_thread_pool_size);
48714890
// Enable tracing when argv has --trace-events-enabled.
48724891
if (trace_enabled) {
48734892
fprintf(stderr, "Warning: Trace event is an experimental feature "

src/node.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#endif
6262

6363
#include "v8.h" // NOLINT(build/include_order)
64+
#include "v8-platform.h" // NOLINT(build/include_order)
6465
#include "node_version.h" // NODE_MODULE_VERSION
6566

6667
#define NODE_MAKE_VERSION(major, minor, patch) \
@@ -209,8 +210,27 @@ NODE_EXTERN void Init(int* argc,
209210
class IsolateData;
210211
class Environment;
211212

212-
NODE_EXTERN IsolateData* CreateIsolateData(v8::Isolate* isolate,
213-
struct uv_loop_s* loop);
213+
class MultiIsolatePlatform : public v8::Platform {
214+
public:
215+
virtual ~MultiIsolatePlatform() { }
216+
virtual void DrainBackgroundTasks(v8::Isolate* isolate) = 0;
217+
218+
// These will be called by the `IsolateData` creation/destruction functions.
219+
virtual void RegisterIsolate(IsolateData* isolate_data,
220+
struct uv_loop_s* loop) = 0;
221+
virtual void UnregisterIsolate(IsolateData* isolate_data) = 0;
222+
};
223+
224+
// If `platform` is passed, it will be used to register new Worker instances.
225+
// It can be `nullptr`, in which case creating new Workers inside of
226+
// Environments that use this `IsolateData` will not work.
227+
NODE_EXTERN IsolateData* CreateIsolateData(
228+
v8::Isolate* isolate,
229+
struct uv_loop_s* loop);
230+
NODE_EXTERN IsolateData* CreateIsolateData(
231+
v8::Isolate* isolate,
232+
struct uv_loop_s* loop,
233+
MultiIsolatePlatform* platform);
214234
NODE_EXTERN void FreeIsolateData(IsolateData* isolate_data);
215235

216236
NODE_EXTERN Environment* CreateEnvironment(IsolateData* isolate_data,

0 commit comments

Comments
 (0)