1/*
2 * Copyright (c) 2014, 2015, 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 */
23package org.graalvm.compiler.hotspot.nodes.type;
24
25import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
26import org.graalvm.compiler.core.common.type.Stamp;
27
28import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider;
29import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
30import jdk.vm.ci.meta.Constant;
31import jdk.vm.ci.meta.JavaConstant;
32import jdk.vm.ci.meta.MemoryAccessProvider;
33import jdk.vm.ci.meta.MetaAccessProvider;
34
35public final class MethodPointerStamp extends MetaspacePointerStamp {
36
37    private static final MethodPointerStamp METHOD = new MethodPointerStamp(false, false);
38
39    private static final MethodPointerStamp METHOD_NON_NULL = new MethodPointerStamp(true, false);
40
41    private static final MethodPointerStamp METHOD_ALWAYS_NULL = new MethodPointerStamp(false, true);
42
43    public static MethodPointerStamp method() {
44        return METHOD;
45    }
46
47    public static MethodPointerStamp methodNonNull() {
48        return METHOD_NON_NULL;
49    }
50
51    private MethodPointerStamp(boolean nonNull, boolean alwaysNull) {
52        super(nonNull, alwaysNull);
53    }
54
55    @Override
56    protected AbstractPointerStamp copyWith(boolean newNonNull, boolean newAlwaysNull) {
57        if (newNonNull) {
58            assert !newAlwaysNull;
59            return METHOD_NON_NULL;
60        } else if (newAlwaysNull) {
61            return METHOD_ALWAYS_NULL;
62        } else {
63            return METHOD;
64        }
65    }
66
67    @Override
68    public boolean isCompatible(Stamp otherStamp) {
69        if (this == otherStamp) {
70            return true;
71        }
72        return otherStamp instanceof MethodPointerStamp;
73    }
74
75    @Override
76    public boolean isCompatible(Constant constant) {
77        if (constant instanceof HotSpotMetaspaceConstant) {
78            return ((HotSpotMetaspaceConstant) constant).asResolvedJavaMethod() != null;
79        } else {
80            return super.isCompatible(constant);
81        }
82    }
83
84    @Override
85    public Stamp constant(Constant c, MetaAccessProvider meta) {
86        if (JavaConstant.NULL_POINTER.equals(c)) {
87            return METHOD_ALWAYS_NULL;
88        } else {
89            assert c instanceof HotSpotMetaspaceConstant;
90            return METHOD_NON_NULL;
91        }
92    }
93
94    @Override
95    public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) {
96        HotSpotMemoryAccessProvider hsProvider = (HotSpotMemoryAccessProvider) provider;
97        return hsProvider.readMethodPointerConstant(base, displacement);
98    }
99
100    @Override
101    public String toString() {
102        StringBuilder ret = new StringBuilder("Method*");
103        appendString(ret);
104        return ret.toString();
105    }
106}
107