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