MonitorTest.java revision 12651:6ef01bd40ce2
1/*
2 * Copyright (c) 2012, 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 */
23package org.graalvm.compiler.replacements.test;
24
25import org.junit.Test;
26
27import org.graalvm.compiler.core.test.GraalCompilerTest;
28import org.graalvm.compiler.nodes.ValueNode;
29import org.graalvm.compiler.replacements.BoxingSnippets;
30import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
31
32public class MonitorTest extends GraalCompilerTest {
33
34    @Test
35    public void test0() {
36        test("lockObjectSimple", new Object(), new Object());
37        test("lockObjectSimple", new Object(), null);
38        test("lockObjectSimple", null, null);
39    }
40
41    @Test
42    public void test01() {
43        test("lockThisSimple", "test1", new Object());
44        test("lockThisSimple", "test1", null);
45    }
46
47    @Test
48    public void test02() {
49        test("lockObjectSimple", null, "test1");
50    }
51
52    @Test
53    public void test101() {
54        test("lockObject", new Object(), "test1", new String[1]);
55    }
56
57    @Test
58    public void test102() {
59        test("lockObject", null, "test1_1", new String[1]);
60    }
61
62    @Test
63    public void test2() {
64        test("lockThis", "test2", new String[1]);
65    }
66
67    /**
68     * Tests monitor operations on {@link PartialEscapePhase virtual objects}.
69     */
70    @Test
71    public void test3() {
72        test("lockLocalObject", "test3", new String[1]);
73    }
74
75    /**
76     * Tests recursive locking of objects which should be biasable.
77     */
78    @Test
79    public void test4() {
80        Chars src = new Chars("1234567890".toCharArray());
81        Chars dst = new Chars(src.data.length);
82        test("copyObj", src, dst, 100);
83    }
84
85    /**
86     * Tests recursive locking of objects which do not appear to be biasable.
87     */
88    @Test
89    public void test5() {
90        char[] src = "1234567890".toCharArray();
91        char[] dst = new char[src.length];
92        test("copyArr", src, dst, 100);
93    }
94
95    /**
96     * Extends {@link #test4()} with contention.
97     */
98    @Test
99    public void test6() {
100        Chars src = new Chars("1234567890".toCharArray());
101        Chars dst = new Chars(src.data.length);
102        int n = Runtime.getRuntime().availableProcessors();
103        testN(n, "copyObj", src, dst, 100);
104    }
105
106    /**
107     * Extends {@link #test5()} with contention.
108     */
109    @Test
110    public void test7() {
111        char[] src = "1234567890".toCharArray();
112        char[] dst = new char[src.length];
113        int n = Math.min(32, Runtime.getRuntime().availableProcessors());
114        testN(n, "copyArr", src, dst, 100);
115    }
116
117    private static String setAndGet(String[] box, String value) {
118        synchronized (box) {
119            box[0] = null;
120        }
121
122        // Do a GC while a object is locked (by the caller)
123        System.gc();
124
125        synchronized (box) {
126            box[0] = value;
127        }
128        return box[0];
129    }
130
131    public static Object lockObjectSimple(Object o, Object value) {
132        synchronized (o) {
133            value.hashCode();
134            return value;
135        }
136    }
137
138    public String lockThisSimple(String value, Object o) {
139        synchronized (this) {
140            synchronized (value) {
141                o.hashCode();
142                return value;
143            }
144        }
145    }
146
147    public static String lockObject(Object o, String value, String[] box) {
148        synchronized (o) {
149            return setAndGet(box, value);
150        }
151    }
152
153    public String lockThis(String value, String[] box) {
154        synchronized (this) {
155            return setAndGet(box, value);
156        }
157    }
158
159    public static String lockLocalObject(String value, String[] box) {
160        Object o = new Object();
161        synchronized (o) {
162            return setAndGet(box, value);
163        }
164    }
165
166    static class Chars {
167
168        final char[] data;
169
170        Chars(int size) {
171            this.data = new char[size];
172        }
173
174        Chars(char[] data) {
175            this.data = data;
176        }
177    }
178
179    public static String copyObj(Chars src, Chars dst, int n) {
180        for (int j = 0; j < n; j++) {
181            for (int i = 0; i < src.data.length; i++) {
182                synchronized (src) {
183                    synchronized (dst) {
184                        synchronized (src) {
185                            synchronized (dst) {
186                                dst.data[i] = src.data[i];
187                            }
188                        }
189                    }
190                }
191            }
192        }
193        return new String(dst.data);
194    }
195
196    public static String copyArr(char[] src, char[] dst, int n) {
197        for (int j = 0; j < n; j++) {
198            for (int i = 0; i < src.length; i++) {
199                synchronized (src) {
200                    synchronized (dst) {
201                        synchronized (src) {
202                            synchronized (dst) {
203                                dst[i] = src[i];
204                            }
205                        }
206                    }
207                }
208            }
209        }
210        return new String(dst);
211    }
212
213    public static String lockBoxedLong(long value) {
214        Long lock = value;
215        synchronized (lock) {
216            return lock.toString();
217        }
218    }
219
220    /**
221     * Reproduces issue reported in https://github.com/graalvm/graal-core/issues/201. The stamp in
222     * the PiNode returned by {@link BoxingSnippets#longValueOf(long)} was overwritten when the node
223     * was subsequently canonicalized because {@code PiNode.computeValue()} ignored the
224     * {@link ValueNode#stamp()} field and used the {@code PiNode.piStamp} field.
225     */
226    @Test
227    public void test8() {
228        test("lockBoxedLong", 5L);
229        test("lockBoxedLong", Long.MAX_VALUE - 1);
230        test("lockBoxedLong", Long.MIN_VALUE + 1);
231    }
232}
233