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 */
23
24
25 package org.graalvm.compiler.graph;
26
27 import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.None;
28 import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Placeholder;
29 import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Substitution;
30
31 import java.util.Objects;
32
33 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
34 import org.graalvm.compiler.bytecode.Bytecodes;
35
36 import jdk.vm.ci.code.BytecodeFrame;
37 import jdk.vm.ci.code.BytecodePosition;
38 import jdk.vm.ci.code.CodeUtil;
39 import jdk.vm.ci.meta.JavaMethod;
40 import jdk.vm.ci.meta.MetaUtil;
41 import jdk.vm.ci.meta.ResolvedJavaMethod;
42
43 public class NodeSourcePosition extends BytecodePosition {
44
45 private static final boolean STRICT_SOURCE_POSITION = Boolean.getBoolean("debug.graal.SourcePositionStrictChecks");
46 private static final boolean SOURCE_POSITION_BYTECODES = Boolean.getBoolean("debug.graal.SourcePositionDisassemble");
47
48 private final int hashCode;
49 private final Marker marker;
50 private final SourceLanguagePosition sourceLanguagePosition;
51
52 /**
53 * Remove marker frames.
54 */
55 public NodeSourcePosition trim() {
56 if (marker != None) {
57 return null;
58 }
59 NodeSourcePosition caller = getCaller();
60 if (caller != null) {
61 caller = caller.trim();
62 }
63 if (caller != getCaller()) {
64 return new NodeSourcePosition(caller, getMethod(), getBCI());
65 }
66 return this;
67 }
68
69 public ResolvedJavaMethod getRootMethod() {
70 NodeSourcePosition cur = this;
71 while (cur.getCaller() != null) {
72 cur = cur.getCaller();
73 }
74 return cur.getMethod();
75 }
76
77 public boolean verifyRootMethod(ResolvedJavaMethod root) {
78 JavaMethod currentRoot = getRootMethod();
79 assert root.equals(currentRoot) || root.getName().equals(currentRoot.getName()) && root.getSignature().toMethodDescriptor().equals(currentRoot.getSignature().toMethodDescriptor()) &&
80 root.getDeclaringClass().getName().equals(currentRoot.getDeclaringClass().getName()) : root + " " + currentRoot;
81 return true;
82 }
83
84 enum Marker {
85 None,
86 Placeholder,
87 Substitution
88 }
89
90 public NodeSourcePosition(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
91 this(caller, method, bci, None);
92 }
93
94 public NodeSourcePosition(NodeSourcePosition caller, ResolvedJavaMethod method, int bci, Marker marker) {
95 this(null, caller, method, bci, marker);
96
97 }
98
99 public NodeSourcePosition(SourceLanguagePosition sourceLanguagePosition, NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
100 this(sourceLanguagePosition, caller, method, bci, None);
101 }
102
103 public NodeSourcePosition(SourceLanguagePosition sourceLanguagePosition, NodeSourcePosition caller, ResolvedJavaMethod method, int bci, Marker marker) {
107 } else {
108 this.hashCode = caller.hashCode * 7 + 31 * bci + method.hashCode();
109 }
110 this.marker = marker;
111 this.sourceLanguagePosition = sourceLanguagePosition;
112 }
113
114 public static NodeSourcePosition placeholder(ResolvedJavaMethod method) {
115 return new NodeSourcePosition(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Placeholder);
116 }
117
118 public static NodeSourcePosition placeholder(ResolvedJavaMethod method, int bci) {
119 return new NodeSourcePosition(null, method, bci, Placeholder);
120 }
121
122 public boolean isPlaceholder() {
123 return marker == Placeholder;
124 }
125
126 public static NodeSourcePosition substitution(ResolvedJavaMethod method) {
127 return substitution(null, method);
128 }
129
130 public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method) {
131 return new NodeSourcePosition(caller, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Substitution);
132 }
133
134 public boolean isSubstitution() {
135 return marker == Substitution;
136 }
137
138 @Override
139 public boolean equals(Object obj) {
140 if (obj == this) {
141 return true;
142 }
143 if (obj != null && getClass() == obj.getClass()) {
144 NodeSourcePosition that = (NodeSourcePosition) obj;
145 if (hashCode != that.hashCode) {
146 return false;
147 }
148 if (this.getBCI() == that.getBCI() && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.getCaller(), that.getCaller()) &&
149 Objects.equals(this.sourceLanguagePosition, that.sourceLanguagePosition)) {
150 return true;
151 }
178 }
179
180 public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link) {
181 return addCaller(newSourceLanguagePosition, link, false);
182 }
183
184 public NodeSourcePosition addCaller(NodeSourcePosition link) {
185 return addCaller(null, link, false);
186 }
187
188 public NodeSourcePosition addCaller(NodeSourcePosition link, boolean isSubstitution) {
189 return addCaller(null, link, isSubstitution);
190 }
191
192 public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link, boolean isSubstitution) {
193 if (getCaller() == null) {
194 if (isPlaceholder()) {
195 return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), 0);
196 }
197 assert link == null || isSubstitution || verifyCaller(this, link) : link;
198
199 return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), getBCI());
200 } else {
201 return new NodeSourcePosition(getCaller().addCaller(newSourceLanguagePosition, link, isSubstitution), getMethod(), getBCI());
202 }
203 }
204
205 @Override
206 public String toString() {
207 StringBuilder sb = new StringBuilder(100);
208 NodeSourcePosition pos = this;
209 while (pos != null) {
210 format(sb, pos);
211 if (pos.sourceLanguagePosition != null) {
212 sb.append(" source=" + pos.sourceLanguagePosition.toShortString());
213 }
214 pos = pos.getCaller();
215 if (pos != null) {
216 sb.append(CodeUtil.NEW_LINE);
217 }
218 }
219 return sb.toString();
220 }
221
222 private static void format(StringBuilder sb, NodeSourcePosition pos) {
223 MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
224 if (SOURCE_POSITION_BYTECODES) {
225 String disassembly = BytecodeDisassembler.disassembleOne(pos.getMethod(), pos.getBCI());
226 if (disassembly != null && disassembly.length() > 0) {
227 sb.append(" // ");
228 sb.append(disassembly);
229 }
230 }
231 }
232
233 String shallowToString() {
234 StringBuilder sb = new StringBuilder(100);
235 format(sb, this);
236 return sb.toString();
237 }
238
239 public boolean verify() {
240 NodeSourcePosition current = this;
241 NodeSourcePosition caller = getCaller();
242 while (caller != null) {
243 assert verifyCaller(current, caller) : current;
|
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 */
23
24
25 package org.graalvm.compiler.graph;
26
27 import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.None;
28 import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Placeholder;
29 import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Substitution;
30
31 import java.util.Iterator;
32 import java.util.Objects;
33
34 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
35 import org.graalvm.compiler.bytecode.Bytecodes;
36
37 import jdk.vm.ci.code.BytecodeFrame;
38 import jdk.vm.ci.code.BytecodePosition;
39 import jdk.vm.ci.code.CodeUtil;
40 import jdk.vm.ci.meta.JavaMethod;
41 import jdk.vm.ci.meta.MetaUtil;
42 import jdk.vm.ci.meta.ResolvedJavaMethod;
43
44 public class NodeSourcePosition extends BytecodePosition implements Iterable<NodeSourcePosition> {
45
46 private static final boolean STRICT_SOURCE_POSITION = Boolean.getBoolean("debug.graal.SourcePositionStrictChecks");
47 private static final boolean SOURCE_POSITION_BYTECODES = Boolean.getBoolean("debug.graal.SourcePositionDisassemble");
48
49 private final int hashCode;
50 private final Marker marker;
51 private final SourceLanguagePosition sourceLanguagePosition;
52
53 /**
54 * Remove marker frames.
55 */
56 public NodeSourcePosition trim() {
57 NodeSourcePosition lastMarker = null;
58 for (NodeSourcePosition current = this; current != null; current = current.getCaller()) {
59 if (current.marker != None) {
60 lastMarker = current;
61 }
62 }
63 if (lastMarker == null) {
64 return this;
65 }
66 return lastMarker.getCaller();
67 }
68
69 public ResolvedJavaMethod getRootMethod() {
70 NodeSourcePosition cur = this;
71 while (cur.getCaller() != null) {
72 cur = cur.getCaller();
73 }
74 return cur.getMethod();
75 }
76
77 public boolean verifyRootMethod(ResolvedJavaMethod root) {
78 JavaMethod currentRoot = getRootMethod();
79 assert root.equals(currentRoot) || root.getName().equals(currentRoot.getName()) && root.getSignature().toMethodDescriptor().equals(currentRoot.getSignature().toMethodDescriptor()) &&
80 root.getDeclaringClass().getName().equals(currentRoot.getDeclaringClass().getName()) : root + " " + currentRoot;
81 return true;
82 }
83
84 @Override
85 public Iterator<NodeSourcePosition> iterator() {
86 return new Iterator<NodeSourcePosition>() {
87 private NodeSourcePosition currentPosition = NodeSourcePosition.this;
88
89 @Override
90 public boolean hasNext() {
91 return currentPosition != null;
92 }
93
94 @Override
95 public NodeSourcePosition next() {
96 NodeSourcePosition current = currentPosition;
97 currentPosition = currentPosition.getCaller();
98 return current;
99 }
100 };
101 }
102
103 enum Marker {
104 None,
105 Placeholder,
106 Substitution
107 }
108
109 public NodeSourcePosition(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
110 this(caller, method, bci, None);
111 }
112
113 public NodeSourcePosition(NodeSourcePosition caller, ResolvedJavaMethod method, int bci, Marker marker) {
114 this(null, caller, method, bci, marker);
115
116 }
117
118 public NodeSourcePosition(SourceLanguagePosition sourceLanguagePosition, NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
119 this(sourceLanguagePosition, caller, method, bci, None);
120 }
121
122 public NodeSourcePosition(SourceLanguagePosition sourceLanguagePosition, NodeSourcePosition caller, ResolvedJavaMethod method, int bci, Marker marker) {
126 } else {
127 this.hashCode = caller.hashCode * 7 + 31 * bci + method.hashCode();
128 }
129 this.marker = marker;
130 this.sourceLanguagePosition = sourceLanguagePosition;
131 }
132
133 public static NodeSourcePosition placeholder(ResolvedJavaMethod method) {
134 return new NodeSourcePosition(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Placeholder);
135 }
136
137 public static NodeSourcePosition placeholder(ResolvedJavaMethod method, int bci) {
138 return new NodeSourcePosition(null, method, bci, Placeholder);
139 }
140
141 public boolean isPlaceholder() {
142 return marker == Placeholder;
143 }
144
145 public static NodeSourcePosition substitution(ResolvedJavaMethod method) {
146 return substitution(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI);
147 }
148
149 public static NodeSourcePosition substitution(ResolvedJavaMethod method, int bci) {
150 return substitution(null, method, bci);
151 }
152
153 public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method) {
154 return substitution(caller, method, BytecodeFrame.INVALID_FRAMESTATE_BCI);
155 }
156
157 public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
158 return new NodeSourcePosition(caller, method, bci, Substitution);
159 }
160
161 public boolean isSubstitution() {
162 return marker == Substitution;
163 }
164
165 @Override
166 public boolean equals(Object obj) {
167 if (obj == this) {
168 return true;
169 }
170 if (obj != null && getClass() == obj.getClass()) {
171 NodeSourcePosition that = (NodeSourcePosition) obj;
172 if (hashCode != that.hashCode) {
173 return false;
174 }
175 if (this.getBCI() == that.getBCI() && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.getCaller(), that.getCaller()) &&
176 Objects.equals(this.sourceLanguagePosition, that.sourceLanguagePosition)) {
177 return true;
178 }
205 }
206
207 public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link) {
208 return addCaller(newSourceLanguagePosition, link, false);
209 }
210
211 public NodeSourcePosition addCaller(NodeSourcePosition link) {
212 return addCaller(null, link, false);
213 }
214
215 public NodeSourcePosition addCaller(NodeSourcePosition link, boolean isSubstitution) {
216 return addCaller(null, link, isSubstitution);
217 }
218
219 public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link, boolean isSubstitution) {
220 if (getCaller() == null) {
221 if (isPlaceholder()) {
222 return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), 0);
223 }
224 assert link == null || isSubstitution || verifyCaller(this, link) : link;
225 assert !isSubstitution || marker == None;
226 return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), getBCI(), isSubstitution ? Substitution : None);
227 } else {
228 return new NodeSourcePosition(getCaller().addCaller(newSourceLanguagePosition, link, isSubstitution), getMethod(), getBCI(), marker);
229 }
230 }
231
232 @Override
233 public String toString() {
234 StringBuilder sb = new StringBuilder(100);
235 NodeSourcePosition pos = this;
236 while (pos != null) {
237 format(sb, pos);
238 if (pos.sourceLanguagePosition != null) {
239 sb.append(" source=" + pos.sourceLanguagePosition.toShortString());
240 }
241 pos = pos.getCaller();
242 if (pos != null) {
243 sb.append(CodeUtil.NEW_LINE);
244 }
245 }
246 return sb.toString();
247 }
248
249 private static void format(StringBuilder sb, NodeSourcePosition pos) {
250 MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
251 if (pos.marker != None) {
252 sb.append(" " + pos.marker);
253 }
254 if (SOURCE_POSITION_BYTECODES) {
255 String disassembly = BytecodeDisassembler.disassembleOne(pos.getMethod(), pos.getBCI());
256 if (disassembly != null && disassembly.length() > 0) {
257 sb.append(" // ");
258 sb.append(disassembly);
259 }
260 }
261 }
262
263 String shallowToString() {
264 StringBuilder sb = new StringBuilder(100);
265 format(sb, this);
266 return sb.toString();
267 }
268
269 public boolean verify() {
270 NodeSourcePosition current = this;
271 NodeSourcePosition caller = getCaller();
272 while (caller != null) {
273 assert verifyCaller(current, caller) : current;
|