Path: blob/master/test/hotspot/jtreg/compiler/locks/TestNestedLocksElimination.java
64474 views
/*1* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324/*25* @test26* @bug 826834727* @summary Nested locks optimization may create unbalanced monitor enter/exit code28*29* @run main/othervm -XX:-BackgroundCompilation30* -XX:CompileCommand=dontinline,TestNestedLocksElimination::foo31* -XX:CompileCommand=dontinline,TestNestedLocksElimination::getNext32* -XX:CompileCommand=dontinline,TestNestedLocksElimination::getHolder33* TestNestedLocksElimination34*/3536import java.util.LinkedList;3738public class TestNestedLocksElimination {3940private LinkedList<char[]> buffers = new LinkedList<>();41private boolean complete = false;42private int bufferSize;4344void foo(char[] ca) {45// Don't inline dummy method46}4748// Don't inline49char[] getNext(int length, int count) {50if (this.buffers.isEmpty()) {51return new char[100];52}53char[] b = (char[]) this.buffers.getFirst();54if (count >= 100) {55this.complete = true;56this.buffers.clear(); // empty57}58return b;59}6061synchronized boolean isComplete() {62return this.complete;63}6465synchronized boolean availableSegment() {66return (buffers.isEmpty() == false);67}6869// Don't inline70TestNestedLocksElimination getHolder(TestNestedLocksElimination s1, TestNestedLocksElimination s2, int count) {71return (count & 7) == 0 ? s2 : s1;72}7374int test(TestNestedLocksElimination s1, TestNestedLocksElimination s2, int maxToSend) {75boolean isComplete = true;76boolean availableSegment = false;77int size = 0;78int count = 0;79do {80TestNestedLocksElimination s = getHolder(s1, s2, count++);8182synchronized(s) {83isComplete = s.isComplete();84availableSegment = s.availableSegment();85}8687synchronized (this) {88size = 0;89while (size < maxToSend) {90char[] b = null;91// This is outer Lock region for object 's'.92// Locks from following inlined methods are "nested"93// because they reference the same object.94synchronized(s) {95b = s.getNext(maxToSend - size, count);9697// The next is bi-morphic call with both calls inlined.98// But one is synchronized and the other is not.99// Class check for bi-morphic call is loop invariant100// and will trigger loop unswitching.101// Loop unswitching will create two versions of loop102// with gollowing calls inlinined in both versions.103104isComplete = s.isComplete();105106// The next synchronized method availableSegment() is107// inlined and its Lock will be "coarsened" with Unlock108// in version of loop with inlined synchronized method109// isComplete().110// Nested Lock Optimization will mark only this Unlock111// as nested (as part of "nested" pair lock/unlock).112// Locks elimination will remove "coarsened" Lock from113// availableSegment() method leaving unmatched unlock.114115availableSegment = s.availableSegment();116}117foo(b);118size += b.length;119}120}121} while (availableSegment == true || isComplete == false);122return size;123}124125public static void main(String[] args) {126int count = 0;127int n = 0;128129TestNestedLocksElimination t = new TestNestedLocksElimination();130TestNestedLocksElimination s1 = new TestNestedLocksElimination();131TestNestedLocksElimination s2 = new TestNestedLocksEliminationSub();132133char[] c = new char[100];134while (n++ < 20_000) {135s1.buffers.add(c);136s2.buffers.add(c);137count += t.test(s1, s2, 10000);138}139140System.out.println(" count: " + count);141}142}143144class TestNestedLocksEliminationSub extends TestNestedLocksElimination {145public boolean isComplete() {146return true;147}148}149150151152