Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove MemEncoder #111086

Merged
merged 3 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4059,6 +4059,7 @@ dependencies = [
"indexmap",
"rustc_macros",
"smallvec",
"tempfile",
"thin-vec",
]

Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
use rustc_session::cstore::{self, CrateSource};
use rustc_session::utils::NativeLibKind;
use rustc_span::symbol::Symbol;
use rustc_span::DebuggerVisualizerFile;
use std::collections::BTreeSet;
use std::io;
use std::path::{Path, PathBuf};

pub mod back;
Expand Down Expand Up @@ -215,8 +216,11 @@ const RLINK_MAGIC: &[u8] = b"rustlink";
const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");

impl CodegenResults {
pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> {
let mut encoder = MemEncoder::new();
pub fn serialize_rlink(
rlink_file: &Path,
codegen_results: &CodegenResults,
) -> Result<usize, io::Error> {
let mut encoder = FileEncoder::new(rlink_file)?;
encoder.emit_raw_bytes(RLINK_MAGIC);
// `emit_raw_bytes` is used to make sure that the version representation does not depend on
// Encoder's inner representation of `u32`.
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_interface/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,8 @@ impl Linker {
}

if sess.opts.unstable_opts.no_link {
let encoded = CodegenResults::serialize_rlink(&codegen_results);
let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
std::fs::write(&rlink_file, encoded)
CodegenResults::serialize_rlink(&rlink_file, &codegen_results)
.map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
return Ok(());
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_serialize/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ thin-vec = "0.2.12"

[dev-dependencies]
rustc_macros = { path = "../rustc_macros" }
tempfile = "3.2"
129 changes: 4 additions & 125 deletions compiler/rustc_serialize/src/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,118 +12,14 @@ use std::ptr;
// Encoder
// -----------------------------------------------------------------------------

pub struct MemEncoder {
pub data: Vec<u8>,
}

impl MemEncoder {
pub fn new() -> MemEncoder {
MemEncoder { data: vec![] }
}

#[inline]
pub fn position(&self) -> usize {
self.data.len()
}

pub fn finish(self) -> Vec<u8> {
self.data
}
}

macro_rules! write_leb128 {
($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{
const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>();
let old_len = $enc.data.len();

if MAX_ENCODED_LEN > $enc.data.capacity() - old_len {
$enc.data.reserve(MAX_ENCODED_LEN);
}

// SAFETY: The above check and `reserve` ensures that there is enough
// room to write the encoded value to the vector's internal buffer.
unsafe {
let buf = &mut *($enc.data.as_mut_ptr().add(old_len)
as *mut [MaybeUninit<u8>; MAX_ENCODED_LEN]);
let encoded = leb128::$fun(buf, $value);
$enc.data.set_len(old_len + encoded.len());
}
}};
}

impl Encoder for MemEncoder {
#[inline]
fn emit_usize(&mut self, v: usize) {
write_leb128!(self, v, usize, write_usize_leb128)
}

#[inline]
fn emit_u128(&mut self, v: u128) {
write_leb128!(self, v, u128, write_u128_leb128);
}

#[inline]
fn emit_u64(&mut self, v: u64) {
write_leb128!(self, v, u64, write_u64_leb128);
}

#[inline]
fn emit_u32(&mut self, v: u32) {
write_leb128!(self, v, u32, write_u32_leb128);
}

#[inline]
fn emit_u16(&mut self, v: u16) {
self.data.extend_from_slice(&v.to_le_bytes());
}

#[inline]
fn emit_u8(&mut self, v: u8) {
self.data.push(v);
}

#[inline]
fn emit_isize(&mut self, v: isize) {
write_leb128!(self, v, isize, write_isize_leb128)
}

#[inline]
fn emit_i128(&mut self, v: i128) {
write_leb128!(self, v, i128, write_i128_leb128)
}

#[inline]
fn emit_i64(&mut self, v: i64) {
write_leb128!(self, v, i64, write_i64_leb128)
}

#[inline]
fn emit_i32(&mut self, v: i32) {
write_leb128!(self, v, i32, write_i32_leb128)
}

#[inline]
fn emit_i16(&mut self, v: i16) {
self.data.extend_from_slice(&v.to_le_bytes());
}

#[inline]
fn emit_raw_bytes(&mut self, s: &[u8]) {
self.data.extend_from_slice(s);
}
}

pub type FileEncodeResult = Result<usize, io::Error>;

/// `FileEncoder` encodes data to file via fixed-size buffer.
///
/// When encoding large amounts of data to a file, using `FileEncoder` may be
/// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
/// `Vec` to file, as the latter uses as much memory as there is encoded data,
/// while the former uses the fixed amount of memory allocated to the buffer.
/// `FileEncoder` also has the advantage of not needing to reallocate as data
/// is appended to it, but the disadvantage of requiring more error handling,
/// which has some runtime overhead.
/// There used to be a `MemEncoder` type that encoded all the data into a
/// `Vec`. `FileEncoder` is better because its memory use is determined by the
/// size of the buffer, rather than the full length of the encoded data, and
/// because it doesn't need to reallocate memory along the way.
pub struct FileEncoder {
/// The input buffer. For adequate performance, we need more control over
/// buffering than `BufWriter` offers. If `BufWriter` ever offers a raw
Expand Down Expand Up @@ -645,13 +541,6 @@ impl<'a> Decoder for MemDecoder<'a> {

// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
// since the default implementations call `encode` on their slices internally.
impl Encodable<MemEncoder> for [u8] {
fn encode(&self, e: &mut MemEncoder) {
Encoder::emit_usize(e, self.len());
e.emit_raw_bytes(self);
}
}

impl Encodable<FileEncoder> for [u8] {
fn encode(&self, e: &mut FileEncoder) {
Encoder::emit_usize(e, self.len());
Expand All @@ -675,16 +564,6 @@ impl IntEncodedWithFixedSize {
pub const ENCODED_SIZE: usize = 8;
}

impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
#[inline]
fn encode(&self, e: &mut MemEncoder) {
let _start_pos = e.position();
e.emit_raw_bytes(&self.0.to_le_bytes());
let _end_pos = e.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
}
}

impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
#[inline]
fn encode(&self, e: &mut FileEncoder) {
Expand Down
56 changes: 49 additions & 7 deletions compiler/rustc_serialize/tests/opaque.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![allow(rustc::internal)]

use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::opaque::{MemDecoder, FileEncoder};
use rustc_serialize::{Decodable, Encodable};
use std::fmt::Debug;
use std::fs;

#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
struct Struct {
Expand All @@ -27,18 +28,21 @@ struct Struct {
}

fn check_round_trip<
T: Encodable<MemEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
T: Encodable<FileEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
>(
values: Vec<T>,
) {
let mut encoder = MemEncoder::new();
let tmpfile = tempfile::NamedTempFile::new().unwrap();
let tmpfile = tmpfile.path();

let mut encoder = FileEncoder::new(&tmpfile).unwrap();
for value in &values {
Encodable::encode(value, &mut encoder);
}
encoder.finish().unwrap();

let data = encoder.finish();
let data = fs::read(&tmpfile).unwrap();
let mut decoder = MemDecoder::new(&data[..], 0);

for value in values {
let decoded = Decodable::decode(&mut decoder);
assert_eq!(value, decoded);
Expand All @@ -61,7 +65,7 @@ fn test_u8() {

#[test]
fn test_u16() {
for i in u16::MIN..u16::MAX {
for i in [u16::MIN, 111, 3333, 55555, u16::MAX] {
check_round_trip(vec![1, 2, 3, i, i, i]);
}
}
Expand Down Expand Up @@ -92,7 +96,7 @@ fn test_i8() {

#[test]
fn test_i16() {
for i in i16::MIN..i16::MAX {
for i in [i16::MIN, -100, 0, 101, i16::MAX] {
check_round_trip(vec![-1, 2, -3, i, i, i, 2]);
}
}
Expand Down Expand Up @@ -251,3 +255,41 @@ fn test_tuples() {
check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]);
check_round_trip(vec![(String::new(), "some string".to_string())]);
}

#[test]
fn test_unit_like_struct() {
#[derive(Encodable, Decodable, PartialEq, Debug)]
struct UnitLikeStruct;

check_round_trip(vec![UnitLikeStruct]);
}

#[test]
fn test_box() {
#[derive(Encodable, Decodable, PartialEq, Debug)]
struct A {
foo: Box<[bool]>,
}

let obj = A { foo: Box::new([true, false]) };
check_round_trip(vec![obj]);
}

#[test]
fn test_cell() {
use std::cell::{Cell, RefCell};

#[derive(Encodable, Decodable, PartialEq, Debug)]
struct A {
baz: isize,
}

#[derive(Encodable, Decodable, PartialEq, Debug)]
struct B {
foo: Cell<bool>,
bar: RefCell<A>,
}

let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
check_round_trip(vec![obj]);
}
34 changes: 0 additions & 34 deletions tests/ui-fulldeps/deriving-encodable-decodable-box.rs

This file was deleted.

44 changes: 0 additions & 44 deletions tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs

This file was deleted.

Loading