comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java @ 15779:8c34e2cc4add

Truffle/Instrumentation: significant reorganization of the instrumentation framework's implementation and connection to the runtime ExecutionContext, with some new features, including a Tag-based "trap" mechanisms.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Mon, 19 May 2014 17:14:36 -0700
parents
children eedf6c293639
comparison
equal deleted inserted replaced
15632:dcaf3993ad17 15779:8c34e2cc4add
1 /*
2 * Copyright (c) 2013, 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.util.*;
28
29 import com.oracle.truffle.api.*;
30 import com.oracle.truffle.api.instrument.*;
31 import com.oracle.truffle.api.instrument.impl.InstrumentationNode.ProbeCallback;
32 import com.oracle.truffle.api.instrument.impl.InstrumentationNode.ProbeImpl;
33 import com.oracle.truffle.api.source.*;
34
35 /**
36 * Factory and services for AST {@link Probe}s
37 */
38 public final class ProbeManager {
39
40 // TODO (mlvdv) use weak references.
41 /**
42 * Map: SourceSection ==> probe associated with that source section in an AST.
43 */
44 private final Map<SourceSection, ProbeImpl> srcToProbe = new HashMap<>();
45
46 // TODO (mlvdv) use weak references.
47 /**
48 * Map: Source line ==> probes associated with source sections starting on the line.
49 */
50 private final Map<SourceLineLocation, Collection<Probe>> lineToProbes = new HashMap<>();
51
52 private final List<ProbeListener> probeListeners = new ArrayList<>();
53
54 private final ProbeCallback probeCallback;
55
56 /**
57 * When non-null, "enter" events with matching tags will trigger a callback.
58 */
59 private PhylumTrap phylumTrap = null;
60
61 public ProbeManager() {
62 this.probeCallback = new ProbeCallback() {
63 /**
64 * Receives (from the {@link Probe} implementation) and distributes notification that a
65 * {@link Probe} has acquired a new {@linkplain PhylumTag tag}.
66 */
67 public void newTagAdded(ProbeImpl probe, PhylumTag tag) {
68 for (ProbeListener listener : probeListeners) {
69 listener.probeTaggedAs(probe, tag);
70 }
71 if (phylumTrap != null && tag == phylumTrap.getTag()) {
72 probe.setTrap(phylumTrap);
73 }
74 }
75 };
76 }
77
78 public void addProbeListener(ProbeListener listener) {
79 assert listener != null;
80 probeListeners.add(listener);
81 }
82
83 public Probe getProbe(SourceSection sourceSection) {
84 assert sourceSection != null;
85
86 ProbeImpl probe = srcToProbe.get(sourceSection);
87
88 if (probe != null) {
89 return probe;
90 }
91 probe = InstrumentationNode.createProbe(sourceSection, probeCallback);
92
93 // Register new probe by unique SourceSection
94 srcToProbe.put(sourceSection, probe);
95
96 // Register new probe by source line, there may be more than one
97 // Create line location for map key
98 final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
99
100 Collection<Probe> probes = lineToProbes.get(lineLocation);
101 if (probes == null) {
102 probes = new ArrayList<>(2);
103 lineToProbes.put(lineLocation, probes);
104 }
105 probes.add(probe);
106
107 for (ProbeListener listener : probeListeners) {
108 listener.newProbeInserted(sourceSection, probe);
109 }
110
111 return probe;
112 }
113
114 public Collection<Probe> findProbesTaggedAs(PhylumTag tag) {
115 final List<Probe> probes = new ArrayList<>();
116 for (Probe probe : srcToProbe.values()) {
117 if (tag == null || probe.isTaggedAs(tag)) {
118 probes.add(probe);
119 }
120 }
121 return probes;
122 }
123
124 public Collection<Probe> findProbesByLine(SourceLineLocation lineLocation) {
125 final Collection<Probe> probes = lineToProbes.get(lineLocation);
126 if (probes == null) {
127 return Collections.emptyList();
128 }
129 return new ArrayList<>(probes);
130 }
131
132 public void setPhylumTrap(PhylumTrap trap) {
133 assert trap != null;
134 if (this.phylumTrap != null) {
135 throw new IllegalStateException("trap already set");
136 }
137 this.phylumTrap = trap;
138
139 PhylumTag tag = trap.getTag();
140 for (ProbeImpl probe : srcToProbe.values()) {
141 if (probe.isTaggedAs(tag)) {
142 probe.setTrap(trap);
143 }
144 }
145 }
146
147 public void clearPhylumTrap() {
148 if (this.phylumTrap == null) {
149 throw new IllegalStateException("no trap set");
150 }
151 for (ProbeImpl probe : srcToProbe.values()) {
152 if (probe.isTaggedAs(phylumTrap.getTag())) {
153 probe.setTrap(null);
154 }
155 }
156 phylumTrap = null;
157 }
158
159 }