comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineToProbesMap.java @ 18485:e3c95cbbb50c

Truffle Instrumentation: major API revision, based around the Probe and Instrument classes; add Instrumentable API for language implementors, with most details automated; reimplemented to handle AST splitting automatically; more JUnit tests.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sun, 23 Nov 2014 16:07:23 -0800
parents
children
comparison
equal deleted inserted replaced
18484:e97e1f07a3d6 18485:e3c95cbbb50c
1 /*
2 * Copyright (c) 2014, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package com.oracle.truffle.api.instrument.impl;
26
27 import java.io.*;
28 import java.util.*;
29
30 import com.oracle.truffle.api.instrument.*;
31 import com.oracle.truffle.api.instrument.Probe.ProbeListener;
32 import com.oracle.truffle.api.source.*;
33
34 /**
35 * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to
36 * a collection of {@link Probe}s whose associated {@link SourceSection} starts on that line.
37 */
38 public class LineToProbesMap implements ProbeListener {
39
40 private static final boolean TRACE = false;
41 private static final PrintStream OUT = System.out;
42
43 private static void trace(String msg) {
44 OUT.println("LineToProbesMap: " + msg);
45 }
46
47 /**
48 * Map: Source line ==> probes associated with source sections starting on the line.
49 */
50 private final Map<LineLocation, Collection<Probe>> lineToProbesMap = new HashMap<>();
51
52 public LineToProbesMap() {
53 }
54
55 public void startASTProbing(Source source) {
56 }
57
58 public void newProbeInserted(Probe probe) {
59 final SourceSection sourceSection = probe.getProbedSourceSection();
60 if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) {
61 final LineLocation lineLocation = sourceSection.getLineLocation();
62 if (TRACE) {
63 trace("ADD " + lineLocation.getShortDescription() + " ==> " + probe.getShortDescription());
64 }
65 this.addProbeToLine(lineLocation, probe);
66 }
67 }
68
69 public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
70 // This map ignores tags
71 }
72
73 public void endASTProbing(Source source) {
74 }
75
76 /**
77 * Returns the {@link Probe}, if any, associated with source that starts on a specified line; if
78 * there are more than one, return the one with the first starting character location.
79 */
80 public Probe findLineProbe(LineLocation lineLocation) {
81 Probe probe = null;
82 final Collection<Probe> probes = getProbesAtLine(lineLocation);
83 for (Probe probesOnLine : probes) {
84 if (probe == null) {
85 probe = probesOnLine;
86 } else if (probesOnLine.getProbedSourceSection().getCharIndex() < probe.getProbedSourceSection().getCharIndex()) {
87 probe = probesOnLine;
88 }
89 }
90 return probe;
91 }
92
93 /**
94 * Records creation of a probe whose associated source starts on the given line.
95 * <p>
96 * If the line already exists in the internal {@link #lineToProbesMap}, this probe will be added
97 * to the existing collection. If no line already exists in the internal map, then a new key is
98 * added along with a new collection containing the probe.
99 * <p>
100 * This class requires that each added line/probe pair hasn't been previously added. However,
101 * attaching the same probe to a new line location is allowed.
102 *
103 * @param line The {@link LineLocation} to attach the probe to.
104 * @param probe The {@link Probe} to attach for that line location.
105 */
106 protected void addProbeToLine(LineLocation line, Probe probe) {
107
108 if (!lineToProbesMap.containsKey(line)) {
109 // Key does not exist, add new probe list
110 final ArrayList<Probe> newProbeList = new ArrayList<>(2);
111 newProbeList.add(probe);
112 lineToProbesMap.put(line, newProbeList);
113 } else {
114 // Probe list exists, add to existing
115 final Collection<Probe> existingProbeList = lineToProbesMap.get(line);
116 assert !existingProbeList.contains(probe);
117 existingProbeList.add(probe);
118 }
119 }
120
121 /**
122 *
123 * Returns a collection of {@link Probe}s whose associated source begins at the given
124 * {@link LineLocation}, an empty list if none.
125 *
126 * @param line The line to check.
127 * @return A collection of probes at the given line.
128 */
129 public Collection<Probe> getProbesAtLine(LineLocation line) {
130 Collection<Probe> probesList = lineToProbesMap.get(line);
131
132 if (probesList == null) {
133 return Collections.emptyList();
134 }
135 return probesList;
136 }
137
138 /**
139 * Convenience method to get probes according to a int line number. Returns a collection of
140 * {@link Probe}s at the given line number, an empty list if none.
141 *
142 * @param lineNumber The line number to check.
143 * @return A collection of probes at the given line.
144 */
145 public Collection<Probe> getProbesAtLineNumber(int lineNumber) {
146
147 final Set<LineLocation> keySet = lineToProbesMap.keySet();
148 if (keySet.size() == 0) {
149 return Collections.emptyList();
150 }
151
152 ArrayList<Probe> probes = new ArrayList<>();
153 for (LineLocation line : keySet) {
154 if (line.getLineNumber() == lineNumber) {
155 probes.addAll(lineToProbesMap.get(line));
156 }
157 }
158
159 return probes;
160 }
161
162 public void forget(Source source) {
163 final Set<LineLocation> mappedLines = lineToProbesMap.keySet();
164 if (mappedLines.size() > 0) {
165 List<LineLocation> forgetLines = new ArrayList<>();
166 for (LineLocation line : mappedLines) {
167 if (line.getSource().equals(source)) {
168 forgetLines.add(line);
169 }
170 }
171 for (LineLocation line : forgetLines) {
172 lineToProbesMap.remove(line);
173 }
174 }
175 }
176 }