1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-26 16:09:27 -05:00

use-snapshots build option for cross compile support. (#1852)

This commit is contained in:
andy finch 2019-03-04 18:09:35 -05:00 committed by Ryan Dahl
parent 77d7ad61f3
commit 75fe80d5a4
9 changed files with 209 additions and 66 deletions

View file

@ -76,6 +76,13 @@ fn main() {
} }
} }
// Enable snapshots for x64 builds
if env::var("CARGO_CFG_TARGET_ARCH").unwrap() == "x86_64" {
// Not related to v8_use_snapshot
// This only enables using pregenerated snapshots for isolate init
println!("cargo:rustc-cfg=feature=\"use-snapshot-init\"");
}
if !gn_out_path.join("build.ninja").exists() { if !gn_out_path.join("build.ninja").exists() {
let status = Command::new("python") let status = Command::new("python")
.env("DENO_BUILD_PATH", &gn_out_dir) .env("DENO_BUILD_PATH", &gn_out_dir)

View file

@ -2,6 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <iostream>
#include <string> #include <string>
#include "third_party/v8/include/libplatform/libplatform.h" #include "third_party/v8/include/libplatform/libplatform.h"
@ -10,6 +11,7 @@
#include "deno.h" #include "deno.h"
#include "exceptions.h" #include "exceptions.h"
#include "file_util.h"
#include "internal.h" #include "internal.h"
extern "C" { extern "C" {
@ -106,10 +108,11 @@ deno_buf deno_get_snapshot(Deno* d_) {
static std::unique_ptr<v8::Platform> platform; static std::unique_ptr<v8::Platform> platform;
void deno_init() { void deno_init() {
CHECK_NULL(platform.get()); if (platform.get() == nullptr) {
platform = v8::platform::NewDefaultPlatform(); platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get()); v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize(); v8::V8::Initialize();
}
} }
const char* deno_v8_version() { return v8::V8::GetVersion(); } const char* deno_v8_version() { return v8::V8::GetVersion(); }

View file

@ -1,6 +1,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::isolate::Buf; use crate::isolate::Buf;
use crate::isolate::IsolateState; use crate::isolate::IsolateState;
use crate::isolate_init;
use crate::msg; use crate::msg;
use crate::permissions::DenoPermissions; use crate::permissions::DenoPermissions;
use crate::resources; use crate::resources;
@ -50,6 +51,7 @@ impl ModuleMetaData {
fn lazy_start(parent_state: &Arc<IsolateState>) -> Resource { fn lazy_start(parent_state: &Arc<IsolateState>) -> Resource {
let mut cell = C_RID.lock().unwrap(); let mut cell = C_RID.lock().unwrap();
let isolate_init = isolate_init::compiler_isolate_init();
let permissions = DenoPermissions { let permissions = DenoPermissions {
allow_read: AtomicBool::new(true), allow_read: AtomicBool::new(true),
allow_write: AtomicBool::new(true), allow_write: AtomicBool::new(true),
@ -59,6 +61,7 @@ fn lazy_start(parent_state: &Arc<IsolateState>) -> Resource {
}; };
let rid = cell.get_or_insert_with(|| { let rid = cell.get_or_insert_with(|| {
let resource = workers::spawn( let resource = workers::spawn(
isolate_init,
parent_state.clone(), parent_state.clone(),
"compilerMain()".to_string(), "compilerMain()".to_string(),
permissions, permissions,

View file

@ -12,6 +12,7 @@ use crate::errors::DenoError;
use crate::errors::DenoResult; use crate::errors::DenoResult;
use crate::errors::RustOrJsError; use crate::errors::RustOrJsError;
use crate::flags; use crate::flags;
use crate::isolate_init::IsolateInit;
use crate::js_errors::apply_source_map; use crate::js_errors::apply_source_map;
use crate::libdeno; use crate::libdeno;
use crate::modules::Modules; use crate::modules::Modules;
@ -166,7 +167,7 @@ static DENO_INIT: Once = ONCE_INIT;
impl Isolate { impl Isolate {
pub fn new( pub fn new(
snapshot: libdeno::deno_buf, init: IsolateInit,
state: Arc<IsolateState>, state: Arc<IsolateState>,
dispatch: Dispatch, dispatch: Dispatch,
permissions: DenoPermissions, permissions: DenoPermissions,
@ -176,7 +177,10 @@ impl Isolate {
}); });
let config = libdeno::deno_config { let config = libdeno::deno_config {
will_snapshot: 0, will_snapshot: 0,
load_snapshot: snapshot, load_snapshot: match init.snapshot {
Some(s) => s,
None => libdeno::deno_buf::empty(),
},
shared: libdeno::deno_buf::empty(), // TODO Use for message passing. shared: libdeno::deno_buf::empty(), // TODO Use for message passing.
recv_cb: pre_dispatch, recv_cb: pre_dispatch,
}; };
@ -184,7 +188,7 @@ impl Isolate {
// 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::<(usize, Buf)>(); let (tx, rx) = mpsc::channel::<(usize, Buf)>();
Self { let new_isolate = Self {
libdeno_isolate, libdeno_isolate,
dispatch, dispatch,
rx, rx,
@ -194,7 +198,17 @@ impl Isolate {
modules: RefCell::new(Modules::new()), modules: RefCell::new(Modules::new()),
state, state,
permissions: Arc::new(permissions), permissions: Arc::new(permissions),
} };
// Run init script if present.
match init.init_script {
Some(init_script) => new_isolate
.execute2(init_script.filename.as_str(), init_script.source.as_str())
.unwrap(),
None => {}
};
new_isolate
} }
#[inline] #[inline]
@ -618,9 +632,12 @@ mod tests {
#[test] #[test]
fn test_dispatch_sync() { fn test_dispatch_sync() {
let state = IsolateState::mock(); let state = IsolateState::mock();
let snapshot = libdeno::deno_buf::empty(); let init = IsolateInit {
let permissions = DenoPermissions::default(); snapshot: None,
let isolate = Isolate::new(snapshot, state, dispatch_sync, permissions); init_script: None,
};
let isolate =
Isolate::new(init, state, dispatch_sync, DenoPermissions::default());
tokio_util::init(|| { tokio_util::init(|| {
isolate isolate
.execute( .execute(
@ -658,10 +675,16 @@ mod tests {
#[test] #[test]
fn test_metrics_sync() { fn test_metrics_sync() {
let state = IsolateState::mock(); let state = IsolateState::mock();
let snapshot = libdeno::deno_buf::empty(); let init = IsolateInit {
let permissions = DenoPermissions::default(); snapshot: None,
let isolate = init_script: None,
Isolate::new(snapshot, state, metrics_dispatch_sync, permissions); };
let isolate = Isolate::new(
init,
state,
metrics_dispatch_sync,
DenoPermissions::default(),
);
tokio_util::init(|| { tokio_util::init(|| {
// Verify that metrics have been properly initialized. // Verify that metrics have been properly initialized.
{ {
@ -694,10 +717,16 @@ mod tests {
#[test] #[test]
fn test_metrics_async() { fn test_metrics_async() {
let state = IsolateState::mock(); let state = IsolateState::mock();
let snapshot = libdeno::deno_buf::empty(); let init = IsolateInit {
let permissions = DenoPermissions::default(); snapshot: None,
let isolate = init_script: None,
Isolate::new(snapshot, state, metrics_dispatch_async, permissions); };
let isolate = Isolate::new(
init,
state,
metrics_dispatch_async,
DenoPermissions::default(),
);
tokio_util::init(|| { tokio_util::init(|| {
// Verify that metrics have been properly initialized. // Verify that metrics have been properly initialized.
{ {
@ -784,9 +813,12 @@ mod tests {
let (flags, rest_argv, _) = flags::set_flags(argv).unwrap(); let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
let state = Arc::new(IsolateState::new(flags, rest_argv, None)); let state = Arc::new(IsolateState::new(flags, rest_argv, None));
let snapshot = libdeno::deno_buf::empty(); let init = IsolateInit {
let permissions = DenoPermissions::default(); snapshot: None,
let mut isolate = Isolate::new(snapshot, state, dispatch_sync, permissions); init_script: None,
};
let mut isolate =
Isolate::new(init, state, dispatch_sync, DenoPermissions::default());
tokio_util::init(|| { tokio_util::init(|| {
isolate isolate
.execute_mod(filename, false) .execute_mod(filename, false)
@ -807,9 +839,12 @@ mod tests {
let (flags, rest_argv, _) = flags::set_flags(argv).unwrap(); let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
let state = Arc::new(IsolateState::new(flags, rest_argv, None)); let state = Arc::new(IsolateState::new(flags, rest_argv, None));
let snapshot = libdeno::deno_buf::empty(); let init = IsolateInit {
let permissions = DenoPermissions::default(); snapshot: None,
let mut isolate = Isolate::new(snapshot, state, dispatch_sync, permissions); init_script: None,
};
let mut isolate =
Isolate::new(init, state, dispatch_sync, DenoPermissions::default());
tokio_util::init(|| { tokio_util::init(|| {
isolate isolate
.execute_mod(filename, false) .execute_mod(filename, false)

86
src/isolate_init.rs Normal file
View file

@ -0,0 +1,86 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::libdeno::deno_buf;
pub struct IsolateInitScript {
pub source: String,
pub filename: String,
}
pub struct IsolateInit {
pub snapshot: Option<deno_buf>,
pub init_script: Option<IsolateInitScript>,
}
pub fn deno_isolate_init() -> IsolateInit {
if cfg!(not(feature = "check-only")) {
if cfg!(feature = "use-snapshot-init") {
let data =
include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/snapshot_deno.bin"));
unsafe {
IsolateInit {
snapshot: Some(deno_buf::from_raw_parts(data.as_ptr(), data.len())),
init_script: None,
}
}
} else {
#[cfg(not(feature = "check-only"))]
let source_bytes =
include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/bundle/main.js"));
#[cfg(feature = "check-only")]
let source_bytes = vec![];
IsolateInit {
snapshot: None,
init_script: Some(IsolateInitScript {
filename: "gen/bundle/main.js".to_string(),
source: std::str::from_utf8(source_bytes).unwrap().to_string(),
}),
}
}
} else {
IsolateInit {
snapshot: None,
init_script: None,
}
}
}
pub fn compiler_isolate_init() -> IsolateInit {
if cfg!(not(feature = "check-only")) {
if cfg!(feature = "use-snapshot-init") {
let data = include_bytes!(concat!(
env!("GN_OUT_DIR"),
"/gen/snapshot_compiler.bin"
));
unsafe {
IsolateInit {
snapshot: Some(deno_buf::from_raw_parts(data.as_ptr(), data.len())),
init_script: None,
}
}
} else {
#[cfg(not(feature = "check-only"))]
let source_bytes =
include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/bundle/compiler.js"));
#[cfg(feature = "check-only")]
let source_bytes = vec![];
IsolateInit {
snapshot: None,
init_script: Some(IsolateInitScript {
filename: "gen/bundle/compiler.js".to_string(),
source: std::str::from_utf8(source_bytes).unwrap().to_string(),
}),
}
}
} else {
IsolateInit {
snapshot: None,
init_script: None,
}
}
}

View file

@ -17,6 +17,7 @@ mod fs;
mod http_body; mod http_body;
mod http_util; mod http_util;
pub mod isolate; pub mod isolate;
pub mod isolate_init;
pub mod js_errors; pub mod js_errors;
pub mod libdeno; pub mod libdeno;
pub mod modules; pub mod modules;
@ -27,7 +28,6 @@ pub mod permissions;
mod repl; mod repl;
pub mod resolve_addr; pub mod resolve_addr;
pub mod resources; pub mod resources;
pub mod snapshot;
mod tokio_util; mod tokio_util;
mod tokio_write; mod tokio_write;
pub mod version; pub mod version;
@ -95,10 +95,10 @@ fn main() {
let should_display_info = flags.info; let should_display_info = flags.info;
let state = Arc::new(isolate::IsolateState::new(flags, rest_argv, None)); let state = Arc::new(isolate::IsolateState::new(flags, rest_argv, None));
let snapshot = snapshot::deno_snapshot(); let isolate_init = isolate_init::deno_isolate_init();
let permissions = permissions::DenoPermissions::from_flags(&state.flags); let permissions = permissions::DenoPermissions::from_flags(&state.flags);
let mut isolate = let mut isolate =
isolate::Isolate::new(snapshot, state, ops::dispatch, permissions); isolate::Isolate::new(isolate_init, state, ops::dispatch, permissions);
tokio_util::init(|| { tokio_util::init(|| {
// Setup runtime. // Setup runtime.

View file

@ -1863,13 +1863,13 @@ fn op_worker_post_message(
mod tests { mod tests {
use super::*; use super::*;
use crate::isolate::{Isolate, IsolateState}; use crate::isolate::{Isolate, IsolateState};
use crate::isolate_init::IsolateInit;
use crate::permissions::DenoPermissions; use crate::permissions::DenoPermissions;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
#[test] #[test]
fn fetch_module_meta_fails_without_read() { fn fetch_module_meta_fails_without_read() {
let state = IsolateState::mock(); let state = IsolateState::mock();
let snapshot = libdeno::deno_buf::empty();
let permissions = DenoPermissions { let permissions = DenoPermissions {
allow_read: AtomicBool::new(false), allow_read: AtomicBool::new(false),
allow_write: AtomicBool::new(true), allow_write: AtomicBool::new(true),
@ -1877,7 +1877,15 @@ mod tests {
allow_net: AtomicBool::new(true), allow_net: AtomicBool::new(true),
allow_run: AtomicBool::new(true), allow_run: AtomicBool::new(true),
}; };
let isolate = Isolate::new(snapshot, state, dispatch, permissions); let isolate = Isolate::new(
IsolateInit {
snapshot: None,
init_script: None,
},
state,
dispatch,
permissions,
);
let builder = &mut FlatBufferBuilder::new(); let builder = &mut FlatBufferBuilder::new();
let fetch_msg_args = msg::FetchModuleMetaDataArgs { let fetch_msg_args = msg::FetchModuleMetaDataArgs {
specifier: Some(builder.create_string("./somefile")), specifier: Some(builder.create_string("./somefile")),
@ -1907,7 +1915,6 @@ mod tests {
#[test] #[test]
fn fetch_module_meta_fails_without_write() { fn fetch_module_meta_fails_without_write() {
let state = IsolateState::mock(); let state = IsolateState::mock();
let snapshot = libdeno::deno_buf::empty();
let permissions = DenoPermissions { let permissions = DenoPermissions {
allow_read: AtomicBool::new(true), allow_read: AtomicBool::new(true),
allow_write: AtomicBool::new(false), allow_write: AtomicBool::new(false),
@ -1915,7 +1922,15 @@ mod tests {
allow_net: AtomicBool::new(true), allow_net: AtomicBool::new(true),
allow_run: AtomicBool::new(true), allow_run: AtomicBool::new(true),
}; };
let isolate = Isolate::new(snapshot, state, dispatch, permissions); let isolate = Isolate::new(
IsolateInit {
snapshot: None,
init_script: None,
},
state,
dispatch,
permissions,
);
let builder = &mut FlatBufferBuilder::new(); let builder = &mut FlatBufferBuilder::new();
let fetch_msg_args = msg::FetchModuleMetaDataArgs { let fetch_msg_args = msg::FetchModuleMetaDataArgs {
specifier: Some(builder.create_string("./somefile")), specifier: Some(builder.create_string("./somefile")),
@ -1945,7 +1960,6 @@ mod tests {
#[test] #[test]
fn fetch_module_meta_fails_without_net() { fn fetch_module_meta_fails_without_net() {
let state = IsolateState::mock(); let state = IsolateState::mock();
let snapshot = libdeno::deno_buf::empty();
let permissions = DenoPermissions { let permissions = DenoPermissions {
allow_read: AtomicBool::new(true), allow_read: AtomicBool::new(true),
allow_write: AtomicBool::new(true), allow_write: AtomicBool::new(true),
@ -1953,7 +1967,15 @@ mod tests {
allow_net: AtomicBool::new(false), allow_net: AtomicBool::new(false),
allow_run: AtomicBool::new(true), allow_run: AtomicBool::new(true),
}; };
let isolate = Isolate::new(snapshot, state, dispatch, permissions); let isolate = Isolate::new(
IsolateInit {
snapshot: None,
init_script: None,
},
state,
dispatch,
permissions,
);
let builder = &mut FlatBufferBuilder::new(); let builder = &mut FlatBufferBuilder::new();
let fetch_msg_args = msg::FetchModuleMetaDataArgs { let fetch_msg_args = msg::FetchModuleMetaDataArgs {
specifier: Some(builder.create_string("./somefile")), specifier: Some(builder.create_string("./somefile")),
@ -1983,7 +2005,6 @@ mod tests {
#[test] #[test]
fn fetch_module_meta_not_permission_denied_with_permissions() { fn fetch_module_meta_not_permission_denied_with_permissions() {
let state = IsolateState::mock(); let state = IsolateState::mock();
let snapshot = libdeno::deno_buf::empty();
let permissions = DenoPermissions { let permissions = DenoPermissions {
allow_read: AtomicBool::new(true), allow_read: AtomicBool::new(true),
allow_write: AtomicBool::new(true), allow_write: AtomicBool::new(true),
@ -1991,7 +2012,15 @@ mod tests {
allow_net: AtomicBool::new(true), allow_net: AtomicBool::new(true),
allow_run: AtomicBool::new(false), allow_run: AtomicBool::new(false),
}; };
let isolate = Isolate::new(snapshot, state, dispatch, permissions); let isolate = Isolate::new(
IsolateInit {
snapshot: None,
init_script: None,
},
state,
dispatch,
permissions,
);
let builder = &mut FlatBufferBuilder::new(); let builder = &mut FlatBufferBuilder::new();
let fetch_msg_args = msg::FetchModuleMetaDataArgs { let fetch_msg_args = msg::FetchModuleMetaDataArgs {
specifier: Some(builder.create_string("./somefile")), specifier: Some(builder.create_string("./somefile")),

View file

@ -1,26 +0,0 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::libdeno::deno_buf;
pub fn deno_snapshot() -> deno_buf {
#[cfg(not(feature = "check-only"))]
let data =
include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/snapshot_deno.bin"));
// The snapshot blob is not available when the Rust Language Server runs
// 'cargo check'.
#[cfg(feature = "check-only")]
let data = vec![];
unsafe { deno_buf::from_raw_parts(data.as_ptr(), data.len()) }
}
pub fn compiler_snapshot() -> deno_buf {
#[cfg(not(feature = "check-only"))]
let data =
include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/snapshot_compiler.bin"));
// The snapshot blob is not available when the Rust Language Server runs
// 'cargo check'.
#[cfg(feature = "check-only")]
let data = vec![];
unsafe { deno_buf::from_raw_parts(data.as_ptr(), data.len()) }
}

View file

@ -3,11 +3,11 @@ use crate::isolate::Buf;
use crate::isolate::Isolate; use crate::isolate::Isolate;
use crate::isolate::IsolateState; use crate::isolate::IsolateState;
use crate::isolate::WorkerChannels; use crate::isolate::WorkerChannels;
use crate::isolate_init::IsolateInit;
use crate::js_errors::JSErrorColor; use crate::js_errors::JSErrorColor;
use crate::ops; use crate::ops;
use crate::permissions::DenoPermissions; use crate::permissions::DenoPermissions;
use crate::resources; use crate::resources;
use crate::snapshot;
use crate::tokio_util; use crate::tokio_util;
use deno_core::JSError; use deno_core::JSError;
@ -24,6 +24,7 @@ pub struct Worker {
impl Worker { impl Worker {
pub fn new( pub fn new(
init: IsolateInit,
parent_state: &Arc<IsolateState>, parent_state: &Arc<IsolateState>,
permissions: DenoPermissions, permissions: DenoPermissions,
) -> (Self, WorkerChannels) { ) -> (Self, WorkerChannels) {
@ -39,8 +40,7 @@ impl Worker {
Some(internal_channels), Some(internal_channels),
)); ));
let snapshot = snapshot::compiler_snapshot(); let isolate = Isolate::new(init, state, ops::dispatch, permissions);
let isolate = Isolate::new(snapshot, state, ops::dispatch, permissions);
let worker = Worker { isolate }; let worker = Worker { isolate };
(worker, external_channels) (worker, external_channels)
@ -56,6 +56,7 @@ impl Worker {
} }
pub fn spawn( pub fn spawn(
init: IsolateInit,
state: Arc<IsolateState>, state: Arc<IsolateState>,
js_source: String, js_source: String,
permissions: DenoPermissions, permissions: DenoPermissions,
@ -68,7 +69,7 @@ pub fn spawn(
let builder = thread::Builder::new().name("worker".to_string()); let builder = thread::Builder::new().name("worker".to_string());
let _tid = builder let _tid = builder
.spawn(move || { .spawn(move || {
let (worker, external_channels) = Worker::new(&state, permissions); let (worker, external_channels) = Worker::new(init, &state, permissions);
let resource = resources::add_worker(external_channels); let resource = resources::add_worker(external_channels);
p.send(resource.clone()).unwrap(); p.send(resource.clone()).unwrap();
@ -95,10 +96,13 @@ pub fn spawn(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::isolate_init;
#[test] #[test]
fn test_spawn() { fn test_spawn() {
let isolate_init = isolate_init::compiler_isolate_init();
let resource = spawn( let resource = spawn(
isolate_init,
IsolateState::mock(), IsolateState::mock(),
r#" r#"
onmessage = function(e) { onmessage = function(e) {
@ -133,7 +137,9 @@ mod tests {
#[test] #[test]
fn removed_from_resource_table_on_close() { fn removed_from_resource_table_on_close() {
let isolate_init = isolate_init::compiler_isolate_init();
let resource = spawn( let resource = spawn(
isolate_init,
IsolateState::mock(), IsolateState::mock(),
"onmessage = () => close();".into(), "onmessage = () => close();".into(),
DenoPermissions::default(), DenoPermissions::default(),