File: SingleStepCompilationTest.java

package info (click to toggle)
openjdk-25 25.0.1%2B8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 825,408 kB
  • sloc: java: 5,585,680; cpp: 1,333,948; xml: 1,321,242; ansic: 488,034; asm: 404,003; objc: 21,088; sh: 15,106; javascript: 13,265; python: 8,319; makefile: 2,518; perl: 357; awk: 351; pascal: 103; exp: 83; sed: 72; jsp: 24
file content (236 lines) | stat: -rw-r--r-- 8,634 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*
 * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

//  THIS TEST IS LINE NUMBER SENSITIVE

/**
 * @test
 * @bug 8229012
 * @summary Verify that during single stepping a method is not compiled and
 *          after single stepping it is compiled.
 * @requires vm.compMode == "Xmixed"
 * @library /test/lib
 * @build jdk.test.whitebox.WhiteBox
 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 * @run build TestScaffold VMConnection TargetListener TargetAdapter
 * @run compile -g SingleStepCompilationTest.java
 * @run driver SingleStepCompilationTest
 */

import com.sun.jdi.*;
import com.sun.jdi.event.*;
import com.sun.jdi.request.*;

import java.util.*;
import java.lang.reflect.Method;

import jdk.test.whitebox.WhiteBox;

class TestTarg {
    public final static int BKPT_LINE = 66;

    public static void main(String[] args) {
        // Call buswork() and verify that is get compiled.
        busyWork("Warmup");
        if (!isCompiled()) {
            throw new RuntimeException("busywork() did not get compiled after warmup");
        }

        // We need to force deopt the method now. Although we are about to force interp_only
        // mode by enabling single stepping, this does not result in the method being
        // deopt right away. It just causes the compiled method not to be used.
        deoptimizeMethod();

        // Call busywork() again. This time the debugger will have single stepping
        // enabled. After calling, verify that busywork() is not compiled.
        busyWork("StepOver"); // BKPT_LINE: We do a STEP_OVER here
        if (isCompiled()) {
            throw new RuntimeException("busywork() compiled during single stepping");
        }

        // Call busywork a 3rd time. This time the debugger will not have single stepping
        // enabled. After calling, verify that busywork is compiled.
        busyWork("AfterStep");
        if (!isCompiled()) {
            throw new RuntimeException("busywork() not compiled after single stepping completes");
        }
    }

    private static final WhiteBox WB = WhiteBox.getWhiteBox();
    private static Method busyWorkMethod;
    static {
        try {
            busyWorkMethod = TestTarg.class.getDeclaredMethod("busyWork", String.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    private static boolean isCompiled() {
        return WB.isMethodCompiled(busyWorkMethod, true) || WB.isMethodCompiled(busyWorkMethod, false);
    }

    private static void deoptimizeMethod() {
        System.out.println("Decompile count before: " + WB.getMethodDecompileCount(busyWorkMethod));
        WB.deoptimizeMethod(busyWorkMethod, true);
        WB.deoptimizeMethod(busyWorkMethod, false);
        System.out.println("Decompile count after: " + WB.getMethodDecompileCount(busyWorkMethod));
    }

    // We put the array and the result variables in static volatiles just to make sure
    // the compiler doesn't optimize them away.
    public static final int ARRAY_SIZE = 1000*1024;
    public static volatile int[] a = new int[ARRAY_SIZE];
    public static volatile long result = 0;

    // Do something compute intensive to trigger compilation.
    public static void busyWork(String phase) {
        // Although timing is not necessary for this test, it is useful to have in the
        // log output for troubleshooting. The timing when step over is enabled should
        // be sigficantly slower than when not.
        long start = System.currentTimeMillis();

        // Burn some CPU time and trigger OSR compilation.
        for (int j = 0; j < 500; j++) {
            for (int i = 0; i < ARRAY_SIZE; i++) {
                a[i] = j*i + i << 5 + j;
            }
        }
        for (int i = 0; i < ARRAY_SIZE; i++) {
            result += a[i];
        }

        long end = System.currentTimeMillis();
        long totalTime = end - start;
        System.out.println(phase + " time: " + totalTime);
    }
}

/********** test program **********/

public class SingleStepCompilationTest extends TestScaffold {
    ClassType targetClass;
    ThreadReference mainThread;

    SingleStepCompilationTest (String args[]) {
        super(args);
    }

    public static void main(String[] args) throws Exception {
        /*
         * We need to pass some extra args to the debuggee for WhiteBox support and
         * for more consistent compilation behavior.
         */
        String[] newArgs = new String[5];
        if (args.length != 0) {
            throw new RuntimeException("Unexpected arguments passed to test");
        }

        // These are all needed for WhiteBoxAPI
        newArgs[0] = "-Xbootclasspath/a:.";
        newArgs[1] = "-XX:+UnlockDiagnosticVMOptions";
        newArgs[2] = "-XX:+WhiteBoxAPI";

        // In order to make sure the compilation is complete before we exit busyWork(),
        // we don't allow background compilations.
        newArgs[3] = "-XX:-BackgroundCompilation";

        // Disabled tiered compilations so a new compilation doesn't start in the middle
        // of executing busyWork(). (Might not really be needed)
        newArgs[4] = "-XX:-TieredCompilation";

        new SingleStepCompilationTest(newArgs).startTests();
    }

    /********** event handlers **********/

    EventRequestManager erm;
    BreakpointRequest bkptRequest;
    StepRequest stepRequest;

    // When we get a bkpt we want to disable the request and enable single stepping.
    public void breakpointReached(BreakpointEvent event) {
        System.out.println("Got BreakpointEvent: " + event);
        EventRequest req = event.request();
        req.disable();
        stepRequest = erm.createStepRequest(mainThread,
                                            StepRequest.STEP_LINE,
                                            StepRequest.STEP_OVER);
        stepRequest.enable();
    }

    public void stepCompleted(StepEvent event) {
        System.out.println("Got StepEvent: " + event);
        EventRequest req = event.request();
        req.disable();
    }

    public void eventSetComplete(EventSet set) {
        set.resume();
    }

    public void vmDisconnected(VMDisconnectEvent event) {
        System.out.println("Got VMDisconnectEvent");
    }

    /********** test core **********/

    protected void runTests() throws Exception {
        /*
         * Get to the top of main() to determine targetClass and mainThread.
         */
        BreakpointEvent bpe = startToMain("TestTarg");
        targetClass = (ClassType)bpe.location().declaringType();
        mainThread = bpe.thread();
        erm = vm().eventRequestManager();

        // The BKPT_LINE is the line we will STEP_OVER.
        Location loc1 = findLocation(targetClass, TestTarg.BKPT_LINE);
        bkptRequest = erm.createBreakpointRequest(loc1);
        bkptRequest.enable();

        try {
            addListener(this);
        } catch (Exception ex) {
            ex.printStackTrace();
            failure("failure: Could not add listener");
            throw new RuntimeException("SingleStepCompilationTest: failed", ex);
        }

        vm().resume();
        waitForVMDisconnect();

        System.out.println("done with loop");
        removeListener(this);

        /*
         * Deal with results of test. If anything has called failure("foo")
         * then testFailed will be true.
         */
        if (!testFailed) {
            System.out.println("SingleStepCompilationTest: passed");
        } else {
            throw new Exception("SingleStepCompilationTest: failed");
        }
    }
}