Skip to content
Permalink
Browse files

core: snapshot improvements (denoland#2052)

* Moves how snapshots are supplied to the Isolate. Previously they were
  given by Behavior::startup_data() but it was only called once at
  startup. It makes more sense (and simplifies Behavior) to pass it to the
  constructor of Isolate.
* Adds new libdeno type deno_snapshot instead of overloading
  deno_buf.
* Adds new libdeno method to delete snapshot deno_snapshot_delete().
* Renames deno_get_snapshot() to deno_snapshot_new().
* Makes StartupData hold references to snapshots. This was implicit when
  it previously held a deno_buf but is made explicit now. Note that
  include_bytes!() returns a &'static [u8] and we want to avoid
  copying that.
  • Loading branch information...
ry committed Apr 8, 2019
1 parent cdb72af commit f7fdb90fd51e340ea598c055bb3573d3cdfbdaa8
@@ -4,24 +4,16 @@ use crate::ops;
use deno::deno_buf;
use deno::Behavior;
use deno::Op;
use deno::StartupData;
use std::sync::Arc;

/// Implements deno::Behavior for the main Deno command-line.
pub struct CliBehavior {
startup_data: Option<StartupData>,
pub state: Arc<IsolateState>,
}

impl CliBehavior {
pub fn new(
startup_data: Option<StartupData>,
state: Arc<IsolateState>,
) -> Self {
Self {
startup_data,
state,
}
pub fn new(state: Arc<IsolateState>) -> Self {
Self { state }
}
}

@@ -38,10 +30,6 @@ impl IsolateStateContainer for CliBehavior {
}

impl Behavior for CliBehavior {
fn startup_data(&mut self) -> Option<StartupData> {
self.startup_data.take()
}

fn dispatch(
&mut self,
control: &[u8],
@@ -17,7 +17,6 @@ use deno::Behavior;
use deno::Buf;
use deno::JSError;
use deno::Op;
use deno::StartupData;
use futures::future::*;
use futures::sync::oneshot;
use futures::Future;
@@ -70,10 +69,6 @@ impl IsolateStateContainer for &CompilerBehavior {
}

impl Behavior for CompilerBehavior {
fn startup_data(&mut self) -> Option<StartupData> {
Some(startup_data::compiler_isolate_init())
}

fn dispatch(
&mut self,
control: &[u8],
@@ -148,6 +143,7 @@ fn lazy_start(parent_state: Arc<IsolateState>) -> ResourceId {
cell
.get_or_insert_with(|| {
let worker_result = workers::spawn(
startup_data::compiler_isolate_init(),
CompilerBehavior::new(
parent_state.flags.clone(),
parent_state.argv.clone(),
@@ -13,6 +13,7 @@ use deno;
use deno::deno_mod;
use deno::Behavior;
use deno::JSError;
use deno::StartupData;
use futures::future::Either;
use futures::Async;
use futures::Future;
@@ -32,10 +33,10 @@ pub struct Isolate<B: Behavior> {
}

impl<B: DenoBehavior> Isolate<B> {
pub fn new(behavior: B) -> Isolate<B> {
pub fn new(startup_data: StartupData, behavior: B) -> Isolate<B> {
let state = behavior.state().clone();
Self {
inner: CoreIsolate::new(behavior),
inner: CoreIsolate::new(startup_data, behavior),
state,
}
}
@@ -270,8 +271,8 @@ mod tests {
let state = Arc::new(IsolateState::new(flags, rest_argv, None, false));
let state_ = state.clone();
tokio_util::run(lazy(move || {
let cli = CliBehavior::new(None, state.clone());
let mut isolate = Isolate::new(cli);
let cli = CliBehavior::new(state.clone());
let mut isolate = Isolate::new(StartupData::None, cli);
if let Err(err) = isolate.execute_mod(&filename, false) {
eprintln!("execute_mod err {:?}", err);
}
@@ -293,8 +294,8 @@ mod tests {
let state = Arc::new(IsolateState::new(flags, rest_argv, None, false));
let state_ = state.clone();
tokio_util::run(lazy(move || {
let cli = CliBehavior::new(None, state.clone());
let mut isolate = Isolate::new(cli);
let cli = CliBehavior::new(state.clone());
let mut isolate = Isolate::new(StartupData::None, cli);
if let Err(err) = isolate.execute_mod(&filename, false) {
eprintln!("execute_mod err {:?}", err);
}
@@ -107,9 +107,8 @@ fn main() {

let state = Arc::new(IsolateState::new(flags, rest_argv, None, false));
let state_ = state.clone();
let startup_data = startup_data::deno_isolate_init();
let cli = CliBehavior::new(Some(startup_data), state_);
let mut isolate = Isolate::new(cli);
let cli = CliBehavior::new(state_);
let mut isolate = Isolate::new(startup_data::deno_isolate_init(), cli);

let main_future = lazy(move || {
// Setup runtime.
@@ -15,6 +15,7 @@ use crate::resolve_addr::resolve_addr;
use crate::resources;
use crate::resources::table_entries;
use crate::resources::Resource;
use crate::startup_data;
use crate::tokio_util;
use crate::tokio_write;
use crate::version;
@@ -1865,6 +1866,7 @@ fn op_create_worker(
parent_state.argv.clone(),
);
match workers::spawn(
startup_data::deno_isolate_init(),
behavior,
&format!("USER-WORKER-{}", specifier),
workers::WorkerInit::Module(specifier.to_string()),
@@ -1,8 +1,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use deno::deno_buf;
use deno::{Script, StartupData};

pub fn deno_isolate_init() -> StartupData {
pub fn deno_isolate_init() -> StartupData<'static> {
if cfg!(feature = "no-snapshot-init") {
debug!("Deno isolate init without snapshots.");
#[cfg(not(feature = "check-only"))]
@@ -12,8 +11,8 @@ pub fn deno_isolate_init() -> StartupData {
let source_bytes = vec![];

StartupData::Script(Script {
filename: "gen/cli/bundle/main.js".to_string(),
source: std::str::from_utf8(&source_bytes[..]).unwrap().to_string(),
filename: "gen/cli/bundle/main.js",
source: std::str::from_utf8(&source_bytes[..]).unwrap(),
})
} else {
debug!("Deno isolate init with snapshots.");
@@ -23,13 +22,11 @@ pub fn deno_isolate_init() -> StartupData {
#[cfg(any(feature = "check-only", feature = "no-snapshot-init"))]
let data = vec![];

unsafe {
StartupData::Snapshot(deno_buf::from_raw_parts(data.as_ptr(), data.len()))
}
StartupData::Snapshot(data)
}
}

pub fn compiler_isolate_init() -> StartupData {
pub fn compiler_isolate_init() -> StartupData<'static> {
if cfg!(feature = "no-snapshot-init") {
debug!("Compiler isolate init without snapshots.");
#[cfg(not(feature = "check-only"))]
@@ -41,8 +38,8 @@ pub fn compiler_isolate_init() -> StartupData {
let source_bytes = vec![];

StartupData::Script(Script {
filename: "gen/cli/bundle/compiler.js".to_string(),
source: std::str::from_utf8(&source_bytes[..]).unwrap().to_string(),
filename: "gen/cli/bundle/compiler.js",
source: std::str::from_utf8(&source_bytes[..]).unwrap(),
})
} else {
debug!("Deno isolate init with snapshots.");
@@ -54,8 +51,6 @@ pub fn compiler_isolate_init() -> StartupData {
#[cfg(any(feature = "check-only", feature = "no-snapshot-init"))]
let data = vec![];

unsafe {
StartupData::Snapshot(deno_buf::from_raw_parts(data.as_ptr(), data.len()))
}
StartupData::Snapshot(data)
}
}
@@ -7,7 +7,6 @@ use crate::isolate_state::IsolateStateContainer;
use crate::isolate_state::WorkerChannels;
use crate::ops;
use crate::resources;
use crate::startup_data;
use deno::deno_buf;
use deno::Behavior;
use deno::Buf;
@@ -44,10 +43,6 @@ impl IsolateStateContainer for &UserWorkerBehavior {
}

impl Behavior for UserWorkerBehavior {
fn startup_data(&mut self) -> Option<StartupData> {
Some(startup_data::deno_isolate_init())
}

fn dispatch(
&mut self,
control: &[u8],
@@ -83,7 +78,7 @@ pub struct Worker<B: WorkerBehavior> {
}

impl<B: WorkerBehavior> Worker<B> {
pub fn new(mut behavior: B) -> Self {
pub fn new(startup_data: StartupData, mut behavior: B) -> Self {
let (worker_in_tx, worker_in_rx) = mpsc::channel::<Buf>(1);
let (worker_out_tx, worker_out_rx) = mpsc::channel::<Buf>(1);

@@ -92,7 +87,7 @@ impl<B: WorkerBehavior> Worker<B> {

behavior.set_internal_channels(internal_channels);

let isolate = Isolate::new(behavior);
let isolate = Isolate::new(startup_data, behavior);

Worker {
isolate,
@@ -129,12 +124,13 @@ pub enum WorkerInit {
}

pub fn spawn<B: WorkerBehavior + 'static>(
startup_data: StartupData,
behavior: B,
worker_debug_name: &str,
init: WorkerInit,
) -> Result<Worker<B>, RustOrJsError> {
let state = behavior.state().clone();
let mut worker = Worker::new(behavior);
let mut worker = Worker::new(startup_data, behavior);

worker
.execute(&format!("denoMain('{}')", worker_debug_name))
@@ -172,6 +168,7 @@ mod tests {
use crate::compiler::CompilerBehavior;
use crate::isolate_state::IsolateState;
use crate::js_errors::JSErrorColor;
use crate::startup_data;
use crate::tokio_util;
use futures::future::lazy;
use std::thread;
@@ -180,6 +177,7 @@ mod tests {
fn test_spawn() {
tokio_util::init(|| {
let worker_result = spawn(
startup_data::compiler_isolate_init(),
CompilerBehavior::new(
IsolateState::mock().flags.clone(),
IsolateState::mock().argv.clone(),
@@ -242,6 +240,7 @@ mod tests {
fn removed_from_resource_table_on_close() {
tokio_util::init(|| {
let worker_result = spawn(
startup_data::compiler_isolate_init(),
CompilerBehavior::new(
IsolateState::mock().flags.clone(),
IsolateState::mock().argv.clone(),
@@ -99,15 +99,6 @@ pub type HttpBenchOp = dyn Future<Item = i32, Error = std::io::Error> + Send;
struct HttpBench();

impl Behavior for HttpBench {
fn startup_data(&mut self) -> Option<StartupData> {
let js_source = include_str!("http_bench.js");

Some(StartupData::Script(Script {
source: js_source.to_string(),
filename: "http_bench.js".to_string(),
}))
}

fn dispatch(
&mut self,
control: &[u8],
@@ -168,7 +159,15 @@ fn main() {
// TODO currently isolate.execute() must be run inside tokio, hence the
// lazy(). It would be nice to not have that contraint. Probably requires
// using v8::MicrotasksPolicy::kExplicit
let isolate = deno::Isolate::new(HttpBench());

let js_source = include_str!("http_bench.js");

let startup_data = StartupData::Script(Script {
source: js_source,
filename: "http_bench.js",
});

let isolate = deno::Isolate::new(startup_data, HttpBench());

isolate.then(|r| {
js_check(r);
Oops, something went wrong.

0 comments on commit f7fdb90

Please sign in to comment.
You can’t perform that action at this time.