Skip to content

Commit

Permalink
[GR-7356] Add ProfileBooleanNode for MethodHandle profiling and castR…
Browse files Browse the repository at this point in the history
…eference intrinsic.

PullRequest: graal/1203
  • Loading branch information
tkrodriguez committed Nov 15, 2018
2 parents d4bbf65 + 38c4461 commit 7b1e51b
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 59 deletions.
Expand Up @@ -69,9 +69,6 @@
import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyNode;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DynamicPiNode;
import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NamedLocationIdentity;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
Expand All @@ -86,7 +83,6 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
Expand All @@ -107,7 +103,6 @@
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
Expand Down Expand Up @@ -227,26 +222,6 @@ private static void registerClassPlugins(Plugins plugins, GraalHotSpotVMConfig c
if (config.getFieldOffset("ArrayKlass::_component_mirror", Integer.class, "oop", Integer.MAX_VALUE) != Integer.MAX_VALUE) {
r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getComponentType", Receiver.class);
}

r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
ValueNode javaClass = receiver.get();
LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), javaClass, object, true));
if (condition.isTautology()) {
b.addPush(JavaKind.Object, object);
} else {
FixedGuardNode fixedGuard = b.add(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
b.addPush(JavaKind.Object, DynamicPiNode.create(b.getAssumptions(), b.getConstantReflection(), object, fixedGuard, javaClass));
}
return true;
}

@Override
public boolean inlineOnly() {
return true;
}
});
}

private static void registerCallSitePlugins(InvocationPlugins plugins) {
Expand Down
Expand Up @@ -26,9 +26,8 @@
*/
package org.graalvm.compiler.jtt.lang;

import org.junit.Test;

import org.graalvm.compiler.jtt.JTTTest;
import org.junit.Test;

public final class Class_cast01 extends JTTTest {

Expand Down Expand Up @@ -57,6 +56,11 @@ public static int test(int i) {
return -1;
}
}
if (i == 4) {
if (int.class.cast(object) == null) {
return -1;
}
}
return i;
}

Expand Down
Expand Up @@ -41,6 +41,7 @@
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DynamicPiNode;
import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
Expand All @@ -52,6 +53,7 @@
import org.graalvm.compiler.nodes.calc.SignExtendNode;
import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
import org.graalvm.compiler.nodes.type.StampTool;

import jdk.vm.ci.code.BailoutException;
Expand Down Expand Up @@ -291,6 +293,17 @@ default ValueNode nullCheckedValue(ValueNode value, DeoptimizationAction action)
return value;
}

default void genCheckcastDynamic(ValueNode object, ValueNode javaClass) {
LogicNode condition = InstanceOfDynamicNode.create(getAssumptions(), getConstantReflection(), javaClass, object, true);
if (condition.isTautology()) {
addPush(JavaKind.Object, object);
} else {
append(condition);
FixedGuardNode fixedGuard = add(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
addPush(JavaKind.Object, DynamicPiNode.create(getAssumptions(), getConstantReflection(), object, fixedGuard, javaClass));
}
}

@SuppressWarnings("unused")
default void notifyReplacedCall(ResolvedJavaMethod targetMethod, ConstantNode node) {

Expand Down
Expand Up @@ -348,6 +348,9 @@ public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node);
COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug);
node.simplify(tool);
if (node.isDeleted()) {
debug.log("Canonicalizer: simplified %s", node);
}
return node.isDeleted();
}
return false;
Expand Down
Expand Up @@ -88,13 +88,13 @@
import org.graalvm.compiler.nodes.debug.BindToRegisterNode;
import org.graalvm.compiler.nodes.debug.BlackholeNode;
import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
import org.graalvm.compiler.nodes.extended.OpaqueNode;
import org.graalvm.compiler.nodes.debug.SpillRegistersNode;
import org.graalvm.compiler.nodes.extended.BoxNode;
import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
import org.graalvm.compiler.nodes.extended.GetClassNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
import org.graalvm.compiler.nodes.extended.OpaqueNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.nodes.extended.RawStoreNode;
import org.graalvm.compiler.nodes.extended.UnboxNode;
Expand All @@ -116,6 +116,7 @@
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.nodes.virtual.EnsureVirtualizedNode;
import org.graalvm.compiler.replacements.nodes.ProfileBooleanNode;
import org.graalvm.compiler.replacements.nodes.ReverseBytesNode;
import org.graalvm.compiler.replacements.nodes.VirtualizableInvokeMacroNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactNode;
Expand Down Expand Up @@ -793,6 +794,19 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
return true;
}
});

r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
b.genCheckcastDynamic(object, receiver.get());
return true;
}

@Override
public boolean inlineOnly() {
return true;
}
});
}

/**
Expand Down Expand Up @@ -1265,7 +1279,26 @@ public boolean inlineOnly() {

private static void registerMethodHandleImplPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
Registration r = new Registration(plugins, "java.lang.invoke.MethodHandleImpl", bytecodeProvider);
// In later JDKs this no longer exists and the usage is replace by Class.cast which is
// already an intrinsic
r.registerOptional2("castReference", Class.class, Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode javaClass, ValueNode object) {
b.genCheckcastDynamic(object, javaClass);
return true;
}

@Override
public boolean inlineOnly() {
return true;
}
});
r.register2("profileBoolean", boolean.class, int[].class, new InvocationPlugin() {
@Override
public boolean inlineOnly() {
return true;
}

@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode result, ValueNode counters) {
if (result.isConstant()) {
Expand Down Expand Up @@ -1298,7 +1331,9 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
b.addPush(JavaKind.Boolean, newResult);
return true;
}
return false;
b.addPush(JavaKind.Boolean,
new ProfileBooleanNode(snippetReflection, b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), result, counters));
return true;
}
});
}
Expand Down
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.replacements.nodes;

import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;

import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Simplifiable;
import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.LogicConstantNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;

import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.ResolvedJavaMethod;

@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN)
public class ProfileBooleanNode extends MacroStateSplitNode implements Simplifiable {
public static final NodeClass<ProfileBooleanNode> TYPE = NodeClass.create(ProfileBooleanNode.class);
private final SnippetReflectionProvider snippetReflection;

public ProfileBooleanNode(SnippetReflectionProvider snippetReflection, CallTargetNode.InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, StampPair returnStamp,
ValueNode... arguments) {
super(TYPE, invokeKind, targetMethod, bci, returnStamp, arguments);
this.snippetReflection = snippetReflection;
}

ValueNode getResult() {
return getArgument(0);
}

ValueNode getCounters() {
return getArgument(1);
}

@Override
public void simplify(SimplifierTool b) {
ValueNode result = getResult();
if (result.isConstant()) {
replaceAtUsages(result);
graph().removeFixed(this);
return;
}
ValueNode counters = getCounters();
if (counters.isConstant()) {
ValueNode newResult = result;
int[] counts = snippetReflection.asObject(int[].class, (JavaConstant) counters.asConstant());
if (counts != null && counts.length == 2) {
int falseCount = counts[0];
int trueCount = counts[1];
int totalCount = trueCount + falseCount;

if (totalCount == 0) {
graph().addBeforeFixed(this,
graph().addOrUniqueWithInputs(
new FixedGuardNode(LogicConstantNode.contradiction(), DeoptimizationReason.TransferToInterpreter, DeoptimizationAction.InvalidateReprofile,
false)));
} else if (falseCount == 0 || trueCount == 0) {
boolean expected = falseCount == 0;
LogicNode condition = graph().addOrUniqueWithInputs(
IntegerEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, result,
ConstantNode.forBoolean(!expected),
NodeView.DEFAULT));

graph().addBeforeFixed(this, graph().add(new FixedGuardNode(condition, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, true)));
newResult = graph().unique(ConstantNode.forBoolean(expected));
} else {
// We cannot use BranchProbabilityNode here since there's no guarantee
// the result of MethodHandleImpl.profileBoolean() is used as the
// test in an `if` statement (as required by BranchProbabilityNode).
}
}
replaceAtUsages(newResult);
graph().removeFixed(this);
}
}
}
Expand Up @@ -51,13 +51,9 @@
import org.graalvm.compiler.graph.NodeList;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DynamicPiNode;
import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.ConditionalNode;
import org.graalvm.compiler.nodes.calc.NarrowNode;
import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode;
Expand All @@ -69,7 +65,6 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
import org.graalvm.compiler.nodes.java.ArrayLengthNode;
import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.nodes.java.StoreIndexedNode;
import org.graalvm.compiler.nodes.type.NarrowOopStamp;
Expand Down Expand Up @@ -128,7 +123,6 @@

import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Local;
Expand Down Expand Up @@ -747,30 +741,6 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
return false;
}
});

r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
ValueNode toType = receiver.get();
LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), toType, object, true));
if (condition.isTautology()) {
b.addPush(JavaKind.Object, object);
} else {
FixedGuardNode fixedGuard = b.add(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
b.addPush(JavaKind.Object, DynamicPiNode.create(b.getAssumptions(), b.getConstantReflection(), object, fixedGuard, toType));
}
return true;
}
});
r.register2("isInstance", Receiver.class, Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
ValueNode type = receiver.get();
LogicNode condition = b.append(InstanceOfDynamicNode.create(null, b.getConstantReflection(), type, object, false));
b.push(JavaKind.Boolean.getStackKind(), b.append(new ConditionalNode(condition).canonical(null)));
return true;
}
});
}

private static void registerEdgesPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins, boolean analysis) {
Expand Down

0 comments on commit 7b1e51b

Please sign in to comment.