1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -05:00

libdeno: Expose snapshot creation.

This commit is contained in:
Ryan Dahl 2018-10-24 01:12:13 -04:00
parent 6afe94b3c8
commit 61cda72881
6 changed files with 82 additions and 47 deletions

View file

@ -42,10 +42,39 @@ Deno* deno_new(deno_buf snapshot, deno_recv_cb cb) {
return reinterpret_cast<Deno*>(d);
}
Deno* deno_new_snapshotter(deno_recv_cb cb, const char* js_filename,
const char* js_source, const char* source_map) {
auto* creator = new v8::SnapshotCreator(deno::external_references);
auto* isolate = creator->GetIsolate();
auto* d = new deno::DenoIsolate(deno::empty_buf, cb);
d->snapshot_creator_ = creator;
d->AddIsolate(isolate);
v8::Isolate::Scope isolate_scope(isolate);
{
v8::HandleScope handle_scope(isolate);
auto context = v8::Context::New(isolate);
creator->SetDefaultContext(context,
v8::SerializeInternalFieldsCallback(
deno::SerializeInternalFields, nullptr));
deno::InitializeContext(isolate, context, js_filename, js_source,
source_map);
}
return reinterpret_cast<Deno*>(d);
}
deno::DenoIsolate* unwrap(Deno* d_) {
return reinterpret_cast<deno::DenoIsolate*>(d_);
}
deno_buf deno_get_snapshot(Deno* d_) {
auto* d = unwrap(d_);
CHECK_NE(d->snapshot_creator_, nullptr);
auto blob = d->snapshot_creator_->CreateBlob(
v8::SnapshotCreator::FunctionCodeHandling::kClear);
return {nullptr, 0, reinterpret_cast<uint8_t*>(const_cast<char*>(blob.data)),
blob.raw_size};
}
void deno_init() {
// v8::V8::InitializeICUDefaultLocation(argv[0]);
// v8::V8::InitializeExternalStartupData(argv[0]);

View file

@ -30,6 +30,19 @@ void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
deserialized_data.push_back(embedder_field);
}
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
void* data) {
DCHECK_EQ(data, nullptr);
InternalFieldData* embedder_field = static_cast<InternalFieldData*>(
holder->GetAlignedPointerFromInternalField(index));
if (embedder_field == nullptr) return {nullptr, 0};
int size = sizeof(*embedder_field);
char* payload = new char[size];
// We simply use memcpy to serialize the content.
memcpy(payload, embedder_field, size);
return {payload, size};
}
DenoIsolate* FromIsolate(v8::Isolate* isolate) {
return static_cast<DenoIsolate*>(isolate->GetData(0));
}
@ -433,8 +446,10 @@ bool Execute(v8::Local<v8::Context> context, const char* js_filename,
}
void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
const char* js_filename, const std::string& js_source,
const std::string* source_map) {
const char* js_filename, const char* js_source,
const char* source_map) {
CHECK_NE(js_source, nullptr);
CHECK_NE(js_filename, nullptr);
v8::HandleScope handle_scope(isolate);
v8::Context::Scope context_scope(context);
@ -483,7 +498,7 @@ void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
.FromJust());
{
auto source = deno::v8_str(js_source.c_str());
auto source = deno::v8_str(js_source);
CHECK(
deno_val->Set(context, deno::v8_str("mainSource"), source).FromJust());
@ -491,10 +506,10 @@ void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
CHECK(r);
if (source_map != nullptr) {
CHECK_GT(source_map->length(), 1u);
v8::TryCatch try_catch(isolate);
v8::ScriptOrigin origin(v8_str("set_source_map.js"));
std::string source_map_parens = "(" + *source_map + ")";
std::string source_map_parens =
std::string("(") + std::string(source_map) + std::string(")");
auto source_map_v8_str = deno::v8_str(source_map_parens.c_str());
auto script = v8::Script::Compile(context, source_map_v8_str, &origin);
if (script.IsEmpty()) {

View file

@ -30,6 +30,11 @@ const char* deno_v8_version();
void deno_set_v8_flags(int* argc, char** argv);
Deno* deno_new(deno_buf snapshot, deno_recv_cb cb);
Deno* deno_new_snapshotter(deno_recv_cb cb, const char* js_filename,
const char* js_source, const char* source_map);
deno_buf deno_get_snapshot(Deno* d);
void deno_delete(Deno* d);
// Returns false on error.

View file

@ -16,6 +16,7 @@ class DenoIsolate {
DenoIsolate(deno_buf snapshot, deno_recv_cb cb)
: isolate_(nullptr),
current_args_(nullptr),
snapshot_creator_(nullptr),
global_import_buf_ptr_(nullptr),
pending_promise_events_(0),
cb_(cb),
@ -30,8 +31,8 @@ class DenoIsolate {
void AddIsolate(v8::Isolate* isolate);
v8::Isolate* isolate_;
// Put v8::Isolate::CreateParams here..
const v8::FunctionCallbackInfo<v8::Value>* current_args_;
v8::SnapshotCreator* snapshot_creator_;
void* global_import_buf_ptr_;
int32_t pending_promise_events_;
deno_recv_cb cb_;
@ -86,11 +87,13 @@ static intptr_t external_references[] = {
reinterpret_cast<intptr_t>(SetPromiseErrorExaminer),
0};
static const deno_buf empty_buf = {nullptr, 0, nullptr, 0};
Deno* NewFromSnapshot(void* user_data, deno_recv_cb cb);
void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
const char* js_filename, const std::string& js_source,
const std::string* source_map);
const char* js_filename, const char* js_source,
const char* source_map);
void HandleException(v8::Local<v8::Context> context,
v8::Local<v8::Value> exception);
@ -98,6 +101,9 @@ void HandleException(v8::Local<v8::Context> context,
void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
v8::StartupData payload, void* data);
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
void* data);
v8::Local<v8::Uint8Array> ImportBuf(DenoIsolate* d, deno_buf buf);
void DeleteDataRef(DenoIsolate* d, int32_t req_id);

View file

@ -16,6 +16,17 @@ TEST(LibDenoTest, InitializesCorrectlyWithoutSnapshot) {
deno_delete(d);
}
TEST(LibDenoTest, Snapshotter) {
Deno* d1 = deno_new_snapshotter(nullptr, "a.js", "a = 1 + 2", nullptr);
deno_buf test_snapshot = deno_get_snapshot(d1);
// TODO(ry) deno_delete(d1);
Deno* d2 = deno_new(test_snapshot, nullptr);
EXPECT_TRUE(
deno_execute(d2, nullptr, "b.js", "if (a != 3) throw Error('x');"));
deno_delete(d2);
}
TEST(LibDenoTest, CanCallFunction) {
Deno* d = deno_new(snapshot, nullptr);
EXPECT_TRUE(deno_execute(d, nullptr, "a.js",

View file

@ -7,42 +7,7 @@
#include "third_party/v8/include/v8.h"
#include "third_party/v8/src/base/logging.h"
namespace deno {
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
void* data) {
DCHECK_EQ(data, nullptr);
InternalFieldData* embedder_field = static_cast<InternalFieldData*>(
holder->GetAlignedPointerFromInternalField(index));
if (embedder_field == nullptr) return {nullptr, 0};
int size = sizeof(*embedder_field);
char* payload = new char[size];
// We simply use memcpy to serialize the content.
memcpy(payload, embedder_field, size);
return {payload, size};
}
v8::StartupData MakeSnapshot(const char* js_filename,
const std::string& js_source,
const std::string* source_map) {
auto* creator = new v8::SnapshotCreator(external_references);
auto* isolate = creator->GetIsolate();
v8::Isolate::Scope isolate_scope(isolate);
{
v8::HandleScope handle_scope(isolate);
auto context = v8::Context::New(isolate);
InitializeContext(isolate, context, js_filename, js_source, source_map);
creator->SetDefaultContext(context, v8::SerializeInternalFieldsCallback(
SerializeInternalFields, nullptr));
}
auto snapshot_blob =
creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
return snapshot_blob;
}
} // namespace deno
namespace deno {} // namespace deno
int main(int argc, char** argv) {
const char* snapshot_out_bin = argv[1];
@ -64,9 +29,13 @@ int main(int argc, char** argv) {
}
deno_init();
auto snapshot_blob = deno::MakeSnapshot(
js_fn, js_source, source_map_fn != nullptr ? &source_map : nullptr);
std::string snapshot_str(snapshot_blob.data, snapshot_blob.raw_size);
Deno* d = deno_new_snapshotter(
nullptr, js_fn, js_source.c_str(),
source_map_fn != nullptr ? source_map.c_str() : nullptr);
auto snapshot = deno_get_snapshot(d);
std::string snapshot_str(reinterpret_cast<char*>(snapshot.data_ptr),
snapshot.data_len);
std::ofstream file_(snapshot_out_bin, std::ios::binary);
file_ << snapshot_str;