1 /* 2 * Copyright (c) 2009, 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.nodes.java; 24 25 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_30; 26 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_30; 27 28 import org.graalvm.compiler.core.common.type.Stamp; 29 import org.graalvm.compiler.core.common.type.TypeReference; 30 import org.graalvm.compiler.graph.NodeClass; 31 import org.graalvm.compiler.graph.spi.Canonicalizable; 32 import org.graalvm.compiler.graph.spi.CanonicalizerTool; 33 import org.graalvm.compiler.nodeinfo.NodeInfo; 34 import org.graalvm.compiler.nodes.BinaryOpLogicNode; 35 import org.graalvm.compiler.nodes.LogicConstantNode; 36 import org.graalvm.compiler.nodes.LogicNode; 37 import org.graalvm.compiler.nodes.ValueNode; 38 import org.graalvm.compiler.nodes.calc.IsNullNode; 39 import org.graalvm.compiler.nodes.spi.Lowerable; 40 import org.graalvm.compiler.nodes.spi.LoweringTool; 41 42 import jdk.vm.ci.meta.Assumptions; 43 import jdk.vm.ci.meta.ConstantReflectionProvider; 44 import jdk.vm.ci.meta.JavaKind; 45 import jdk.vm.ci.meta.ResolvedJavaType; 46 import jdk.vm.ci.meta.TriState; 47 48 /** 49 * The {@code InstanceOfDynamicNode} represents a type check where the type being checked is not 50 * known at compile time. This is used, for instance, to intrinsify {@link Class#isInstance(Object)} 51 * . 52 */ 53 @NodeInfo(cycles = CYCLES_30, size = SIZE_30) 54 public class InstanceOfDynamicNode extends BinaryOpLogicNode implements Canonicalizable.Binary<ValueNode>, Lowerable { 55 public static final NodeClass<InstanceOfDynamicNode> TYPE = NodeClass.create(InstanceOfDynamicNode.class); 56 57 private final boolean allowNull; 58 59 public static LogicNode create(Assumptions assumptions, ConstantReflectionProvider constantReflection, ValueNode mirror, ValueNode object, boolean allowNull) { 60 LogicNode synonym = findSynonym(assumptions, constantReflection, mirror, object, allowNull); 61 if (synonym != null) { 62 return synonym; 63 } 64 return new InstanceOfDynamicNode(mirror, object, allowNull); 65 } 66 67 protected InstanceOfDynamicNode(ValueNode mirror, ValueNode object, boolean allowNull) { 68 super(TYPE, mirror, object); 69 this.allowNull = allowNull; 70 assert mirror.getStackKind() == JavaKind.Object || mirror.getStackKind() == JavaKind.Illegal : mirror.getStackKind(); 71 } 72 73 public boolean isMirror() { 74 return getMirrorOrHub().getStackKind() == JavaKind.Object; 75 } 76 77 public boolean isHub() { 78 return !isMirror(); 79 } 80 81 @Override 82 public void lower(LoweringTool tool) { 83 tool.getLowerer().lower(this, tool); 84 } 85 86 private static LogicNode findSynonym(Assumptions assumptions, ConstantReflectionProvider constantReflection, ValueNode forMirror, ValueNode forObject, 87 boolean allowNull) { 88 if (forMirror.isConstant()) { 89 ResolvedJavaType t = constantReflection.asJavaType(forMirror.asConstant()); 90 if (t != null) { 91 if (t.isPrimitive()) { 92 if (allowNull) { 93 return IsNullNode.create(forObject); 94 } else { 95 return LogicConstantNode.contradiction(); 96 } 97 } else { 98 TypeReference type = TypeReference.createTrusted(assumptions, t); 99 if (allowNull) { 100 return InstanceOfNode.createAllowNull(type, forObject, null, null); 101 } else { 102 return InstanceOfNode.create(type, forObject); 103 } 104 } 105 } 106 } 107 return null; 108 } 109 110 public ValueNode getMirrorOrHub() { 111 return this.getX(); 112 } 113 114 public ValueNode getObject() { 115 return this.getY(); 116 } 117 118 @Override 119 public LogicNode canonical(CanonicalizerTool tool, ValueNode forMirror, ValueNode forObject) { 120 LogicNode result = findSynonym(tool.getAssumptions(), tool.getConstantReflection(), forMirror, forObject, allowNull); 121 if (result != null) { 122 return result; 123 } 124 return this; 125 } 126 127 public void setMirror(ValueNode newObject) { 128 this.updateUsages(x, newObject); 129 this.x = newObject; 130 } 131 132 public boolean allowsNull() { 133 return allowNull; 134 } 135 136 @Override 137 public Stamp getSucceedingStampForX(boolean negated, Stamp xStamp, Stamp yStamp) { 138 return null; 139 } 140 141 @Override 142 public Stamp getSucceedingStampForY(boolean negated, Stamp xStamp, Stamp yStamp) { 143 return null; 144 } 145 146 @Override 147 public TriState tryFold(Stamp xStamp, Stamp yStamp) { 148 return TriState.UNKNOWN; 149 } 150 }