diff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java @ 19248:a2ff253c458f

Truffle/Instrumentation: code cleanups in tools CoverageTracker and NodeExecCounter, especially for tutorial value
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 10 Feb 2015 16:44:19 -0800
parents c5b20395a8bf
children b5467bb34b24
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java	Tue Feb 10 16:44:11 2015 -0800
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java	Tue Feb 10 16:44:19 2015 -0800
@@ -49,7 +49,7 @@
  * <p>
  * <ul>
  * <li>"Execution call" on a node is is defined as invocation of a node method that is instrumented
- * to produce the event {@link TruffleEventReceiver#enter(Node, VirtualFrame)};</li>
+ * to produce the event {@link TruffleEventListener#enter(Node, VirtualFrame)};</li>
  * <li>Execution calls are tabulated only at <em>instrumented</em> nodes, i.e. those for which
  * {@linkplain Node#isInstrumentable() isInstrumentable() == true};</li>
  * <li>Execution calls are tabulated only at nodes present in the AST when originally created;
@@ -92,26 +92,38 @@
     }
 
     /**
-     * Receiver for events at instrumented nodes. Counts are maintained in a shared table, so the
-     * receiver is stateless and can be shared by every {@link Instrument}.
+     * Listener for events at instrumented nodes. Counts are maintained in a shared table, so the
+     * listener is stateless and can be shared by every {@link Instrument}.
      */
-    private final TruffleEventReceiver eventReceiver = new DefaultEventReceiver() {
+    private final TruffleEventListener eventListener = new DefaultEventListener() {
         @Override
         public void enter(Node node, VirtualFrame frame) {
-            internalReceive(node);
+            if (isEnabled()) {
+                final Class<?> nodeClass = node.getClass();
+                /*
+                 * Everything up to here is inlined by Truffle compilation. Delegate the next part
+                 * to a method behind an inlining boundary.
+                 *
+                 * Note that it is not permitted to pass a {@link VirtualFrame} across an inlining
+                 * boundary; they are truly virtual in inlined code.
+                 */
+                AtomicLong nodeCounter = getCounter(nodeClass);
+                nodeCounter.getAndIncrement();
+            }
         }
 
+        /**
+         * Mark this method as a boundary that will stop Truffle inlining, which should not be
+         * allowed to inline the hash table method or any other complex library code.
+         */
         @TruffleBoundary
-        private void internalReceive(Node node) {
-            if (isEnabled()) {
-                final Class<?> nodeClass = node.getClass();
-                AtomicLong nodeCounter = counters.get(nodeClass);
-                if (nodeCounter == null) {
-                    nodeCounter = new AtomicLong();
-                    counters.put(nodeClass, nodeCounter);
-                }
-                nodeCounter.getAndIncrement();
+        private AtomicLong getCounter(Class<?> nodeClass) {
+            AtomicLong nodeCounter = counters.get(nodeClass);
+            if (nodeCounter == null) {
+                nodeCounter = new AtomicLong();
+                counters.put(nodeClass, nodeCounter);
             }
+            return nodeCounter;
         }
     };
 
@@ -268,7 +280,7 @@
 
             if (node.isInstrumentable()) {
                 try {
-                    final Instrument instrument = Instrument.create(eventReceiver, "NodeExecCounter");
+                    final Instrument instrument = Instrument.create(eventListener, "NodeExecCounter");
                     instruments.add(instrument);
                     node.probe().attach(instrument);
                 } catch (ProbeException ex) {
@@ -292,7 +304,7 @@
         @Override
         public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
             if (countingTag == tag) {
-                final Instrument instrument = Instrument.create(eventReceiver, NodeExecCounter.class.getSimpleName());
+                final Instrument instrument = Instrument.create(eventListener, NodeExecCounter.class.getSimpleName());
                 instruments.add(instrument);
                 probe.attach(instrument);
             }