[External] : Re: API to create a new Allocate node?

Liu, Xin xxinliu at amazon.com
Wed May 18 04:46:22 UTC 2022


hi, Vladimir and Cesar,

I fail to comprehend this part. Here I build a program like you did.
black() is an external method.

$cat MergeObjects.java
public class MergeObjects {
    static class Point {
        public int x;
        public int y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void black() {}
    // java -Xcomp -XX:CompileOnly=compileonly,MergeObjects::merge2
-XX:CompileCommand=dontinline,MergeObjects::black -XX:+PrintCompilation
-XX:CompileCommand=quiet -XX:+PrintEscapeAnalysis
-XX:+PrintEscapeAnalysis MergeObject
    public static int merge2(boolean cond) {
      Point p;
      if (cond){
         p = new Point(0, 0);
      } else {
         p = new Point(1, 2);
      }
      black(); // Allocation does not escape but it is refernced in
debug info in JVMS of this call.
      return p.x;
    }

    public static void main(String[] args) {
        Point p = new Point(0, 0); // force to load class Point()
        merge2(true);
    }
}


If CU can't inline black(),  black() becomes a game changer. we have to
preserve live locals because bci=30 right after invokestatic #12
references local #1, which is p2 = phi(p0, p1).  We don't know black(),
it may trigger deoptimiztion for whatever reason and return to bci:30 in
interpreter.

  public static int merge2(boolean);
    descriptor: (Z)I
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=2, args_size=1
         0: iload_0
         1: ifeq          17
         4: new           #7                  // class MergeObjects$Point
         7: dup
         8: iconst_0
         9: iconst_0
        10: invokespecial #9                  // Method
MergeObjects$Point."<init>":(II)V
        13: astore_1
        14: goto          27
        17: new           #7                  // class MergeObjects$Point
        20: dup
        21: iconst_1
        22: iconst_2
        23: invokespecial #9                  // Method
MergeObjects$Point."<init>":(II)V
        26: astore_1
        27: invokestatic  #12                 // Method black:()V
        30: aload_1
        31: getfield      #17                 // Field
MergeObjects$Point.x:I
        34: ireturn


No matter we invent a device or split if node, I think it's inevitable
to rematerialize local#1 in deoptimization. Does HotSpot support that?

From my reading, we serialize an object pool in the backend. Each object
has an identifier which was its allocate node idx(even though the
allocate node has long gone after codegen). I feel we can't perform this
rematerialization in flow sensitive way because we miss a selector in
debuginfo.

I see many uncommon_trap nodes retain locals references. That's why I am
working on JDK-8286104. I think this can be a new feature of
deoptimization module. Allow me rephrase it. Is it worth pursuing?

In general, there is a phiNode L = phi(p0, p1, ... , pk). p0 is a unique
non-escaping object and others are global objects. L is live at a
safepoint Node. deoptimization supports to rematerialize it.

thanks,
--lx




On 4/29/22 4:20 PM, Vladimir Kozlov wrote:
> has own ID which we can use to
> construct debug info for deoptimization. And it will be gone after macro expansion - replaced with
> SafePointScalarObjectNode or simply removed if it is not referenced.


More information about the hotspot-compiler-dev mailing list