Escape Analysis and Stack Allocation

Jeremy Manson jeremymanson at google.com
Mon Jan 27 23:44:50 PST 2014


That was basically what mine did, too.  I put on a pointy hat and became
more of a manager than a programmer, but I never stopped wondering what
would happen if I had an opportunity to wire the two things together.

There are obvious optimizations to make, too.  For example, the MLAB
doesn't have to go in the YG - it could go in a generation devoted to them.
 They can be stolen by a second thread when the first thread blocks (TLABs
could do this, too - always wondered why they didn't).  You would probably
want to resize MLABs like you resize TLABs.  It's a career path getting it
right.

If you have something that can go into HS24 pretty easily, I can probably
slap it in and try it out on some programs that are substantially more
interesting than jbb2005.  Might be hard to revive after four years, though.

Jeremy


On Mon, Jan 27, 2014 at 10:08 PM, Vladimir Kozlov <
vladimir.kozlov at oracle.com> wrote:

> I did the same experiment 4 years ago, back in jdk6 era. Called it MLAB,
> method local allocation buffer, works like thread local stack for
> non-escaping objects but was allocated in java heap as special TLAB. Got it
> worked but did not see benefits in jbb2005. GC requires no holes in heap,
> as result I had to give the buffer back to GC when young gen collection was
> needed. After GC a thread get new MLAB and starts allocation from scratch
> which nullified performance benefits.
>
> I can try to find those changes if someone interested.
>
> Regards,
> Vladimir
>
>
> On 1/27/14 9:21 PM, Jeremy Manson wrote:
>
>> I tried implementing direct stack allocation in Hotspot a couple of years
>> ago.  It was a pain to try to allocate anything outside the heap - there
>> are a lot of checks to make sure that your objects live on the heap.
>>
>> I ended up creating TLAB-like regions in the heap that could hold objects
>> allocated in a stack-like way.  It was a lot easier that way, and seemed
>> to
>> give the kinds of performance benefits you would expect.
>>
>> I never got around to trying to wire it up to Hotspot's escape analysis,
>> but it was a fairly obvious next step.
>>
>> Jeremy
>>
>>
>> On Sun, Jan 26, 2014 at 12:26 PM, Aaron Grunthal <
>> aaron.grunthal at infinite-source.de> wrote:
>>
>>  There also is an issue with merge points [1] which prevents objects in
>>> loops with an accumulator (e.g. reduce operations on streams) to
>>> stack-allocate the intermediate values.
>>>
>>> [1] https://bugs.openjdk.java.net/browse/JDK-6853701
>>>
>>> - Aaron
>>>
>>>
>>> On 26.01.2014 07:04, Benedict Elliott Smith wrote:
>>>
>>>  Hi,
>>>>
>>>> I was digging into some (to me) unexpected behaviour of escape analysis,
>>>> namely that some references that clearly weren't escaping, and easily
>>>> determined to be so, were not being stack allocated.
>>>>
>>>> So, after some digging through the hotspot code, I discovered some
>>>> things
>>>> that were probably obvious to everyone on this list, but also some
>>>> things
>>>> I'm still a little perplexed about. I was hoping somebody could
>>>> enlighten
>>>> me about the latter.
>>>>
>>>> 1) I cannot see a reason why stores to a primitive array, for instance,
>>>> should cause the argument to escape in bcEscapeAnalyser.cpp
>>>> *iterate_one_block()*; most interestingly, a store to an object array
>>>> does
>>>> not result in this, which seems incongruous;
>>>>
>>>> 2) An object array store *does* however result in *set_global_escape()*
>>>> for
>>>> the value being stored, which makes sense, except that this should only
>>>> be
>>>> *set_method_escape()*, as per the paper, in the case where the target
>>>> array
>>>> is one of the method arguments. This seems to be missing, here and for
>>>> *putfield*.
>>>>
>>>> Some other weird ones are *arraylength*, *getfield*, *ifnonnull*, etc.
>>>> The
>>>> fact that these all result in *set_method_escape()*, and that
>>>> *putfield*and
>>>> *aastore* don't optimise *set_global_escape()* to
>>>> *set_method_escape()*where possible, seem to point to the conclusion
>>>> that *_is_arg_stack
>>>> / set_method_escape()* actually encode only *!is_scalar_replaceable*. Is
>>>> this the case? If so, why the confusing name?*
>>>>
>>>>
>>>> Which leads to a much trickier but more interesting question, which is:
>>>> what are the barriers to performing actual stack allocation of full
>>>> objects, instead of scalar replacement? It is something I would be keen
>>>> to
>>>> investigate, but given my lack of familiarity with the codebase, it
>>>> would
>>>> be immensely helpful to hear what the major difficulties / showstoppers
>>>> might be before trying to attack it.
>>>>
>>>> Thanks in advance,
>>>>
>>>> Benedict
>>>>
>>>>
>>>> *I do note that in escape.cpp *ArgEscape* is defined and is explicitly
>>>> overloaded to include some of the characteristics of
>>>> *is_scalar_replaceable*.
>>>> However the *is_arg_stack()* method is commented with "The given
>>>> argument
>>>> escapes the callee, but does not become globally reachable." which seems
>>>> to
>>>> correspond to *ArgEscape* in the paper, but only *invoke()* seems to
>>>> follow
>>>> the spec, when invoking a method that cannot be analysed, and this would
>>>> also be true for *!is_scalar_replaceable.*
>>>>
>>>>
>>>>
>>>


More information about the hotspot-dev mailing list