-
Notifications
You must be signed in to change notification settings - Fork 9
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
Can explicit allocator calls be removed? #101
Comments
I think we should be conservative with custom (non-global) allocators and just treat them as a library concept. Some allocators can be used for extremely specialized cases, such as allocating GPU memory, where you really want to maintain strict control over what allocations are made and not leave its interpretation up to the compiler. Also as per #21 we will eventually want to deprecate the |
(I was just using If I do concur, however, that this is quite likely too subtle/implicit, and the magic barrier should just be in the definition of Footnotes
|
Could we solve this by adding a wrapper struct
|
In terms of semantics, that would probably work. The one thing I'd be careful of is to make sure that it's clear that In terms of actual implementation, removable allocation is IIRC based on LLVM treating The other potential option is some sort of |
It is absolutely the intent that calls to
__rust_alloc
/__rust_dealloc
can be removed. It happens in practice. As such, calls toGlobal.alloc
or other allocation directly onGlobal
, as well as the free functions, can be removed by inlining because they have no observable effect other than that of__rust_[de|re]alloc
. This isn't in question.#[global_allocator]
is defined such thatGlobal
allocations can be provided directly by the language or serviced by calling the#[global_allocator]
. Still completely1 uncontroversial.The question here is that if I have a concrete
GlobalAlloc
implementation and I callGlobalAlloc::alloc
on it, are its side effects considered observable?The simplest answer is that this code is specified to print to stdout; it directly calls a function which does so. Define
__rust_[de]alloc
as working in terms of the magical AM "rust allocated objects" rather than direct calls#[global_allocator]
and then everything else just falls out from that.But this is still not great. Say for example I have some sea-of-pointers style graph and I want to instrument how much allocation pressure it's putting out, but ignore allocations in the rest of the program. If calls to a normal implementation of
GlobalAlloc
can't be removed, then instrumenting doesn't actually give me an accurate picture, just an overestimate! This is because while the actual allocations can still be optimized out, the instrumentation remains there. Ideally, it'd be possible to use an observableGlobalAlloc
implementation to accurately2 track the allocations that are happening after optimization.While IIRC adding spurious (language-serviced) allocations is important for optimization, I think we can get away with only allowing explicit
GlobalAlloc
calls to be removed. If the actual allocation is known to be serviced by__rust_alloc
, then normal optimization rules apply; it's only the state and side effects of the allocator which fall under the more restrictive rules.I think I have a rough system that at the very least still justifies loop hoisting that I'm working on getting written down, but I wanted to make sure that the overall thought didn't get lost.
Footnotes
Well, if we accept that 1) spurious calls to the
#[global_allocator]
are accepted, and 2) program execution on an FFI abstract machine can emit arbitrary sound allocation calls as well as arbitrary non-data-race reads and writes of memory allocated by such. And maybe we want#[global_allocator]
to disable the FFI machine's permission to do FFI allocation calls; otherwise a valid#[global_allocator]
implementation is#[cfg(FALSE)]
. So not completely uncontroversial at all. ↩Allowing the accuracy to rely on Quality of Implementation is probably fine, but specifying it such that instrumented allocations can't be fully removed is extremely unfortunate. ↩
The text was updated successfully, but these errors were encountered: