001/*
002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.compiler.test.tutorial;
024
025import java.lang.reflect.*;
026import java.util.*;
027
028import jdk.internal.jvmci.meta.*;
029
030import org.junit.*;
031
032import com.oracle.graal.api.runtime.*;
033import com.oracle.graal.compiler.target.*;
034import com.oracle.graal.compiler.test.tutorial.StaticAnalysis.MethodState;
035import com.oracle.graal.compiler.test.tutorial.StaticAnalysis.TypeFlow;
036import com.oracle.graal.nodes.spi.*;
037import com.oracle.graal.phases.util.*;
038import com.oracle.graal.runtime.*;
039
040public class StaticAnalysisTests {
041
042    static class A {
043        Object foo(Object arg) {
044            return arg;
045        }
046    }
047
048    static class B extends A {
049        @Override
050        Object foo(Object arg) {
051            if (arg instanceof Data) {
052                return ((Data) arg).f;
053            } else {
054                return super.foo(arg);
055            }
056        }
057    }
058
059    static class Data {
060        Object f;
061    }
062
063    private final MetaAccessProvider metaAccess;
064    private final StampProvider stampProvider;
065
066    public StaticAnalysisTests() {
067        Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
068        Providers providers = backend.getProviders();
069        this.metaAccess = providers.getMetaAccess();
070        this.stampProvider = providers.getStampProvider();
071    }
072
073    static void test01Entry() {
074        A a = new A();
075        a.foo(null);
076    }
077
078    @Test
079    public void test01() {
080        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
081        sa.addMethod(findMethod(StaticAnalysisTests.class, "test01Entry"));
082        sa.finish();
083
084        assertEquals(sa.getResults().getAllInstantiatedTypes(), t(A.class));
085        assertEquals(f(sa, Data.class, "f"));
086        assertEquals(m(sa, A.class, "foo").getFormalParameters()[0], t(A.class));
087        assertEquals(m(sa, A.class, "foo").getFormalParameters()[1]);
088        assertEquals(m(sa, A.class, "foo").getFormalReturn());
089    }
090
091    static void test02Entry() {
092        A a = new A();
093        a.foo(new Data());
094
095        B b = new B();
096        b.foo(null);
097    }
098
099    @Test
100    public void test02() {
101        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
102        sa.addMethod(findMethod(StaticAnalysisTests.class, "test02Entry"));
103        sa.finish();
104
105        assertEquals(sa.getResults().getAllInstantiatedTypes(), t(A.class), t(B.class), t(Data.class));
106        assertEquals(f(sa, Data.class, "f"));
107        assertEquals(m(sa, A.class, "foo").getFormalParameters()[0], t(A.class), t(B.class));
108        assertEquals(m(sa, A.class, "foo").getFormalParameters()[1], t(Data.class));
109        assertEquals(m(sa, A.class, "foo").getFormalReturn(), t(Data.class));
110        assertEquals(m(sa, B.class, "foo").getFormalParameters()[0], t(B.class));
111        assertEquals(m(sa, B.class, "foo").getFormalParameters()[1]);
112        assertEquals(m(sa, B.class, "foo").getFormalReturn(), t(Data.class));
113    }
114
115    static void test03Entry() {
116        Data data = new Data();
117        data.f = new Integer(42);
118
119        A a = new A();
120        a.foo(new Data());
121
122        B b = new B();
123        b.foo(null);
124    }
125
126    @Test
127    public void test03() {
128        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
129        sa.addMethod(findMethod(StaticAnalysisTests.class, "test03Entry"));
130        sa.finish();
131
132        assertEquals(sa.getResults().getAllInstantiatedTypes(), t(A.class), t(B.class), t(Data.class), t(Integer.class));
133        assertEquals(f(sa, Data.class, "f"), t(Integer.class));
134        assertEquals(m(sa, A.class, "foo").getFormalParameters()[0], t(A.class), t(B.class));
135        assertEquals(m(sa, A.class, "foo").getFormalParameters()[1], t(Data.class));
136        assertEquals(m(sa, A.class, "foo").getFormalReturn(), t(Data.class));
137        assertEquals(m(sa, B.class, "foo").getFormalParameters()[0], t(B.class));
138        assertEquals(m(sa, B.class, "foo").getFormalParameters()[1]);
139        assertEquals(m(sa, B.class, "foo").getFormalReturn(), t(Data.class), t(Integer.class));
140    }
141
142    static void test04Entry() {
143        Data data = null;
144        for (int i = 0; i < 2; i++) {
145            if (i == 0) {
146                data = new Data();
147            } else if (i == 1) {
148                data.f = new Integer(42);
149            }
150        }
151
152        A a = new A();
153        a.foo(data);
154    }
155
156    @Test
157    public void test04() {
158        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
159        sa.addMethod(findMethod(StaticAnalysisTests.class, "test04Entry"));
160        sa.finish();
161
162        assertEquals(sa.getResults().getAllInstantiatedTypes(), t(A.class), t(Data.class), t(Integer.class));
163        assertEquals(f(sa, Data.class, "f"), t(Integer.class));
164        assertEquals(m(sa, A.class, "foo").getFormalParameters()[0], t(A.class));
165        assertEquals(m(sa, A.class, "foo").getFormalParameters()[1], t(Data.class));
166        assertEquals(m(sa, A.class, "foo").getFormalReturn(), t(Data.class));
167    }
168
169    private MethodState m(StaticAnalysis sa, Class<?> declaringClass, String name) {
170        return sa.getResults().lookupMethod(findMethod(declaringClass, name));
171    }
172
173    private TypeFlow f(StaticAnalysis sa, Class<?> declaringClass, String name) {
174        return sa.getResults().lookupField(findField(declaringClass, name));
175    }
176
177    private static void assertEquals(TypeFlow actual, Object... expected) {
178        Collection<?> actualTypes = actual.getTypes();
179        if (actualTypes.size() != expected.length || !actualTypes.containsAll(Arrays.asList(expected))) {
180            Assert.fail(actualTypes + " != " + Arrays.asList(expected));
181        }
182    }
183
184    private ResolvedJavaType t(Class<?> clazz) {
185        return metaAccess.lookupJavaType(clazz);
186    }
187
188    private ResolvedJavaMethod findMethod(Class<?> declaringClass, String name) {
189        Method reflectionMethod = null;
190        for (Method m : declaringClass.getDeclaredMethods()) {
191            if (m.getName().equals(name)) {
192                assert reflectionMethod == null : "More than one method with name " + name + " in class " + declaringClass.getName();
193                reflectionMethod = m;
194            }
195        }
196        assert reflectionMethod != null : "No method with name " + name + " in class " + declaringClass.getName();
197        return metaAccess.lookupJavaMethod(reflectionMethod);
198    }
199
200    private ResolvedJavaField findField(Class<?> declaringClass, String name) {
201        Field reflectionField;
202        try {
203            reflectionField = declaringClass.getDeclaredField(name);
204        } catch (NoSuchFieldException | SecurityException ex) {
205            throw new AssertionError(ex);
206        }
207        return metaAccess.lookupJavaField(reflectionField);
208    }
209}