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 * @test
26 * @bug 8059022
27 * @modules java.base/jdk.internal.misc:+open
28 * @summary Validate barriers after Unsafe getObject, CAS and swap (GetAndSet)
29 * @requires vm.gc.Z & !vm.graal.enabled
30 * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UnlockDiagnosticVMOptions -XX:+ZUnmapBadViews -XX:ZCollectionInterval=1 -XX:-CreateCoredumpOnCrash -XX:CompileCommand=dontinline,*::mergeImpl* compiler.gcbarriers.UnsafeIntrinsicsTest
31 */
32
33 package compiler.gcbarriers;
34
35 import java.lang.reflect.Field;
36 import java.util.ArrayList;
37 import java.util.Random;
38 import sun.misc.Unsafe;
39
40 public class UnsafeIntrinsicsTest {
41
42 /*
43 * This test triggers the loadbarriers by allocating a lot, keeping the objects alive and then
44 * letting them die in a way that maximizes fragmentation.
45 *
46 * All subtests (OperationType's) could run in parallel.
47 */
48
246 }
247 case Weak_CAS:
248 if (test_fail) {
249 return mergeImplWeakCASFail(startNode, expectedNext, head);
250 } else {
251 return mergeImplWeakCAS(startNode, expectedNext, head);
252 }
253 case CMPX:
254 if (test_fail) {
255 return mergeImplCMPXFail(startNode, expectedNext, head);
256 } else {
257 return mergeImplCMPX(startNode, expectedNext, head);
258 }
259 default:
260 throw new Error("Unimplemented");
261 }
262 }
263
264 private Node mergeImplLoad(Node startNode, Node expectedNext, Node head) {
265 // Atomic load version
266 Node temp = (Node) UNSAFE.getObject(startNode, offset);
267 startNode.setNext(head);
268 return temp;
269 }
270
271 private Node mergeImplSwap(Node startNode, Node expectedNext, Node head) {
272 // Swap version
273 return (Node) UNSAFE.getAndSetObject(startNode, offset, head);
274 }
275
276 private Node mergeImplCAS(Node startNode, Node expectedNext, Node head) {
277 // CAS - should always be true within a single thread - no other thread can have overwritten
278 if (!UNSAFE.compareAndSetObject(startNode, offset, expectedNext, head)) {
279 throw new Error("CAS should always succeed on thread local objects, check you barrier implementation");
280 }
281 return expectedNext; // continue on old circle
282 }
283
284 private Node mergeImplCASFail(Node startNode, Node expectedNext, Node head) {
285 // Force a fail
286 if (UNSAFE.compareAndSetObject(startNode, offset, "fail", head)) {
287 throw new Error("This CAS should always fail, check you barrier implementation");
288 }
289 if (startNode.next() != expectedNext) {
290 throw new Error("Shouldn't have changed");
291 }
292 return current;
293 }
294
295 private Node mergeImplWeakCAS(Node startNode, Node expectedNext, Node head) {
296 // Weak CAS - should always be true within a single thread - no other thread can have overwritten
297 if (!UNSAFE.weakCompareAndSetObject(startNode, offset, expectedNext, head)) {
298 throw new Error("Weak CAS should always succeed on thread local objects, check you barrier implementation");
299 }
300 return expectedNext; // continue on old circle
301 }
302
303 private Node mergeImplWeakCASFail(Node startNode, Node expectedNext, Node head) {
304 // Force a fail
305 if (UNSAFE.weakCompareAndSetObject(startNode, offset, "fail", head)) {
306 throw new Error("This weak CAS should always fail, check you barrier implementation");
307 }
308 if (startNode.next() != expectedNext) {
309 throw new Error("Shouldn't have changed");
310 }
311 return current;
312 }
313
314 private Node mergeImplCMPX(Node startNode, Node expectedNext, Node head) {
315 // CmpX - should always be true within a single thread - no other thread can have overwritten
316 Object res = UNSAFE.compareAndExchangeObject(startNode, offset, expectedNext, head);
317 if (!res.equals(expectedNext)) {
318 throw new Error("Fail CmpX should always succeed on thread local objects, check you barrier implementation");
319 }
320 return expectedNext; // continue on old circle
321 }
322
323 private Node mergeImplCMPXFail(Node startNode, Node expectedNext, Node head) {
324 Object res = UNSAFE.compareAndExchangeObject(startNode, offset, head, head);
325 if (startNode.next() != expectedNext) {
326 throw new Error("Shouldn't have changed");
327 }
328 if (head == expectedNext) {
329 throw new Error("Test malfunction");
330 }
331 if (!res.equals(expectedNext)) {
332 throw new Error("This CmpX should have returned 'expectedNext' when it failed");
333 }
334 if (res.equals(head)) {
335 throw new Error("This CmpX shouldn't have returned head when it failed. count: "+ iterations);
336 }
337
338 return current;
339 }
340
341 // Create a new branch that will replace a part of the circle
342 public Node makeBranch(Node end_node, int count) {
343 Node head = end_node;
344 for (int i = 0; i < count; i++) {
|
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 * @test
26 * @bug 8059022
27 * @modules java.base/jdk.internal.misc:+open
28 * @summary Validate barriers after Unsafe getReference, CAS and swap (GetAndSet)
29 * @requires vm.gc.Z & !vm.graal.enabled
30 * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UnlockDiagnosticVMOptions -XX:+ZUnmapBadViews -XX:ZCollectionInterval=1 -XX:-CreateCoredumpOnCrash -XX:CompileCommand=dontinline,*::mergeImpl* compiler.gcbarriers.UnsafeIntrinsicsTest
31 */
32
33 package compiler.gcbarriers;
34
35 import java.lang.reflect.Field;
36 import java.util.ArrayList;
37 import java.util.Random;
38 import sun.misc.Unsafe;
39
40 public class UnsafeIntrinsicsTest {
41
42 /*
43 * This test triggers the loadbarriers by allocating a lot, keeping the objects alive and then
44 * letting them die in a way that maximizes fragmentation.
45 *
46 * All subtests (OperationType's) could run in parallel.
47 */
48
246 }
247 case Weak_CAS:
248 if (test_fail) {
249 return mergeImplWeakCASFail(startNode, expectedNext, head);
250 } else {
251 return mergeImplWeakCAS(startNode, expectedNext, head);
252 }
253 case CMPX:
254 if (test_fail) {
255 return mergeImplCMPXFail(startNode, expectedNext, head);
256 } else {
257 return mergeImplCMPX(startNode, expectedNext, head);
258 }
259 default:
260 throw new Error("Unimplemented");
261 }
262 }
263
264 private Node mergeImplLoad(Node startNode, Node expectedNext, Node head) {
265 // Atomic load version
266 Node temp = (Node) UNSAFE.getReference(startNode, offset);
267 startNode.setNext(head);
268 return temp;
269 }
270
271 private Node mergeImplSwap(Node startNode, Node expectedNext, Node head) {
272 // Swap version
273 return (Node) UNSAFE.getAndSetReference(startNode, offset, head);
274 }
275
276 private Node mergeImplCAS(Node startNode, Node expectedNext, Node head) {
277 // CAS - should always be true within a single thread - no other thread can have overwritten
278 if (!UNSAFE.compareAndSetReference(startNode, offset, expectedNext, head)) {
279 throw new Error("CAS should always succeed on thread local objects, check you barrier implementation");
280 }
281 return expectedNext; // continue on old circle
282 }
283
284 private Node mergeImplCASFail(Node startNode, Node expectedNext, Node head) {
285 // Force a fail
286 if (UNSAFE.compareAndSetReference(startNode, offset, "fail", head)) {
287 throw new Error("This CAS should always fail, check you barrier implementation");
288 }
289 if (startNode.next() != expectedNext) {
290 throw new Error("Shouldn't have changed");
291 }
292 return current;
293 }
294
295 private Node mergeImplWeakCAS(Node startNode, Node expectedNext, Node head) {
296 // Weak CAS - should always be true within a single thread - no other thread can have overwritten
297 if (!UNSAFE.weakCompareAndSetReference(startNode, offset, expectedNext, head)) {
298 throw new Error("Weak CAS should always succeed on thread local objects, check you barrier implementation");
299 }
300 return expectedNext; // continue on old circle
301 }
302
303 private Node mergeImplWeakCASFail(Node startNode, Node expectedNext, Node head) {
304 // Force a fail
305 if (UNSAFE.weakCompareAndSetReference(startNode, offset, "fail", head)) {
306 throw new Error("This weak CAS should always fail, check you barrier implementation");
307 }
308 if (startNode.next() != expectedNext) {
309 throw new Error("Shouldn't have changed");
310 }
311 return current;
312 }
313
314 private Node mergeImplCMPX(Node startNode, Node expectedNext, Node head) {
315 // CmpX - should always be true within a single thread - no other thread can have overwritten
316 Object res = UNSAFE.compareAndExchangeReference(startNode, offset, expectedNext, head);
317 if (!res.equals(expectedNext)) {
318 throw new Error("Fail CmpX should always succeed on thread local objects, check you barrier implementation");
319 }
320 return expectedNext; // continue on old circle
321 }
322
323 private Node mergeImplCMPXFail(Node startNode, Node expectedNext, Node head) {
324 Object res = UNSAFE.compareAndExchangeReference(startNode, offset, head, head);
325 if (startNode.next() != expectedNext) {
326 throw new Error("Shouldn't have changed");
327 }
328 if (head == expectedNext) {
329 throw new Error("Test malfunction");
330 }
331 if (!res.equals(expectedNext)) {
332 throw new Error("This CmpX should have returned 'expectedNext' when it failed");
333 }
334 if (res.equals(head)) {
335 throw new Error("This CmpX shouldn't have returned head when it failed. count: "+ iterations);
336 }
337
338 return current;
339 }
340
341 // Create a new branch that will replace a part of the circle
342 public Node makeBranch(Node end_node, int count) {
343 Node head = end_node;
344 for (int i = 0; i < count; i++) {
|