C2 Scalar Replacement Behavior?

Vladimir Kozlov Vladimir.Kozlov at Sun.COM
Mon Dec 1 10:48:03 PST 2008


Edward Lee wrote:
> On Mon, Nov 17, 2008 at 2:35 PM, Vladimir Kozlov
> <Vladimir.Kozlov at sun.com> wrote:
>> All uses of scalar replaceable object's fields should be replaced
>> with values stored into the fields (or with default value 0 if
>> there were no stores).
> Ah, okay. Thanks. I've been seeing this behavior by setting the
> PrintOptoAssembly option for a method through .hotspot_compiler. In
> particular, I've been looking at a "pack-and-pass" pattern for short
> lifetime objects:
> 
> foo(A,B) {
>   bar(new pack(A,B))
> }
> 
> Where the optimized asm has the inlined bar() accessing B directly
> (foo's param) with +DoEscapeAnalysis instead of dereferencing an extra
> pointer of an allocated pack object.
> 
> (Side question, where do I find the structure of Thread::current()? A
> quick glance seems to imply [[current() + #68] + #24] is the thread's
> allocation bump pointer position and [current() + #76] is perhaps a
> allocation watermark where exceeding it slowpaths to
> _new_instance_Java. Is this runtime/thread.hpp or is there a simple
> way to see what offsets correspond to?)

Thread structure is defined in src/share/vm/runtime/thread.hpp

Note, PrintOptoAssembly prints a pseudo-assembler code which
may hide the actual assembler code to reduce output.
The code for next pseudo-assembler code

    	MOV    EBX, Thread::current()

is in OS/platform specific AD file, for example in

src/os_cpu/linux_x86/vm/linux_x86_32.ad

it "instruct tlsLoadP" and it uses MacroAssembler::get_thread()
in assembler_linux_x86.cpp to generate assembler code.

The offsets you see is for TLAB allocation and the offset are
defined in thread.hpp (look for TLAB_FIELD_OFFSET macro)
and in src/share/vm/memory/threadLocalAllocBuffer.hpp.

> 
>> We have to keep allocations if optimizer was not able to eliminate
>> all loads (for example, volatile fields).
> So on the way to macro expand deciding if all the loads of the
> allocation have been eliminated, the ideal graph has 2 pairs of nodes:
> one using the foo's parameter and another using the allocated pack
> object's fields. Assuming an allocation can't be scalar replaced, at
> what point does the optimizer drop "use param" and go with "use
> alloced object?"

We keep both.
It is safe to keep only fields loads which were not eliminated
by Optimizer and "use param" for other fields values since EA determined
that the object does not escape.

> 
> When I turn off -DoEscapeAnalysis, I notice that field references are
> again field references even though the value is available through the
> parameter. Arguably, the field access needs to be there because
> potentially another thread might have changed that newly allocated

Yes, it is correct. We have to keep loads since we don't know
at what point an object may escape without EA.

> object's field. Or is it that optimize_memory_chain wouldn't have
> decided to use the param without escape analysis?
> 
> Ed

Vladimir



More information about the hotspot-dev mailing list