# HG changeset patch # User David Piorkowski # Date 1408652902 25200 # Node ID 7661cc464239a0fc9ab0530885dc48677d35753f # Parent 7af9301efe6b78a1882fcf299ee3a89e0dfda18a Truffle/Instrumentation: Added Instrumentable interface and LineLocationToSourceSections map SL: Updated implementation to use new Instrumentable interface diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java Thu Aug 21 13:28:22 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 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; + +import com.oracle.truffle.api.*; + +public interface Instrumentable { + + /** + * Optionally applies instrumentation at a Truffle AST node, depending on guest + * language characteristics and use-case policy. Ideally, the parent node of the guest language + * implements this interface. + * + * + * @param context The {@link ExecutionContext} of the guest language used to create probes on + * the wrapper. + * @return The probe that was created. + */ + public Probe probe(ExecutionContext context); +} diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java Thu Aug 21 13:28:22 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -43,8 +43,8 @@ } public void newProbeInserted(SourceSection source, Probe probe) { - final LineLocation line = source.getLineLocation(); - this.addProbeToLine(line, probe); + if (source != null && !(source instanceof NullSourceSection)) + this.addProbeToLine(source.getLineLocation(), probe); } public void probeTaggedAs(Probe probe, SyntaxTag tag) { @@ -81,7 +81,7 @@ * @param line The {@link LineLocation} to attach the probe to. * @param probe The {@link Probe} to attach for that line location. */ - private void addProbeToLine(LineLocation line, Probe probe) { + protected void addProbeToLine(LineLocation line, Probe probe) { if (!lineToProbesMap.containsKey(line)) { // Key does not exist, add new probe list @@ -98,17 +98,36 @@ /** * Returns a collection of {@link Probe}s at the given {@link LineLocation}. If there are no - * probes at that line, an empty list is returned. + * probes at that line, a new empty list of size 1 is returned. * * @param line The line to check. * @return A iterable collection of probes at the given line. */ - private Collection getProbesAtLine(LineLocation line) { + public Collection getProbesAtLine(LineLocation line) { Collection probeList = lineToProbesMap.get(line); if (probeList == null) - probeList = new ArrayList<>(2); + probeList = new ArrayList<>(1); return probeList; } + + /** + * Convenience method to get probes according to a int line number. Returns a collection of + * {@link Probe}s at the given line number. If there are no probes at that line, a new empty + * list is returned. + * + * @param lineNumber The line number to check. + * @return A iterable collection of probes at the given line. + */ + public Collection getProbesAtLineNumber(int lineNumber) { + ArrayList probes = new ArrayList<>(); + + for (LineLocation line : lineToProbesMap.keySet()) { + if (line.getLineNumber() == lineNumber) + probes.addAll(lineToProbesMap.get(line)); + } + + return probes; + } } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java Thu Aug 21 13:28:22 2014 -0700 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 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.instrument.*; +import com.oracle.truffle.api.source.*; + +/** + * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to + * a collection of {@link SourceSection}s that exist on that line. This class assumes that all nodes + * are instrumented as it uses the {@link ProbeListener} interface to determine the source sections + * that exist in the file. + */ +public class LineLocationToSourceSectionCollectionMap implements ProbeListener { + + /** + * Map: Source line ==> source sections that exist on the line. + */ + private final Map> lineToSourceSectionsMap = new HashMap<>(); + + public LineLocationToSourceSectionCollectionMap() { + + } + + public void newProbeInserted(SourceSection sourceSection, Probe probe) { + if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) { + this.addSourceSectionToLine(sourceSection.getLineLocation(), sourceSection); + } + } + + public void probeTaggedAs(Probe probe, SyntaxTag tag) { + // This map ignores tags, but this subclasses can override this method to operate on tags. + } + + /** + * Adds a source section to the given line. + *

+ * If the line already exists in the internal {@link #lineToSourceSectionsMap}, this source + * section will be added to the existing collection. If no line already exists in the internal + * map, then a new key is added along with a new collection containing the source section. + *

+ * This class does not check if a source section has already been added to a line. + * + * @param line The {@link LineLocation} to attach the source section to. + * @param sourceSection The {@link SourceSection} to attach for that line location. + */ + protected void addSourceSectionToLine(LineLocation line, SourceSection sourceSection) { + if (!lineToSourceSectionsMap.containsKey(line)) { + // Key does not exist, add new source section list + final ArrayList newSourceSectionList = new ArrayList<>(2); + newSourceSectionList.add(sourceSection); + lineToSourceSectionsMap.put(line, newSourceSectionList); + } else { + // Source section list exists, add to existing + final Collection existingSourceSectionList = lineToSourceSectionsMap.get(line); + existingSourceSectionList.add(sourceSection); + } + } + + /** + * Returns a collection of {@link SourceSection}s at the given {@link LineLocation}. If there + * are no source sections at that line, a new empty list of size 1 is returned. + * + * @param line The line to check. + * @return A iterable collection of source sections at the given line. + */ + public Collection getSourceSectionsAtLine(LineLocation line) { + Collection sourceSectionList = lineToSourceSectionsMap.get(line); + + if (sourceSectionList == null) + sourceSectionList = new ArrayList<>(1); + + return sourceSectionList; + } + + /** + * Convenience method to get source sections according to a int line number. Returns a + * collection of {@link SourceSection}s at the given line number. If there are no source + * sections at that line, a new empty list is returned. + * + * @param lineNumber The line number to check. + * @return A iterable collection of source sections at the given line. + */ + public Collection getSourceSectionsAtLineNumber(int lineNumber) { + ArrayList sourceSections = new ArrayList<>(); + + for (LineLocation line : lineToSourceSectionsMap.keySet()) { + if (line.getLineNumber() == lineNumber) + sourceSections.addAll(lineToSourceSectionsMap.get(line)); + } + + return sourceSections; + } +} diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLCheckVariableEqualityInstrument.java --- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLCheckVariableEqualityInstrument.java Tue Aug 19 19:25:44 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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.sl.test.instrument; - -import java.io.*; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.sl.nodes.controlflow.*; -import com.oracle.truffle.sl.runtime.*; - -/** - * This sample instrument provides an example of a naive way to check if two numbers in SL are - * equivalent using their variable names. This instrument is designed to be attached to an - * {@link SLReturnNode}, but provides no guards ensuring this. - */ -public class SLCheckVariableEqualityInstrument extends Instrument { - - private final String varName1; - private final String varName2; - private final PrintStream output; - - /** - * Constructor - * - * @param varName1 The name of the first variable to compare - * @param varName2 The name of the second variable to compare - * @param output The {@link PrintStream} from the context used to print results. See - * {@link SLContext#getOutput()} for more info. - */ - public SLCheckVariableEqualityInstrument(String varName1, String varName2, PrintStream output) { - this.varName1 = varName1; - this.varName2 = varName2; - this.output = output; - } - - /** - * In the instrumentation test, this instrument is attached to a return statement. Since returns - * are handled via exceptions in Simple, we need to override the leaveExceptional method. This - * method does very limited error checking and simply prints "true" if the passed-in variables - * match or "false" if they do not. - */ - @Override - public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { - FrameSlot f1 = frame.getFrameDescriptor().findFrameSlot(varName1); - FrameSlot f2 = frame.getFrameDescriptor().findFrameSlot(varName2); - - if (f1 == null || f2 == null) - output.println("false"); - else { - try { - output.println(frame.getLong(f1) == frame.getLong(f2)); - } catch (FrameSlotTypeException e1) { - e1.printStackTrace(); - } - } - - } -} diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestNodeProber.java --- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestNodeProber.java Tue Aug 19 19:25:44 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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.sl.test.instrument; - -import static com.oracle.truffle.api.instrument.StandardSyntaxTag.*; - -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.controlflow.*; -import com.oracle.truffle.sl.nodes.instrument.*; -import com.oracle.truffle.sl.nodes.local.*; -import com.oracle.truffle.sl.runtime.*; - -/** - * This sample AST Node Prober for simple is used to instrument the nodes that we are interested in - * testing. This prober wraps return nodes and assignment nodes. For the purposes of this example, - * this is appropriate, but ideally there would be only one node prober responsible for - * instrumenting all the nodes of interest instead of a selective one like this one. - * - */ -public final class SLInstrumentTestNodeProber implements SLNodeProber { - private final SLContext slContext; - - public SLInstrumentTestNodeProber(SLContext slContext) { - this.slContext = slContext; - } - - /** - * Not implemented, only returns the astNode that was passed in. - */ - public Node probeAs(Node astNode, SyntaxTag tag, Object... args) { - // TODO dp: Currently does nothing in the general case - return astNode; - } - - /** - * If the passed in node is a {@link SLStatementWrapper}, then this simply tags it as a - * statement. If the passed in node is a {@link SLReturnNode}, then it is instrumented and - * tagged as a statement for testing. Only SLReturnNodes are wrapped. - */ - public SLStatementNode probeAsStatement(SLStatementNode node) { - assert node != null; - - SLStatementWrapper wrapper = null; - if (node instanceof SLStatementWrapper) { - wrapper = (SLStatementWrapper) node; - wrapper.tagAs(STATEMENT); - return wrapper; - } else if (node instanceof SLReturnNode) { - wrapper = new SLStatementWrapper(slContext, node); - wrapper.tagAs(STATEMENT); - return wrapper; - } - return node; - } - - /** - * Not implemented. Returns the passed in node. - */ - public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) { - return node; - } - - /** - * If the passed in node is a {@link SLExpressionWrapper}, then this simply tags it as an - * assignment. If the passed in node is a {@link SLWriteLocalVariableNode}, then it is - * instrumented and tagged as a assignment for testing. Only SLWriteLocalVariableNode are - * wrapped. - */ - public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) { - assert node != null; - - SLExpressionWrapper wrapper = null; - if (node instanceof SLExpressionWrapper) { - wrapper = (SLExpressionWrapper) node; - wrapper.tagAs(ASSIGNMENT); - return wrapper; - } else if (node instanceof SLWriteLocalVariableNode) { - wrapper = new SLExpressionWrapper(slContext, node); - wrapper.tagAs(ASSIGNMENT); - return wrapper; - } - return node; - } - -} \ No newline at end of file diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java --- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Thu Aug 21 13:28:22 2014 -0700 @@ -37,12 +37,11 @@ import org.junit.runners.model.*; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.parser.*; import com.oracle.truffle.sl.runtime.*; -import com.oracle.truffle.sl.test.*; import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase; /** @@ -58,8 +57,7 @@ private static final String SOURCE_SUFFIX = ".sl"; private static final String INPUT_SUFFIX = ".input"; private static final String OUTPUT_SUFFIX = ".output"; - private static final String VISITOR_ASSIGNMENT_COUNT_SUFFIX = "_assnCount"; - private static final String VISITOR_VARIABLE_COMPARE_SUFFIX = "_varCompare"; + private static final String ASSIGNMENT_VALUE_SUFFIX = "_assnCount"; private static final String LF = System.getProperty("line.separator"); private static SLContext slContext; @@ -128,7 +126,8 @@ protected static List createTests(final Class c) throws IOException, InitializationError { SLInstrumentTestSuite suite = c.getAnnotation(SLInstrumentTestSuite.class); if (suite == null) { - throw new InitializationError(String.format("@%s annotation required on class '%s' to run with '%s'.", SLTestSuite.class.getSimpleName(), c.getName(), SLTestRunner.class.getSimpleName())); + throw new InitializationError(String.format("@%s annotation required on class '%s' to run with '%s'.", SLInstrumentTestSuite.class.getSimpleName(), c.getName(), + SLInstrumentTestRunner.class.getSimpleName())); } String[] paths = suite.value(); @@ -200,57 +199,29 @@ PrintStream printer = new PrintStream(out); try { // We use the name of the file to determine what visitor to attach to it. - if (testCase.baseName.endsWith(VISITOR_ASSIGNMENT_COUNT_SUFFIX) || testCase.baseName.endsWith(VISITOR_VARIABLE_COMPARE_SUFFIX)) { - NodeVisitor nodeVisitor = null; + if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) { + // Set up the execution context for Simple and register our two listeners slContext = new SLContext(new BufferedReader(new StringReader(testCase.testInput)), printer); - final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName); - SLASTProber prober = new SLASTProber(); - - // Note that the visitor looks for an attachment point via line number - if (testCase.baseName.endsWith(VISITOR_ASSIGNMENT_COUNT_SUFFIX)) { - nodeVisitor = new NodeVisitor() { - - public boolean visit(Node node) { - if (node instanceof SLExpressionWrapper) { - SLExpressionWrapper wrapper = (SLExpressionWrapper) node; - int lineNum = wrapper.getSourceSection().getLineLocation().getLineNumber(); - if (lineNum == 4) { - wrapper.getProbe().addInstrument(new SLPrintAssigmentValueInstrument(slContext.getOutput())); - } - } - return true; - } - }; - - // Note that the visitor looks for an attachment point via line number - } else if (testCase.baseName.endsWith(VISITOR_VARIABLE_COMPARE_SUFFIX)) { - nodeVisitor = new NodeVisitor() { - - public boolean visit(Node node) { - if (node instanceof SLStatementWrapper) { - SLStatementWrapper wrapper = (SLStatementWrapper) node; - int lineNum = wrapper.getSourceSection().getLineLocation().getLineNumber(); - - if (lineNum == 6) { - wrapper.getProbe().addInstrument(new SLCheckVariableEqualityInstrument("i", "count", slContext.getOutput())); - } - } - return true; - } - }; - } - - prober.addNodeProber(new SLInstrumentTestNodeProber(slContext)); - Parser.parseSL(slContext, source, prober); + final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName); + Parser.parseSL(slContext, source); List functionList = slContext.getFunctionRegistry().getFunctions(); // Since only functions can be global in SL, this guarantees that we instrument // everything of interest. Parsing must occur before accepting the visitors since - // parsing is what creates our instrumentation points. + // the visitor which creates our instrumentation points expects a complete AST. + for (SLFunction function : functionList) { RootCallTarget rootCallTarget = function.getCallTarget(); - rootCallTarget.getRootNode().accept(nodeVisitor); + rootCallTarget.getRootNode().accept(new SLInstrumenter(slContext)); + } + + // We iterate over all tags the SLInsturmenter tagged as assignments and attach our + // test instrument to those. + for (Probe probe : slContext.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) { + if (probe.isTaggedAs(StandardSyntaxTag.ASSIGNMENT)) { + probe.addInstrument(new SLPrintAssigmentValueInstrument(printer)); + } } SLFunction main = slContext.getFunctionRegistry().lookup("main"); @@ -272,7 +243,7 @@ public static void runInMain(Class testClass, String[] args) throws InitializationError, NoTestsRemainException { JUnitCore core = new JUnitCore(); core.addListener(new TextListener(System.out)); - SLTestRunner suite = new SLTestRunner(testClass); + SLInstrumentTestRunner suite = new SLInstrumentTestRunner(testClass); if (args.length > 0) { suite.filter(new NameFilter(args[0])); } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output --- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output Thu Aug 21 13:28:22 2014 -0700 @@ -1,3 +1,5 @@ +100 +0 1 2 3 diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl --- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl Thu Aug 21 13:28:22 2014 -0700 @@ -8,5 +8,4 @@ function main() { count = loop(100); - println(count); } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.output --- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.output Tue Aug 19 19:25:44 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -true -100 diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.sl --- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.sl Tue Aug 19 19:25:44 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -function loop(count) { - i = 0; - while (i < count) { - i = i + 1; - } - return i; -} - -function main() { - count = loop(100); - println(count); -} diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Thu Aug 21 13:28:22 2014 -0700 @@ -152,7 +152,7 @@ if (sourceCallback != null) { sourceCallback.startLoading(source); } - Parser.parseSL(context, source, null); + Parser.parseSL(context, source); if (sourceCallback != null) { sourceCallback.endLoading(source); } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Thu Aug 21 13:28:22 2014 -0700 @@ -50,6 +50,6 @@ private static void doDefineFunction(SLContext context, String code) { Source source = Source.fromText(code, "[defineFunction]"); /* The same parsing code as for parsing the initial source. */ - Parser.parseSL(context, source, null); + Parser.parseSL(context, source); } } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Thu Aug 21 13:28:22 2014 -0700 @@ -29,8 +29,6 @@ public final class SLContextFactory { - private static SLASTProber astProber; - private SLContextFactory() { } @@ -39,12 +37,6 @@ final SLContext slContext = new SLContext(new BufferedReader(new InputStreamReader(System.in)), System.out); slContext.initialize(); slContext.setVisualizer(new SLDefaultVisualizer()); - astProber = new SLASTProber(); - slContext.setASTNodeProber(astProber); return slContext; } - - public static void addNodeProber(SLNodeProber nodeProber) { - astProber.addNodeProber(nodeProber); - } } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java Thu Aug 21 13:28:22 2014 -0700 @@ -24,10 +24,13 @@ import java.math.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; /** @@ -87,4 +90,20 @@ public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame)); } + + @Override + public Probe probe(ExecutionContext context) { + Node parent = getParent(); + + if (parent == null) + throw new IllegalStateException("Cannot probe a node without a parent"); + + if (parent instanceof SLExpressionWrapper) + return ((SLExpressionWrapper) parent).getProbe(); + + SLExpressionWrapper wrapper = new SLExpressionWrapper((SLContext) context, this); + this.replace(wrapper); + wrapper.insertChild(); + return wrapper.getProbe(); + } } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Thu Aug 21 13:28:22 2014 -0700 @@ -22,9 +22,13 @@ */ package com.oracle.truffle.sl.nodes; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.nodes.instrument.*; +import com.oracle.truffle.sl.runtime.*; /** * The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as @@ -32,7 +36,7 @@ * local variables. */ @NodeInfo(language = "Simple Language", description = "The abstract base node for all statements") -public abstract class SLStatementNode extends Node { +public abstract class SLStatementNode extends Node implements Instrumentable { public SLStatementNode(SourceSection src) { super(src); @@ -46,4 +50,20 @@ public SLStatementNode getNonWrapperNode() { return this; } + + @Override + public Probe probe(ExecutionContext context) { + Node parent = getParent(); + + if (parent == null) + throw new IllegalStateException("Cannot probe a node without a parent"); + + if (parent instanceof SLStatementWrapper) + return ((SLStatementWrapper) parent).getProbe(); + + SLStatementWrapper wrapper = new SLStatementWrapper((SLContext) context, this); + this.replace(wrapper); + wrapper.insertChild(); + return wrapper.getProbe(); + } } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java Tue Aug 19 19:25:44 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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.sl.nodes.instrument; - -import java.util.*; - -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.sl.nodes.*; - -/** - * SLASTProber contains the collection of {@link SLNodeProber}s and methods to attach the probers to - * nodes. - */ -public final class SLASTProber implements ASTProber, SLNodeProber { - - private ArrayList nodeProbers = new ArrayList<>(); - - public SLASTProber() { - } - - /** - * Adds a {@link SLNodeProber} to this SLASTProber. Probes must be of type {@link SLNodeProber} - * and must not already have been added. - * - * @param nodeProber the {@link SLNodeProber} to add. - */ - public void addNodeProber(ASTNodeProber nodeProber) { - if (nodeProber instanceof SLNodeProber) { - assert !nodeProbers.contains(nodeProber); - nodeProbers.add((SLNodeProber) nodeProber); - } else { - throw new IllegalArgumentException("invalid prober for SL implementation"); - } - } - - /** - * Unimplemented, does nothing. - */ - public Node probeAs(Node astNode, SyntaxTag tag, Object... args) { - return astNode; - } - - /** - * Attaches the current probers to the given {@link SLStatementNode} as a statement. - * - * @param node The {@link SLStatementNode} to attach the stored set of probers to. - */ - @Override - public SLStatementNode probeAsStatement(SLStatementNode node) { - SLStatementNode result = node; - for (SLNodeProber nodeProber : nodeProbers) { - result = nodeProber.probeAsStatement(result); - } - return result; - } - - /** - * Attaches the current probers to the given {@link SLExpressionNode} as a call. This will wrap - * the passed in node in an {@link SLExpressionWrapper}, tag it as a call and attach an - * instrument to it. - * - * @param node The {@link SLExpressionNode} to attach the stored set of probers to. - * @param callName The name of the call ??? - * - */ - @Override - public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) { - SLExpressionNode result = node; - for (SLNodeProber nodeProber : nodeProbers) { - result = nodeProber.probeAsCall(node, callName); - } - return result; - } - - /** - * Attaches the current probers to the given {@link SLExpressionNode} as an assignment. This - * will wrap the passed in node in an {@link SLExpressionWrapper}, tag it as an assignment and - * attach an instrument to it. - * - * @param node The {@link SLExpressionNode} to attached the stored set of probers to. - * @param localName The name of the assignment ??? - * - */ - @Override - public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) { - SLExpressionNode result = node; - for (SLNodeProber nodeProber : nodeProbers) { - result = nodeProber.probeAsLocalAssignment(result, localName); - } - return result; - } - - public ASTNodeProber getCombinedNodeProber() { - return nodeProbers.isEmpty() ? null : this; - } - -} diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Thu Aug 21 13:28:22 2014 -0700 @@ -46,11 +46,19 @@ private final Probe probe; + /** + * Constructor. + * + * @param context The current Simple execution context + * @param child The {@link SLExpressionNode} that this wrapper is wrapping + */ public SLExpressionWrapper(SLContext context, SLExpressionNode child) { super(child.getSourceSection()); assert !(child instanceof SLExpressionWrapper); - this.child = insert(child); this.probe = context.createProbe(child.getSourceSection()); + this.child = child; + // The child should only be inserted after a replace, so we defer inserting the child to the + // creator of the wrapper. } @Override @@ -145,4 +153,11 @@ public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame)); } + + /** + * Sets the parent pointer of this wrapper's child. + */ + public void insertChild() { + insert(this.child); + } } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java Thu Aug 21 13:28:22 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 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. + * + * 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.sl.nodes.instrument; + +import static com.oracle.truffle.api.instrument.StandardSyntaxTag.*; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.controlflow.*; +import com.oracle.truffle.sl.nodes.local.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * This is a general purpose visitor which traverses a completely parsed Simple AST and instruments + * all the nodes within it. This visitor is designed to visit the tree immediately after it has been + * parsed. + * + */ +public class SLInstrumenter implements NodeVisitor { + + private final SLContext context; + + public SLInstrumenter(SLContext context) { + this.context = context; + } + + /** + * Instruments and tags all relevant {@link SLStatementNode}s and {@link SLExpressionNode}s. + * Currently, only SLStatementNodes that are not SLExpressionNodes are tagged as statements. + */ + public boolean visit(Node node) { + // We have to distinguish between SLExpressionNode and SLStatementNode since some of the + // generated factories have methods that require SLExpressionNodes as parameters. Since + // SLExpressionNodes are a subclass of SLStatementNode, we check if something is an + // SLExpressionNode first. + if (node instanceof SLExpressionNode && node.getParent() != null) { + SLExpressionNode expressionNode = (SLExpressionNode) node; + Probe probe = expressionNode.probe(context); + // probe.tagAs(STATEMENT); + + if (node instanceof SLWriteLocalVariableNode) + probe.tagAs(ASSIGNMENT); + + } else if (node instanceof SLStatementNode && node.getParent() != null) { + + SLStatementNode statementNode = (SLStatementNode) node; + Probe probe = statementNode.probe(context); + probe.tagAs(STATEMENT); + + if (node instanceof SLWhileNode) + probe.tagAs(START_LOOP); + } + + return true; + } +} diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java Tue Aug 19 19:25:44 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * 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.sl.nodes.instrument; - -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.sl.nodes.*; - -public interface SLNodeProber extends ASTNodeProber { - - SLStatementNode probeAsStatement(SLStatementNode result); - - SLExpressionNode probeAsCall(SLExpressionNode node, String callName); - - SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName); -} diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Thu Aug 21 13:28:22 2014 -0700 @@ -48,8 +48,10 @@ public SLStatementWrapper(SLContext context, SLStatementNode child) { super(child.getSourceSection()); assert !(child instanceof SLStatementWrapper); - this.child = insert(child); this.probe = context.createProbe(child.getSourceSection()); + this.child = child; + // The child should only be inserted after a replace, so we defer inserting the child to the + // creator of the wrapper. } @Override @@ -94,6 +96,12 @@ probe.leaveExceptional(child, frame, e); throw (e); } + } + /** + * Sets the parent pointer of this wrapper's child. + */ + public void insertChild() { + insert(this.child); } } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Thu Aug 21 13:28:22 2014 -0700 @@ -33,7 +33,6 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -52,9 +51,9 @@ public final Errors errors; private final SLNodeFactory factory; -->declarations - public Parser(SLContext context, Source source, SLNodeProber astProber) { + public Parser(SLContext context, Source source) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source, astProber); + this.factory = new SLNodeFactory(context, source); errors = new Errors(); } @@ -135,8 +134,8 @@ -->initialization }; - public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { - Parser parser = new Parser(context, source, astProber); + public static void parseSL(SLContext context, Source source) { + Parser parser = new Parser(context, source); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Thu Aug 21 13:28:22 2014 -0700 @@ -30,7 +30,6 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -53,10 +52,10 @@ public final Scanner scanner; public final Errors errors; private final SLNodeFactory factory; - - public Parser(SLContext context, Source source, SLNodeProber astProber) { + + public Parser(SLContext context, Source source) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source, astProber); + this.factory = new SLNodeFactory(context, source); errors = new Errors(); } @@ -134,43 +133,43 @@ void Function() { Expect(4); Expect(1); - Token identifierToken = t; + Token identifierToken = t; Expect(5); - int bodyStartPos = t.charPos; - factory.startFunction(identifierToken, bodyStartPos); + int bodyStartPos = t.charPos; + factory.startFunction(identifierToken, bodyStartPos); if (la.kind == 1) { Get(); - factory.addFormalParameter(t); + factory.addFormalParameter(t); while (la.kind == 6) { Get(); Expect(1); - factory.addFormalParameter(t); + factory.addFormalParameter(t); } } Expect(7); SLStatementNode body = Block(false); - factory.finishFunction(body); + factory.finishFunction(body); } SLStatementNode Block(boolean inLoop) { SLStatementNode result; factory.startBlock(); - List body = new ArrayList<>(); + List body = new ArrayList<>(); Expect(8); - int start = t.charPos; + int start = t.charPos; while (StartOf(1)) { SLStatementNode s = Statement(inLoop); - body.add(s); + body.add(s); } Expect(9); - int length = (t.charPos + t.val.length()) - start; - result = factory.finishBlock(body, start, length); + int length = (t.charPos + t.val.length()) - start; + result = factory.finishBlock(body, start, length); return result; } SLStatementNode Statement(boolean inLoop) { SLStatementNode result; - result = null; + result = null; switch (la.kind) { case 13: { result = WhileStatement(); @@ -178,13 +177,13 @@ } case 10: { Get(); - if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } + if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } Expect(11); break; } case 12: { Get(); - if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } + if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } Expect(11); break; } @@ -209,29 +208,29 @@ SLStatementNode WhileStatement() { SLStatementNode result; Expect(13); - Token whileToken = t; + Token whileToken = t; Expect(5); SLExpressionNode condition = Expression(); Expect(7); SLStatementNode body = Block(true); - result = factory.createWhile(whileToken, condition, body); + result = factory.createWhile(whileToken, condition, body); return result; } SLStatementNode IfStatement(boolean inLoop) { SLStatementNode result; Expect(14); - Token ifToken = t; + Token ifToken = t; Expect(5); SLExpressionNode condition = Expression(); Expect(7); SLStatementNode thenPart = Block(inLoop); - SLStatementNode elsePart = null; + SLStatementNode elsePart = null; if (la.kind == 15) { Get(); elsePart = Block(inLoop); } - result = factory.createIf(ifToken, condition, thenPart, elsePart); + result = factory.createIf(ifToken, condition, thenPart, elsePart); return result; } @@ -239,11 +238,11 @@ SLStatementNode result; Expect(16); Token returnToken = t; - SLExpressionNode value = null; + SLExpressionNode value = null; if (StartOf(2)) { value = Expression(); } - result = factory.createReturn(returnToken, value); + result = factory.createReturn(returnToken, value); Expect(11); return result; } @@ -253,9 +252,9 @@ result = LogicTerm(); while (la.kind == 17) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicTerm(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -265,9 +264,9 @@ result = LogicFactor(); while (la.kind == 18) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicFactor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -302,9 +301,9 @@ break; } } - Token op = t; + Token op = t; SLExpressionNode right = Arithmetic(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -318,9 +317,9 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Term(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -334,56 +333,56 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Factor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } SLExpressionNode Factor() { SLExpressionNode result; - result = null; + result = null; if (la.kind == 1) { Get(); - Token nameToken = t; + Token nameToken = t; if (la.kind == 5) { Get(); List parameters = new ArrayList<>(); - SLExpressionNode parameter; + SLExpressionNode parameter; if (StartOf(2)) { parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); while (la.kind == 6) { Get(); parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); } } Expect(7); - Token finalToken = t; - result = factory.createCall(nameToken, parameters, finalToken); + Token finalToken = t; + result = factory.createCall(nameToken, parameters, finalToken); } else if (la.kind == 29) { Get(); SLExpressionNode value = Expression(); - result = factory.createAssignment(nameToken, value); + result = factory.createAssignment(nameToken, value); } else if (StartOf(4)) { - result = factory.createRead(nameToken); + result = factory.createRead(nameToken); } else SynErr(32); } else if (la.kind == 2) { Get(); - result = factory.createStringLiteral(t); + result = factory.createStringLiteral(t); } else if (la.kind == 3) { Get(); - result = factory.createNumericLiteral(t); + result = factory.createNumericLiteral(t); } else if (la.kind == 5) { Get(); - int start = t.charPos; + int start = t.charPos; result = Expression(); - SLExpressionNode expr = result; + SLExpressionNode expr = result; Expect(7); - int length = (t.charPos + t.val.length()) - start; - result = factory.createParenExpression(expr, start, length); + int length = (t.charPos + t.val.length()) - start; + result = factory.createParenExpression(expr, start, length); } else SynErr(33); return result; } @@ -408,8 +407,8 @@ }; - public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { - Parser parser = new Parser(context, source, astProber); + public static void parseSL(SLContext context, Source source) { + Parser parser = new Parser(context, source); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Thu Aug 21 13:28:22 2014 -0700 @@ -32,7 +32,6 @@ import com.oracle.truffle.sl.nodes.call.*; import com.oracle.truffle.sl.nodes.controlflow.*; import com.oracle.truffle.sl.nodes.expression.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.runtime.*; @@ -75,12 +74,9 @@ /* State while parsing a block. */ private LexicalScope lexicalScope; - private final SLNodeProber prober; - - public SLNodeFactory(SLContext context, Source source, SLNodeProber prober) { + public SLNodeFactory(SLContext context, Source source) { this.context = context; this.source = source; - this.prober = prober; } public void startFunction(Token nameToken, int bodyStartPos) { @@ -156,114 +152,69 @@ } /** - * Returns a {@link SLBreakNode} for the given token. This node will be instrumented, tagged as - * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was - * initialized in this class. ({@link #prober} != null) + * Returns an {@link SLBreakNode} for the given token. * - * @param breakToken The token containing the break node's info - * @return either: - *

    - *
  • An un-instrumented SLBreakNode if there is no prober
  • - *
  • An {@link SLStatementWrapper} instrumenting this node.
  • - *
+ * @param breakToken The token containing the break node's info. + * @return A SLBreakNode for the given token. */ public SLStatementNode createBreak(Token breakToken) { final SLBreakNode breakNode = new SLBreakNode(srcFromToken(breakToken)); - if (prober != null) { - return prober.probeAsStatement(breakNode); - } return breakNode; } /** - * Returns a {@link SLContinueNode} for the given token. This node will be instrumented, tagged - * as a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was - * initialized in this class. ({@link #prober} != null) + * Returns an {@link SLContinueNode} for the given token. * - * @param continueToken The token containing the continue node's info - * @return either: - *
    - *
  • An un-instrumented SLContinueNode if there is no prober
  • - *
  • An {@link SLStatementWrapper} instrumenting this node.
  • - *
+ * @param continueToken The token containing the continue node's info. + * @return A SLContinueNode built using the given token. */ public SLStatementNode createContinue(Token continueToken) { final SLContinueNode continueNode = new SLContinueNode(srcFromToken(continueToken)); - if (prober != null) { - return prober.probeAsStatement(continueNode); - } return continueNode; } /** - * Returns a {@link SLWhileNode} for the given token. This node will be instrumented, tagged as - * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was - * initialized in this class. ({@link #prober} != null) + * Returns an {@link SLWhileNode} for the given parameters. * * @param whileToken The token containing the while node's info * @param conditionNode The conditional node for this while loop * @param bodyNode The body of the while loop - * @return either: - *
    - *
  • An un-instrumented SLWhileNode if there is no prober
  • - *
  • An {@link SLStatementWrapper} instrumenting this node.
  • - *
+ * @return A SLWhileNode built using the given parameters. */ public SLStatementNode createWhile(Token whileToken, SLExpressionNode conditionNode, SLStatementNode bodyNode) { final int start = whileToken.charPos; final int end = bodyNode.getSourceSection().getCharEndIndex(); final SLWhileNode whileNode = new SLWhileNode(source.createSection(whileToken.val, start, end - start), conditionNode, bodyNode); - if (prober != null) { - return prober.probeAsStatement(whileNode); - } return whileNode; } /** - * Returns a {@link SLIfNode} for the given token. This node will be instrumented, tagged as a - * statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was - * initialized in this class. ({@link #prober} != null) + * Returns an {@link SLIfNode} for the given parameters. * * @param ifToken The token containing the if node's info * @param conditionNode The condition node of this if statement * @param thenPartNode The then part of the if * @param elsePartNode The else part of the if - * @return either: - *
    - *
  • An un-instrumented SLIfNode if there is no prober
  • - *
  • An {@link SLStatementWrapper} instrumenting this node.
  • - *
+ * @return An SLIfNode for the given parameters. */ public SLStatementNode createIf(Token ifToken, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { final int start = ifToken.charPos; final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex(); final SLIfNode ifNode = new SLIfNode(source.createSection(ifToken.val, start, end - start), conditionNode, thenPartNode, elsePartNode); - if (prober != null) { - return prober.probeAsStatement(ifNode); - } return ifNode; } /** - * Returns a {@link SLReturnNode} for the given token. This node will be instrumented, tagged as - * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was - * initialized in this class. ({@link #prober} != null) + * Returns an {@link SLReturnNode} for the given parameters. * * @param t The token containing the return node's info * @param valueNode The value of the return - * @return either: - *
    - *
  • An un-instrumented SLReturnNode if there is no prober
  • - *
  • An {@link SLStatementWrapper} instrumenting this node.
  • - *
+ * @return An SLReturnNode for the given parameters. */ public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) { final int start = t.charPos; final int length = valueNode == null ? t.val.length() : valueNode.getSourceSection().getCharEndIndex() - start; final SLReturnNode returnNode = new SLReturnNode(source.createSection(t.val, start, length), valueNode); - if (prober != null) { - return prober.probeAsStatement(returnNode); - } return returnNode; } @@ -274,7 +225,7 @@ * @param opToken The operator of the binary expression * @param leftNode The left node of the expression * @param rightNode The right node of the expression - * @return A subclass of SLExpressionNode for the operation given by opToken. + * @return A subclass of SLExpressionNode using the given parameters based on the given opToken. */ public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) { int start = leftNode.getSourceSection().getCharIndex(); @@ -311,54 +262,33 @@ } /** - * Returns a {@link SLInvokeNode} for the given token. This node will be instrumented, tagged as - * a call and wrapped in an {@link SLExpressionWrapper} if an {@link SLASTProber} was - * initialized in this class. ({@link #prober} != null) + * Returns an {@link SLInvokeNode} for the given parameters. * * @param nameToken The name of the function being called * @param parameterNodes The parameters of the function call * @param finalToken A token used to determine the end of the sourceSelection for this call - * @return either: - *
    - *
  • An un-instrumented SLInvokeNode if there is no prober
  • - *
  • An {@link SLExpressionWrapper} instrumenting this node.
  • - *
+ * @return An SLInvokeNode for the given parameters. */ public SLExpressionNode createCall(Token nameToken, List parameterNodes, Token finalToken) { final int startPos = nameToken.charPos; final int endPos = finalToken.charPos + finalToken.val.length(); final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos); SLExpressionNode functionNode = createRead(nameToken); - if (prober != null) { - SLExpressionNode wrappedNode = prober.probeAsCall(functionNode, nameToken.val); - return SLInvokeNode.create(src, wrappedNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); - } return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); } /** - * Returns a {@link SLWriteLocalVariableNode} for the given token. This node will be - * instrumented, tagged as an assignment and wrapped in an {@link SLExpressionWrapper} if an - * {@link SLASTProber} was initialized in this class. ({@link #prober} != null) + * Returns an {@link SLWriteLocalVariableNode} for the given parameters. * * @param nameToken The name of the variable being assigned * @param valueNode The value to be assigned - * @return either: - *
    - *
  • An un-instrumented SLWriteLocalVariableNode if there is no prober
  • - *
  • An {@link SLExpressionWrapper} instrumenting this node.
  • - *
+ * @return An SLExpressionNode for the given parameters. */ public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) { FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val); lexicalScope.locals.put(nameToken.val, frameSlot); final int start = nameToken.charPos; final int length = valueNode.getSourceSection().getCharEndIndex() - start; - if (prober != null) { - SLWriteLocalVariableNode writeNode = SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot); - final SLExpressionNode wrappedNode = prober.probeAsLocalAssignment(writeNode, nameToken.val); - return wrappedNode; - } return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot); } diff -r 7af9301efe6b -r 7661cc464239 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Tue Aug 19 19:25:44 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Thu Aug 21 13:28:22 2014 -0700 @@ -33,7 +33,6 @@ import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.builtins.*; import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.parser.*; @@ -52,7 +51,6 @@ private final PrintStream output; private final SLFunctionRegistry functionRegistry; private SourceCallback sourceCallback = null; - private SLASTProber astProber; public SLContext(BufferedReader input, PrintStream output) { this.input = input; @@ -154,7 +152,7 @@ sourceCallback.startLoading(source); } - Parser.parseSL(this, source, astProber); + Parser.parseSL(this, source); if (sourceCallback != null) { sourceCallback.endLoading(source); @@ -166,13 +164,4 @@ } main.getCallTarget().call(); } - - /** - * Sets the {@link SLASTProber} for the executeMain method. - * - * @param astProber The prober to use for adding instrumentation for this context. - */ - public void setASTNodeProber(SLASTProber astProber) { - this.astProber = astProber; - } }