src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUsageWithEquals.java
author chegar
Thu, 17 Oct 2019 20:54:25 +0100
branchdatagramsocketimpl-branch
changeset 58679 9c3209ff7550
parent 58678 9cf78a70fa4f
parent 58299 6df94ce3ab2f
permissions -rw-r--r--
datagramsocketimpl-branch: merge with default
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52910
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     1
/*
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 55509
diff changeset
     2
 * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
52910
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     4
 *
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     7
 * published by the Free Software Foundation.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     8
 *
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    13
 * accompanied this code).
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    14
 *
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    18
 *
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    21
 * questions.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    22
 */
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    23
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    24
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    25
package org.graalvm.compiler.core.test;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    26
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    27
import org.graalvm.compiler.core.common.type.ObjectStamp;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    28
import org.graalvm.compiler.nodes.Invoke;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    29
import org.graalvm.compiler.nodes.NodeView;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    30
import org.graalvm.compiler.nodes.ParameterNode;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    31
import org.graalvm.compiler.nodes.StructuredGraph;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    32
import org.graalvm.compiler.nodes.ValueNode;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    33
import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    34
import org.graalvm.compiler.nodes.java.LoadFieldNode;
55509
d58442b8abc1 8225497: Update Graal
jwilhelm
parents: 54328
diff changeset
    35
import org.graalvm.compiler.nodes.spi.CoreProviders;
52910
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    36
import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    37
import org.graalvm.compiler.nodes.type.StampTool;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    38
import org.graalvm.compiler.phases.VerifyPhase;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    39
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    40
import jdk.vm.ci.meta.JavaField;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    41
import jdk.vm.ci.meta.JavaKind;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    42
import jdk.vm.ci.meta.JavaMethod;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    43
import jdk.vm.ci.meta.JavaType;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    44
import jdk.vm.ci.meta.MetaAccessProvider;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    45
import jdk.vm.ci.meta.ResolvedJavaMethod;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    46
import jdk.vm.ci.meta.ResolvedJavaType;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    47
import jdk.vm.ci.meta.Signature;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    48
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    49
/**
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    50
 * For certain types, object identity should not be used for object equality check. This phase
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    51
 * checks the correct usage of the given type. Equality checks with == or != (except null checks)
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    52
 * results in an {@link AssertionError}.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    53
 */
55509
d58442b8abc1 8225497: Update Graal
jwilhelm
parents: 54328
diff changeset
    54
public class VerifyUsageWithEquals extends VerifyPhase<CoreProviders> {
52910
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    55
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    56
    @Override
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    57
    public boolean checkContract() {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    58
        return false;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    59
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    60
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    61
    /**
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    62
     * The type of values that must not use identity for testing object equality.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    63
     */
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    64
    private final Class<?> restrictedClass;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    65
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    66
    public VerifyUsageWithEquals(Class<?> restrictedClass) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    67
        this.restrictedClass = restrictedClass;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    68
        assert !restrictedClass.isInterface() || isTrustedInterface(restrictedClass);
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    69
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    70
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    71
    private static final Class<?>[] trustedInterfaceTypes = {JavaType.class, JavaField.class, JavaMethod.class};
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    72
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    73
    private static boolean isTrustedInterface(Class<?> cls) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    74
        for (Class<?> trusted : trustedInterfaceTypes) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    75
            if (trusted.isAssignableFrom(cls)) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    76
                return true;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    77
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    78
        }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    79
        return false;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    80
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    81
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    82
    /**
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    83
     * Determines whether the type of {@code node} is assignable to the {@link #restrictedClass}.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    84
     */
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    85
    private boolean isAssignableToRestrictedType(ValueNode node, MetaAccessProvider metaAccess) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    86
        if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    87
            ResolvedJavaType restrictedType = metaAccess.lookupJavaType(restrictedClass);
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    88
            ResolvedJavaType nodeType = StampTool.typeOrNull(node);
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    89
            if (nodeType == null && node instanceof LoadFieldNode) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    90
                nodeType = (ResolvedJavaType) ((LoadFieldNode) node).field().getType();
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    91
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    92
            if (nodeType == null && node instanceof Invoke) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    93
                ResolvedJavaMethod target = ((Invoke) node).callTarget().targetMethod();
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    94
                nodeType = (ResolvedJavaType) target.getSignature().getReturnType(target.getDeclaringClass());
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    95
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    96
            if (nodeType == null && node instanceof UncheckedInterfaceProvider) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    97
                nodeType = StampTool.typeOrNull(((UncheckedInterfaceProvider) node).uncheckedStamp());
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    98
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
    99
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   100
            if (nodeType != null && restrictedType.isAssignableFrom(nodeType)) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   101
                return true;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   102
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   103
        }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   104
        return false;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   105
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   106
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   107
    private static boolean isNullConstant(ValueNode node) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   108
        return node.isConstant() && node.isNullConstant();
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   109
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   110
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   111
    private static boolean isEqualsMethod(ResolvedJavaMethod method) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   112
        if (method.getName().equals("equals")) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   113
            Signature sig = method.getSignature();
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   114
            if (sig.getReturnKind() == JavaKind.Boolean) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   115
                if (sig.getParameterCount(false) == 1) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   116
                    ResolvedJavaType ptype = (ResolvedJavaType) sig.getParameterType(0, method.getDeclaringClass());
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   117
                    if (ptype.isJavaLangObject()) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   118
                        return true;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   119
                    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   120
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   121
                }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   122
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   123
        }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   124
        return false;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   125
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   126
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   127
    private static boolean isThisParameter(ValueNode node) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   128
        return node instanceof ParameterNode && ((ParameterNode) node).index() == 0;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   129
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   130
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   131
    /**
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   132
     * Checks whether the type of {@code x} is assignable to the restricted type and that {@code y}
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   133
     * is not a null constant.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   134
     */
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   135
    private boolean isIllegalUsage(ResolvedJavaMethod method, ValueNode x, ValueNode y, MetaAccessProvider metaAccess) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   136
        if (isAssignableToRestrictedType(x, metaAccess) && !isNullConstant(y)) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   137
            if (isEqualsMethod(method) && isThisParameter(x) || isThisParameter(y)) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   138
                return false;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   139
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   140
            return true;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   141
        }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   142
        return false;
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   143
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   144
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   145
    @Override
55509
d58442b8abc1 8225497: Update Graal
jwilhelm
parents: 54328
diff changeset
   146
    protected void verify(StructuredGraph graph, CoreProviders context) {
52910
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   147
        for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   148
            // bail out if we compare an object of type klass with == or != (except null checks)
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   149
            ResolvedJavaMethod method = graph.method();
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   150
            ResolvedJavaType restrictedType = context.getMetaAccess().lookupJavaType(restrictedClass);
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   151
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   152
            if (method.getDeclaringClass().equals(restrictedType)) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   153
                // Allow violation in methods of the restricted type itself.
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   154
            } else if (isIllegalUsage(method, cn.getX(), cn.getY(), context.getMetaAccess()) || isIllegalUsage(method, cn.getY(), cn.getX(), context.getMetaAccess())) {
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   155
                throw new VerificationError("Verification of " + restrictedClass.getName() + " usage failed: Comparing " + cn.getX() + " and " + cn.getY() + " in " + method +
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   156
                                " must use .equals() for object equality, not '==' or '!='");
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   157
            }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   158
        }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   159
    }
583fd71c47d6 8214023: Update Graal
dlong
parents:
diff changeset
   160
}