1 /*
2 * Copyright (c) 2016, 2024, 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 */
23
24 /*
25 * @test
26 * @bug 8155643 8268125 8270461 8270098 8332959
27 * @summary Test Object.clone() intrinsic.
28 * @modules java.base/java.lang:+open
29 *
30 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-ReduceInitialCardMarks
31 * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
32 * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
33 * compiler.arraycopy.TestObjectArrayClone
34 * @run main/othervm -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
35 * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
36 * compiler.arraycopy.TestObjectArrayClone
37 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedClassPointers -Xmx128m
38 * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
39 * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
40 * compiler.arraycopy.TestObjectArrayClone
41 * @run main/othervm -Xbatch -XX:-UseTypeProfile
42 * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
43 * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
44 * -XX:CompileCommand=compileonly,*::invokeVirtual
45 * compiler.arraycopy.TestObjectArrayClone
46 * @run main/othervm -Xbatch -XX:-UseTypeProfile -XX:-ReduceInitialCardMarks
47 * -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
48 * -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
49 * compiler.arraycopy.TestObjectArrayClone
50 */
51
52 package compiler.arraycopy;
53
54 import java.lang.invoke.*;
55 import java.lang.reflect.InvocationTargetException;
56 import java.lang.reflect.Method;
57
58 class Payload implements Cloneable {
59 boolean b;
60 int i;
61 char c;
62 String str;
63 short s;
64 int i2;
65
66 public Payload(boolean b, int i, char c, String str, short s, int i2) {
67 super();
68 this.b = b;
69 this.i = i;
70 this.c = c;
71 this.str = str;
72 this.s = s;
73 this.i2 = i2;
74 }
75
76 public Payload clonep() {
77 try {
78 return (Payload) super.clone();
79 } catch (CloneNotSupportedException e) {
80 return null;
81 }
82 }
83 }
84
85 class Payload2 implements Cloneable {
86 boolean b;
87 int i;
88 char c;
89 String str;
90 short s;
91 int i2;
92 boolean b2;
93 int i3;
94 char c2;
95 String str2;
96 short s2;
97 int i4;
98
99 public Payload2(boolean b, int i, char c, String str, short s, int i2, boolean b2, int i3, char c2, String str2,
100 short s2, int i4) {
101 super();
102 this.b = b;
103 this.i = i;
104 this.c = c;
105 this.str = str;
106 this.s = s;
107 this.i2 = i2;
108 this.b2 = b2;
109 this.i3 = i3;
110 this.c2 = c2;
111 this.str2 = str2;
112 this.s2 = s2;
113 this.i4 = i4;
114 }
115
116 public Payload2 clonep() {
117 try {
118 return (Payload2) super.clone();
119 } catch(CloneNotSupportedException e) {
120 return null;
121 }
122 }
123 }
124
125 public class TestObjectArrayClone {
126
127 public static String[] escape_arr;
128
129 public static String str1 = new String("1");
130 public static String str2 = new String("2");
131 public static String str3 = new String("3");
132 public static String str4 = new String("4");
133 public static String str5 = new String("5");
134
135 public static String[] testCloneObjectArray(String[] arr) {
136 return arr.clone();
137 }
138
139 public static String[] testCloneObjectArrayCopy(String[] arr) {
140 String[] arr2 = new String[arr.length];
141 System.arraycopy(arr, 0, arr2, 0, arr.length);
142 return arr2;
143 }
144
145 public static String[] testCloneShortObjectArray() {
146 String[] arr = new String[5];
147 arr[0] = str1;
148 arr[1] = str2;
149 arr[2] = str3;
150 arr[3] = str4;
151 arr[4] = str5;
152 escape_arr = arr;
153 return arr.clone();
154 }
155
156 public static String[] testCloneShortObjectArray2(Method clone) throws Exception {
157 String[] arr = new String[5];
158 arr[0] = str1;
159 arr[1] = str2;
160 arr[2] = str3;
161 arr[3] = str4;
162 arr[4] = str5;
163 escape_arr = arr;
164 return (String[]) testCloneObject(clone, arr);
165 }
166
167 public static String[] testCloneShortObjectArrayCopy() {
168 String[] arr = new String[5];
169 arr[0] = str1;
170 arr[1] = str2;
171 arr[2] = str3;
172 arr[3] = str4;
173 arr[4] = str5;
174 escape_arr = arr;
175 String[] arr2 = new String[arr.length];
176 System.arraycopy(arr, 0, arr2, 0, arr.length);
177 return arr2;
178 }
179
180 public static int[] testClonePrimitiveArray(int[] arr) {
181 return arr.clone();
182 }
183
184 public static Object testCloneOop(Payload p) {
185 return p.clonep();
186 }
187
188 public static Object testCloneOop2(Payload2 p) {
189 return p.clonep();
190 }
191
192 public static Object testCloneObject(Method clone, Object obj) throws Exception {
193 return clone.invoke(obj);
194 }
195
196 public static Object testCloneObjectWithMethodHandle(MethodHandle clone, Object obj) throws Throwable {
197 return clone.invokeExact(obj);
198 }
199
200 public static void main(String[] args) throws Throwable {
201 Method clone = Object.class.getDeclaredMethod("clone");
202 clone.setAccessible(true);
203
204 MethodHandles.Lookup privateLookup = MethodHandles.privateLookupIn(Object.class, MethodHandles.lookup());
205 MethodType mt = MethodType.methodType(Object.class);
206 MethodHandle mh = privateLookup.findVirtual(Object.class, "clone", mt);
207
208 String[] arr1 = new String[42];
209 for (int j = 0; j < arr1.length; j++) {
210 arr1[j] = new String(Integer.toString(j));
211 }
212
213 for (int i = 0; i < 50_000; i++) {
214 String[] arr2 = testCloneObjectArray(arr1);
215 verifyStr(arr1, arr2);
216 String[] arr3 = testCloneObjectArray(arr1);
217 verifyStr(arr1, arr3);
218 String[] arr4 = testCloneObjectArray(arr1);
219 verifyStr(arr1, arr4);
220 verifyStr(arr1, arr3);
221 verifyStr(arr1, arr2);
222 }
223
224 for (int i = 0; i < 50_000; i++) {
225 for (int j = 0; j < arr1.length; j++) {
226 arr1[j] = new String(Integer.toString(j));
227 }
228 String[] arr2 = (String[]) testCloneObject(clone, arr1);
229 verifyStr(arr1, arr2);
230 String[] arr3 = (String[]) testCloneObject(clone, arr1);
231 verifyStr(arr1, arr3);
232 String[] arr4 = (String[]) testCloneObject(clone, arr1);
233 verifyStr(arr1, arr4);
234 verifyStr(arr1, arr3);
235 verifyStr(arr1, arr2);
236 }
237
238 for (int i = 0; i < 50_000; i++) {
239 String[] value = testCloneShortObjectArray();
240 verifyStr(value, escape_arr);
241 String[] value2 = testCloneShortObjectArray();
242 verifyStr(value2, escape_arr);
243 String[] value3 = testCloneShortObjectArray();
244 verifyStr(value3, escape_arr);
245 String[] value4 = testCloneShortObjectArray2(clone);
246 verifyStr(value4, escape_arr);
247 verifyStr(value, value4);
248 verifyStr(value, value3);
249 verifyStr(value, value2);
250 }
251
252 for (int i = 0; i < 50_000; i++) {
253 String[] arr2 = testCloneObjectArrayCopy(arr1);
254 verifyStr(arr1, arr2);
255 String[] arr3 = testCloneObjectArrayCopy(arr1);
256 verifyStr(arr1, arr3);
257 String[] arr4 = testCloneObjectArrayCopy(arr1);
258 verifyStr(arr1, arr4);
259 verifyStr(arr1, arr3);
260 verifyStr(arr1, arr2);
261 }
262
263 for (int i = 0; i < 50_000; i++) {
264 String[] value = testCloneShortObjectArrayCopy();
265 verifyStr(value, escape_arr);
266 String[] value2 = testCloneShortObjectArrayCopy();
267 verifyStr(value2, escape_arr);
268 String[] value3 = testCloneShortObjectArrayCopy();
269 verifyStr(value3, escape_arr);
270 verifyStr(value, value3);
271 verifyStr(value, value2);
272 }
273
274 for (int i = 0; i < 50_000; i++) {
275 String[] arr2 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
276 verifyStr(arr1, arr2);
277 String[] arr3 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
278 verifyStr(arr1, arr3);
279 String[] arr4 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
280 verifyStr(arr1, arr4);
281 verifyStr(arr1, arr3);
282 verifyStr(arr1, arr2);
283 }
284
285 int[] arr2 = new int[42];
286 for (int i = 0; i < arr2.length; i++) {
287 arr2[i] = i;
288 }
289 for (int i = 0; i < 50_000; i++) {
290 int[] res1 = testClonePrimitiveArray(arr2);
291 int[] res2 = (int[])testCloneObject(clone, arr2);
292 for (int j = 0; j < arr2.length; j++) {
293 if (res1[j] != j) {
294 throw new RuntimeException("Unexpected result: " + res1[j] + " != " + j);
295 }
296 if (res2[j] != j) {
297 throw new RuntimeException("Unexpected result: " + res2[j] + " != " + j);
298 }
299 }
300 }
301
302 Payload ref = new Payload(false, -1, 'c', str1, (short) 5, -1);
303 for (int i = 0; i < 50_000; i++) {
304 Payload p1 = (Payload) testCloneOop(ref);
305 verifyPayload(ref, p1);
306 Payload p2 = (Payload) testCloneOop(ref);
307 verifyPayload(ref, p2);
308 Payload p3 = (Payload) testCloneOop(ref);
309 verifyPayload(ref, p3);
310 verifyPayload(p2, p3);
311 verifyPayload(p1, p3);
312 }
313
314 for (int i = 0; i < 50_000; i++) {
315 Payload p1 = (Payload) testCloneObject(clone, ref);
316 verifyPayload(ref, p1);
317 Payload p2 = (Payload) testCloneObject(clone, ref);
318 verifyPayload(ref, p2);
319 Payload p3 = (Payload) testCloneObject(clone, ref);
320 verifyPayload(ref, p3);
321 verifyPayload(p2, p3);
322 verifyPayload(p1, p3);
323 }
324
325 Payload2 ref2 = new Payload2(false, -1, 'c', str1, (short) 5, -1, false, 0, 'k', str2, (short)-1, 0);
326 for (int i = 0; i < 50_000; i++) {
327 Payload2 p1 = (Payload2) testCloneOop2(ref2);
328 verifyPayload2(ref2, p1);
329 Payload2 p2 = (Payload2) testCloneOop2(ref2);
330 verifyPayload2(ref2, p2);
331 Payload2 p3 = (Payload2) testCloneOop2(ref2);
332 verifyPayload2(ref2, p3);
333 verifyPayload2(p2, p3);
334 verifyPayload2(p1, p3);
335 }
336
337 for (int i = 0; i < 50_000; i++) {
338 Payload2 p1 = (Payload2) testCloneObject(clone, ref2);
339 verifyPayload2(ref2, p1);
340 Payload2 p2 = (Payload2) testCloneObject(clone, ref2);
341 verifyPayload2(ref2, p2);
342 Payload2 p3 = (Payload2) testCloneObject(clone, ref2);
343 verifyPayload2(ref2, p3);
344 verifyPayload2(p2, p3);
345 verifyPayload2(p1, p3);
346 }
347
348 for (int i = 0; i < 50_000; i++) {
349 Payload2 p1 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
350 verifyPayload2(ref2, p1);
351 Payload2 p2 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
352 verifyPayload2(ref2, p2);
353 Payload2 p3 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
354 verifyPayload2(ref2, p3);
355 verifyPayload2(p2, p3);
356 verifyPayload2(p1, p3);
357 }
358 }
359
360 public static void verifyPayload(Payload p1, Payload p2) {
361 if (p1.b != p2.b) {
362 throw new RuntimeException("b is wrong");
363 }
364 if (p1.c != p2.c) {
365 throw new RuntimeException("c is wrong");
366 }
367 if (p1.i != p2.i) {
368 throw new RuntimeException("i is wrong");
369 }
370 if (p1.s != p2.s) {
371 throw new RuntimeException("s is wrong");
372 }
373 if (p1.i2 != p2.i2) {
374 throw new RuntimeException("i2 is wrong");
375 }
376 if (p1.str != p2.str) {
377 throw new RuntimeException("str is wrong");
378 }
379 if (!p1.str.equals(p2.str)) {
380 throw new RuntimeException("str content is wrong");
381 }
382 }
383
384 public static void verifyPayload2(Payload2 p1, Payload2 p2) {
385 if (p1.b != p2.b) {
386 throw new RuntimeException("b is wrong");
387 }
388 if (p1.c != p2.c) {
389 throw new RuntimeException("c is wrong");
390 }
391 if (p1.i != p2.i) {
392 throw new RuntimeException("i is wrong");
393 }
394 if (p1.s != p2.s) {
395 throw new RuntimeException("s is wrong");
396 }
397 if (p1.i2 != p2.i2) {
398 throw new RuntimeException("i2 is wrong");
399 }
400 if (p1.str != p2.str) {
401 throw new RuntimeException("str is wrong");
402 }
403 if (!p1.str.equals(p2.str)) {
404 throw new RuntimeException("str content is wrong");
405 }
406 if (p1.b2 != p2.b2) {
407 throw new RuntimeException("b is wrong");
408 }
409 if (p1.c2 != p2.c2) {
410 throw new RuntimeException("c is wrong");
411 }
412 if (p1.i3 != p2.i3) {
413 throw new RuntimeException("i is wrong");
414 }
415 if (p1.s2 != p2.s2) {
416 throw new RuntimeException("s is wrong");
417 }
418 if (p1.i4 != p2.i4) {
419 throw new RuntimeException("i2 is wrong");
420 }
421 if (p1.str2 != p2.str2) {
422 throw new RuntimeException("str is wrong");
423 }
424 if (!p1.str2.equals(p2.str2)) {
425 throw new RuntimeException("str content is wrong");
426 }
427 }
428
429 public static void verifyStr(String[] arr1, String[] arr2) {
430 if (arr1 == arr2) {
431 throw new RuntimeException("Must not be the same");
432 }
433 if (arr1.length != arr2.length) {
434 throw new RuntimeException("Must have the same length");
435 }
436 for (int i = 0; i < arr1.length; i++) {
437 if (arr1[i] != arr2[i]) {
438 throw new RuntimeException("Fail cloned element not the same: " + i);
439 }
440 if (!arr1[i].equals(arr2[i])) {
441 throw new RuntimeException("Fail cloned element content not the same");
442 }
443 }
444 }
445 }
446