1 /*
2 * Copyright (c) 2012, 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.hotspot.replacements;
26
27 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
28 import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated;
29 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
30 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PRIMARY_SUPERS_LOCATION;
31 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.SECONDARY_SUPER_CACHE_LOCATION;
32 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
33 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TypeCheckMaxHints;
34 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TypeCheckMinProfileHitProbability;
35 import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkSecondarySubType;
36 import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkUnknownSubType;
37 import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.createHints;
38 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
39 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
40 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY;
41 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
42
43 import org.graalvm.compiler.api.replacements.Snippet;
44 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
45 import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
46 import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter;
47 import org.graalvm.compiler.core.common.type.ObjectStamp;
48 import org.graalvm.compiler.core.common.type.StampFactory;
49 import org.graalvm.compiler.debug.DebugHandlersFactory;
50 import org.graalvm.compiler.debug.GraalError;
51 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
52 import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
119 boolean positive = hintIsPositive[i];
120 if (probability(LIKELY_PROBABILITY, hintHub.equal(objectHub))) {
121 counters.hintsHit.inc();
122 return positive ? trueValue : falseValue;
123 }
124 counters.hintsMiss.inc();
125 }
126 // This maybe just be a rare event but it might also indicate a phase change
127 // in the application. Ideally we want to use DeoptimizationAction.None for
128 // the former but the cost is too high if indeed it is the latter. As such,
129 // we defensively opt for InvalidateReprofile.
130 DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, OptimizedTypeCheckViolated);
131 return falseValue;
132 }
133
134 /**
135 * A test against a final type.
136 */
137 @Snippet
138 public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
139 if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
140 counters.isNull.inc();
141 return falseValue;
142 }
143 GuardingNode anchorNode = SnippetAnchorNode.anchor();
144 KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
145 if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) {
146 counters.exactMiss.inc();
147 return falseValue;
148 }
149 counters.exactHit.inc();
150 return trueValue;
151 }
152
153 /**
154 * A test against a primary type.
155 */
156 @Snippet
157 public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
158 if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
159 counters.isNull.inc();
160 return falseValue;
161 }
162 GuardingNode anchorNode = SnippetAnchorNode.anchor();
163 KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
164 if (probability(NOT_LIKELY_PROBABILITY, objectHub.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub))) {
207 counters.isNull.inc();
208 if (allowNull) {
209 return trueValue;
210 } else {
211 return falseValue;
212 }
213 }
214 GuardingNode anchorNode = SnippetAnchorNode.anchor();
215 KlassPointer nonNullObjectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
216 // The hub of a primitive type can be null => always return false in this case.
217 if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !hub.isNull())) {
218 if (checkUnknownSubType(hub, nonNullObjectHub, counters)) {
219 return trueValue;
220 }
221 }
222 return falseValue;
223 }
224
225 @Snippet
226 public static Object isAssignableFrom(@NonNullParameter Class<?> thisClassNonNull, Class<?> otherClass, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
227 if (otherClass == null) {
228 DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
229 return false;
230 }
231 GuardingNode anchorNode = SnippetAnchorNode.anchor();
232 Class<?> otherClassNonNull = PiNode.piCastNonNullClass(otherClass, anchorNode);
233
234 if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, thisClassNonNull == otherClassNonNull)) {
235 return trueValue;
236 }
237
238 KlassPointer thisHub = ClassGetHubNode.readClass(thisClassNonNull);
239 KlassPointer otherHub = ClassGetHubNode.readClass(otherClassNonNull);
240 if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !thisHub.isNull())) {
241 if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !otherHub.isNull())) {
242 GuardingNode guardNonNull = SnippetAnchorNode.anchor();
243 KlassPointer nonNullOtherHub = ClassGetHubNode.piCastNonNull(otherHub, guardNonNull);
244 if (TypeCheckSnippetUtils.checkUnknownSubType(thisHub, nonNullOtherHub, counters)) {
245 return trueValue;
246 }
247 }
|
1 /*
2 * Copyright (c) 2012, 2019, 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.hotspot.replacements;
26
27 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
28 import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated;
29 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
30 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PRIMARY_SUPERS_LOCATION;
31 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.SECONDARY_SUPER_CACHE_LOCATION;
32 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
33 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubOrNullIntrinsic;
34 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TypeCheckMaxHints;
35 import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TypeCheckMinProfileHitProbability;
36 import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkSecondarySubType;
37 import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkUnknownSubType;
38 import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.createHints;
39 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
40 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
41 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY;
42 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
43
44 import org.graalvm.compiler.api.replacements.Snippet;
45 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
46 import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
47 import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter;
48 import org.graalvm.compiler.core.common.type.ObjectStamp;
49 import org.graalvm.compiler.core.common.type.StampFactory;
50 import org.graalvm.compiler.debug.DebugHandlersFactory;
51 import org.graalvm.compiler.debug.GraalError;
52 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
53 import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
120 boolean positive = hintIsPositive[i];
121 if (probability(LIKELY_PROBABILITY, hintHub.equal(objectHub))) {
122 counters.hintsHit.inc();
123 return positive ? trueValue : falseValue;
124 }
125 counters.hintsMiss.inc();
126 }
127 // This maybe just be a rare event but it might also indicate a phase change
128 // in the application. Ideally we want to use DeoptimizationAction.None for
129 // the former but the cost is too high if indeed it is the latter. As such,
130 // we defensively opt for InvalidateReprofile.
131 DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, OptimizedTypeCheckViolated);
132 return falseValue;
133 }
134
135 /**
136 * A test against a final type.
137 */
138 @Snippet
139 public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
140 KlassPointer objectHub = loadHubOrNullIntrinsic(object);
141 if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) {
142 counters.exactMiss.inc();
143 return falseValue;
144 }
145 counters.exactHit.inc();
146 return trueValue;
147 }
148
149 /**
150 * A test against a primary type.
151 */
152 @Snippet
153 public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
154 if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
155 counters.isNull.inc();
156 return falseValue;
157 }
158 GuardingNode anchorNode = SnippetAnchorNode.anchor();
159 KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
160 if (probability(NOT_LIKELY_PROBABILITY, objectHub.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub))) {
203 counters.isNull.inc();
204 if (allowNull) {
205 return trueValue;
206 } else {
207 return falseValue;
208 }
209 }
210 GuardingNode anchorNode = SnippetAnchorNode.anchor();
211 KlassPointer nonNullObjectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
212 // The hub of a primitive type can be null => always return false in this case.
213 if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !hub.isNull())) {
214 if (checkUnknownSubType(hub, nonNullObjectHub, counters)) {
215 return trueValue;
216 }
217 }
218 return falseValue;
219 }
220
221 @Snippet
222 public static Object isAssignableFrom(@NonNullParameter Class<?> thisClassNonNull, Class<?> otherClass, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
223 if (BranchProbabilityNode.probability(BranchProbabilityNode.DEOPT_PROBABILITY, otherClass == null)) {
224 DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
225 return false;
226 }
227 GuardingNode anchorNode = SnippetAnchorNode.anchor();
228 Class<?> otherClassNonNull = PiNode.piCastNonNullClass(otherClass, anchorNode);
229
230 if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, thisClassNonNull == otherClassNonNull)) {
231 return trueValue;
232 }
233
234 KlassPointer thisHub = ClassGetHubNode.readClass(thisClassNonNull);
235 KlassPointer otherHub = ClassGetHubNode.readClass(otherClassNonNull);
236 if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !thisHub.isNull())) {
237 if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !otherHub.isNull())) {
238 GuardingNode guardNonNull = SnippetAnchorNode.anchor();
239 KlassPointer nonNullOtherHub = ClassGetHubNode.piCastNonNull(otherHub, guardNonNull);
240 if (TypeCheckSnippetUtils.checkUnknownSubType(thisHub, nonNullOtherHub, counters)) {
241 return trueValue;
242 }
243 }
|