Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/test/hotspot/jtreg/compiler/locks/TestNestedLocksElimination.java
64474 views
1
/*
2
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
/*
26
* @test
27
* @bug 8268347
28
* @summary Nested locks optimization may create unbalanced monitor enter/exit code
29
*
30
* @run main/othervm -XX:-BackgroundCompilation
31
* -XX:CompileCommand=dontinline,TestNestedLocksElimination::foo
32
* -XX:CompileCommand=dontinline,TestNestedLocksElimination::getNext
33
* -XX:CompileCommand=dontinline,TestNestedLocksElimination::getHolder
34
* TestNestedLocksElimination
35
*/
36
37
import java.util.LinkedList;
38
39
public class TestNestedLocksElimination {
40
41
private LinkedList<char[]> buffers = new LinkedList<>();
42
private boolean complete = false;
43
private int bufferSize;
44
45
void foo(char[] ca) {
46
// Don't inline dummy method
47
}
48
49
// Don't inline
50
char[] getNext(int length, int count) {
51
if (this.buffers.isEmpty()) {
52
return new char[100];
53
}
54
char[] b = (char[]) this.buffers.getFirst();
55
if (count >= 100) {
56
this.complete = true;
57
this.buffers.clear(); // empty
58
}
59
return b;
60
}
61
62
synchronized boolean isComplete() {
63
return this.complete;
64
}
65
66
synchronized boolean availableSegment() {
67
return (buffers.isEmpty() == false);
68
}
69
70
// Don't inline
71
TestNestedLocksElimination getHolder(TestNestedLocksElimination s1, TestNestedLocksElimination s2, int count) {
72
return (count & 7) == 0 ? s2 : s1;
73
}
74
75
int test(TestNestedLocksElimination s1, TestNestedLocksElimination s2, int maxToSend) {
76
boolean isComplete = true;
77
boolean availableSegment = false;
78
int size = 0;
79
int count = 0;
80
do {
81
TestNestedLocksElimination s = getHolder(s1, s2, count++);
82
83
synchronized(s) {
84
isComplete = s.isComplete();
85
availableSegment = s.availableSegment();
86
}
87
88
synchronized (this) {
89
size = 0;
90
while (size < maxToSend) {
91
char[] b = null;
92
// This is outer Lock region for object 's'.
93
// Locks from following inlined methods are "nested"
94
// because they reference the same object.
95
synchronized(s) {
96
b = s.getNext(maxToSend - size, count);
97
98
// The next is bi-morphic call with both calls inlined.
99
// But one is synchronized and the other is not.
100
// Class check for bi-morphic call is loop invariant
101
// and will trigger loop unswitching.
102
// Loop unswitching will create two versions of loop
103
// with gollowing calls inlinined in both versions.
104
105
isComplete = s.isComplete();
106
107
// The next synchronized method availableSegment() is
108
// inlined and its Lock will be "coarsened" with Unlock
109
// in version of loop with inlined synchronized method
110
// isComplete().
111
// Nested Lock Optimization will mark only this Unlock
112
// as nested (as part of "nested" pair lock/unlock).
113
// Locks elimination will remove "coarsened" Lock from
114
// availableSegment() method leaving unmatched unlock.
115
116
availableSegment = s.availableSegment();
117
}
118
foo(b);
119
size += b.length;
120
}
121
}
122
} while (availableSegment == true || isComplete == false);
123
return size;
124
}
125
126
public static void main(String[] args) {
127
int count = 0;
128
int n = 0;
129
130
TestNestedLocksElimination t = new TestNestedLocksElimination();
131
TestNestedLocksElimination s1 = new TestNestedLocksElimination();
132
TestNestedLocksElimination s2 = new TestNestedLocksEliminationSub();
133
134
char[] c = new char[100];
135
while (n++ < 20_000) {
136
s1.buffers.add(c);
137
s2.buffers.add(c);
138
count += t.test(s1, s2, 10000);
139
}
140
141
System.out.println(" count: " + count);
142
}
143
}
144
145
class TestNestedLocksEliminationSub extends TestNestedLocksElimination {
146
public boolean isComplete() {
147
return true;
148
}
149
}
150
151
152