RFR: 8297036: Generalize C2 stub mechanism

Roman Kennke rkennke at openjdk.org
Thu Nov 24 15:40:23 UTC 2022


On Wed, 16 Nov 2022 15:03:07 GMT, Roman Kennke <rkennke at openjdk.org> wrote:

> Currently, we have two implementations of out-of-line stubs in C2, one for safepoint poll stubs (C2SafepointPollStubTable in output.hpp) and another for nmmethod entry barriers (C2EntryBarrierStubTable in output.hpp). I will need a few more for Lilliput: One for checking lock-stack size in method prologue, one for handling lock failures (both for fast-locking), and another one for load-klass slow-path. It would be good to generalize the mechanism and consolidate the existing uses on the new general mechanism.
> 
> Testing:
>  - [x] tier1 (x86_64, x86_32, aarch64)
>  - [x] tier2 (x86_64, x86_32, aarch64)
>  - [x] tier3 (x86_64, x86_32, aarch64)

Hi Xiaolin,

> This is a very nice refactoring, but we find this patch can interestingly break the RISC-V native fastdebug/slowdebug building process.
> 
> The root cause is the `measure_code_size()` is always a `0` value, for `PhaseOutput::init_buffer()` is too early to collect all CodeStubs emitted in the future. This issue appears to exist before this patch.
> 
> What is different is, originally `C2EntryBarrierStubTable::estimate_stub_size()` seems to return a non-zero value at all times for now (nmethod entry barriers for continuations). However, due to the pre-existing issue mentioned above, our new code using a sum to calculate the total size will always return a `0`, shrinking the `measure_code_size()` from a non-zero value to `0`. So the `stub_req` is smaller than before. Some code generated in RISC-V would just exceed the smaller threshold when emitting trampolines stubs, causing some failures.
> 
> The below print can show the zero value when `-XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode` are on.
> 
> ```
> diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp
> index f189a12316b..1416c196faf 100644
> --- a/src/hotspot/share/opto/output.cpp
> +++ b/src/hotspot/share/opto/output.cpp
> @@ -1244,7 +1244,11 @@ CodeBuffer* PhaseOutput::init_buffer() {
> 
>    BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
>    stub_req += bs->estimate_stub_size();
> -  stub_req += _stub_list.measure_code_size();
> +  int newlist_size = _stub_list.measure_code_size();
> +  stub_req += newlist_size;
> +  if (UseNewCode) {
> +    tty->print_cr("the measured size is: %d", newlist_size);
> +  }
> 
>    // nmethod and CodeBuffer count stubs & constants as part of method's code.
>    // class HandlerImpl is platform-specific and defined in the *.ad files.
> ```
> 
> one hs_err file here. (the line number may not match, for I added some debugging stuff in my codebase) [hs_err_pid1282.log](https://github.com/openjdk/jdk/files/10085047/hs_err_pid1282.log)

I don't quite understand. Are you saying that in init_buffer(), we don't have any method_entry_barrier stubs, yet, and therefore we return 0 there? In this case I don't see how it could have worked before. Or are you saying that we have one method entry barrier stub, but measuring its size returns 0? In this case I don't understand why. The measurement creates a scratch buffer, and emits one stub to it, and measures the size of the generated code. C2MethodEntryBarrier::emit() doesn't have any relevant conditional in it, it should always emit something, and the size should be > 0. Or what am I missing?

Thank you,
Roman

-------------

PR: https://git.openjdk.org/jdk/pull/11188


More information about the hotspot-compiler-dev mailing list