Skip to content

Commit 037011b

Browse files
committed
WIP snapshot format
1 parent a725e89 commit 037011b

File tree

9 files changed

+259
-25
lines changed

9 files changed

+259
-25
lines changed

boa_cli/src/debug/snapshot.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use std::{
44
};
55

66
use boa_engine::{
7-
object::ObjectInitializer, snapshot::Serializer, Context, JsNativeError, JsObject, JsResult,
8-
JsValue, NativeFunction,
7+
object::ObjectInitializer, snapshot::SnapshotSerializer, Context, JsNativeError, JsObject,
8+
JsResult, JsValue, NativeFunction,
99
};
1010

1111
const SNAPSHOT_PATH: &str = "./snapshot.bin";
@@ -16,7 +16,7 @@ fn create(_: &JsValue, _: &[JsValue], context: &mut Context<'_>) -> JsResult<JsV
1616
};
1717

1818
let mut file = BufWriter::new(file);
19-
let mut serializer = Serializer::new(&mut file);
19+
let mut serializer = SnapshotSerializer::new(&mut file);
2020

2121
serializer.serialize(context).unwrap();
2222
serializer.finish().unwrap();

boa_engine/src/context/intrinsics.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ pub struct Intrinsics {
2626
pub(super) templates: ObjectTemplates,
2727
}
2828

29+
impl crate::snapshot::Serialize for Intrinsics {
30+
fn serialize(
31+
&self,
32+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
33+
) -> Result<(), crate::snapshot::SnapshotError> {
34+
self.constructors.serialize(s)?;
35+
Ok(())
36+
}
37+
}
38+
2939
impl Intrinsics {
3040
pub(crate) fn new(root_shape: &RootShape) -> Self {
3141
let constructors = StandardConstructors::default();
@@ -62,6 +72,17 @@ pub struct StandardConstructor {
6272
prototype: JsObject,
6373
}
6474

75+
impl crate::snapshot::Serialize for StandardConstructor {
76+
fn serialize(
77+
&self,
78+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
79+
) -> Result<(), crate::snapshot::SnapshotError> {
80+
self.constructor.serialize(s)?;
81+
self.prototype.serialize(s)?;
82+
Ok(())
83+
}
84+
}
85+
6586
impl Default for StandardConstructor {
6687
fn default() -> Self {
6788
Self {
@@ -153,6 +174,67 @@ pub struct StandardConstructors {
153174
segmenter: StandardConstructor,
154175
}
155176

177+
impl crate::snapshot::Serialize for StandardConstructors {
178+
fn serialize(
179+
&self,
180+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
181+
) -> Result<(), crate::snapshot::SnapshotError> {
182+
self.object.serialize(s)?;
183+
self.proxy.serialize(s)?;
184+
self.date.serialize(s)?;
185+
self.function.serialize(s)?;
186+
self.async_function.serialize(s)?;
187+
self.generator_function.serialize(s)?;
188+
self.async_generator_function.serialize(s)?;
189+
self.array.serialize(s)?;
190+
self.bigint.serialize(s)?;
191+
self.number.serialize(s)?;
192+
self.boolean.serialize(s)?;
193+
self.string.serialize(s)?;
194+
self.regexp.serialize(s)?;
195+
self.symbol.serialize(s)?;
196+
self.error.serialize(s)?;
197+
self.type_error.serialize(s)?;
198+
self.reference_error.serialize(s)?;
199+
self.range_error.serialize(s)?;
200+
self.syntax_error.serialize(s)?;
201+
self.eval_error.serialize(s)?;
202+
self.uri_error.serialize(s)?;
203+
self.aggregate_error.serialize(s)?;
204+
self.map.serialize(s)?;
205+
self.set.serialize(s)?;
206+
self.typed_array.serialize(s)?;
207+
self.typed_int8_array.serialize(s)?;
208+
self.typed_uint8_array.serialize(s)?;
209+
self.typed_uint8clamped_array.serialize(s)?;
210+
self.typed_int16_array.serialize(s)?;
211+
self.typed_uint16_array.serialize(s)?;
212+
self.typed_int32_array.serialize(s)?;
213+
self.typed_uint32_array.serialize(s)?;
214+
self.typed_bigint64_array.serialize(s)?;
215+
self.typed_biguint64_array.serialize(s)?;
216+
self.typed_float32_array.serialize(s)?;
217+
self.typed_float64_array.serialize(s)?;
218+
self.array_buffer.serialize(s)?;
219+
self.data_view.serialize(s)?;
220+
self.date_time_format.serialize(s)?;
221+
self.promise.serialize(s)?;
222+
self.weak_ref.serialize(s)?;
223+
self.weak_map.serialize(s)?;
224+
self.weak_set.serialize(s)?;
225+
#[cfg(feature = "intl")]
226+
self.collator.serialize(s)?;
227+
#[cfg(feature = "intl")]
228+
self.list_format.serialize(s)?;
229+
#[cfg(feature = "intl")]
230+
self.locale.serialize(s)?;
231+
#[cfg(feature = "intl")]
232+
self.segmenter.serialize(s)?;
233+
234+
Ok(())
235+
}
236+
}
237+
156238
impl Default for StandardConstructors {
157239
fn default() -> Self {
158240
Self {

boa_engine/src/context/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,9 +976,10 @@ where
976976
impl crate::snapshot::Serialize for Context<'_> {
977977
fn serialize(
978978
&self,
979-
s: &mut crate::snapshot::Serializer<'_>,
979+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
980980
) -> Result<(), crate::snapshot::SnapshotError> {
981981
s.write_bool(self.strict)?;
982+
self.realm.serialize(s)?;
982983
Ok(())
983984
}
984985
}

boa_engine/src/object/builtins/jsfunction.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ pub struct JsFunction {
1616
inner: JsObject,
1717
}
1818

19+
impl crate::snapshot::Serialize for JsFunction {
20+
fn serialize(
21+
&self,
22+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
23+
) -> Result<(), crate::snapshot::SnapshotError> {
24+
self.inner.serialize(s)?;
25+
Ok(())
26+
}
27+
}
28+
1929
impl JsFunction {
2030
/// Creates a new `JsFunction` from an object, without checking if the object is callable.
2131
pub(crate) fn from_object_unchecked(object: JsObject) -> Self {

boa_engine/src/object/jsobject.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ pub struct VTableObject {
5151
vtable: &'static InternalObjectMethods,
5252
}
5353

54+
impl crate::snapshot::Serialize for VTableObject {
55+
fn serialize(
56+
&self,
57+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
58+
) -> StdResult<(), crate::snapshot::SnapshotError> {
59+
Ok(())
60+
}
61+
}
62+
5463
impl Default for JsObject {
5564
fn default() -> Self {
5665
let data = ObjectData::ordinary();

boa_engine/src/realm.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ pub struct Realm {
2525
inner: Gc<Inner>,
2626
}
2727

28+
impl crate::snapshot::Serialize for Realm {
29+
fn serialize(
30+
&self,
31+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
32+
) -> Result<(), crate::snapshot::SnapshotError> {
33+
self.inner.serialize(s)?;
34+
Ok(())
35+
}
36+
}
37+
2838
impl Eq for Realm {}
2939

3040
impl PartialEq for Realm {
@@ -54,6 +64,16 @@ struct Inner {
5464
loaded_modules: GcRefCell<FxHashMap<JsString, Module>>,
5565
}
5666

67+
impl crate::snapshot::Serialize for Inner {
68+
fn serialize(
69+
&self,
70+
s: &mut crate::snapshot::SnapshotSerializer<'_>,
71+
) -> Result<(), crate::snapshot::SnapshotError> {
72+
self.intrinsics.serialize(s)?;
73+
Ok(())
74+
}
75+
}
76+
5777
impl Realm {
5878
/// Create a new Realm.
5979
#[inline]

boa_engine/src/snapshot/mod.rs

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
#![allow(dead_code)]
55

66
use std::{
7+
collections::hash_map::Entry,
78
fmt::{Debug, Display},
89
io::Write,
910
};
1011

11-
use crate::Context;
12+
use rustc_hash::FxHashMap;
13+
14+
use crate::{Context, JsObject};
1215

1316
/// TODO: doc
1417
#[derive(Debug, Clone, Copy)]
@@ -21,27 +24,40 @@ pub struct Header {
2124
/// TODO: doc
2225
pub trait Serialize {
2326
/// Serialize type
24-
fn serialize(&self, s: &mut Serializer<'_>) -> Result<(), SnapshotError>;
27+
fn serialize(&self, s: &mut SnapshotSerializer<'_>) -> Result<(), SnapshotError>;
2528
}
2629

2730
impl Serialize for Header {
28-
fn serialize(&self, s: &mut Serializer<'_>) -> Result<(), SnapshotError> {
31+
fn serialize(&self, s: &mut SnapshotSerializer<'_>) -> Result<(), SnapshotError> {
2932
s.write_bytes(&self.signature)?;
3033
s.write_u32(self.version)?;
3134
Ok(())
3235
}
3336
}
3437

38+
impl Serialize for JsObject {
39+
fn serialize(&self, s: &mut SnapshotSerializer<'_>) -> Result<(), SnapshotError> {
40+
let len = s.objects.len();
41+
let value = match s.objects.entry(self.clone()) {
42+
Entry::Occupied(entry) => *entry.get(),
43+
Entry::Vacant(entry) => *entry.insert(len as u32),
44+
};
45+
46+
s.write_u32(value)?;
47+
Ok(())
48+
}
49+
}
50+
3551
/// TODO: doc
3652
pub struct Snapshot {
3753
header: Header,
3854
bytes: Vec<u8>,
3955
}
4056

4157
/// TODO: doc
42-
pub struct Serializer<'writer> {
58+
pub struct SnapshotSerializer<'writer> {
4359
writer: &'writer mut dyn Write,
44-
// ... other state ...
60+
objects: FxHashMap<usize, u32>,
4561
}
4662

4763
/// TODO: doc
@@ -68,15 +84,27 @@ impl From<std::io::Error> for SnapshotError {
6884
}
6985
}
7086

71-
impl<'writer> Serializer<'writer> {
87+
impl<'writer> SnapshotSerializer<'writer> {
7288
/// TODO: doc
7389
pub fn new(writer: &'writer mut dyn Write) -> Self {
74-
Self { writer }
90+
Self {
91+
writer,
92+
objects: FxHashMap::default(),
93+
}
7594
}
7695

7796
/// Serialize the given [`Context`].
7897
pub fn serialize(&mut self, context: &mut Context<'_>) -> Result<(), SnapshotError> {
79-
let header = Header { signature: *b".boa", version: 256 };
98+
boa_gc::force_collect();
99+
100+
// boa_gc::walk_gc_alloc_pointers(|address| {
101+
102+
// });
103+
104+
let header = Header {
105+
signature: *b".boa",
106+
version: 256,
107+
};
80108

81109
header.serialize(self)?;
82110
context.serialize(self)
@@ -97,59 +125,59 @@ impl<'writer> Serializer<'writer> {
97125
}
98126
/// Writes a binary i8 to the dyn Write
99127
pub fn write_i8(&mut self, v: i8) -> Result<(), SnapshotError> {
100-
Ok(self.write_bytes(&v.to_ne_bytes())?)
128+
Ok(self.write_bytes(&v.to_le_bytes())?)
101129
}
102130

103131
/// Writes a binary little endian u16 to the dyn Write
104132
pub fn write_u16(&mut self, v: u16) -> Result<(), SnapshotError> {
105-
Ok(self.write_bytes(&v.to_ne_bytes())?)
133+
Ok(self.write_bytes(&v.to_le_bytes())?)
106134
}
107135
/// Writes a binary little endian i16 to the dyn Write
108136
pub fn write_i16(&mut self, v: i16) -> Result<(), SnapshotError> {
109-
Ok(self.write_bytes(&v.to_ne_bytes())?)
137+
Ok(self.write_bytes(&v.to_le_bytes())?)
110138
}
111139

112140
/// Writes a binary little endian u32 to the dyn Write
113141
pub fn write_u32(&mut self, v: u32) -> Result<(), SnapshotError> {
114-
Ok(self.write_bytes(&v.to_ne_bytes())?)
142+
Ok(self.write_bytes(&v.to_le_bytes())?)
115143
}
116144
/// Writes a binary little endian i32 to the dyn Write
117145
pub fn write_i32(&mut self, v: i32) -> Result<(), SnapshotError> {
118-
Ok(self.write_bytes(&v.to_ne_bytes())?)
146+
Ok(self.write_bytes(&v.to_le_bytes())?)
119147
}
120148

121149
/// Writes a binary little endian f32 to the dyn Write
122150
pub fn write_f32(&mut self, v: f32) -> Result<(), SnapshotError> {
123-
Ok(self.write_bytes(&v.to_ne_bytes())?)
151+
Ok(self.write_bytes(&v.to_le_bytes())?)
124152
}
125153
/// Writes a binary little endian f64 to the dyn Write
126154
pub fn write_f64(&mut self, v: f64) -> Result<(), SnapshotError> {
127-
Ok(self.write_bytes(&v.to_ne_bytes())?)
155+
Ok(self.write_bytes(&v.to_le_bytes())?)
128156
}
129157

130158
/// Writes a binary little endian u64 to the dyn Write
131159
pub fn write_u64(&mut self, v: u64) -> Result<(), SnapshotError> {
132-
Ok(self.write_bytes(&v.to_ne_bytes())?)
160+
Ok(self.write_bytes(&v.to_le_bytes())?)
133161
}
134162
/// Writes a binary little endian i64 to the dyn Write
135163
pub fn write_i64(&mut self, v: i64) -> Result<(), SnapshotError> {
136-
Ok(self.write_bytes(&v.to_ne_bytes())?)
164+
Ok(self.write_bytes(&v.to_le_bytes())?)
137165
}
138166
/// Writes a binary little endian u128 to the dyn Write
139167
pub fn write_u128(&mut self, v: u128) -> Result<(), SnapshotError> {
140-
Ok(self.write_bytes(&v.to_ne_bytes())?)
168+
Ok(self.write_bytes(&v.to_le_bytes())?)
141169
}
142170
/// Writes a binary little endian i128 to the dyn Write
143171
pub fn write_i128(&mut self, v: i128) -> Result<(), SnapshotError> {
144-
Ok(self.write_bytes(&v.to_ne_bytes())?)
172+
Ok(self.write_bytes(&v.to_le_bytes())?)
145173
}
146174
/// Writes a binary little endian usize as u64 to the dyn Write
147175
pub fn write_usize(&mut self, v: usize) -> Result<(), SnapshotError> {
148-
Ok(self.write_bytes(&(v as u64).to_ne_bytes())?)
176+
Ok(self.write_bytes(&(v as u64).to_le_bytes())?)
149177
}
150178
/// Writes a binary little endian isize as i64 to the dyn Write
151179
pub fn write_isize(&mut self, v: isize) -> Result<(), SnapshotError> {
152-
Ok(self.write_bytes(&(v as i64).to_ne_bytes())?)
180+
Ok(self.write_bytes(&(v as i64).to_le_bytes())?)
153181
}
154182
/// Writes a binary u8 array to the dyn Write
155183
pub fn write_buf(&mut self, v: &[u8]) -> Result<(), SnapshotError> {

0 commit comments

Comments
 (0)