summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/env.cc147
-rw-r--r--src/env.h8
-rw-r--r--src/node_main_instance.cc25
-rw-r--r--src/node_main_instance.h19
4 files changed, 149 insertions, 50 deletions
diff --git a/src/env.cc b/src/env.cc
index cbb8ab6fe2..5ef32e2b0e 100644
--- a/src/env.cc
+++ b/src/env.cc
@@ -37,6 +37,7 @@ using v8::NewStringType;
using v8::Number;
using v8::Object;
using v8::Private;
+using v8::SnapshotCreator;
using v8::StackTrace;
using v8::String;
using v8::Symbol;
@@ -49,22 +50,58 @@ int const Environment::kNodeContextTag = 0x6e6f64;
void* const Environment::kNodeContextTagPtr = const_cast<void*>(
static_cast<const void*>(&Environment::kNodeContextTag));
-IsolateData::IsolateData(Isolate* isolate,
- uv_loop_t* event_loop,
- MultiIsolatePlatform* platform,
- ArrayBufferAllocator* node_allocator)
- : isolate_(isolate),
- event_loop_(event_loop),
- allocator_(isolate->GetArrayBufferAllocator()),
- node_allocator_(node_allocator == nullptr ?
- nullptr : node_allocator->GetImpl()),
- uses_node_allocator_(allocator_ == node_allocator_),
- platform_(platform) {
- CHECK_NOT_NULL(allocator_);
+std::vector<size_t> IsolateData::Serialize(SnapshotCreator* creator) {
+ Isolate* isolate = creator->GetIsolate();
+ std::vector<size_t> indexes;
+ HandleScope handle_scope(isolate);
+ // XXX(joyeecheung): technically speaking, the indexes here should be
+ // consecutive and we could just return a range instead of an array,
+ // but that's not part of the V8 API contract so we use an array
+ // just to be safe.
+
+#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
+#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
+#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
+#define V(TypeName, PropertyName) \
+ indexes.push_back(creator->AddData(PropertyName##_.Get(isolate)));
+ PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
+ PER_ISOLATE_SYMBOL_PROPERTIES(VY)
+ PER_ISOLATE_STRING_PROPERTIES(VS)
+#undef V
+#undef VY
+#undef VS
+#undef VP
- options_.reset(
- new PerIsolateOptions(*(per_process::cli_options->per_isolate)));
+ return indexes;
+}
+void IsolateData::DeserializeProperties(
+ const NodeMainInstance::IndexArray* indexes) {
+ size_t i = 0;
+ HandleScope handle_scope(isolate_);
+
+#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
+#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
+#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
+#define V(TypeName, PropertyName) \
+ do { \
+ MaybeLocal<TypeName> field = \
+ isolate_->GetDataFromSnapshotOnce<TypeName>(indexes->Get(i++)); \
+ if (field.IsEmpty()) { \
+ fprintf(stderr, "Failed to deserialize " #PropertyName "\n"); \
+ } \
+ PropertyName##_.Set(isolate_, field.ToLocalChecked()); \
+ } while (0);
+ PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
+ PER_ISOLATE_SYMBOL_PROPERTIES(VY)
+ PER_ISOLATE_STRING_PROPERTIES(VS)
+#undef V
+#undef VY
+#undef VS
+#undef VP
+}
+
+void IsolateData::CreateProperties() {
// Create string and private symbol properties as internalized one byte
// strings after the platform is properly initialized.
//
@@ -76,44 +113,68 @@ IsolateData::IsolateData(Isolate* isolate,
// One byte because our strings are ASCII and we can safely skip V8's UTF-8
// decoding step.
- HandleScope handle_scope(isolate);
+ HandleScope handle_scope(isolate_);
-#define V(PropertyName, StringValue) \
- PropertyName ## _.Set( \
- isolate, \
- Private::New( \
- isolate, \
- String::NewFromOneByte( \
- isolate, \
- reinterpret_cast<const uint8_t*>(StringValue), \
- NewStringType::kInternalized, \
- sizeof(StringValue) - 1).ToLocalChecked()));
+#define V(PropertyName, StringValue) \
+ PropertyName##_.Set( \
+ isolate_, \
+ Private::New(isolate_, \
+ String::NewFromOneByte( \
+ isolate_, \
+ reinterpret_cast<const uint8_t*>(StringValue), \
+ NewStringType::kInternalized, \
+ sizeof(StringValue) - 1) \
+ .ToLocalChecked()));
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
#undef V
-#define V(PropertyName, StringValue) \
- PropertyName ## _.Set( \
- isolate, \
- Symbol::New( \
- isolate, \
- String::NewFromOneByte( \
- isolate, \
- reinterpret_cast<const uint8_t*>(StringValue), \
- NewStringType::kInternalized, \
- sizeof(StringValue) - 1).ToLocalChecked()));
+#define V(PropertyName, StringValue) \
+ PropertyName##_.Set( \
+ isolate_, \
+ Symbol::New(isolate_, \
+ String::NewFromOneByte( \
+ isolate_, \
+ reinterpret_cast<const uint8_t*>(StringValue), \
+ NewStringType::kInternalized, \
+ sizeof(StringValue) - 1) \
+ .ToLocalChecked()));
PER_ISOLATE_SYMBOL_PROPERTIES(V)
#undef V
-#define V(PropertyName, StringValue) \
- PropertyName ## _.Set( \
- isolate, \
- String::NewFromOneByte( \
- isolate, \
- reinterpret_cast<const uint8_t*>(StringValue), \
- NewStringType::kInternalized, \
- sizeof(StringValue) - 1).ToLocalChecked());
+#define V(PropertyName, StringValue) \
+ PropertyName##_.Set( \
+ isolate_, \
+ String::NewFromOneByte(isolate_, \
+ reinterpret_cast<const uint8_t*>(StringValue), \
+ NewStringType::kInternalized, \
+ sizeof(StringValue) - 1) \
+ .ToLocalChecked());
PER_ISOLATE_STRING_PROPERTIES(V)
#undef V
}
+IsolateData::IsolateData(Isolate* isolate,
+ uv_loop_t* event_loop,
+ MultiIsolatePlatform* platform,
+ ArrayBufferAllocator* node_allocator,
+ const NodeMainInstance::IndexArray* indexes)
+ : isolate_(isolate),
+ event_loop_(event_loop),
+ allocator_(isolate->GetArrayBufferAllocator()),
+ node_allocator_(node_allocator == nullptr ? nullptr
+ : node_allocator->GetImpl()),
+ uses_node_allocator_(allocator_ == node_allocator_),
+ platform_(platform) {
+ CHECK_NOT_NULL(allocator_);
+
+ options_.reset(
+ new PerIsolateOptions(*(per_process::cli_options->per_isolate)));
+
+ if (indexes == nullptr) {
+ CreateProperties();
+ } else {
+ DeserializeProperties(indexes);
+ }
+}
+
void IsolateData::MemoryInfo(MemoryTracker* tracker) const {
#define V(PropertyName, StringValue) \
tracker->TrackField(#PropertyName, PropertyName(isolate()));
diff --git a/src/env.h b/src/env.h
index def7cba388..24050cc9f4 100644
--- a/src/env.h
+++ b/src/env.h
@@ -33,6 +33,7 @@
#include "node.h"
#include "node_binding.h"
#include "node_http2_state.h"
+#include "node_main_instance.h"
#include "node_options.h"
#include "req_wrap.h"
#include "util.h"
@@ -418,10 +419,12 @@ class IsolateData : public MemoryRetainer {
IsolateData(v8::Isolate* isolate,
uv_loop_t* event_loop,
MultiIsolatePlatform* platform = nullptr,
- ArrayBufferAllocator* node_allocator = nullptr);
+ ArrayBufferAllocator* node_allocator = nullptr,
+ const NodeMainInstance::IndexArray* indexes = nullptr);
SET_MEMORY_INFO_NAME(IsolateData);
SET_SELF_SIZE(IsolateData);
void MemoryInfo(MemoryTracker* tracker) const override;
+ std::vector<size_t> Serialize(v8::SnapshotCreator* creator);
inline uv_loop_t* event_loop() const;
inline MultiIsolatePlatform* platform() const;
@@ -451,6 +454,9 @@ class IsolateData : public MemoryRetainer {
IsolateData& operator=(const IsolateData&) = delete;
private:
+ void DeserializeProperties(const NodeMainInstance::IndexArray* indexes);
+ void CreateProperties();
+
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc
index 4b05149b23..11dfadabb9 100644
--- a/src/node_main_instance.cc
+++ b/src/node_main_instance.cc
@@ -23,7 +23,8 @@ NodeMainInstance::NodeMainInstance(Isolate* isolate,
isolate_(isolate),
platform_(platform),
isolate_data_(nullptr),
- owns_isolate_(false) {
+ owns_isolate_(false),
+ deserialize_mode_(false) {
isolate_data_.reset(new IsolateData(isolate_, event_loop, platform, nullptr));
SetIsolateUpForNode(isolate_, IsolateSettingCategories::kMisc);
}
@@ -41,7 +42,8 @@ NodeMainInstance::NodeMainInstance(Isolate::CreateParams* params,
uv_loop_t* event_loop,
MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
- const std::vector<std::string>& exec_args)
+ const std::vector<std::string>& exec_args,
+ const IndexArray* per_isolate_data_indexes)
: args_(args),
exec_args_(exec_args),
array_buffer_allocator_(ArrayBufferAllocator::Create()),
@@ -58,10 +60,20 @@ NodeMainInstance::NodeMainInstance(Isolate::CreateParams* params,
SetIsolateCreateParamsForNode(params);
Isolate::Initialize(isolate_, *params);
- isolate_data_.reset(new IsolateData(
- isolate_, event_loop, platform, array_buffer_allocator_.get()));
+ deserialize_mode_ = per_isolate_data_indexes != nullptr;
+ // If the indexes are not nullptr, we are not deserializing
+ CHECK_IMPLIES(deserialize_mode_, params->external_references != nullptr);
+ isolate_data_.reset(new IsolateData(isolate_,
+ event_loop,
+ platform,
+ array_buffer_allocator_.get(),
+ per_isolate_data_indexes));
SetIsolateUpForNode(isolate_, IsolateSettingCategories::kMisc);
- SetIsolateUpForNode(isolate_, IsolateSettingCategories::kErrorHandlers);
+ if (!deserialize_mode_) {
+ // If in deserialize mode, delay until after the deserialization is
+ // complete.
+ SetIsolateUpForNode(isolate_, IsolateSettingCategories::kErrorHandlers);
+ }
}
void NodeMainInstance::Dispose() {
@@ -160,6 +172,9 @@ std::unique_ptr<Environment> NodeMainInstance::CreateMainEnvironment(
}
Local<Context> context = NewContext(isolate_);
+ if (deserialize_mode_) {
+ SetIsolateUpForNode(isolate_, IsolateSettingCategories::kErrorHandlers);
+ }
CHECK(!context.IsEmpty());
Context::Scope context_scope(context);
diff --git a/src/node_main_instance.h b/src/node_main_instance.h
index 0a8be137a0..615fda1f49 100644
--- a/src/node_main_instance.h
+++ b/src/node_main_instance.h
@@ -15,6 +15,18 @@ namespace node {
// We may be able to create an abstract class to reuse some of the routines.
class NodeMainInstance {
public:
+ // An array of indexes that can be used to deserialize data from a V8
+ // snapshot.
+ struct IndexArray {
+ const size_t* data;
+ size_t length;
+
+ size_t Get(size_t index) const {
+ DCHECK_LT(index, length);
+ return data[index];
+ }
+ };
+
// To create a main instance that does not own the isoalte,
// The caller needs to do:
//
@@ -45,12 +57,15 @@ class NodeMainInstance {
uv_loop_t* event_loop,
MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
- const std::vector<std::string>& exec_args);
+ const std::vector<std::string>& exec_args,
+ const IndexArray* per_isolate_data_indexes = nullptr);
~NodeMainInstance();
// Start running the Node.js instances, return the exit code when finished.
int Run();
+ IsolateData* isolate_data() { return isolate_data_.get(); }
+
// TODO(joyeecheung): align this with the CreateEnvironment exposed in node.h
// and the environment creation routine in workers somehow.
std::unique_ptr<Environment> CreateMainEnvironment(int* exit_code);
@@ -66,6 +81,7 @@ class NodeMainInstance {
MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args);
+
std::vector<std::string> args_;
std::vector<std::string> exec_args_;
std::unique_ptr<ArrayBufferAllocator> array_buffer_allocator_;
@@ -73,6 +89,7 @@ class NodeMainInstance {
MultiIsolatePlatform* platform_;
std::unique_ptr<IsolateData> isolate_data_;
bool owns_isolate_ = false;
+ bool deserialize_mode_ = false;
};
} // namespace node