8058828: Wrong ciConstant type for arrays from ConstantPool::_resolved_reference

Wed, 01 Oct 2014 12:34:38 -0700

author
vlivanov
date
Wed, 01 Oct 2014 12:34:38 -0700
changeset 7288
9dc314de223d
parent 7287
8ed0a8dbea70
child 7289
b9c94af14fd0

8058828: Wrong ciConstant type for arrays from ConstantPool::_resolved_reference
Reviewed-by: kvn, jrose

src/share/vm/ci/ciEnv.cpp file | annotate | diff | comparison | revisions
src/share/vm/ci/ciTypeFlow.cpp file | annotate | diff | comparison | revisions
test/compiler/jsr292/VMAnonymousClasses.java file | annotate | diff | comparison | revisions
     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 +}

mercurial