Update on PEA in C2 (Episode2)
Liu, Xin
xxinliu at amazon.com
Fri Mar 3 18:56:22 UTC 2023
Hi,
I would like to update what we have done in C2 PEA. This message consists of 3 parts. First of all, allow me to brief our progress.
Second, I will cover what we have done recently. Last, I will share our source code and our document.
We managed to compile all methods of java.base module using CTW without inliner. We start looking into them with inliner.
This is challenging. Not only the compilation units are exponentially bigger, but we also need to track allocation state across method boundary.
By fixing a couple of bugs, we can compile 1581 out of 59,000 methods. The remaining methods are not compiled yet because CTW cannot skip an error and keep going.
Since last correspondence, we mainly refactored materialization. In our design, PEA clones the object and initializes its fields when a virtual object converts to a materialized object.
Of course, we materialize an object when it is about to escape. This is easier to deal with because the bytecodes that may cause escapement are fixed.
In contrast, it's hard to anticipate the position when we need to materialize an object at merge points. I refer to this as 'passive materialization'.
Basically, we coerce a phi of an object to 'materialized'. One predecessor has materialized, so PEA has to materialize it from the other predecessor.
AllocateNode is dependent on JVMState. Sometimes, the current JVMState isn't fit to emit AllocateNode at all. There are multiple reasons.
1) sp has been changed. We need reexecute_sp but Parse doesn't support it.
2) there are dead locals so we can't call GraphKit::add_safepoint_edges().
3) bci isn't where is supposed to generate uncommon_trap.
Because PEA emits a cluster of nodes to an arbitrary position and it implies a Throwable exception, we have seen that materialization altered the program semantics by accident.
Eg. try-finally below captures 'Throwable'. If we materialize 'attrs' at call lstat0(because it's a native method), we mistakenly wire the exception to the exception handler.
static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
try (NativeBuffer buffer = copyToNativeBuffer(path)) {
long comp = Blocker.begin();
try {
lstat0(buffer.address(), attrs); // materialize attrs here.
} finally { // here is a hidden catch(Throwable) block
Blocker.end(comp);
}
}
}
It requires quite a lot of hacks to overcome those issues. I decide to ensure materialization is position-agnostic. I implemented the following measures for this goal.
1. I copy debug edges and JVMState from the original AllocateNode.
2. use deoptimization rather than the real exception
Last, I would like to ask advice. Our leadership asks me to add more transparency and engagement in the project. I also could use the community helps or it looks like I am grinding.
What should I do to make this situation better?
1. source-code
We have packed source code here.
https://github.com/navyxliu/jdk/tree/PEA_beta
In particular, PEA/Makefile can drive all regression tests. Eg. make run-ctw-no-inline compile java.base module without inliner. Currently, I merge jdk/master from time to time.
Should I check in the source code to 'sandbox repo' of jdk? Or this is fine to share?
2. issue management.
I am working on PEA_Parser branch.
https://github.com/navyxliu/jdk/tree/PEA_parser
now I start filing PRs on github. I try to explain the issues in PR and how I fixed them.
Somehow, I still need an issue system to track bugs and tasks. Should I file them in JBS? I'm concerned that I abuse the JBS. I don't know what maintainer's take on such experimental feature.
3. doc
For people who are interested in reviewing what we have done, I prepare a document of details. This is the continuation of our high-level design.
https://gist.github.com/navyxliu/d1994ae68a999a70300d6ea7096a2b97#file-c2_pea_details-md
thanks,
--lx
More information about the hotspot-compiler-dev
mailing list