Skip to content

Store store barrier at the end of initializer of an object without final fields #1504

Closed
@armLeiJin

Description

@armLeiJin

We find when graal news an object without final field, it produces one store store barrier at the end of the object initializer.

According to the Java language spec, thread which only can observe a object field after the object construction finishes, also has chance to observe a default value of it if the field is no final. And the barrier inserted at the end of object initializer is not required. We compare the assembely codes on AArch64 produced by graal and c2 seperately and find c2 doesn't have such a barrier.

Java source code

public class Node {
private double item;

 Node(double item) {
     this.item = Math.sqrt(item);
 }

}

private static Node createSqrt(double data) {
double input = data * (data - 3);
return new Node(input);
}

C2 assembly on AArch64
0x0000ffff851cb674: mov x10, #0x7c78 // #31864
0x0000ffff851cb678: movk x10, #0x9, lsl #16
0x0000ffff851cb67c: movk x10, #0x8, lsl #32
0x0000ffff851cb680: str x11, [x28,#320]
0x0000ffff851cb684: ldr x10, [x10,#184]
0x0000ffff851cb688: str x10, [x0]
0x0000ffff851cb68c: mov x10, #0x90000 // #589824
0x0000ffff851cb690: movk x10, #0x7c78
0x0000ffff851cb694: stp w10, wzr, [x0,#8]
0x0000ffff851cb698: prfm pstl1keep, [x11,#192]
0x0000ffff851cb69c: str xzr, [x0,#16]
0x0000ffff851cb6a0: dmb ishst
0x0000ffff851cb6a4: fsqrt d16, d16
0x0000ffff851cb6a8: str d16, [x0,#16]
0x0000ffff851cb6ac: ldp x29, x30, [sp,#32]
0x0000ffff851cb6b0: add sp, sp, #0x30
0x0000ffff851cb6b4: ldr x8, [x28,#296]
0x0000ffff851cb6b8: ldr wzr, [x8]
0x0000ffff851cb6bc: ret

Graal assembly on AArch64
0x0000ffff741c6c74: str x2, [x28,#320]
0x0000ffff741c6c78: prfm pstl1keep, [x0,#216]
0x0000ffff741c6c7c: ldr x1, [x3,#184]
0x0000ffff741c6c80: str x1, [x0]
0x0000ffff741c6c84: mov x1, #0xd0000 // #851968
0x0000ffff741c6c88: movk x1, #0xbad0
0x0000ffff741c6c8c: str w1, [x0,#8]
0x0000ffff741c6c90: str wzr, [x0,#12]
0x0000ffff741c6c94: str xzr, [x0,#16]
0x0000ffff741c6c98: dmb ishst
0x0000ffff741c6c9c: fmov d1, #3.000000000000000000e+00
0x0000ffff741c6ca0: fsub d1, d0, d1
0x0000ffff741c6ca4: fmul d0, d1, d0
0x0000ffff741c6ca8: fsqrt d0, d0
0x0000ffff741c6cac: str d0, [x0,#16]
0x0000ffff741c6cb0: dmb ishst
0x0000ffff741c6cb4: ldp x29, x30, [sp,#32]
0x0000ffff741c6cb8: add sp, sp, #0x30
0x0000ffff741c6cbc: ldr x8, [x28,#296]
0x0000ffff741c6cc0: ldr wzr, [x8]
0x0000ffff741c6cc4: ret

We also check the implementation in Graal and find the such an additional barrier is inserted when lower the commitAllocationNode.

/**
 * Insert the required {@link MemoryBarriers#STORE_STORE} barrier for an allocation and also
 * include the {@link MemoryBarriers#LOAD_STORE} required for final fields if any final fields
 * are being written, as if {@link FinalFieldBarrierNode} were emitted.
 */
private static void insertAllocationBarrier(CommitAllocationNode commit, StructuredGraph graph) {
    int barrier = MemoryBarriers.STORE_STORE;
    outer: for (VirtualObjectNode vobj : commit.getVirtualObjects()) {
        for (ResolvedJavaField field : vobj.type().getInstanceFields(true)) {
            if (field.isFinal()) {
                barrier = barrier | MemoryBarriers.LOAD_STORE;
                break outer;
            }
        }
    }
    graph.addAfterFixed(commit, graph.add(new MembarNode(barrier, LocationIdentity.init())));
}

According to the codes above, a store store barrier is inserted as a default logic and the barrier will be upgraded into a release one if the object has a final field. We would like to know why a store store barrier is demanded here if no final field? Can we remove it and keep release barrier logic only? Thanks!

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions