1/*
2 * Copyright (c) 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.salver.util;
24
25import static org.graalvm.compiler.debug.GraalDebugConfig.asJavaMethod;
26
27import java.util.ArrayList;
28
29import org.graalvm.compiler.debug.Debug;
30import org.graalvm.compiler.debug.DebugDumpScope;
31import org.graalvm.compiler.graph.Graph;
32import org.graalvm.compiler.salver.util.MethodContext.Item;
33
34import jdk.vm.ci.meta.JavaMethod;
35
36public class MethodContext extends ArrayList<Item> {
37
38    private static final long serialVersionUID = 1L;
39
40    public static final class Item {
41
42        private String name;
43        private JavaMethod method;
44        private int debugId;
45
46        private Item(String name, JavaMethod method, int debugId) {
47            this.name = name;
48            this.method = method;
49            this.debugId = debugId;
50        }
51
52        private Item(JavaMethod method) {
53            this(method.format("%H::%n(%p)"), method, -1);
54        }
55
56        private Item(String name) {
57            this(name, null, -1);
58        }
59
60        public String getName() {
61            return name;
62        }
63
64        public JavaMethod getMethod() {
65            return method;
66        }
67
68        public int getDebugId() {
69            return debugId;
70        }
71    }
72
73    public MethodContext() {
74        Object lastMethodOrGraph = null;
75        for (Object obj : Debug.context()) {
76            JavaMethod method = asJavaMethod(obj);
77            if (method != null) {
78                JavaMethod lastAsMethod = asJavaMethod(lastMethodOrGraph);
79                if (lastAsMethod == null || !lastAsMethod.equals(method)) {
80                    add(new Item(method));
81                } else {
82                    /*
83                     * This prevents multiple adjacent method context objects for the same method
84                     * from resulting in multiple IGV tree levels. This works on the assumption that
85                     * real inlining debug scopes will have a graph context object between the
86                     * inliner and inlinee context objects.
87                     */
88                }
89            } else if (obj instanceof DebugDumpScope) {
90                DebugDumpScope debugDumpScope = (DebugDumpScope) obj;
91                if (debugDumpScope.decorator && !isEmpty()) {
92                    try {
93                        get(size() - 1).debugId = Integer.parseInt(debugDumpScope.name);
94                    } catch (NumberFormatException e) {
95                        // Ignore
96                    }
97                } else {
98                    add(new Item(debugDumpScope.name));
99                }
100            }
101            if (obj instanceof JavaMethod || obj instanceof Graph) {
102                lastMethodOrGraph = obj;
103            }
104        }
105        if (isEmpty()) {
106            add(new Item("Top Scope"));
107        }
108    }
109
110    public boolean itemEquals(int index, MethodContext context) {
111        Item i1 = get(index);
112        Item i2 = context != null ? context.get(index) : null;
113        if (i1 != null && i2 != null && i1.name != null && i2.name != null) {
114            return i1.name.equals(i2.name) && i1.debugId == i2.debugId;
115        }
116        return false;
117    }
118}
119