Java Allocation and C2

 
Java Allocation and C2
Escape Analysis
 
 
xxinliu@JDKTeam
 
Object and scalar in Java
 
Scalars are ALL on JVM Operand stack (JVM Spec 2.6.2)
8 primitives: short, int,long,float,double, byte,char, Boolean
Reference: points to an object or its field.
Objects are on Java Heap (runtime managed memory), aka. ‘oop’
Each Object has a header
Object
Array T[]
 
Allocation in Java
 
Who is allocating object? Where?
Keyword ‘new’ in java
new Object() => bytecode new
new int[]        => bytecode newarray
Variants: anewarray, multianewarray
Autoboxing => int
 java.lang.Integer
java.lang.Object.clone() -> Object
java.util.Arrays.copyOf() -> T[]
Reflection : java.lang.reflection.Constructor.newInstance()
Native code can allocate objects
JVM itself can allocate internal objects.
 
Allocation in Java
 
Bottom line:  it’s hard to keep tracking all object allocation.
JFR is an low-cost proximate approach
ObjectAllocationInNewTLAB
ObjectAllocationOutsideTLAB
 
HotSpot Escape Analysis
 
bcEscapeAnalyzer
Inter-procedural
Input: method in bytecode
Output: method data(MDO)
C2 EA
intra-procedural
Input: compilation unit(after inlining) in ideal graph
Intermediate: connection graph
Output: annotation of Allocations nodes
 
class AllocationNode {
...
  // Result of Escape Analysis
  bool _is_scalar_replacement;
  bool _is_non_escaping;
...
};
 
Connection Graph
 
Nodes:
Java Object(JO), only JOs are on-heap!
Local Variable(LV)
Field of an Object(FO)
Edges
Result:  for each JO node
Escape? {No, Arg, Global}
NSR: Non-Scalar-Replaceable?
 
Escape Analysis by an example
 
Edges: points-to
 
Uses: nodes which point to this
 
Example
 
-XX:+PrintEscapeAnalysis
 
JO’s points-to set {91F, 88F}
{38, 43} point-to JO, or uses
 
Ideal graph & Connection graph
Java Object
LV: o
FO: x
 
Points-to
 relationship: 2 variables p & q,
p points-to q if p and q may refer to the
same 
memory location
.
 
Points-to
 
Points-to
 
Ideal Graph
 
Connection Graph
 
Scalar Replacement
 
Is not putting an object entirely with header on java stack
It works as if program break down an instance into scalars
Happens in 
MacroExpand
 phase.
Macro nodes: 
LockNode, AllocateNode, AllocateArrayNode, ArrayCopyNode
 
Scalar Replacement
 
Outline
Precondition
Non-escaping
Unique-typing
Scalar replacement:
boils down to disambiguate all individual memories of fields and rewire to the scalar
value
Memory disambiguation
Postcondition
Emits information to the debug info section
Used to reallocate and initialize the objects in deoptimization
 
Scalar Replacement: Precondition
 
AllocateNode::_is_non_escaping is true
Not NSR or autoboxing node or dead object
 
Part-2
 
Mainly talking about non-escaping but NSR objects
Recap
Points-to analysis
Unique typing
: a java object is ‘exclusively’ used by all Local variables.
a few reasons to mark an object NSR
merging nodes hinder unique typing.
Induction variable as the index of array
 
 
 
 
 
Non-escaping but NSR
 
trivial
 
NSR due to aliasing
Java Object: a
LV: o
FO: x
 
Points-to
Java Object: b
LV: o
Java Object: a
 
Points-to
 
Points-to
 
o.x => x
 
o.x => phi(0, x), but it doesn’t work in deoptimization…
 
Unique typing!
 
Close-up: a merging point
Java Object: b
LV: o
Java Object: a
 
Points-to
 
Points-to
 
28 Allocate is pointed by {40, 45, 200}. Among them, 200 points to {28P, 115P}.
because 200, both 28 and 115 are not unique typing!
 
Why unique typing matters for SR?
 
We can scalarize a non-unique-typing object using phi anyway, but…
JVM assumes all objects live on Java Heap 
=> JVM maintains local
variables on frames, which ’points-to’ java heap.  Once out of a
nmethod, we have to keep this assumption(illusion?).
How does it work?
SR: If a local variable is 
live
 at a safepoint, create a SafePointScalarObject
which collects field values.  (
unique typing 
is required here)
Codegen: emit DebugInfo to codecache for each SafePointScalarObject.
Deoptimization: use debug info to reallocate those objects and initialize them.
 
How C2 enforces unique typing?
 
Ivanov/Divino’s splitting approach
 
Introducing a selector to decouple a merging point.
B0: o1 = new
MyPair(0, 0);
If cond
B2: 
o2 = new
MyPair(x, y);
B2: o3 = PHI(o1, o2);
Load o3.x
B0: o1 = new
MyPair(0, 0);
B1: 
o2 = new
MyPair(x, y);
B2: selector = PHI(o1,
o2);
Cmp selector, 0
B3
x1 = o1.x
B4
x2 = o2.x
B5: x3 = phi(x1, x2)
 
Memory Disambiguation
 
Alias Analysis
Java programs still have aliases. They are strong-typed.
Type-based Alias Analysis(TBAA)
Alias == memslice == adr_type(mapped)
C2 MemSSA
Always maintain ssa-form  for memories.
Nodes with memory side effect: TypePtr * adr_type()  <=> alias_type.
Some PHIs are memory PHI. Phi->type() is Memory, aka. yellow phi
A MergeMemNode bookkeeps alias state.
Unique typing: distinct an instance from the general type
 
 
 
Close-up: a merging point
 
2 distinct memory locations
28 Allocate JO(3)
115 Allocate JO(4)
converge at 200 PHI & 198 PHI
 
My idea: splitting for better aliases
 
Let’s refocus on MergeMem, merge->in(6) == 198 PHI
LoadI<6> contains 2 mem locations
Splitting for more precise AA
Split_through_phi exists
In LoadNode boxing objs
In LoopOpts
 
Split_through_phi
 
alias<6> splits into alias<X> and alias<X+1>!
 
SR in a special case
 
recap: If a local variable is 
live
 at a safepoint, create a
SafePointScalarObject which collects its field values.
Sometimes an object has been dead before reaching any safepoint…
 
 
 
In this case, o is dead at the exit block, so both 2 objects have been
dead at the safepoint. Therefore, we can proceed to SR even they are
not unique typing….
 
 
A safepoint is inserted here at exit
Slide Note
Embed
Share

Java object allocation and escape analysis play crucial roles in memory management and performance optimization within the Java Virtual Machine (JVM). This comprehensive overview covers topics such as object vs. scalar allocation, object allocation mechanisms, hotspot escape analysis, ideal and connection graphs, and points-to relationships.

  • Java
  • Object Allocation
  • Escape Analysis
  • JVM
  • Memory Management

Uploaded on Mar 26, 2024 | 3 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Java Allocation and C2 Escape Analysis xxinliu@JDKTeam

  2. Object and scalar in Java Scalars are ALL on JVM Operand stack (JVM Spec 2.6.2) 8 primitives: short, int,long,float,double, byte,char, Boolean Reference: points to an object or its field. Objects are on Java Heap (runtime managed memory), aka. oop Each Object has a header Object Array T[]

  3. Allocation in Java Who is allocating object? Where? Keyword new in java new Object() => bytecode new new int[] => bytecode newarray Variants: anewarray, multianewarray Autoboxing => int java.lang.Integer java.lang.Object.clone() -> Object java.util.Arrays.copyOf() -> T[] Reflection : java.lang.reflection.Constructor.newInstance() Native code can allocate objects JVM itself can allocate internal objects.

  4. Allocation in Java Bottom line: it s hard to keep tracking all object allocation. JFR is an low-cost proximate approach ObjectAllocationInNewTLAB ObjectAllocationOutsideTLAB

  5. HotSpot Escape Analysis bcEscapeAnalyzer Inter-procedural Input: method in bytecode Output: method data(MDO) C2 EA intra-procedural Input: compilation unit(after inlining) in ideal graph Intermediate: connection graph Output: annotation of Allocations nodes class AllocationNode { ... // Result of Escape Analysis bool _is_scalar_replacement; bool _is_non_escaping; ... };

  6. Connection Graph Nodes: Java Object(JO), only JOs are on-heap! Local Variable(LV) Field of an Object(FO) Edges Result: for each JO node Escape? {No, Arg, Global} NSR: Non-Scalar-Replaceable?

  7. Escape Analysis by an example Example Edges: points-to -XX:+PrintEscapeAnalysis Uses: nodes which point to this JO s points-to set {91F, 88F} {38, 43} point-to JO, or uses

  8. Ideal graph & Connection graph Connection Graph Ideal Graph Points-to Java Object LV: o Points-to FO: x Points-to relationship: 2 variables p & q, p points-to q if p and q may refer to the same memory location.

  9. Scalar Replacement Is not putting an object entirely with header on java stack It works as if program break down an instance into scalars Happens in MacroExpand phase. Macro nodes: LockNode, AllocateNode, AllocateArrayNode, ArrayCopyNode

  10. Scalar Replacement Outline Precondition Non-escaping Unique-typing Scalar replacement: boils down to disambiguate all individual memories of fields and rewire to the scalar value Memory disambiguation Postcondition Emits information to the debug info section Used to reallocate and initialize the objects in deoptimization

  11. Scalar Replacement: Precondition AllocateNode::_is_non_escaping is true Not NSR or autoboxing node or dead object

  12. Part-2 Mainly talking about non-escaping but NSR objects Recap Points-to analysis Unique typing: a java object is exclusively used by all Local variables. a few reasons to mark an object NSR merging nodes hinder unique typing. Induction variable as the index of array

  13. Non-escaping but NSR trivial NSR due to aliasing Unique typing! Java Object: a LV: o Points-to Java Object: a Java Object: b Points-to Points-to FO: x LV: o o.x => x o.x => phi(0, x), but it doesn t work in deoptimization

  14. Close-up: a merging point Java Object: a Java Object: b Points-to Points-to LV: o 28 Allocate is pointed by {40, 45, 200}. Among them, 200 points to {28P, 115P}. because 200, both 28 and 115 are not unique typing!

  15. Why unique typing matters for SR? We can scalarize a non-unique-typing object using phi anyway, but JVM assumes all objects live on Java Heap => JVM maintains local variables on frames, which points-to java heap. Once out of a nmethod, we have to keep this assumption(illusion?). How does it work? SR: If a local variable is live at a safepoint, create a SafePointScalarObject which collects field values. (unique typing is required here) Codegen: emit DebugInfo to codecache for each SafePointScalarObject. Deoptimization: use debug info to reallocate those objects and initialize them.

  16. How C2 enforces unique typing? Def: A java object is exclusively used by all Local variables. ??,??????_????_??????(lv) ConnectionGraph::split_unique_types() Phase 1: refine allocate s adr_type to an instance-specific TypeOopPtr, and AddP, Phi, Cast etc. Phase 2~3: redefine mem nodes(load/store, mergemem, memphi) with the new alias

  17. Ivanov/Divinos splitting approach Introducing a selector to decouple a merging point. B0: o1 = new MyPair(0, 0); B0: o1 = new MyPair(0, 0); If cond B1: o2 = new MyPair(x, y); B2: o2 = new MyPair(x, y); B2: selector = PHI(o1, o2); Cmp selector, 0 B2: o3 = PHI(o1, o2); Load o3.x B3 x1 = o1.x B4 x2 = o2.x B5: x3 = phi(x1, x2)

  18. Memory Disambiguation Alias Analysis Java programs still have aliases. They are strong-typed. Type-based Alias Analysis(TBAA) Alias == memslice == adr_type(mapped) C2 MemSSA Always maintain ssa-form for memories. Nodes with memory side effect: TypePtr * adr_type() <=> alias_type. Some PHIs are memory PHI. Phi->type() is Memory, aka. yellow phi A MergeMemNode bookkeeps alias state. Unique typing: distinct an instance from the general type

  19. Close-up: a merging point 2 distinct memory locations 28 Allocate JO(3) 115 Allocate JO(4) converge at 200 PHI & 198 PHI

  20. My idea: splitting for better aliases Let s refocus on MergeMem, merge->in(6) == 198 PHI LoadI<6> contains 2 mem locations Splitting for more precise AA Split_through_phi exists In LoadNode boxing objs In LoopOpts

  21. Split_through_phi alias<6> splits into alias<X> and alias<X+1>!

  22. SR in a special case recap: If a local variable is live at a safepoint, create a SafePointScalarObject which collects its field values. Sometimes an object has been dead before reaching any safepoint A safepoint is inserted here at exit In this case, o is dead at the exit block, so both 2 objects have been dead at the safepoint. Therefore, we can proceed to SR even they are not unique typing .

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#