1 /* 2 * Copyright (c) 2016, 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 package org.graalvm.compiler.replacements.test; 24 25 import java.util.ArrayList; 26 import java.util.Collection; 27 28 import org.junit.Assert; 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 import org.junit.runners.Parameterized; 32 import org.junit.runners.Parameterized.Parameter; 33 import org.junit.runners.Parameterized.Parameters; 34 35 import org.graalvm.compiler.api.directives.GraalDirectives; 36 import org.graalvm.compiler.core.common.type.Stamp; 37 import org.graalvm.compiler.core.common.type.StampFactory; 38 import org.graalvm.compiler.core.common.type.TypeReference; 39 import org.graalvm.compiler.nodes.ConstantNode; 40 import org.graalvm.compiler.nodes.ValueNode; 41 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; 42 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; 43 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; 44 45 import jdk.vm.ci.meta.Constant; 46 import jdk.vm.ci.meta.ResolvedJavaMethod; 47 import jdk.vm.ci.meta.ResolvedJavaType; 48 49 @RunWith(Parameterized.class) 50 public class ClassCastBytecodeExceptionTest extends BytecodeExceptionTest { 51 52 private static class Exceptions { 53 54 public static void throwClassCast(Object obj, Class<?> cls) { 55 /* 56 * We don't use cls.cast(obj) here because that gives a different exception message than 57 * the checkcast bytecode. 58 */ 59 if (cls == Double.class) { 60 Double cast = (Double) obj; 61 GraalDirectives.blackhole(cast); 62 } else if (cls == byte[].class) { 63 byte[] cast = (byte[]) obj; 64 GraalDirectives.blackhole(cast); 65 } else if (cls == String[].class) { 66 String[] cast = (String[]) obj; 67 GraalDirectives.blackhole(cast); 68 } else if (cls == Object[][].class) { 69 Object[][] cast = (Object[][]) obj; 70 GraalDirectives.blackhole(cast); 71 } else { 72 Assert.fail("unexpected class argument"); 73 } 74 } 75 } 76 77 @Override 78 protected void registerPlugin(InvocationPlugins plugins) { 79 plugins.register(new InvocationPlugin() { 80 @Override 81 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode obj, ValueNode classNode) { 82 ResolvedJavaType type = b.getConstantReflection().asJavaType(classNode.asConstant()); 83 Constant hub = b.getConstantReflection().asObjectHub(type); 84 Stamp hubStamp = b.getStampProvider().createHubStamp(StampFactory.object(TypeReference.createExactTrusted(type))); 85 ConstantNode hubConst = b.add(ConstantNode.forConstant(hubStamp, hub, b.getMetaAccess())); 86 return throwBytecodeException(b, ClassCastException.class, obj, hubConst); 87 } 88 }, Exceptions.class, "throwClassCast", Object.class, Class.class); 89 } 90 91 @Parameter(0) public Object object; 92 @Parameter(1) public Class<?> cls; 93 94 @Parameters(name = "{1}") 95 public static Collection<Object[]> data() { 96 Object[] objects = {"string", 42, new int[0], new Object[0], new double[0][]}; 97 98 ArrayList<Object[]> ret = new ArrayList<>(objects.length); 99 for (Object o : objects) { 100 ret.add(new Object[]{o, o.getClass()}); 101 } 102 return ret; 103 } 104 105 public static void castToDouble(Object obj) { 106 Exceptions.throwClassCast(obj, Double.class); 107 } 108 109 @Test 110 public void testCastToDouble() { 111 test("castToDouble", object); 112 } 113 114 public static void castToByteArray(Object obj) { 115 Exceptions.throwClassCast(obj, byte[].class); 116 } 117 118 @Test 119 public void testCastToByteArray() { 120 test("castToByteArray", object); 121 } 122 123 public static void castToStringArray(Object obj) { 124 Exceptions.throwClassCast(obj, String[].class); 125 } 126 127 @Test 128 public void testCastToStringArray() { 129 test("castToStringArray", object); 130 } 131 132 public static void castToArrayArray(Object obj) { 133 Exceptions.throwClassCast(obj, Object[][].class); 134 } 135 136 @Test 137 public void testCastToArrayArray() { 138 test("castToArrayArray", object); 139 } 140 }