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