All Downloads are FREE. Search and download functionalities are using the official Maven repository.

template.trace.Tracer.tt Maven / Gradle / Ivy

There is a newer version: 2.3.6
Show newest version
# Copyright (c) 2013-2015, The JastAdd Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the Lund University nor the names of its
#       contributors may be used to endorse or promote products derived from
#       this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# Code for the class ASTNodeState.Trace.
TraceClass [[
$if(TracingEnabled)
public static class Trace {

  /**
   * Trace filter interface used to filter the list of collected trace class.
   */
  public interface Filter {
    public boolean include($StateClass.Trace.Entry e);
    public String desc();
  }

  /**
   * Interface used to process collected trace objects.
   *
   * 

Use it together with the method $StateClass.Trace.process($StateClass.Trace.Processor). */ public interface Processor { public void process($StateClass.Trace.Entry e); } /** Prints trace events to an output stream. */ public static class PrintProcessor implements Processor { private final java.io.PrintStream out; public PrintProcessor(java.io.PrintStream outStream) { this.out = outStream; } @Override public void process($StateClass.Trace.Entry e) { out.println(e); } }; /** * Trace entries collected during attribute evaluation. */ public static class Entry { public final $StateClass.Trace.Event event; public final String node; public final String nodeType; public final String attr; public final String params; public final String value; public final long timeStamp; public Entry($StateClass.Trace.Event e, String n, String t, String a, String p, String v) { event = e; node = n; nodeType = t; attr = a; params = p; value = v; timeStamp = System.nanoTime(); } public String toString() { return "[trace: " + event + ", " + attr + "[" + params + "]=" + value + " - " + node + "]"; } } /** * Trace events corresponding to where trace entries where collected. * * These events can be filtered statically using the flag --tracing to * JastAdd2. For example, the flag --tracing=compute,cache will only trace * compute events and cache events. The flag --tracing will enable all events. * * These events can also be filtered dynamically by extending the InputFilter * class and then register this subclass using the method * registerInputFilter($StateClass.Trace.InputFilter). */ public enum Event { // Flag --tracing=compute COMPUTE_BEGIN, COMPUTE_END, // Flag --tracing=cache CACHED, CACHE_ABORT, CACHE_READ, // Flag --tracing=rewrite REWRITE_CASE1_START, REWRITE_CASE1_CHANGE, REWRITE_CASE1_RETURN, REWRITE_CASE2_RETURN, REWRITE_CASE3_RETURN, // Flag --tracing=circular CIRCULAR_NTA_CASE1_START, CIRCULAR_NTA_CASE1_CHANGE, CIRCULAR_NTA_CASE1_RETURN, CIRCULAR_NTA_CASE2_START, CIRCULAR_NTA_CASE2_CHANGE, CIRCULAR_NTA_CASE2_RETURN, CIRCULAR_NTA_CASE3_RETURN, CIRCULAR_CASE1_START, CIRCULAR_CASE1_CHANGE, CIRCULAR_CASE1_RETURN, CIRCULAR_CASE2_START, CIRCULAR_CASE2_CHANGE, CIRCULAR_CASE2_RETURN, CIRCULAR_CASE3_RETURN, // Flag --tracing=copy COPY_NODE, // Flag --tracing=flush FLUSH_ATTR, FLUSH_REWRITE, FLUSH_REWRITE_INIT } /** * Class used to filter input */ public static abstract class InputFilter implements Filter { public Entry createEntry($StateClass.Trace.Event evt, $ASTNode node, String attr, Object params, Object value) { String paramsString; if (params instanceof $ASTNode) { paramsString = String.format("%08X", params.hashCode()); } else { paramsString = String.valueOf(params); } String valueString; if (value instanceof $ASTNode) { valueString = String.format("%08X", value.hashCode()); } else { valueString = String.valueOf(value); } return new Entry(evt, String.format("%08X", node.hashCode()), node.getClass().getName(), attr, paramsString, valueString); } public String desc() { return "Custom input filter"; } } // Default input filter accepting all events private final InputFilter defaultInputFilter = new InputFilter() { public boolean include(Entry e) { return true; } public String desc() { return "Default input filter accepting all events"; } }; $if(CacheAnalyzeEnabled) private final CacheAnalyzer cacheAnalyzer = new CacheAnalyzer(); public CacheAnalyzer cacheAnalyzer() { return cacheAnalyzer; } private Trace.InputFilter inputFilter = cacheAnalyzer; $else private Trace.InputFilter inputFilter = defaultInputFilter; $endif /** * Registers an input filter to use during tracing. * @param filter The input filter to register. */ public void registerInputFilter($StateClass.Trace.InputFilter filter) { if (filter != null) { inputFilter = filter; } } /** * Resets the input filter to the default input filter accepting all events. */ public void unregisterInputFilter() { inputFilter = defaultInputFilter; } private java.util.List<$StateClass.Trace.Entry> list = new java.util.ArrayList<$StateClass.Trace.Entry>(); /** * Add a trace event for an attribute instance. * @param node The host node. * @param attr The attribute name. * @param params The parameter list. * @param value The current value of the attribute instance. */ private void add($StateClass.Trace.Event evt, $ASTNode node, String attr, Object params, Object value) { $StateClass.Trace.Entry e = inputFilter.createEntry(evt, node, attr, params, value); if (inputFilter.include(e)) { list.add(e); } } public void clear() { list.clear(); } /** * Trace that an attribute instance started its computation. * @param value The value of the attribute instance. */ public void computeBegin($ASTNode node, String attr, Object params, Object value) { add(Event.COMPUTE_BEGIN, node, attr, params, value); } /** * Trace that an attribute instance ended its computation. * @param value The value of the attribute instance. */ public void computeEnd($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.COMPUTE_END, node, attr, params, value); } /** * Trace that the cache of an attribute instances was read. * @param value The value of the attribute instance. */ public void cacheRead($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CACHE_READ, node, attr, params, value); } /** * Trace that an attribute instance was cached. * @param value The value of the attribute instance. */ public void cacheWrite($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CACHED, node, attr, params, value); } /** * Trace that the caching of an attribute instance was aborted. * @param value The value of the attribute instance. */ public void cacheAbort($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CACHE_ABORT, node, attr, params, value); } /** * Trace that a rewrite evaluation entered case 1. * @param value The value of the rewrite. */ public void enterRewriteCase1($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.REWRITE_CASE1_START, node, attr, params, value); } /** * Trace that a rewrite in evaluation case 1 changed value. * @param value The value of the rewrite before and after. */ public void rewriteChange($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.REWRITE_CASE1_CHANGE, node, attr, params, value); } /** * Trace that a rewrite returned from evaluation case 1. * @param value The value of the rewrite. */ public void exitRewriteCase1($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.REWRITE_CASE1_RETURN, node, attr, params, value); } /** * Trace that a rewrite returned from evaluation case 2. * @param value The value of the rewrite. */ public void exitRewriteCase2($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.REWRITE_CASE2_RETURN, node, attr, params, value); } /** * Trace that a rewrite returned from evaluation case 3. * @param value The value of the rewrite. */ public void exitRewriteCase3($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.REWRITE_CASE3_RETURN, node, attr, params, value); } /** * Trace that a circular attribute instance entered evaluation case 1. * @param value The value of the circular attribute instance. */ public void enterCircularCase1($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_CASE1_START, node, attr, params, value); } /** * Trace that a circular attribute instance in evaluation case 1 changed value. * @param value The value of the circular attribute instance, before and after. */ public void circularCase1Change($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_CASE1_CHANGE, node, attr, params, value); } /** * Trace that a circular attribute instance returned from evaluation case 1. * @param value The value of the circular attribute instance. */ public void exitCircularCase1($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_CASE1_RETURN, node, attr, params, value); } /** * Trace that a circular attribute instance entered evaluation case 2. * @param value The value of the circular attribute instance. */ public void enterCircularCase2($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_CASE2_START, node, attr, params, value); } /** * Trace that a circular attribute instance in evaluation case 2 changed value. * @param value The value of the circular attribute instance, before and after. */ public void circularCase2Change($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_CASE2_CHANGE, node, attr, params, value); } /** * Trace that a circular attribute instance returned from evaluation case 2. * @param value The value of the circular attribute instance. */ public void exitCircularCase2($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_CASE2_RETURN, node, attr, params, value); } /** * Trace that a circular attribute instance returned from evaluation case 2. * @param value The value of the circular attribute instance. */ public void exitCircularCase3($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_CASE3_RETURN, node, attr, params, value); } /** * Trace that a circular NTA entered evaluation case 1. * @param value The value of the circular NTA. */ public void enterCircularNTACase1($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_NTA_CASE1_START, node, attr, params, value); } /** * Trace that a circular NTA in evaluation case 1 changed value. * @param value The value of the circular NTA, before and after. */ public void circularNTACase1Change($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_NTA_CASE1_CHANGE, node, attr, params, value); } /** * Trace that a circular NTA returned from evaluation case 1. * @param value The value of the circular NTA. */ public void exitCircularNTACase1($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_NTA_CASE1_RETURN, node, attr, params, value); } /** * Trace that a circular NTA entered evaluation case 2. * @param value The value of the circular NTA. */ public void enterCircularNTACase2($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_NTA_CASE2_START, node, attr, params, value); } /** * Trace that a circular NTA in evaluation case 2 changed value. * @param value The value of the circular NTA, before and after. */ public void circularNTACase2Change($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_NTA_CASE2_CHANGE, node, attr, params, value); } /** * Trace that a circular NTA returned from evaluation case 2. * @param value The value of the circular NTA. */ public void exitCircularNTACase2($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_NTA_CASE2_RETURN, node, attr, params, value); } /** * Trace that a circular NTA returned from evaluation case 2. * @param value The value of the circular NTA. */ public void exitCircularNTACase3($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.CIRCULAR_NTA_CASE3_RETURN, node, attr, params, value); } /** * Trace that an AST node was copied. * @param node The copied node. * @param value The value of the node. */ public void copyNode($ASTNode node, Object value) { add($StateClass.Trace.Event.COPY_NODE, node, "ASTNode.copy", "", value); } /** * Trace that an attribute was flushed. * @param value The value of the attribute. */ public void flushAttr($ASTNode node, String attr, Object params, Object value) { add($StateClass.Trace.Event.FLUSH_ATTR, node, attr, params, value); } /** * Process all trace entries given a trace processor */ public void process($StateClass.Trace.Processor processor) { for ($StateClass.Trace.Entry e: list) { processor.process(e); } } /** * Print report from collected trace using the given filter. * @param out Print writer to use. * @param filter The filter to use. */ public void printReport(java.io.PrintWriter out, $StateClass.Trace.Filter filter) { // Construct report model: attr->param->node:count java.util.Map>> attrMap = new java.util.HashMap>>(); for ($StateClass.Trace.Entry e : list) { if (filter.include(e)) { if (!attrMap.containsKey(e.attr)) { attrMap.put(e.attr, new java.util.HashMap>()); } java.util.Map> paramMap = attrMap.get(e.attr); if (!paramMap.containsKey(e.params)) { paramMap.put(e.params, new java.util.HashMap()); } java.util.Map nodeMap = paramMap.get(e.params); if (!nodeMap.containsKey(e.node)) { nodeMap.put(e.node, Integer.valueOf(0)); } Integer nodeCount = nodeMap.get(e.node); nodeMap.put(e.node, Integer.valueOf(nodeCount + 1)); } } // Create result string int totalCount = 0; StringBuffer res = new StringBuffer(); for (String attr : attrMap.keySet()) { int attrCount = 0; StringBuffer paramBuf = new StringBuffer(); java.util.Map> paramMap = attrMap.get(attr); for (String param : paramMap.keySet()) { int paramCount = 0; StringBuffer nodeBuf = new StringBuffer(); java.util.Map nodeMap = paramMap.get(param); for (java.util.Map.Entry e : nodeMap.entrySet()) { nodeBuf.append(indentToStr(3) + e.getKey() + " - " + e.getValue() + "\n"); paramCount += e.getValue(); } paramBuf.append((!param.equals("") ? indentToStr(2) + "[" + param + "] - " + paramCount + "\n" : "") + nodeBuf.toString()); attrCount += paramCount; } res.append(indentToStr(1) + attr + " - " + attrCount + "\n" + paramBuf.toString()); totalCount += attrCount; } out.println("[report:" + filter.desc() + "] - " + totalCount + "\n" + res.toString()); out.flush(); } protected boolean incIndent($StateClass.Trace.Event evt) { switch (evt) { case COMPUTE_BEGIN: case REWRITE_CASE1_START: case CIRCULAR_NTA_CASE1_START: case CIRCULAR_NTA_CASE2_START: return true; default: return false; } } protected boolean decIndent($StateClass.Trace.Event evt) { switch (evt) { case COMPUTE_END: case REWRITE_CASE1_RETURN: case CIRCULAR_NTA_CASE1_RETURN: case CIRCULAR_NTA_CASE2_RETURN: return true; default: return false; } } protected String INDENT_STEP = " "; protected String indentToStr(int indent) { StringBuffer buf = new StringBuffer(); for(int i = 0; i < indent; i++) { buf.append(INDENT_STEP); } return buf.toString(); } /** * Prints all objects in the collected trace list. */ public void printTrace(java.io.PrintWriter out) { boolean firstTimeStamp = true; long prevTime = 0; long startTime = 0; int indent = 0; for ($StateClass.Trace.Entry e : list) { if (firstTimeStamp) { firstTimeStamp = false; prevTime = startTime = e.timeStamp; } out.print(indentToStr(indent) + e + " - "); out.print(((e.timeStamp-prevTime)/1000000) + " ms - "); out.println(((e.timeStamp-startTime)/1000000) + " ms"); if (incIndent(e.event)) indent++; else if (decIndent(e.event)) indent--; prevTime = e.timeStamp; } out.flush(); } /** * Prints all of attribute instance computations (cached or aborted). */ public void printComputeReport(java.io.PrintWriter out) { printReport(out, new $StateClass.Trace.Filter() { public boolean include($StateClass.Trace.Entry e) { return e.event == $StateClass.Trace.Event.CACHE_ABORT || e.event == $StateClass.Trace.Event.CACHED; } public String desc() { return "computed(i.e.,CACHE_ABORT||CACHED)"; } }); } /** * Prints all cache aborts. */ public void printCacheAbortReport(java.io.PrintWriter out) { printReport(out, new $StateClass.Trace.Filter() { public boolean include($StateClass.Trace.Entry e) { return e.event == $StateClass.Trace.Event.CACHE_ABORT; } public String desc() { return "CACHE_ABORT"; } }); } /** * Prints all cached. */ public void printCacheReport(java.io.PrintWriter out) { printReport(out, new $StateClass.Trace.Filter() { public boolean include($StateClass.Trace.Entry e) { return e.event == $StateClass.Trace.Event.CACHED; } public String desc() { return "CACHED"; } }); } /** * Prints all copied nodes. */ public void printCopyReport(java.io.PrintWriter out) { printReport(out, new $StateClass.Trace.Filter() { public boolean include($StateClass.Trace.Entry e) { return e.event == $StateClass.Trace.Event.COPY_NODE; } public String desc() { return "COPY_NODE"; } }); } /** * Prints report of maxiumum nesting of circular NTA evaluations. */ public void printCircularNtaNestingReport(java.io.PrintWriter out) { class NestingCounter { int nesting = 0; int maxNesting = 0; public void push() { nesting++; if (nesting > maxNesting) { maxNesting = nesting; } } public void pop() { nesting--; } public int max() { return maxNesting; } } final NestingCounter counter = new NestingCounter(); printReport(out, new $StateClass.Trace.Filter() { public boolean include($StateClass.Trace.Entry e) { boolean res = false; if (e.event == $StateClass.Trace.Event.CIRCULAR_NTA_CASE1_START || e.event == $StateClass.Trace.Event.CIRCULAR_NTA_CASE2_START) { res = true; counter.push(); } if (e.event == $StateClass.Trace.Event.CIRCULAR_NTA_CASE1_RETURN || e.event == $StateClass.Trace.Event.CIRCULAR_NTA_CASE2_RETURN) { counter.pop(); } return res; } public String desc() { return "CIRCULAR_NTA_CASE*_START"; } }); System.out.println("Max nesting: " + counter.max() + "\n"); } } $endif ]]





© 2015 - 2024 Weber Informatics LLC | Privacy Policy