Use roc_serialize for subs serialization

This commit is contained in:
Ayaz Hafiz 2022-10-11 09:19:25 -05:00
parent ad10bf07c5
commit 46aab8ad8c
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
5 changed files with 58 additions and 113 deletions

View file

@ -11,5 +11,6 @@ roc_region = { path = "../region" }
roc_module = { path = "../module" }
roc_error_macros = {path="../../error_macros"}
roc_debug_flags = {path="../debug_flags"}
roc_serialize = {path="../serialize"}
bumpalo = { version = "3.11.0", features = ["collections"] }
static_assertions = "1.1.0"

View file

@ -112,19 +112,11 @@ impl SubsHeader {
}
}
unsafe fn slice_as_bytes<T>(slice: &[T]) -> &[u8] {
let ptr = slice.as_ptr();
let byte_length = std::mem::size_of::<T>() * slice.len();
unsafe { std::slice::from_raw_parts(ptr as *const u8, byte_length) }
}
fn round_to_multiple_of(value: usize, base: usize) -> usize {
(value + (base - 1)) / base * base
}
#[derive(Clone, Copy)]
struct SerializedTagName(SubsSlice<u8>);
use roc_serialize::bytes;
impl Subs {
pub fn serialize(
&self,
@ -139,15 +131,15 @@ impl Subs {
written = self.utable.serialize(writer, written)?;
written = Self::serialize_slice(&self.variables, writer, written)?;
written = bytes::serialize_slice(&self.variables, writer, written)?;
written = Self::serialize_tag_names(&self.tag_names, writer, written)?;
written = Self::serialize_slice(&self.closure_names, writer, written)?;
written = bytes::serialize_slice(&self.closure_names, writer, written)?;
written = Self::serialize_field_names(&self.field_names, writer, written)?;
written = Self::serialize_slice(&self.record_fields, writer, written)?;
written = Self::serialize_slice(&self.variable_slices, writer, written)?;
written = Self::serialize_slice(&self.unspecialized_lambda_sets, writer, written)?;
written = bytes::serialize_slice(&self.record_fields, writer, written)?;
written = bytes::serialize_slice(&self.variable_slices, writer, written)?;
written = bytes::serialize_slice(&self.unspecialized_lambda_sets, writer, written)?;
written = Self::serialize_uls_of_var(&self.uls_of_var, writer, written)?;
written = Self::serialize_slice(exposed_vars_by_symbol, writer, written)?;
written = bytes::serialize_slice(exposed_vars_by_symbol, writer, written)?;
Ok(written)
}
@ -167,9 +159,9 @@ impl Subs {
slices.push(slice);
}
let written = Self::serialize_slice(&slices, writer, written)?;
let written = bytes::serialize_slice(&slices, writer, written)?;
Self::serialize_slice(&buf, writer, written)
bytes::serialize_slice(&buf, writer, written)
}
/// Global tag names can be heap-allocated
@ -188,9 +180,9 @@ impl Subs {
slices.push(serialized);
}
let written = Self::serialize_slice(&slices, writer, written)?;
let written = bytes::serialize_slice(&slices, writer, written)?;
Self::serialize_slice(&buf, writer, written)
bytes::serialize_slice(&buf, writer, written)
}
fn serialize_uls_of_var(
@ -198,62 +190,25 @@ impl Subs {
writer: &mut impl std::io::Write,
written: usize,
) -> std::io::Result<usize> {
let (uls_keys, uls_vals) = uls_of_vars.0.unzip_slices();
let written = Self::serialize_slice(uls_keys, writer, written)?;
// Serialize the keys Vec<VecSet<Variable>> to &[[Variable]]
let mut var_buf: Vec<Variable> = Vec::new();
let mut uls_var_slices: Vec<VariableSubsSlice> = Vec::new();
for uls_vars in uls_vals {
let slice = SubsSlice::extend_new(&mut var_buf, uls_vars.iter().copied());
uls_var_slices.push(slice);
}
let written = Self::serialize_slice(&uls_var_slices, writer, written)?;
Self::serialize_slice(&var_buf, writer, written)
bytes::serialize_vec_map(
&uls_of_vars.0,
bytes::serialize_slice,
bytes::serialize_slice_of_slices,
writer,
written,
)
}
fn deserialize_uls_of_var(bytes: &[u8], length: usize, offset: usize) -> (UlsOfVar, usize) {
let (uls_keys, offset) = Self::deserialize_slice(bytes, length, offset);
let (vec_map, offset) = bytes::deserialize_vec_map(
bytes,
bytes::deserialize_vec,
bytes::deserialize_slice_of_slices,
length,
offset,
);
// The bytes are serialized as the list of uls_slices, and following all that, the vars
// that the uls_slices index into.
let (uls_slices, offset) =
Self::deserialize_slice::<VariableSubsSlice>(bytes, length, offset);
let (vars_slice, offset) = {
let total_uls_vars = uls_slices.iter().map(|s| s.len()).sum();
Self::deserialize_slice::<Variable>(bytes, total_uls_vars, offset)
};
let mut uls_var_lists = Vec::with_capacity(length);
for uls_slice in uls_slices {
let slice = &vars_slice[uls_slice.indices()];
uls_var_lists.push(VecSet::from_iter(slice.iter().copied()));
}
let uls_of_var = UlsOfVar(unsafe { VecMap::zip(uls_keys.to_vec(), uls_var_lists) });
(uls_of_var, offset)
}
pub(crate) fn serialize_slice<T>(
slice: &[T],
writer: &mut impl std::io::Write,
written: usize,
) -> std::io::Result<usize> {
let alignment = std::mem::align_of::<T>();
let padding_bytes = round_to_multiple_of(written, alignment) - written;
for _ in 0..padding_bytes {
writer.write_all(&[0])?;
}
let bytes_slice = unsafe { slice_as_bytes(slice) };
writer.write_all(bytes_slice)?;
Ok(written + padding_bytes + bytes_slice.len())
(UlsOfVar(vec_map), offset)
}
pub fn deserialize(bytes: &[u8]) -> (Self, &[(Symbol, Variable)]) {
@ -264,23 +219,24 @@ impl Subs {
let (utable, offset) = UnificationTable::deserialize(bytes, header.utable as usize, offset);
let (variables, offset) = Self::deserialize_slice(bytes, header.variables as usize, offset);
let (variables, offset) =
bytes::deserialize_slice(bytes, header.variables as usize, offset);
let (tag_names, offset) =
Self::deserialize_tag_names(bytes, header.tag_names as usize, offset);
let (closure_names, offset) =
Self::deserialize_slice(bytes, header.closure_names as usize, offset);
bytes::deserialize_slice(bytes, header.closure_names as usize, offset);
let (field_names, offset) =
Self::deserialize_field_names(bytes, header.field_names as usize, offset);
let (record_fields, offset) =
Self::deserialize_slice(bytes, header.record_fields as usize, offset);
bytes::deserialize_slice(bytes, header.record_fields as usize, offset);
let (variable_slices, offset) =
Self::deserialize_slice(bytes, header.variable_slices as usize, offset);
bytes::deserialize_slice(bytes, header.variable_slices as usize, offset);
let (unspecialized_lambda_sets, offset) =
Self::deserialize_slice(bytes, header.unspecialized_lambda_sets as usize, offset);
bytes::deserialize_slice(bytes, header.unspecialized_lambda_sets as usize, offset);
let (uls_of_var, offset) =
Self::deserialize_uls_of_var(bytes, header.uls_of_var as usize, offset);
let (exposed_vars_by_symbol, _) =
Self::deserialize_slice(bytes, header.exposed_vars_by_symbol as usize, offset);
bytes::deserialize_slice(bytes, header.exposed_vars_by_symbol as usize, offset);
(
Self {
@ -305,7 +261,7 @@ impl Subs {
length: usize,
offset: usize,
) -> (Vec<Lowercase>, usize) {
let (slices, mut offset) = Self::deserialize_slice::<SubsSlice<u8>>(bytes, length, offset);
let (slices, mut offset) = bytes::deserialize_slice::<SubsSlice<u8>>(bytes, length, offset);
let string_slice = &bytes[offset..];
@ -323,7 +279,7 @@ impl Subs {
fn deserialize_tag_names(bytes: &[u8], length: usize, offset: usize) -> (Vec<TagName>, usize) {
let (slices, mut offset) =
Self::deserialize_slice::<SerializedTagName>(bytes, length, offset);
bytes::deserialize_slice::<SerializedTagName>(bytes, length, offset);
let string_slice = &bytes[offset..];
@ -340,24 +296,6 @@ impl Subs {
(tag_names, offset)
}
pub(crate) fn deserialize_slice<T>(
bytes: &[u8],
length: usize,
mut offset: usize,
) -> (&[T], usize) {
let alignment = std::mem::align_of::<T>();
let size = std::mem::size_of::<T>();
offset = round_to_multiple_of(offset, alignment);
let byte_length = length * size;
let byte_slice = &bytes[offset..][..byte_length];
let slice = unsafe { std::slice::from_raw_parts(byte_slice.as_ptr() as *const T, length) };
(slice, offset + byte_length)
}
}
/// Mapping of variables to [Content::LambdaSet]s containing unspecialized lambda sets depending on

View file

@ -1,6 +1,7 @@
use std::hint::unreachable_unchecked;
use crate::subs::{Content, Descriptor, Mark, OptVariable, Rank, Variable, VariableSubsSlice};
use roc_serialize::bytes;
#[derive(Clone, Default)]
pub struct UnificationTable {
@ -376,9 +377,7 @@ impl UnificationTable {
writer: &mut impl std::io::Write,
mut written: usize,
) -> std::io::Result<usize> {
use crate::subs::Subs;
written = Subs::serialize_slice(&self.contents, writer, written)?;
written = bytes::serialize_slice(&self.contents, writer, written)?;
let mut ranks = Vec::new();
let mut marks = Vec::new();
@ -406,22 +405,20 @@ impl UnificationTable {
}
}
written = Subs::serialize_slice(&ranks, writer, written)?;
written = Subs::serialize_slice(&marks, writer, written)?;
written = Subs::serialize_slice(&copies, writer, written)?;
written = Subs::serialize_slice(&redirects, writer, written)?;
written = bytes::serialize_slice(&ranks, writer, written)?;
written = bytes::serialize_slice(&marks, writer, written)?;
written = bytes::serialize_slice(&copies, writer, written)?;
written = bytes::serialize_slice(&redirects, writer, written)?;
Ok(written)
}
pub(crate) fn deserialize(bytes: &[u8], length: usize, offset: usize) -> (Self, usize) {
use crate::subs::Subs;
let (contents, offset) = Subs::deserialize_slice::<Content>(bytes, length, offset);
let (ranks, offset) = Subs::deserialize_slice::<Rank>(bytes, length, offset);
let (marks, offset) = Subs::deserialize_slice::<Mark>(bytes, length, offset);
let (copies, offset) = Subs::deserialize_slice::<OptVariable>(bytes, length, offset);
let (redirects, offset) = Subs::deserialize_slice::<OptVariable>(bytes, length, offset);
let (contents, offset) = bytes::deserialize_slice::<Content>(bytes, length, offset);
let (ranks, offset) = bytes::deserialize_slice::<Rank>(bytes, length, offset);
let (marks, offset) = bytes::deserialize_slice::<Mark>(bytes, length, offset);
let (copies, offset) = bytes::deserialize_slice::<OptVariable>(bytes, length, offset);
let (redirects, offset) = bytes::deserialize_slice::<OptVariable>(bytes, length, offset);
let mut metadata = Vec::with_capacity(ranks.len());