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

Split a func into cold/hot parts, reducing binary size #80042

Merged
merged 1 commit into from
Jan 12, 2021
Merged
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
26 changes: 20 additions & 6 deletions compiler/rustc_target/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,22 +238,38 @@ pub enum Endian {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
#[derive(HashStable_Generic)]
pub struct Size {
// The top 3 bits are ALWAYS zero.
raw: u64,
Copy link
Member

@RalfJung RalfJung Mar 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am concerned by this comment that has been added here.

  • It doesn't seem actually enforced -- with Size::from_bytes I can easily construct a Size that violates this.
  • I would like to use this type to represent the size of any possible Rust object in Miri (including for things like size_of_val_raw, where the object does not actually have to exist in the address space). However, the size limit for that is isize::MAX. Something seems off if the compiler's Size type cannot be used to represent the size of all objects in the language...

Currently Miri enforces dl.obj_size_bound() as the size limit, but that is probably wrong -- it does not match what the reference and size_of_val_raw say the limit should be (they both say it is isize::MAX).

}

impl Size {
pub const ZERO: Size = Size { raw: 0 };

#[inline]
/// Rounds `bits` up to the next-higher byte boundary, if `bits` is
/// is not aligned.
pub fn from_bits(bits: impl TryInto<u64>) -> Size {
let bits = bits.try_into().ok().unwrap();

#[cold]
fn overflow(bits: u64) -> ! {
panic!("Size::from_bits({}) has overflowed", bits);
}

// This is the largest value of `bits` that does not cause overflow
// during rounding, and guarantees that the resulting number of bytes
// cannot cause overflow when multiplied by 8.
if bits > 0xffff_ffff_ffff_fff8 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also very confused by this check. bits / 8 + ((bits % 8) + 7) / 8 will never overflow I think, so what does this have to do with "overflow during rounding"?

overflow(bits);
}

// Avoid potential overflow from `bits + 7`.
Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8)
Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
}

#[inline]
pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
Size { raw: bytes.try_into().ok().unwrap() }
let bytes: u64 = bytes.try_into().ok().unwrap();
Size { raw: bytes }
}

#[inline]
Expand All @@ -268,9 +284,7 @@ impl Size {

#[inline]
pub fn bits(self) -> u64 {
self.bytes().checked_mul(8).unwrap_or_else(|| {
panic!("Size::bits: {} bytes in bits doesn't fit in u64", self.bytes())
})
self.raw << 3
}

#[inline]
Expand Down