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

librustc: Apply null pointer optimization to slices, closures & trait objects. #15406

Merged
merged 6 commits into from
Jul 8, 2014

Conversation

luqmana
Copy link
Member

@luqmana luqmana commented Jul 4, 2014

Extend the null ptr optimization to work with slices, closures, procs, & trait objects by using the internal pointers as the discriminant.

This decreases the size of Option<&[int]> (and similar) by one word.

1 as *const T
static PTR_MARKER: u8 = 0;
if self.ptr.is_null() {
&PTR_MARKER as *const _ as *const T
Copy link
Contributor

Choose a reason for hiding this comment

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

My stalled-out PR #14436 has a commit that relied on changing this to always return self.ptr. The reason given is that otherwise Vec::from_raw_parts(v.len(), v.cap(), v.as_mut_ptr()) will be incorrect. If at all possible, it would be nice to make that work while you're changing things.

My preference would be to make as_ptr() and as_mut_ptr() return null whenever appropriate, and instead do the null-test when constructing the slice.

@thestinger
Copy link
Contributor

The Vec<T> pointer is intended to always be non-null when the length is 0 and the only necessary change should be in the constructor functions. It will never pass the pointer to deallocate with a zero length.

@lilyball
Copy link
Contributor

lilyball commented Jul 4, 2014

@thestinger That can't be true, because a brand new Vec::new() has a null pointer. It's only non-null once it's capacity is nonzero. And preserving the behavior of Vec::new() starting with zero capacity is important.

@thestinger
Copy link
Contributor

As I said, the only required change is to the constructor functions. It can use an arbitrary non-null value because it will never pass it to deallocate. Passing a null pointer to deallocate has undefined behaviour and will likely cause a null pointer dereference at the moment.

@lilyball
Copy link
Contributor

lilyball commented Jul 4, 2014

@thestinger What benefit is there to having Vec use a non-null value for its pointer field? Right now, to the best of my knowledge, its pointer field is always valid (or null).

Slice should just deal with non-null itself.

That said, having Vec always have a non-null pointer and therefore always returning its pointer field from as_ptr() and as_mut_ptr() would resolve my concern, and so is better than what we're doing today and what this PR is doing, I just think it would be great if the need for a non-null Slice pointer could avoid leaking outside of Slice.

@thestinger
Copy link
Contributor

The non-null enum optimization can and should be extended to library types like Rc<T> and Vec<T>. It doesn't benefit in any way from the pointer being null and the code will be simpler if it's guaranteed not to be.

// pointer as the first element in the vector, but this will end up
// being Some(NULL) which is optimized to None. So instead we set ptr
// to some arbitrary non-null value which is fine since we never call
// deallocate on the ptr if cap is 0.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is misleading. It suggests the non-null pointer is purely because of 0-sized types (not 0-sized vectors!), but one would expect a size_of() test in that case. It should be rewritten to explain that Slice wants to never have a null pointer so it can benefit from null pointer optimization, and the easiest way to do that is to make Vec never have a null pointer.

bors added a commit that referenced this pull request Jul 8, 2014
Extend the null ptr optimization to work with slices, closures, procs, & trait objects by using the internal pointers as the discriminant.

This decreases the size of `Option<&[int]>` (and similar) by one word.
@bors bors closed this Jul 8, 2014
@bors bors merged commit fa8da9d into rust-lang:master Jul 8, 2014
@luqmana luqmana deleted the nop branch July 8, 2014 02:13
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 7, 2023
…r=lnicola

Don't provide `generate_default_from_new` when impl self ty is missing

Also don't provide the assist when the `Default` trait can't be found.

Part of rust-lang#15398
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants