blob: 608ca1676c189f1f36cc1368f4bc7f5cbe3fcd39 [file] [log] [blame]
/*
* Copyright (c) 2012, 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 org.graalvm.compiler.replacements.test;
import org.junit.Test;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.replacements.BoxingSnippets;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
public class MonitorTest extends GraalCompilerTest {
@Test
public void test0() {
test("lockObjectSimple", new Object(), new Object());
test("lockObjectSimple", new Object(), null);
test("lockObjectSimple", null, null);
}
@Test
public void test01() {
test("lockThisSimple", "test1", new Object());
test("lockThisSimple", "test1", null);
}
@Test
public void test02() {
test("lockObjectSimple", null, "test1");
}
@Test
public void test101() {
test("lockObject", new Object(), "test1", new String[1]);
}
@Test
public void test102() {
test("lockObject", null, "test1_1", new String[1]);
}
@Test
public void test2() {
test("lockThis", "test2", new String[1]);
}
/**
* Tests monitor operations on {@link PartialEscapePhase virtual objects}.
*/
@Test
public void test3() {
test("lockLocalObject", "test3", new String[1]);
}
/**
* Tests recursive locking of objects which should be biasable.
*/
@Test
public void test4() {
Chars src = new Chars("1234567890".toCharArray());
Chars dst = new Chars(src.data.length);
test("copyObj", src, dst, 100);
}
/**
* Tests recursive locking of objects which do not appear to be biasable.
*/
@Test
public void test5() {
char[] src = "1234567890".toCharArray();
char[] dst = new char[src.length];
test("copyArr", src, dst, 100);
}
/**
* Extends {@link #test4()} with contention.
*/
@Test
public void test6() {
Chars src = new Chars("1234567890".toCharArray());
Chars dst = new Chars(src.data.length);
int n = Runtime.getRuntime().availableProcessors();
testN(n, "copyObj", src, dst, 100);
}
/**
* Extends {@link #test5()} with contention.
*/
@Test
public void test7() {
char[] src = "1234567890".toCharArray();
char[] dst = new char[src.length];
int n = Math.min(32, Runtime.getRuntime().availableProcessors());
testN(n, "copyArr", src, dst, 100);
}
private static String setAndGet(String[] box, String value) {
synchronized (box) {
box[0] = null;
}
// Do a GC while a object is locked (by the caller)
System.gc();
synchronized (box) {
box[0] = value;
}
return box[0];
}
public static Object lockObjectSimple(Object o, Object value) {
synchronized (o) {
value.hashCode();
return value;
}
}
public String lockThisSimple(String value, Object o) {
synchronized (this) {
synchronized (value) {
o.hashCode();
return value;
}
}
}
public static String lockObject(Object o, String value, String[] box) {
synchronized (o) {
return setAndGet(box, value);
}
}
public String lockThis(String value, String[] box) {
synchronized (this) {
return setAndGet(box, value);
}
}
public static String lockLocalObject(String value, String[] box) {
Object o = new Object();
synchronized (o) {
return setAndGet(box, value);
}
}
static class Chars {
final char[] data;
Chars(int size) {
this.data = new char[size];
}
Chars(char[] data) {
this.data = data;
}
}
public static String copyObj(Chars src, Chars dst, int n) {
for (int j = 0; j < n; j++) {
for (int i = 0; i < src.data.length; i++) {
synchronized (src) {
synchronized (dst) {
synchronized (src) {
synchronized (dst) {
dst.data[i] = src.data[i];
}
}
}
}
}
}
return new String(dst.data);
}
public static String copyArr(char[] src, char[] dst, int n) {
for (int j = 0; j < n; j++) {
for (int i = 0; i < src.length; i++) {
synchronized (src) {
synchronized (dst) {
synchronized (src) {
synchronized (dst) {
dst[i] = src[i];
}
}
}
}
}
}
return new String(dst);
}
public static String lockBoxedLong(long value) {
Long lock = value;
synchronized (lock) {
return lock.toString();
}
}
/**
* Reproduces issue reported in https://github.com/graalvm/graal-core/issues/201. The stamp in
* the PiNode returned by {@link BoxingSnippets#longValueOf} was overwritten when the node was
* subsequently canonicalized because {@code PiNode.computeValue()} ignored the
* {@link ValueNode#stamp(org.graalvm.compiler.nodes.NodeView)} field and used the
* {@code PiNode.piStamp} field.
*/
@Test
public void test8() {
test("lockBoxedLong", 5L);
test("lockBoxedLong", Long.MAX_VALUE - 1);
test("lockBoxedLong", Long.MIN_VALUE + 1);
}
}