diff --git a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp index bc605711570..facfbdd4de0 100644 --- a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp @@ -323,8 +323,9 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, // -2- test (hdr - SP) if the low two bits are 0 sub(tmp2, hdr, SP, eq); movs(tmp2, AsmOperand(tmp2, lsr, exact_log2(os::vm_page_size())), eq); - // If 'eq' then OK for recursive fast locking: store 0 into a lock record. - str(tmp2, Address(disp_hdr, mark_offset), eq); + // If still 'eq' then recursive locking OK + // set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8267042) + str(tmp2, Address(disp_hdr, mark_offset)); b(fast_lock_done, eq); // else need slow case b(slow_case); diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index 5d0f8cb62f3..25366a8af54 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -1622,8 +1622,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // -2- test (hdr - SP) if the low two bits are 0 __ sub(Rtemp, mark, SP, eq); __ movs(Rtemp, AsmOperand(Rtemp, lsr, exact_log2(os::vm_page_size())), eq); - // If still 'eq' then recursive locking OK: set displaced header to 0 - __ str(Rtemp, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes()), eq); + // If still 'eq' then recursive locking OK + // set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8267042) + __ str(Rtemp, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes())); __ b(lock_done, eq); __ b(slow_lock); diff --git a/test/hotspot/jtreg/compiler/c1/Test8267042.java b/test/hotspot/jtreg/compiler/c1/Test8267042.java new file mode 100644 index 00000000000..1569dd46949 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c1/Test8267042.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021, 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. + */ + +package compiler.c1; + +import java.io.IOException; +import java.io.InterruptedIOException; + +/* + * @test + * @author Chris Cole + * @bug 8267042 + * @summary missing displaced_header initialization causes hangup + * @run main/othervm -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-BackgroundCompilation -XX:CompileThreshold=1 + * -XX:CompileOnly=compiler.c1.Test8267042::write + * compiler.c1.Test8267042 + */ +public class Test8267042 { + + private static int DATA_SIZE = 4; + + private char buffer; + private boolean empty = true; + + public static void main(String[] args) { + Test8267042 test = new Test8267042(); + test.run(); + } + + private void run() { + System.out.println("Starting test"); + + Thread writeThread = new Thread(new Runnable() { + @Override + public void run() { + char data[] = new char[DATA_SIZE]; + try { + write(data, 0, data.length); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + writeThread.setDaemon(true); + writeThread.start(); + + Thread readThread = new Thread(new Runnable() { + @Override + public void run() { + try { + for (int i = 0; i < DATA_SIZE; i++) { + read(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + readThread.setDaemon(true); + readThread.start(); + + try { + writeThread.join(5000); + if (writeThread.isAlive()) { + throw new InternalError("write thread deadlocked"); + } + readThread.join(5000); + if (readThread.isAlive()) { + throw new InternalError("read thread deadlocked"); + } + } catch (InterruptedException e) { + throw new InternalError("unexpected InterrruptedException while waiting to join threads", e); + } + System.out.println("Test passed"); + } + + synchronized void write(char data[], int offset, int length) throws IOException { + while (--length >= 0) { + getZeroOnStack(offset); + write(data[offset++]); + } + } + + synchronized void write(int c) throws IOException { + while (!empty) { + try { + wait(1000); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } + buffer = (char) c; + empty = false; + notifyAll(); + } + + public synchronized int read() throws IOException { + while (empty) { + try { + System.out.println("read() before wait"); + wait(1000); + System.out.println("read() after wait"); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } + int value = buffer; + empty = true; + notifyAll(); + return value; + } + + private void getZeroOnStack(int offset) { + int l1; + int l2; + int l3; + int l4; + int l5; + int l6; + int l7; + int l8; + int l9; + int l10; + int l11; + int l12; + int l13; + int l14; + int l15; + int l16; + + l1 = 0; + l2 = 0; + l3 = 0; + l4 = 0; + l5 = 0; + l6 = 0; + l7 = 0; + l8 = 0; + l9 = 0; + l10 = 0; + l11 = 0; + l12 = 0; + l13 = 0; + l14 = 0; + l15 = 0; + l16 = 0; + } +} +