libdeno: deno_new should take a snapshot parameter.

This commit is contained in:
Ryan Dahl 2018-10-23 19:39:31 -04:00
parent 3438dbe350
commit fd68f85ce8
13 changed files with 201 additions and 168 deletions

View file

@ -390,7 +390,11 @@ after_test:
Select-String $trap -Path $files -SimpleMatch | where { Select-String $trap -Path $files -SimpleMatch | where {
# V8 took the liberty to produce an absolute path in their ninja # V8 took the liberty to produce an absolute path in their ninja
# output. We can't do much about that, so we just ignore it. # output. We can't do much about that, so we just ignore it.
$_.Line -notmatch "v8/builtins-generated/bytecodes-builtins-list.h" $_.Line -notmatch "v8/builtins-generated/bytecodes-builtins-list.h" -and
# The absolute path to snapshot_libdeno_test.bin is passed to test_cc
# via pre-processor variable. It's absolute because we want to be able
# to execute test_cc from both the project root and the build root.
$_.Line -notmatch "snapshot_libdeno_test.bin"
} | tee -Variable line_matches } | tee -Variable line_matches
if ($line_matches) { if ($line_matches) {
$ctx = $line_matches.Line | $ctx = $line_matches.Line |

122
BUILD.gn
View file

@ -124,9 +124,49 @@ rust_executable("deno") {
extern = main_extern extern = main_extern
deps = [ deps = [
":libdeno", ":libdeno",
":snapshot",
] ]
} }
source_set("snapshot") {
sources = [
"src/snapshot.cc",
]
configs += [ ":deno_config" ]
data = [
"$target_gen_dir/snapshot_deno.bin",
]
deps = [
":create_snapshot_deno",
]
# snapshot.cc doesn't need to depend on libdeno, it just needs deno_buf.
include_dirs = [ "libdeno/" ]
# src/snapshot.cc uses an assembly '.incbin' directive to embed the snapshot.
# This causes trouble when using sccache: since the snapshot file is not
# inlined by the c preprocessor, sccache doesn't take its contents into
# consideration, leading to false-positive cache hits.
# Maybe other caching tools have this issue too, but ccache is unaffected.
# Therefore, if a cc_wrapper is used that isn't ccache, include a generated
# header file that contains the the sha256 hash of the snapshot.
if (cc_wrapper != "" && cc_wrapper != "ccache") {
hash_h = "$target_gen_dir/bundle/hash.h"
inputs = [
hash_h,
]
deps += [ ":bundle_hash_h" ]
if (is_win) {
cflags = [ "/FI" + rebase_path(hash_h, target_out_dir) ]
} else {
cflags = [
"-include",
rebase_path(hash_h, target_out_dir),
]
}
}
}
rust_executable("hyper_hello") { rust_executable("hyper_hello") {
source_root = "tools/hyper_hello.rs" source_root = "tools/hyper_hello.rs"
extern = [ extern = [
@ -140,100 +180,48 @@ rust_test("test_rs") {
extern = main_extern extern = main_extern
deps = [ deps = [
":libdeno", ":libdeno",
":snapshot",
] ]
} }
v8_executable("test_cc") { v8_executable("test_cc") {
testonly = true testonly = true
sources = [ sources = [
"libdeno/file_util_test.cc",
"libdeno/libdeno_test.cc",
"libdeno/test.cc", "libdeno/test.cc",
] ]
deps = [ deps = [
":deno_base_test", ":create_snapshot_libdeno_test",
":libdeno",
"//testing/gtest:gtest", "//testing/gtest:gtest",
] ]
data = [
"$target_gen_dir/snapshot_libdeno_test.bin",
]
snapshot_abs_path = rebase_path(data[0])
defines = [ "SNAPSHOT_PATH=\"$snapshot_abs_path\"" ]
configs = [ ":deno_config" ] configs = [ ":deno_config" ]
} }
static_library("libdeno") {
complete_static_lib = true
sources = [
"libdeno/from_snapshot.cc",
]
inputs = [
"$target_gen_dir/snapshot_deno.bin",
]
deps = [
":create_snapshot_deno",
":deno_bindings",
]
configs += [ ":deno_config" ]
# from_snapshot.cc uses an assembly '.incbin' directive to embed the snapshot.
# This causes trouble when using sccache: since the snapshot file is not
# inlined by the c preprocessor, sccache doesn't take its contents into
# consideration, leading to false-positive cache hits.
# Maybe other caching tools have this issue too, but ccache is unaffected.
# Therefore, if a cc_wrapper is used that isn't ccache, include a generated
# header file that contains the the sha256 hash of the snapshot.
if (cc_wrapper != "" && cc_wrapper != "ccache") {
hash_h = "$target_gen_dir/bundle/hash.h"
inputs += [ hash_h ]
deps += [ ":bundle_hash_h" ]
if (is_win) {
cflags = [ "/FI" + rebase_path(hash_h, target_out_dir) ]
} else {
cflags = [
"-include",
rebase_path(hash_h, target_out_dir),
]
}
}
}
# Only functionality needed for libdeno_test and snapshot_creator # Only functionality needed for libdeno_test and snapshot_creator
# In particular no flatbuffers, no assets, no rust, no msg handlers. # In particular no flatbuffers, no assets, no rust, no msg handlers.
# Because snapshots are slow, it's important that snapshot_creator's # Because snapshots are slow, it's important that snapshot_creator's
# dependencies are minimal. # dependencies are minimal.
v8_source_set("deno_base") { static_library("libdeno") {
complete_static_lib = true
sources = [ sources = [
"libdeno/binding.cc", "libdeno/binding.cc",
"libdeno/deno.h", "libdeno/deno.h",
"libdeno/file_util.cc", "libdeno/file_util.cc",
"libdeno/file_util.h", "libdeno/file_util.h",
"libdeno/internal.h", "libdeno/internal.h",
"libdeno/new.cc",
] ]
public_deps = [ public_deps = [
"third_party/v8:v8_monolith", "third_party/v8:v8_monolith",
] ]
configs = [ ":deno_config" ] configs += [ ":deno_config" ]
}
v8_source_set("deno_base_test") {
testonly = true
sources = [
"libdeno/file_util_test.cc",
"libdeno/from_snapshot.cc",
"libdeno/libdeno_test.cc",
"libdeno/test.cc",
]
deps = [
":create_snapshot_libdeno_test",
":deno_base",
"//testing/gtest:gtest",
]
data = [
"$target_gen_dir/snapshot_libdeno_test.bin",
]
defines = [ "LIBDENO_TEST" ]
configs = [ ":deno_config" ]
}
v8_source_set("deno_bindings") {
deps = [
":deno_base",
]
configs = [ ":deno_config" ]
} }
executable("snapshot_creator") { executable("snapshot_creator") {
@ -241,7 +229,7 @@ executable("snapshot_creator") {
"libdeno/snapshot_creator.cc", "libdeno/snapshot_creator.cc",
] ]
deps = [ deps = [
":deno_base", ":libdeno",
] ]
configs += [ ":deno_config" ] configs += [ ":deno_config" ]
} }

View file

@ -30,7 +30,7 @@ void deno_init();
const char* deno_v8_version(); const char* deno_v8_version();
void deno_set_v8_flags(int* argc, char** argv); void deno_set_v8_flags(int* argc, char** argv);
Deno* deno_new(deno_recv_cb cb); Deno* deno_new(deno_buf snapshot, deno_recv_cb cb);
void deno_delete(Deno* d); void deno_delete(Deno* d);
// Returns false on error. // Returns false on error.

View file

@ -17,7 +17,7 @@ struct deno_s {
v8::Persistent<v8::Function> global_error_handler; v8::Persistent<v8::Function> global_error_handler;
v8::Persistent<v8::Function> promise_reject_handler; v8::Persistent<v8::Function> promise_reject_handler;
v8::Persistent<v8::Function> promise_error_examiner; v8::Persistent<v8::Function> promise_error_examiner;
v8::StartupData snapshot;
v8::Persistent<v8::ArrayBuffer> global_import_buf; v8::Persistent<v8::ArrayBuffer> global_import_buf;
void* global_import_buf_ptr; void* global_import_buf_ptr;

View file

@ -1,23 +1,30 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license. // Copyright 2018 the Deno authors. All rights reserved. MIT license.
#include "testing/gtest/include/gtest/gtest.h" #include "test.h"
#include "deno.h"
TEST(LibDenoTest, InitializesCorrectly) { TEST(LibDenoTest, InitializesCorrectly) {
Deno* d = deno_new(nullptr); printf("snapshot.data_ptr %p\n", snapshot.data_ptr);
EXPECT_NE(snapshot.data_ptr, nullptr);
Deno* d = deno_new(empty, nullptr);
EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "1 + 2"));
deno_delete(d);
}
TEST(LibDenoTest, InitializesCorrectlyWithoutSnapshot) {
deno_buf empty = {nullptr, 0, nullptr, 0};
Deno* d = deno_new(empty, nullptr);
EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "1 + 2")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "1 + 2"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, CanCallFunction) { TEST(LibDenoTest, CanCallFunction) {
Deno* d = deno_new(nullptr); Deno* d = deno_new(snapshot, nullptr);
EXPECT_TRUE(deno_execute(d, nullptr, "a.js", EXPECT_TRUE(deno_execute(d, nullptr, "a.js",
"if (CanCallFunction() != 'foo') throw Error();")); "if (CanCallFunction() != 'foo') throw Error();"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, ErrorsCorrectly) { TEST(LibDenoTest, ErrorsCorrectly) {
Deno* d = deno_new(nullptr); Deno* d = deno_new(snapshot, nullptr);
EXPECT_FALSE(deno_execute(d, nullptr, "a.js", "throw Error()")); EXPECT_FALSE(deno_execute(d, nullptr, "a.js", "throw Error()"));
deno_delete(d); deno_delete(d);
} }
@ -54,7 +61,7 @@ void assert_null(deno_buf b) {
TEST(LibDenoTest, RecvReturnEmpty) { TEST(LibDenoTest, RecvReturnEmpty) {
static int count = 0; static int count = 0;
Deno* d = deno_new([](auto _, int req_id, auto buf, auto data_buf) { Deno* d = deno_new(snapshot, [](auto _, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
count++; count++;
EXPECT_EQ(static_cast<size_t>(3), buf.data_len); EXPECT_EQ(static_cast<size_t>(3), buf.data_len);
@ -69,56 +76,58 @@ TEST(LibDenoTest, RecvReturnEmpty) {
TEST(LibDenoTest, RecvReturnBar) { TEST(LibDenoTest, RecvReturnBar) {
static int count = 0; static int count = 0;
Deno* d = deno_new([](auto user_data, int req_id, auto buf, auto data_buf) { Deno* d = deno_new(snapshot,
auto d = reinterpret_cast<Deno*>(user_data); [](auto user_data, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); auto d = reinterpret_cast<Deno*>(user_data);
count++; assert_null(data_buf);
EXPECT_EQ(static_cast<size_t>(3), buf.data_len); count++;
EXPECT_EQ(buf.data_ptr[0], 'a'); EXPECT_EQ(static_cast<size_t>(3), buf.data_len);
EXPECT_EQ(buf.data_ptr[1], 'b'); EXPECT_EQ(buf.data_ptr[0], 'a');
EXPECT_EQ(buf.data_ptr[2], 'c'); EXPECT_EQ(buf.data_ptr[1], 'b');
deno_respond(d, user_data, req_id, strbuf("bar")); EXPECT_EQ(buf.data_ptr[2], 'c');
}); deno_respond(d, user_data, req_id, strbuf("bar"));
});
EXPECT_TRUE(deno_execute(d, d, "a.js", "RecvReturnBar()")); EXPECT_TRUE(deno_execute(d, d, "a.js", "RecvReturnBar()"));
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, DoubleRecvFails) { TEST(LibDenoTest, DoubleRecvFails) {
Deno* d = deno_new(nullptr); Deno* d = deno_new(snapshot, nullptr);
EXPECT_FALSE(deno_execute(d, nullptr, "a.js", "DoubleRecvFails()")); EXPECT_FALSE(deno_execute(d, nullptr, "a.js", "DoubleRecvFails()"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, SendRecvSlice) { TEST(LibDenoTest, SendRecvSlice) {
static int count = 0; static int count = 0;
Deno* d = deno_new([](auto user_data, int req_id, auto buf, auto data_buf) { Deno* d = deno_new(
auto d = reinterpret_cast<Deno*>(user_data); snapshot, [](auto user_data, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); auto d = reinterpret_cast<Deno*>(user_data);
static const size_t alloc_len = 1024; assert_null(data_buf);
size_t i = count++; static const size_t alloc_len = 1024;
// Check the size and offset of the slice. size_t i = count++;
size_t data_offset = buf.data_ptr - buf.alloc_ptr; // Check the size and offset of the slice.
EXPECT_EQ(data_offset, i * 11); size_t data_offset = buf.data_ptr - buf.alloc_ptr;
EXPECT_EQ(buf.data_len, alloc_len - i * 30); EXPECT_EQ(data_offset, i * 11);
EXPECT_EQ(buf.alloc_len, alloc_len); EXPECT_EQ(buf.data_len, alloc_len - i * 30);
// Check values written by the JS side. EXPECT_EQ(buf.alloc_len, alloc_len);
EXPECT_EQ(buf.data_ptr[0], 100 + i); // Check values written by the JS side.
EXPECT_EQ(buf.data_ptr[buf.data_len - 1], 100 - i); EXPECT_EQ(buf.data_ptr[0], 100 + i);
// Make copy of the backing buffer -- this is currently necessary EXPECT_EQ(buf.data_ptr[buf.data_len - 1], 100 - i);
// because deno_respond() takes ownership over the buffer, but we are // Make copy of the backing buffer -- this is currently necessary
// not given ownership of `buf` by our caller. // because deno_respond() takes ownership over the buffer, but we are
uint8_t* alloc_ptr = reinterpret_cast<uint8_t*>(malloc(alloc_len)); // not given ownership of `buf` by our caller.
memcpy(alloc_ptr, buf.alloc_ptr, alloc_len); uint8_t* alloc_ptr = reinterpret_cast<uint8_t*>(malloc(alloc_len));
// Make a slice that is a bit shorter than the original. memcpy(alloc_ptr, buf.alloc_ptr, alloc_len);
deno_buf buf2{alloc_ptr, alloc_len, alloc_ptr + data_offset, // Make a slice that is a bit shorter than the original.
buf.data_len - 19}; deno_buf buf2{alloc_ptr, alloc_len, alloc_ptr + data_offset,
// Place some values into the buffer for the JS side to verify. buf.data_len - 19};
buf2.data_ptr[0] = 200 + i; // Place some values into the buffer for the JS side to verify.
buf2.data_ptr[buf2.data_len - 1] = 200 - i; buf2.data_ptr[0] = 200 + i;
// Send back. buf2.data_ptr[buf2.data_len - 1] = 200 - i;
deno_respond(d, user_data, req_id, buf2); // Send back.
}); deno_respond(d, user_data, req_id, buf2);
});
EXPECT_TRUE(deno_execute(d, d, "a.js", "SendRecvSlice()")); EXPECT_TRUE(deno_execute(d, d, "a.js", "SendRecvSlice()"));
EXPECT_EQ(count, 5); EXPECT_EQ(count, 5);
deno_delete(d); deno_delete(d);
@ -126,7 +135,7 @@ TEST(LibDenoTest, SendRecvSlice) {
TEST(LibDenoTest, JSSendArrayBufferViewTypes) { TEST(LibDenoTest, JSSendArrayBufferViewTypes) {
static int count = 0; static int count = 0;
Deno* d = deno_new([](auto _, int req_id, auto buf, auto data_buf) { Deno* d = deno_new(snapshot, [](auto _, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
count++; count++;
size_t data_offset = buf.data_ptr - buf.alloc_ptr; size_t data_offset = buf.data_ptr - buf.alloc_ptr;
@ -141,20 +150,20 @@ TEST(LibDenoTest, JSSendArrayBufferViewTypes) {
} }
TEST(LibDenoTest, TypedArraySnapshots) { TEST(LibDenoTest, TypedArraySnapshots) {
Deno* d = deno_new(nullptr); Deno* d = deno_new(snapshot, nullptr);
EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "TypedArraySnapshots()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "TypedArraySnapshots()"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, SnapshotBug) { TEST(LibDenoTest, SnapshotBug) {
Deno* d = deno_new(nullptr); Deno* d = deno_new(snapshot, nullptr);
EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "SnapshotBug()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "SnapshotBug()"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, GlobalErrorHandling) { TEST(LibDenoTest, GlobalErrorHandling) {
static int count = 0; static int count = 0;
Deno* d = deno_new([](auto _, int req_id, auto buf, auto data_buf) { Deno* d = deno_new(snapshot, [](auto _, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
count++; count++;
EXPECT_EQ(static_cast<size_t>(1), buf.data_len); EXPECT_EQ(static_cast<size_t>(1), buf.data_len);
@ -166,7 +175,7 @@ TEST(LibDenoTest, GlobalErrorHandling) {
} }
TEST(LibDenoTest, DoubleGlobalErrorHandlingFails) { TEST(LibDenoTest, DoubleGlobalErrorHandlingFails) {
Deno* d = deno_new(nullptr); Deno* d = deno_new(snapshot, nullptr);
EXPECT_FALSE( EXPECT_FALSE(
deno_execute(d, nullptr, "a.js", "DoubleGlobalErrorHandlingFails()")); deno_execute(d, nullptr, "a.js", "DoubleGlobalErrorHandlingFails()"));
deno_delete(d); deno_delete(d);
@ -175,16 +184,17 @@ TEST(LibDenoTest, DoubleGlobalErrorHandlingFails) {
TEST(LibDenoTest, DataBuf) { TEST(LibDenoTest, DataBuf) {
static int count = 0; static int count = 0;
static deno_buf data_buf_copy; static deno_buf data_buf_copy;
Deno* d = deno_new([](auto _, int req_id, deno_buf buf, deno_buf data_buf) { Deno* d = deno_new(snapshot,
count++; [](auto _, int req_id, deno_buf buf, deno_buf data_buf) {
data_buf.data_ptr[0] = 4; count++;
data_buf.data_ptr[1] = 2; data_buf.data_ptr[0] = 4;
data_buf_copy = data_buf; data_buf.data_ptr[1] = 2;
EXPECT_EQ(2u, buf.data_len); data_buf_copy = data_buf;
EXPECT_EQ(2u, data_buf.data_len); EXPECT_EQ(2u, buf.data_len);
EXPECT_EQ(buf.data_ptr[0], 1); EXPECT_EQ(2u, data_buf.data_len);
EXPECT_EQ(buf.data_ptr[1], 2); EXPECT_EQ(buf.data_ptr[0], 1);
}); EXPECT_EQ(buf.data_ptr[1], 2);
});
EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "DataBuf()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "DataBuf()"));
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
// data_buf was subsequently changed in JS, let's check that our copy reflects // data_buf was subsequently changed in JS, let's check that our copy reflects
@ -196,7 +206,7 @@ TEST(LibDenoTest, DataBuf) {
TEST(LibDenoTest, PromiseRejectCatchHandling) { TEST(LibDenoTest, PromiseRejectCatchHandling) {
static int count = 0; static int count = 0;
Deno* d = deno_new([](auto _, int req_id, auto buf, auto data_buf) { Deno* d = deno_new(snapshot, [](auto _, int req_id, auto buf, auto data_buf) {
// If no error, nothing should be sent, and count should not increment // If no error, nothing should be sent, and count should not increment
count++; count++;
}); });

View file

@ -10,22 +10,6 @@
#include "deno.h" #include "deno.h"
#include "internal.h" #include "internal.h"
extern const char deno_snapshot_start asm("deno_snapshot_start");
extern const char deno_snapshot_end asm("deno_snapshot_end");
#ifdef LIBDENO_TEST
asm(".data\n"
"deno_snapshot_start: .incbin \"gen/snapshot_libdeno_test.bin\"\n"
"deno_snapshot_end:\n"
".globl deno_snapshot_start;\n"
".globl deno_snapshot_end;");
#else
asm(".data\n"
"deno_snapshot_start: .incbin \"gen/snapshot_deno.bin\"\n"
"deno_snapshot_end:\n"
".globl deno_snapshot_start;\n"
".globl deno_snapshot_end;");
#endif // LIBDENO_TEST
namespace deno { namespace deno {
std::vector<InternalFieldData*> deserialized_data; std::vector<InternalFieldData*> deserialized_data;
@ -43,7 +27,11 @@ void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
deserialized_data.push_back(embedder_field); deserialized_data.push_back(embedder_field);
} }
Deno* NewFromSnapshot(deno_recv_cb cb) { } // namespace deno
extern "C" {
Deno* deno_new(deno_buf snapshot, deno_recv_cb cb) {
Deno* d = new Deno; Deno* d = new Deno;
d->currentArgs = nullptr; d->currentArgs = nullptr;
d->cb = cb; d->cb = cb;
@ -51,16 +39,16 @@ Deno* NewFromSnapshot(deno_recv_cb cb) {
v8::Isolate::CreateParams params; v8::Isolate::CreateParams params;
params.array_buffer_allocator = params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator(); v8::ArrayBuffer::Allocator::NewDefaultAllocator();
params.external_references = external_references; params.external_references = deno::external_references;
CHECK_NE(&deno_snapshot_start, nullptr); if (snapshot.data_ptr) {
int snapshot_len = d->snapshot.data = reinterpret_cast<const char*>(snapshot.data_ptr);
static_cast<int>(&deno_snapshot_end - &deno_snapshot_start); d->snapshot.raw_size = static_cast<int>(snapshot.data_len);
static v8::StartupData snapshot = {&deno_snapshot_start, snapshot_len}; params.snapshot_blob = &d->snapshot;
params.snapshot_blob = &snapshot; }
v8::Isolate* isolate = v8::Isolate::New(params); v8::Isolate* isolate = v8::Isolate::New(params);
AddIsolate(d, isolate); deno::AddIsolate(d, isolate);
v8::Locker locker(isolate); v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate); v8::Isolate::Scope isolate_scope(isolate);
@ -70,15 +58,10 @@ Deno* NewFromSnapshot(deno_recv_cb cb) {
v8::Context::New(isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(), v8::Context::New(isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
v8::MaybeLocal<v8::Value>(), v8::MaybeLocal<v8::Value>(),
v8::DeserializeInternalFieldsCallback( v8::DeserializeInternalFieldsCallback(
DeserializeInternalFields, nullptr)); deno::DeserializeInternalFields, nullptr));
d->context.Reset(d->isolate, context); d->context.Reset(d->isolate, context);
} }
return d; return d;
} }
} // namespace deno
extern "C" {
Deno* deno_new(deno_recv_cb cb) { return deno::NewFromSnapshot(cb); }
} }

View file

@ -1,8 +1,20 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license. // Copyright 2018 the Deno authors. All rights reserved. MIT license.
#include "deno.h" #include "test.h"
#include "testing/gtest/include/gtest/gtest.h" #include "file_util.h"
deno_buf snapshot = {nullptr, 0, nullptr, 0};
int main(int argc, char** argv) { int main(int argc, char** argv) {
// Load the snapshot.
std::string contents;
if (!deno::ReadFileToString(SNAPSHOT_PATH, &contents)) {
printf("Failed to read file %s\n", SNAPSHOT_PATH);
return 1;
}
snapshot.data_ptr =
reinterpret_cast<uint8_t*>(const_cast<char*>(contents.c_str()));
snapshot.data_len = contents.size();
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
deno_init(); deno_init();
deno_set_v8_flags(&argc, argv); deno_set_v8_flags(&argc, argv);

11
libdeno/test.h Normal file
View file

@ -0,0 +1,11 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
#ifndef TEST_H
#define TEST_H
#include "deno.h"
#include "testing/gtest/include/gtest/gtest.h"
extern deno_buf snapshot; // Loaded in libdeno/test.cc
const deno_buf empty = {nullptr, 0, nullptr, 0};
#endif // TEST_H

View file

@ -8,6 +8,7 @@ use deno_dir;
use errors::DenoError; use errors::DenoError;
use flags; use flags;
use libdeno; use libdeno;
use snapshot;
use futures::Future; use futures::Future;
use libc::c_void; use libc::c_void;
@ -109,7 +110,9 @@ impl Isolate {
unsafe { libdeno::deno_init() }; unsafe { libdeno::deno_init() };
}); });
let libdeno_isolate = unsafe { libdeno::deno_new(pre_dispatch) }; let libdeno_isolate = unsafe {
libdeno::deno_new(snapshot::deno_snapshot.clone(), pre_dispatch)
};
// This channel handles sending async messages back to the runtime. // This channel handles sending async messages back to the runtime.
let (tx, rx) = mpsc::channel::<(i32, Buf)>(); let (tx, rx) = mpsc::channel::<(i32, Buf)>();

View file

@ -1,6 +1,4 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license. // Copyright 2018 the Deno authors. All rights reserved. MIT license.
#![allow(dead_code)]
extern crate libc;
use libc::c_char; use libc::c_char;
use libc::c_int; use libc::c_int;
use libc::c_void; use libc::c_void;
@ -11,7 +9,7 @@ pub struct isolate {
} }
#[repr(C)] #[repr(C)]
#[derive(PartialEq)] #[derive(Clone, PartialEq)]
pub struct deno_buf { pub struct deno_buf {
pub alloc_ptr: *mut u8, pub alloc_ptr: *mut u8,
pub alloc_len: usize, pub alloc_len: usize,
@ -30,7 +28,7 @@ extern "C" {
pub fn deno_init(); pub fn deno_init();
pub fn deno_v8_version() -> *const c_char; pub fn deno_v8_version() -> *const c_char;
pub fn deno_set_v8_flags(argc: *mut c_int, argv: *mut *mut c_char); pub fn deno_set_v8_flags(argc: *mut c_int, argv: *mut *mut c_char);
pub fn deno_new(cb: DenoRecvCb) -> *const isolate; pub fn deno_new(snapshot: deno_buf, cb: DenoRecvCb) -> *const isolate;
pub fn deno_delete(i: *const isolate); pub fn deno_delete(i: *const isolate);
pub fn deno_last_exception(i: *const isolate) -> *const c_char; pub fn deno_last_exception(i: *const isolate) -> *const c_char;
pub fn deno_check_promise_errors(i: *const isolate); pub fn deno_check_promise_errors(i: *const isolate);

View file

@ -32,6 +32,7 @@ mod isolate;
mod libdeno; mod libdeno;
pub mod ops; pub mod ops;
mod resources; mod resources;
mod snapshot;
mod tokio_util; mod tokio_util;
mod tokio_write; mod tokio_write;
mod version; mod version;

18
src/snapshot.cc Normal file
View file

@ -0,0 +1,18 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
#include "deno.h"
extern "C" {
extern const char snapshot_start asm("snapshot_start");
extern const char snapshot_end asm("snapshot_end");
asm(".data\n"
"snapshot_start: .incbin \"gen/snapshot_deno.bin\"\n"
"snapshot_end:\n"
".globl snapshot_start;\n"
".globl snapshot_end;");
extern const deno_buf deno_snapshot = {
nullptr, 0, reinterpret_cast<uint8_t*>(const_cast<char*>(&snapshot_start)),
static_cast<size_t>(&snapshot_end - &snapshot_start)};
}

5
src/snapshot.rs Normal file
View file

@ -0,0 +1,5 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
use libdeno::deno_buf;
extern "C" {
pub static deno_snapshot: deno_buf;
}