RFR: 8178287: AsyncGetCallTrace fails to traverse valid Java stacks [v2]

Jaroslav Bachorik jbachorik at openjdk.java.net
Thu Jun 17 11:17:12 UTC 2021


On Thu, 10 Jun 2021 07:50:57 GMT, Ludovic Henry <luhenry at openjdk.org> wrote:

>> When the signal sent for AsyncGetCallTrace or JFR would land on a runtime stub (like arraycopy), a vtable stub, or the prolog of a compiled method,  it wouldn't be able to detect the sender (caller) frame for multiple reasons. This patch fixes these cases through adding CodeBlob-specific frame parser which are in the best position to know how a frame is setup.
>> 
>> The following examples have been profiled with honest-profiler which uses `AsyncGetCallTrace`.
>> 
>> # `Prof1`
>> 
>> public class Prof1 {
>> 
>>     public static void main(String[] args) {
>>         StringBuilder sb = new StringBuilder();
>>         for (int i = 0; i < 1000000; i++) {
>>             sb.append("ab");
>>             sb.delete(0, 1);
>>         }
>>         System.out.println(sb.length());
>>     }
>> }
>> 
>> 
>> - Baseline:
>> 
>> Flat Profile (by method):
>>         (t 99.4,s 99.4) AGCT::Unknown Java[ERR=-5]
>>         (t  0.5,s  0.2) Prof1::main
>>         (t  0.2,s  0.2) java.lang.AbstractStringBuilder::append
>>         (t  0.1,s  0.1) AGCT::Unknown not Java[ERR=-3]
>>         (t  0.0,s  0.0) java.lang.AbstractStringBuilder::ensureCapacityInternal
>>         (t  0.0,s  0.0) java.lang.AbstractStringBuilder::shift
>>         (t  0.0,s  0.0) java.lang.String::getBytes
>>         (t  0.0,s  0.0) java.lang.AbstractStringBuilder::putStringAt
>>         (t  0.0,s  0.0) java.lang.StringBuilder::delete
>>         (t  0.2,s  0.0) java.lang.StringBuilder::append
>>         (t  0.0,s  0.0) java.lang.AbstractStringBuilder::delete
>>         (t  0.0,s  0.0) java.lang.AbstractStringBuilder::putStringAt
>> 
>> - With `StubRoutinesBlob::FrameParser`:
>> 
>> Flat Profile (by method):
>>         (t 98.7,s 98.7) java.lang.AbstractStringBuilder::ensureCapacityInternal
>>         (t  0.9,s  0.9) java.lang.AbstractStringBuilder::delete
>>         (t 99.8,s  0.2) Prof1::main
>>         (t  0.1,s  0.1) AGCT::Unknown not Java[ERR=-3]
>>         (t  0.0,s  0.0) AGCT::Unknown Java[ERR=-5]
>>         (t 98.8,s  0.0) java.lang.AbstractStringBuilder::append
>>         (t 98.8,s  0.0) java.lang.StringBuilder::append
>>         (t  0.9,s  0.0) java.lang.StringBuilder::delete
>> 
>> 
>> # `Prof2`
>> 
>> import java.util.function.Supplier;
>> 
>> public class Prof2 {
>> 
>>     public static void main(String[] args) {
>>         var rand = new java.util.Random(0);
>>         Supplier[] suppliers = {
>>                 () -> 0,
>>                 () -> 1,
>>                 () -> 2,
>>                 () -> 3,
>>         };
>> 
>>         long sum = 0;
>>         for (int i = 0; i >= 0; i++) {
>>             sum += (int)suppliers[i % suppliers.length].get();
>>         }
>>     }
>> }
>> 
>> 
>> - Baseline:
>> 
>> Flat Profile (by method):
>>         (t 60.7,s 60.7) AGCT::Unknown Java[ERR=-5]
>>         (t 39.2,s 35.2) Prof2::main
>>         (t  1.4,s  1.4) Prof2::lambda$main$3
>>         (t  1.0,s  1.0) Prof2::lambda$main$2
>>         (t  0.9,s  0.9) Prof2::lambda$main$1
>>         (t  0.7,s  0.7) Prof2::lambda$main$0
>>         (t  0.1,s  0.1) AGCT::Unknown not Java[ERR=-3]
>>         (t  0.0,s  0.0) java.lang.Thread::exit
>>         (t  0.9,s  0.0) Prof2$$Lambda$2.0x0000000800c00c28::get
>>         (t  1.0,s  0.0) Prof2$$Lambda$3.0x0000000800c01000::get
>>         (t  1.4,s  0.0) Prof2$$Lambda$4.0x0000000800c01220::get
>>         (t  0.7,s  0.0) Prof2$$Lambda$1.0x0000000800c00a08::get
>> 
>> 
>> - With `VtableBlob::FrameParser` and `nmethod::FrameParser`:
>> 
>> Flat Profile (by method):
>>         (t 74.1,s 70.3) Prof2::main
>>         (t  6.5,s  5.5) Prof2$$Lambda$29.0x0000000800081220::get
>>         (t  6.6,s  5.4) Prof2$$Lambda$28.0x0000000800081000::get
>>         (t  5.7,s  5.0) Prof2$$Lambda$26.0x0000000800080a08::get
>>         (t  5.9,s  5.0) Prof2$$Lambda$27.0x0000000800080c28::get
>>         (t  4.9,s  4.9) AGCT::Unknown Java[ERR=-5]
>>         (t  1.2,s  1.2) Prof2::lambda$main$2
>>         (t  0.9,s  0.9) Prof2::lambda$main$3
>>         (t  0.9,s  0.9) Prof2::lambda$main$1
>>         (t  0.7,s  0.7) Prof2::lambda$main$0
>>         (t  0.1,s  0.1) AGCT::Unknown not Java[ERR=-3]
>
> Ludovic Henry has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR.

I have done a sanity check to make sure that the code was not functionally modified while moving around.
No problems found there.

src/hotspot/cpu/aarch64/codeBlob_aarch64.cpp line 47:

> 45: 
> 46:   if (check && !_cb->is_frame_complete_at(pc)) {
> 47:     if (_cb->is_adapter_blob()) {

Please, update the comment at L41-44 to correspond to the modified condition,

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

PR: https://git.openjdk.java.net/jdk/pull/4436


More information about the serviceability-dev mailing list