Wed, 01 Oct 2014 12:34:38 -0700
8058828: Wrong ciConstant type for arrays from ConstantPool::_resolved_reference
Reviewed-by: kvn, jrose
1.1 --- a/src/share/vm/ci/ciEnv.cpp Wed Oct 01 12:34:45 2014 -0700 1.2 +++ b/src/share/vm/ci/ciEnv.cpp Wed Oct 01 12:34:38 2014 -0700 1.3 @@ -559,7 +559,12 @@ 1.4 oop obj = cpool->resolved_references()->obj_at(cache_index); 1.5 if (obj != NULL) { 1.6 ciObject* ciobj = get_object(obj); 1.7 - return ciConstant(T_OBJECT, ciobj); 1.8 + if (ciobj->is_array()) { 1.9 + return ciConstant(T_ARRAY, ciobj); 1.10 + } else { 1.11 + assert(ciobj->is_instance(), "should be an instance"); 1.12 + return ciConstant(T_OBJECT, ciobj); 1.13 + } 1.14 } 1.15 index = cpool->object_to_cp_index(cache_index); 1.16 } 1.17 @@ -586,8 +591,12 @@ 1.18 } 1.19 } 1.20 ciObject* constant = get_object(string); 1.21 - assert (constant->is_instance(), "must be an instance, or not? "); 1.22 - return ciConstant(T_OBJECT, constant); 1.23 + if (constant->is_array()) { 1.24 + return ciConstant(T_ARRAY, constant); 1.25 + } else { 1.26 + assert (constant->is_instance(), "must be an instance, or not? "); 1.27 + return ciConstant(T_OBJECT, constant); 1.28 + } 1.29 } else if (tag.is_klass() || tag.is_unresolved_klass()) { 1.30 // 4881222: allow ldc to take a class type 1.31 ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
2.1 --- a/src/share/vm/ci/ciTypeFlow.cpp Wed Oct 01 12:34:45 2014 -0700 2.2 +++ b/src/share/vm/ci/ciTypeFlow.cpp Wed Oct 01 12:34:38 2014 -0700 2.3 @@ -730,7 +730,7 @@ 2.4 if (obj->is_null_object()) { 2.5 push_null(); 2.6 } else { 2.7 - assert(obj->is_instance(), "must be java_mirror of klass"); 2.8 + assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass"); 2.9 push_object(obj->klass()); 2.10 } 2.11 } else {
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/compiler/jsr292/VMAnonymousClasses.java Wed Oct 01 12:34:38 2014 -0700 3.3 @@ -0,0 +1,125 @@ 3.4 +/* 3.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/** 3.28 + * @test 3.29 + * @bug 8058828 3.30 + * @run main/bootclasspath -Xbatch VMAnonymousClasses 3.31 + */ 3.32 + 3.33 +import jdk.internal.org.objectweb.asm.ClassWriter; 3.34 +import jdk.internal.org.objectweb.asm.MethodVisitor; 3.35 +import jdk.internal.org.objectweb.asm.Opcodes; 3.36 +import sun.misc.Unsafe; 3.37 + 3.38 +import java.lang.invoke.ConstantCallSite; 3.39 +import java.lang.invoke.MethodHandle; 3.40 +import java.lang.invoke.MethodHandles; 3.41 +import java.lang.invoke.MethodType; 3.42 +import java.lang.invoke.MutableCallSite; 3.43 +import java.lang.invoke.VolatileCallSite; 3.44 + 3.45 +public class VMAnonymousClasses { 3.46 + static final String TEST_METHOD_NAME = "constant"; 3.47 + 3.48 + static final Unsafe UNSAFE = Unsafe.getUnsafe(); 3.49 + 3.50 + static int getConstantPoolSize(byte[] classFile) { 3.51 + // The first few bytes: 3.52 + // u4 magic; 3.53 + // u2 minor_version; 3.54 + // u2 major_version; 3.55 + // u2 constant_pool_count; 3.56 + return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF); 3.57 + } 3.58 + 3.59 + static void test(Object value) throws ReflectiveOperationException { 3.60 + System.out.printf("Test: %s", value != null ? value.getClass() : "null"); 3.61 + 3.62 + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); 3.63 + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "Test", null, "java/lang/Object", null); 3.64 + 3.65 + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, TEST_METHOD_NAME, "()Ljava/lang/Object;", null, null); 3.66 + 3.67 + String placeholder = "CONSTANT"; 3.68 + int index = cw.newConst(placeholder); 3.69 + mv.visitLdcInsn(placeholder); 3.70 + mv.visitInsn(Opcodes.ARETURN); 3.71 + 3.72 + mv.visitMaxs(0, 0); 3.73 + mv.visitEnd(); 3.74 + 3.75 + byte[] classFile = cw.toByteArray(); 3.76 + 3.77 + Object[] cpPatches = new Object[getConstantPoolSize(classFile)]; 3.78 + cpPatches[index] = value; 3.79 + 3.80 + Class<?> test = UNSAFE.defineAnonymousClass(VMAnonymousClasses.class, classFile, cpPatches); 3.81 + 3.82 + Object expectedResult = (value != null) ? value : placeholder; 3.83 + for (int i = 0; i<15000; i++) { 3.84 + Object result = test.getMethod(TEST_METHOD_NAME).invoke(null); 3.85 + if (result != expectedResult) { 3.86 + throw new AssertionError(String.format("Wrong value returned: %s != %s", value, result)); 3.87 + } 3.88 + } 3.89 + System.out.println(" PASSED"); 3.90 + } 3.91 + 3.92 + public static void main(String[] args) throws ReflectiveOperationException { 3.93 + // Objects 3.94 + test(new Object()); 3.95 + test("TEST"); 3.96 + test(new VMAnonymousClasses()); 3.97 + test(null); 3.98 + 3.99 + // Class 3.100 + test(String.class); 3.101 + 3.102 + // Arrays 3.103 + test(new boolean[0]); 3.104 + test(new byte[0]); 3.105 + test(new char[0]); 3.106 + test(new short[0]); 3.107 + test(new int[0]); 3.108 + test(new long[0]); 3.109 + test(new float[0]); 3.110 + test(new double[0]); 3.111 + test(new Object[0]); 3.112 + 3.113 + // Multi-dimensional arrays 3.114 + test(new byte[0][0]); 3.115 + test(new Object[0][0]); 3.116 + 3.117 + // MethodHandle-related 3.118 + MethodType mt = MethodType.methodType(void.class, String[].class); 3.119 + MethodHandle mh = MethodHandles.lookup().findStatic(VMAnonymousClasses.class, "main", mt); 3.120 + test(mt); 3.121 + test(mh); 3.122 + test(new ConstantCallSite(mh)); 3.123 + test(new MutableCallSite(MethodType.methodType(void.class))); 3.124 + test(new VolatileCallSite(MethodType.methodType(void.class))); 3.125 + 3.126 + System.out.println("TEST PASSED"); 3.127 + } 3.128 +}