diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java	Mon May 19 17:14:36 2014 -0700
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.InstrumentationNode.ProbeCallback;
+import com.oracle.truffle.api.instrument.impl.InstrumentationNode.ProbeImpl;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Factory and services for AST {@link Probe}s
+ */
+public final class ProbeManager {
+
+    // TODO (mlvdv) use weak references.
+    /**
+     * Map: SourceSection ==> probe associated with that source section in an AST.
+     */
+    private final Map<SourceSection, ProbeImpl> srcToProbe = new HashMap<>();
+
+    // TODO (mlvdv) use weak references.
+    /**
+     * Map: Source line ==> probes associated with source sections starting on the line.
+     */
+    private final Map<SourceLineLocation, Collection<Probe>> lineToProbes = new HashMap<>();
+
+    private final List<ProbeListener> probeListeners = new ArrayList<>();
+
+    private final ProbeCallback probeCallback;
+
+    /**
+     * When non-null, "enter" events with matching tags will trigger a callback.
+     */
+    private PhylumTrap phylumTrap = null;
+
+    public ProbeManager() {
+        this.probeCallback = new ProbeCallback() {
+            /**
+             * Receives (from the {@link Probe} implementation) and distributes notification that a
+             * {@link Probe} has acquired a new {@linkplain PhylumTag tag}.
+             */
+            public void newTagAdded(ProbeImpl probe, PhylumTag tag) {
+                for (ProbeListener listener : probeListeners) {
+                    listener.probeTaggedAs(probe, tag);
+                }
+                if (phylumTrap != null && tag == phylumTrap.getTag()) {
+                    probe.setTrap(phylumTrap);
+                }
+            }
+        };
+    }
+
+    public void addProbeListener(ProbeListener listener) {
+        assert listener != null;
+        probeListeners.add(listener);
+    }
+
+    public Probe getProbe(SourceSection sourceSection) {
+        assert sourceSection != null;
+
+        ProbeImpl probe = srcToProbe.get(sourceSection);
+
+        if (probe != null) {
+            return probe;
+        }
+        probe = InstrumentationNode.createProbe(sourceSection, probeCallback);
+
+        // Register new probe by unique SourceSection
+        srcToProbe.put(sourceSection, probe);
+
+        // Register new probe by source line, there may be more than one
+        // Create line location for map key
+        final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
+
+        Collection<Probe> probes = lineToProbes.get(lineLocation);
+        if (probes == null) {
+            probes = new ArrayList<>(2);
+            lineToProbes.put(lineLocation, probes);
+        }
+        probes.add(probe);
+
+        for (ProbeListener listener : probeListeners) {
+            listener.newProbeInserted(sourceSection, probe);
+        }
+
+        return probe;
+    }
+
+    public Collection<Probe> findProbesTaggedAs(PhylumTag tag) {
+        final List<Probe> probes = new ArrayList<>();
+        for (Probe probe : srcToProbe.values()) {
+            if (tag == null || probe.isTaggedAs(tag)) {
+                probes.add(probe);
+            }
+        }
+        return probes;
+    }
+
+    public Collection<Probe> findProbesByLine(SourceLineLocation lineLocation) {
+        final Collection<Probe> probes = lineToProbes.get(lineLocation);
+        if (probes == null) {
+            return Collections.emptyList();
+        }
+        return new ArrayList<>(probes);
+    }
+
+    public void setPhylumTrap(PhylumTrap trap) {
+        assert trap != null;
+        if (this.phylumTrap != null) {
+            throw new IllegalStateException("trap already set");
+        }
+        this.phylumTrap = trap;
+
+        PhylumTag tag = trap.getTag();
+        for (ProbeImpl probe : srcToProbe.values()) {
+            if (probe.isTaggedAs(tag)) {
+                probe.setTrap(trap);
+            }
+        }
+    }
+
+    public void clearPhylumTrap() {
+        if (this.phylumTrap == null) {
+            throw new IllegalStateException("no trap set");
+        }
+        for (ProbeImpl probe : srcToProbe.values()) {
+            if (probe.isTaggedAs(phylumTrap.getTag())) {
+                probe.setTrap(null);
+            }
+        }
+        phylumTrap = null;
+    }
+
+}