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