# HG changeset patch # User Jaroslav Tulach # Date 1446839689 -3600 # Node ID 56e71849d356cd689d72f49216e6716462f1c37f # Parent 536c5b85fe1da32a64c55bc9ac490f8d778339b9# Parent 7d9b7365b6757666cfc11ddf7c28d5ac33dc3171 Merging eval instrument with parameters diff -r 536c5b85fe1d -r 56e71849d356 truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java --- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java Fri Nov 06 09:16:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java Fri Nov 06 20:54:49 2015 +0100 @@ -99,7 +99,7 @@ final Source source42 = InstrumentationTestingLanguage.createConstantSource42("testEvalInstrumentListener"); final int[] evalResult = {0}; final int[] evalCount = {0}; - final Instrument instrument = instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, new EvalInstrumentListener() { + final Instrument instrument = instrumenter.attach(addNodeProbe[0], source42, new EvalInstrumentListener() { public void onExecution(Node node, VirtualFrame vFrame, Object result) { evalCount[0] = evalCount[0] + 1; @@ -112,7 +112,7 @@ fail("Eval test evaluates without exception"); } - }, "test EvalInstrument"); + }, "test EvalInstrument", null); assertEquals(vm.eval(source13).get(), 13); assertEquals(evalCount[0], 1); @@ -124,7 +124,7 @@ assertEquals(evalResult[0], 42); // Add new eval instrument with no listener, no effect on third execution - instrumenter.attach(addNodeProbe[0], InstrumentationTestingLanguage.class, source42, null, ""); + instrumenter.attach(addNodeProbe[0], source42, null, "", null); assertEquals(vm.eval(source13).get(), 13); assertEquals(evalCount[0], 3); assertEquals(evalResult[0], 42); diff -r 536c5b85fe1d -r 56e71849d356 truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java --- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java Fri Nov 06 09:16:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java Fri Nov 06 20:54:49 2015 +0100 @@ -818,7 +818,15 @@ return impl; } } - throw new IllegalStateException("Cannot find language " + languageClazz + " among " + langs); + return null; + } + + TruffleLanguage findLanguage(String mimeType) { + Language languageDescription = this.langs.get(mimeType); + if (languageDescription != null) { + return languageDescription.getImpl(true); + } + return null; } TruffleLanguage findLanguage(Probe probe) { @@ -919,9 +927,19 @@ } @Override - protected TruffleLanguage findLanguageImpl(Object obj, Class languageClazz) { + protected TruffleLanguage findLanguageImpl(Object obj, Class languageClazz, String mimeType) { final PolyglotEngine vm = (PolyglotEngine) obj; - return vm.findLanguage(languageClazz); + TruffleLanguage language = null; + if (languageClazz != null) { + language = vm.findLanguage(languageClazz); + } + if (language == null && mimeType != null) { + language = vm.findLanguage(mimeType); + } + if (language == null) { + throw new IllegalStateException("Cannot find language " + languageClazz + " with mimeType" + mimeType + " among " + vm.langs); + } + return language; } @Override diff -r 536c5b85fe1d -r 56e71849d356 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java Fri Nov 06 09:16:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java Fri Nov 06 20:54:49 2015 +0100 @@ -44,7 +44,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.Debugger.BreakpointCallback; import com.oracle.truffle.api.debug.Debugger.WarningLog; import com.oracle.truffle.api.frame.VirtualFrame; @@ -372,7 +371,6 @@ } } - @SuppressWarnings("rawtypes") private void attach(Probe newProbe) { if (getState() == DISPOSED) { throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME); @@ -382,8 +380,7 @@ if (conditionSource == null) { newInstrument = instrumenter.attach(newProbe, new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME); } else { - final Class languageClass = Debugger.ACCESSOR.findLanguage(newProbe); - newInstrument = instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME); + newInstrument = instrumenter.attach(newProbe, conditionSource, this, BREAKPOINT_NAME, null); } instruments.add(newInstrument); changeState(isEnabled ? ENABLED : DISABLED); diff -r 536c5b85fe1d -r 56e71849d356 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Fri Nov 06 09:16:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Fri Nov 06 20:54:49 2015 +0100 @@ -42,7 +42,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.Debugger.BreakpointCallback; import com.oracle.truffle.api.debug.Debugger.WarningLog; import com.oracle.truffle.api.frame.VirtualFrame; @@ -333,7 +332,6 @@ } } - @SuppressWarnings("rawtypes") private void attach(Probe newProbe) { if (getState() == DISPOSED) { throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME); @@ -343,8 +341,7 @@ if (conditionSource == null) { newInstrument = instrumenter.attach(newProbe, new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME); } else { - final Class languageClass = Debugger.ACCESSOR.findLanguage(newProbe); - instrumenter.attach(newProbe, languageClass, conditionSource, this, BREAKPOINT_NAME); + instrumenter.attach(newProbe, conditionSource, this, BREAKPOINT_NAME, null); } instruments.add(newInstrument); changeState(isEnabled ? ENABLED : DISABLED); diff -r 536c5b85fe1d -r 56e71849d356 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Fri Nov 06 09:16:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Fri Nov 06 20:54:49 2015 +0100 @@ -180,7 +180,7 @@ protected boolean isInstrumentable(Object vm, Node node) { final RootNode rootNode = node.getRootNode(); Class languageClazz = findLanguage(rootNode); - TruffleLanguage language = findLanguageImpl(vm, languageClazz); + TruffleLanguage language = findLanguageImpl(vm, languageClazz, null); return isInstrumentable(node, language); } @@ -195,7 +195,7 @@ protected WrapperNode createWrapperNode(Object vm, Node node) { final RootNode rootNode = node.getRootNode(); Class languageClazz = findLanguage(rootNode); - TruffleLanguage language = findLanguageImpl(vm, languageClazz); + TruffleLanguage language = findLanguageImpl(vm, languageClazz, null); return createWrapperNode(node, language); } @@ -231,7 +231,7 @@ } @SuppressWarnings("rawtypes") - protected TruffleLanguage findLanguageImpl(Object known, Class languageClass) { + protected TruffleLanguage findLanguageImpl(Object known, Class languageClass, String mimeType) { Object vm; if (known == null) { vm = CURRENT_VM.get(); @@ -241,7 +241,7 @@ } else { vm = known; } - return SPI.findLanguageImpl(vm, languageClass); + return SPI.findLanguageImpl(vm, languageClass, mimeType); } protected Instrumenter getInstrumenter(Object known) { @@ -334,7 +334,7 @@ @SuppressWarnings("rawtypes") protected CallTarget parse(Class languageClass, Source code, Node context, String... argumentNames) throws IOException { - final TruffleLanguage truffleLanguage = findLanguageImpl(null, languageClass); + final TruffleLanguage truffleLanguage = findLanguageImpl(null, languageClass, code.getMimeType()); return parse(truffleLanguage, code, context, argumentNames); } diff -r 536c5b85fe1d -r 56e71849d356 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Fri Nov 06 09:16:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Fri Nov 06 20:54:49 2015 +0100 @@ -46,6 +46,7 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; +import java.util.Map; /** * Client access to instrumentation services in a Truffle execution environment. @@ -478,11 +479,71 @@ * @param listener optional client callback for results/failure notification * @param instrumentInfo instrumentInfo optional documentation about the Instrument * @return a handle for access to the binding + * @deprecated */ + @Deprecated @SuppressWarnings("rawtypes") public ProbeInstrument attach(Probe probe, Class languageClass, Source source, EvalInstrumentListener listener, String instrumentInfo) { + return attach(probe, languageClass, source, listener, instrumentInfo, new String[0], new Object[0]); + } + + /** + * Attaches a fragment of source text that is to be evaluated just before execution + * enters the location of a {@link Probe}, creating a binding called an + * {@link ProbeInstrument}. The outcome of the evaluation is reported to an optional + * {@link EvalInstrumentListener listener}, but the outcome does not affect the flow of guest + * language execution, even if the evaluation produces an exception. + *

+ * The source text is assumed to be expressed in the language identified by its associated + * {@linkplain Source#getMimeType() MIME type}, if specified, otherwise by the language + * associated with the AST location associated with the {@link Probe}. + *

+ * The source text is parsed in the lexical context of the AST location associated with the + * {@link Probe}. + *

+ * The source text executes subject to full Truffle optimization. + * + * @param probe source of AST execution events, non-null + * @param source the source code to be evaluated, non-null and non-empty, preferably with + * {@link Source#withMimeType(java.lang.String) specified mime type} that determines + * the {@link TruffleLanguage} to use when processing the source + * @param listener optional client callback for results/failure notification + * @param instrumentInfo instrumentInfo optional documentation about the Instrument + * @param parameters keys are the parameter names to pass to + * {@link TruffleLanguage#parse(com.oracle.truffle.api.source.Source, com.oracle.truffle.api.nodes.Node, java.lang.String...) + * parse} method; values will be passed to + * {@link CallTarget#call(java.lang.Object...)} returned from the parse + * method; the value can be null + * @return a handle for access to the binding + */ + public ProbeInstrument attach(Probe probe, Source source, EvalInstrumentListener listener, String instrumentInfo, Map parameters) { + final int size = parameters == null ? 0 : parameters.size(); + String[] names = new String[size]; + Object[] params = new Object[size]; + if (parameters != null) { + int index = 0; + for (Map.Entry entry : parameters.entrySet()) { + names[index] = entry.getKey(); + params[index] = entry.getValue(); + index++; + } + } + return attach(probe, null, source, listener, instrumentInfo, names, params); + } + + @SuppressWarnings("rawtypes") + private ProbeInstrument attach(Probe probe, Class languageClass, Source source, EvalInstrumentListener listener, String instrumentInfo, String[] argumentNames, + Object[] parameters) { assert probe.getInstrumenter() == this; - final EvalInstrument instrument = new EvalInstrument(languageClass, source, listener, instrumentInfo); + Class foundLanguageClass = null; + if (languageClass == null) { + if (source.getMimeType() == null) { + foundLanguageClass = ACCESSOR.findLanguage(probe); + } + } else { + foundLanguageClass = languageClass; + } + final EvalInstrument instrument = new EvalInstrument(foundLanguageClass, source, listener, instrumentInfo, argumentNames, parameters); probe.attach(instrument); return instrument; } diff -r 536c5b85fe1d -r 56e71849d356 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Fri Nov 06 09:16:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Fri Nov 06 20:54:49 2015 +0100 @@ -54,10 +54,7 @@ * @see Instrumenter */ public abstract class ProbeInstrument extends Instrument { - - private static final String[] NO_ARGS = new String[0]; - - protected Probe probe = null; + Probe probe = null; /** *

Implementation Notes

@@ -345,13 +342,17 @@ @SuppressWarnings("rawtypes") private final Class languageClass; private final Source source; private final EvalInstrumentListener evalListener; + private final String[] names; + private final Object[] params; @SuppressWarnings("rawtypes") - EvalInstrument(Class languageClass, Source source, EvalInstrumentListener evalListener, String instrumentInfo) { + EvalInstrument(Class languageClass, Source source, EvalInstrumentListener evalListener, String instrumentInfo, String[] argumentNames, Object[] parameters) { super(instrumentInfo); this.languageClass = languageClass; this.source = source; this.evalListener = evalListener; + this.names = argumentNames; + this.params = parameters; } @Override @@ -392,7 +393,7 @@ public void enter(Node node, VirtualFrame vFrame) { if (callNode == null) { try { - final CallTarget callTarget = Instrumenter.ACCESSOR.parse(languageClass, source, node, NO_ARGS); + final CallTarget callTarget = Instrumenter.ACCESSOR.parse(languageClass, source, node, names); if (callTarget != null) { callNode = Truffle.getRuntime().createDirectCallNode(callTarget); callNode.forceInlining(); @@ -407,7 +408,7 @@ } if (callNode != null) { try { - final Object result = callNode.call(vFrame, NO_ARGS); + final Object result = callNode.call(vFrame, params); if (evalListener != null) { evalListener.onExecution(node, vFrame, result); }