Anything that the runtime can’t prove to be non-escaping… It’s an optimization detail that’s constantly changing (and I’m currently working on multiple changes that can hopefully make it more consistent). Also note that even if an object doesn’t escape, we will never be able to guarantee that the allocation can be elided, we can only guarantee that if an object does escape than it will be allocated on the heap. OTOH, cases that don’t escape but are allocated can be reported as performance bugs.
Keeping that in mind, what count as escape isn’t too different from other languages, i.e. if the identity/address of the object is used in an unknown way than it’s escaped. This also shows why it’s very hard to give a definition since as the compiler gets smarter the “unknown” set will get smaller. There are cases where we guarantee that the object identity will escape, this includes,
ccall
with argument type ofAny
orRef
of abstract type. (apart from certain runtime c functions known to the runtime)- Store to global.
There are also cases where the pointer and therefore the layout of the object esape but not it’s identity, i.e.
pointer_from_objref
, this is being exploided in Add LLVM level allocation optimization pass by yuyichao · Pull Request #22684 · JuliaLang/julia · GitHub
And there are cases that’s currently considered escaping but may not in the future,
- used in function call to non-inlined function
- stored to argument of non-inlined function
Additionally, the current optimization pass is also affected by the exact structure of the AST which causes `enumerate` allocates for arrays of mutables · Issue #16190 · JuliaLang/julia · GitHub and that’s the issue I’m currently working on.