pub mod config;
pub mod manager;
pub mod snapshot;
pub use config::*;
pub use manager::*;
pub use snapshot::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::OnceLock;
pub const SNAPSHOT_MAGIC: &[u8; 8] = b"AMBER_V3";
static CLI_STARTUP_SNAPSHOT: AtomicBool = AtomicBool::new(true);
pub fn enable_startup_snapshot_for_cli() {
CLI_STARTUP_SNAPSHOT.store(true, Ordering::SeqCst);
}
pub fn startup_snapshot_name() -> String {
let mode = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};
let v8_version = rusty_v8::V8::get_version();
format!(
"amberjs-startup-v{}-{}-v8-{}-warmup-v3.bin",
env!("CARGO_PKG_VERSION"),
mode,
v8_version
)
}
pub fn startup_cache_dir() -> std::path::PathBuf {
std::env::var_os("AMBER_SNAPSHOT_DIR")
.map(std::path::PathBuf::from)
.or_else(|| {
std::env::var_os("HOME").map(|home| {
std::path::PathBuf::from(home)
.join(".cache")
.join("amberjs")
})
})
.unwrap_or_else(std::env::temp_dir)
}
pub fn startup_blob_path() -> std::path::PathBuf {
startup_cache_dir().join(startup_snapshot_name())
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct SnapshotStatusInfo {
pub enabled: bool,
pub path: std::path::PathBuf,
pub exists: bool,
pub size_bytes: u64,
pub version: &'static str,
}
pub fn startup_blob_status() -> SnapshotStatusInfo {
let path = startup_blob_path();
let (exists, size_bytes) = match std::fs::metadata(&path) {
Ok(m) => (true, m.len()),
Err(_) => (false, 0),
};
let enabled = !std::env::var_os("AMBER_DISABLE_STARTUP_SNAPSHOT").is_some()
&& (CLI_STARTUP_SNAPSHOT.load(Ordering::SeqCst)
|| std::env::var_os("AMBER_STARTUP_SNAPSHOT").is_some());
SnapshotStatusInfo {
enabled,
path,
exists,
size_bytes,
version: env!("CARGO_PKG_VERSION"),
}
}
pub fn clear_startup_blob_cache() -> std::io::Result<bool> {
let path = startup_blob_path();
if path.exists() {
std::fs::remove_file(path)?;
Ok(true)
} else {
Ok(false)
}
}
pub fn rebuild_startup_blob() -> anyhow::Result<usize> {
let path = startup_blob_path();
if let Some(parent) = path.parent() {
let _ = std::fs::create_dir_all(parent);
}
let manager = SnapshotManager::new(SnapshotConfig::default());
let snapshot = manager.generate_snapshot()?;
let payload = wrap_snapshot_payload(&snapshot.snapshot_data);
std::fs::write(&path, &payload)?;
Ok(snapshot.snapshot_data.len())
}
fn wrap_snapshot_payload(data: &[u8]) -> Vec<u8> {
let version_bytes = env!("CARGO_PKG_VERSION").as_bytes();
let mut payload = Vec::with_capacity(8 + 2 + version_bytes.len() + 8 + data.len());
payload.extend_from_slice(SNAPSHOT_MAGIC);
payload.extend_from_slice(&(version_bytes.len() as u16).to_le_bytes());
payload.extend_from_slice(version_bytes);
payload.extend_from_slice(&(data.len() as u64).to_le_bytes());
payload.extend_from_slice(data);
payload
}
fn unwrap_snapshot_bounds(bytes: &[u8]) -> Option<(usize, usize)> {
if bytes.len() < 8 + 2 + 8 {
return None;
}
if &bytes[0..8] != SNAPSHOT_MAGIC {
return None;
}
let vlen = u16::from_le_bytes([bytes[8], bytes[9]]) as usize;
if bytes.len() < 10 + vlen + 8 {
return None;
}
let version = std::str::from_utf8(&bytes[10..10 + vlen]).ok()?;
if version != env!("CARGO_PKG_VERSION") {
return None;
}
let dlen_offset = 10 + vlen;
let mut dlen_bytes = [0u8; 8];
dlen_bytes.copy_from_slice(&bytes[dlen_offset..dlen_offset + 8]);
let dlen = u64::from_le_bytes(dlen_bytes) as usize;
let data_offset = dlen_offset + 8;
if bytes.len() < data_offset + dlen {
return None;
}
Some((data_offset, dlen))
}
pub fn unwrap_snapshot_payload(bytes: &[u8]) -> Option<Vec<u8>> {
let (offset, len) = unwrap_snapshot_bounds(bytes)?;
Some(bytes[offset..offset + len].to_vec())
}
pub fn cached_startup_blob() -> Option<&'static [u8]> {
if std::env::var_os("AMBER_DISABLE_STARTUP_SNAPSHOT").is_some() {
return None;
}
let enabled = CLI_STARTUP_SNAPSHOT.load(Ordering::SeqCst)
|| std::env::var_os("AMBER_STARTUP_SNAPSHOT").is_some();
if !enabled {
return None;
}
static BLOB: OnceLock<Option<&'static [u8]>> = OnceLock::new();
*BLOB.get_or_init(load_or_create_startup_blob_cow)
}
pub fn is_startup_blob_cow_active() -> bool {
cached_startup_blob().is_some()
}
fn load_or_create_startup_blob_cow() -> Option<&'static [u8]> {
let path = startup_blob_path();
if let Ok(file) = std::fs::File::open(&path) {
if let Ok(mmap) = unsafe { memmap2::Mmap::map(&file) } {
#[cfg(unix)]
{
let _ = mmap.advise(memmap2::Advice::WillNeed);
}
if let Some((offset, len)) = unwrap_snapshot_bounds(&mmap) {
let leaked_mmap: &'static memmap2::Mmap = Box::leak(Box::new(mmap));
return Some(&leaked_mmap[offset..offset + len]);
} else {
let _ = std::fs::remove_file(&path);
}
}
}
let manager = SnapshotManager::new(SnapshotConfig::default());
let snapshot = match manager.generate_snapshot() {
Ok(s) => s,
Err(e) => {
eprintln!("Warning: failed to generate V8 startup snapshot: {e}");
return None;
}
};
if let Some(parent) = path.parent() {
let _ = std::fs::create_dir_all(parent);
}
let payload = wrap_snapshot_payload(&snapshot.snapshot_data);
if std::fs::write(&path, &payload).is_ok() {
if let Ok(file) = std::fs::File::open(&path) {
if let Ok(mmap) = unsafe { memmap2::Mmap::map(&file) } {
#[cfg(unix)]
{
let _ = mmap.advise(memmap2::Advice::WillNeed);
}
if let Some((offset, len)) = unwrap_snapshot_bounds(&mmap) {
let leaked_mmap: &'static memmap2::Mmap = Box::leak(Box::new(mmap));
return Some(&leaked_mmap[offset..offset + len]);
}
}
}
}
let leaked_vec: &'static Vec<u8> = Box::leak(Box::new(snapshot.snapshot_data));
Some(leaked_vec.as_slice())
}