use of com.oracle.truffle.api.instrumentation.Tag in project graal by oracle.
the class PolyglotEngineDispatch method attachExecutionListener.
@Override
public ExecutionListener attachExecutionListener(Object engineReceiver, Consumer<ExecutionEvent> onEnter, Consumer<ExecutionEvent> onReturn, boolean expressions, boolean statements, boolean roots, Predicate<Source> sourceFilter, Predicate<String> rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions) {
PolyglotEngineImpl engine = (PolyglotEngineImpl) engineReceiver;
Instrumenter instrumenter = (Instrumenter) EngineAccessor.INSTRUMENT.getEngineInstrumenter(engine.instrumentationHandler);
List<Class<? extends Tag>> tags = new ArrayList<>();
if (expressions) {
tags.add(StandardTags.ExpressionTag.class);
}
if (statements) {
tags.add(StandardTags.StatementTag.class);
}
if (roots) {
tags.add(StandardTags.RootTag.class);
}
if (tags.isEmpty()) {
throw new IllegalArgumentException("No elements specified to listen to for execution listener. Need to specify at least one element kind: expressions, statements or roots.");
}
if (onReturn == null && onEnter == null) {
throw new IllegalArgumentException("At least one event consumer must be provided for onEnter or onReturn.");
}
SourceSectionFilter.Builder filterBuilder = SourceSectionFilter.newBuilder().tagIs(tags.toArray(new Class<?>[0]));
filterBuilder.includeInternal(false);
PolyglotExecutionListenerDispatch.ListenerImpl config = new PolyglotExecutionListenerDispatch.ListenerImpl(polyglot.getExecutionEventDispatch(), engine, onEnter, onReturn, collectInputValues, collectReturnValues, collectExceptions);
filterBuilder.sourceIs(new SourceSectionFilter.SourcePredicate() {
public boolean test(com.oracle.truffle.api.source.Source s) {
String language = s.getLanguage();
if (language == null) {
return false;
} else if (!engine.idToLanguage.containsKey(language)) {
return false;
} else if (sourceFilter != null) {
try {
return sourceFilter.test(PolyglotImpl.getOrCreatePolyglotSource(polyglot, s));
} catch (Throwable e) {
if (config.closing) {
// configuration is closing ignore errors.
return false;
}
throw engine.host.toHostException(null, e);
}
} else {
return true;
}
}
});
if (rootFilter != null) {
filterBuilder.rootNameIs(new Predicate<String>() {
public boolean test(String s) {
try {
return rootFilter.test(s);
} catch (Throwable e) {
if (config.closing) {
// configuration is closing ignore errors.
return false;
}
throw engine.host.toHostException(null, e);
}
}
});
}
SourceSectionFilter filter = filterBuilder.build();
EventBinding<?> binding;
try {
boolean mayNeedInputValues = config.collectInputValues && config.onReturn != null;
boolean mayNeedReturnValue = config.collectReturnValues && config.onReturn != null;
boolean mayNeedExceptions = config.collectExceptions;
if (mayNeedInputValues || mayNeedReturnValue || mayNeedExceptions) {
binding = instrumenter.attachExecutionEventFactory(filter, mayNeedInputValues ? filter : null, new ExecutionEventNodeFactory() {
public ExecutionEventNode create(EventContext context) {
return new PolyglotExecutionListenerDispatch.ProfilingNode(config, context);
}
});
} else {
// fast path no collection of additional profiles
binding = instrumenter.attachExecutionEventFactory(filter, null, new ExecutionEventNodeFactory() {
public ExecutionEventNode create(EventContext context) {
return new PolyglotExecutionListenerDispatch.DefaultNode(config, context);
}
});
}
} catch (Throwable t) {
throw PolyglotImpl.guestToHostException(engine, t);
}
config.binding = binding;
return polyglot.getManagement().newExecutionListener(polyglot.getExecutionListenerDispatch(), config);
}
use of com.oracle.truffle.api.instrumentation.Tag in project graal by oracle.
the class LanguageCache method getProvidedTags.
@SuppressWarnings("unchecked")
Set<? extends Class<? extends Tag>> getProvidedTags() {
Set<Class<? extends Tag>> res = providedTags;
if (res == null) {
ProvidedTags tags = provider.getClass().getAnnotation(ProvidedTags.class);
if (tags == null) {
res = Collections.emptySet();
} else {
res = new HashSet<>();
Collections.addAll(res, (Class<? extends Tag>[]) tags.value());
res = Collections.unmodifiableSet(res);
}
providedTags = res;
}
return res;
}
use of com.oracle.truffle.api.instrumentation.Tag in project graal by oracle.
the class InstrumentationTest method testNearestExecutionNode.
@Test
public void testNearestExecutionNode() throws IOException {
NearestExecutionNodeTester tester = new NearestExecutionNodeTester();
Source source = Source.create(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo1, ROOT(STATEMENT, VARIABLE(a, 10), STATEMENT, EXPRESSION))," + "DEFINE(foo2, ROOT(EXPRESSION, CALL(foo1), STATEMENT, STATEMENT(EXPRESSION))))");
tester.set(StandardTags.StatementTag.class, (offset, node) -> {
int pos = node.getSourceSection().getCharIndex();
if (offset <= 31) {
return pos == 23;
} else if (offset <= 75) {
return pos == 51;
} else if (offset <= 125) {
return pos == 117;
} else {
return pos == 128;
}
});
instrumentEnv.getInstrumenter().attachExecuteSourceListener(SourceFilter.ANY, new ExecuteSourceListener() {
@Override
public void onExecute(ExecuteSourceEvent event) {
int length = event.getSource().getLength();
instrumentEnv.getInstrumenter().attachLoadSourceSectionListener(SourceSectionFilter.ANY, new LoadSourceSectionListener() {
@Override
public void onLoad(LoadSourceSectionEvent evt) {
if (!(evt.getNode() instanceof InstrumentableNode)) {
return;
}
InstrumentableNode node = (InstrumentableNode) evt.getNode();
SourceSection ss = evt.getNode().getSourceSection();
if (ss == null || ss.getCharacters().toString().startsWith("ROOT(DEFINE")) {
// No SourceSection, or the outer function
return;
}
Class<? extends Tag> tag = tester.getTag();
Set<Class<? extends Tag>> tags = Collections.singleton(tag);
for (int offset = 0; offset < length; offset++) {
if (ss.getCharIndex() <= offset && offset < ss.getCharEndIndex()) {
Node nearestNode = node.findNearestNodeAt(offset, tags);
tester.checkNearest(offset, nearestNode);
}
}
}
}, true);
}
}, true);
run(source);
assertNull(tester.getFailures());
}
use of com.oracle.truffle.api.instrumentation.Tag in project graal by oracle.
the class InsightFilter method create.
static InsightFilter.Data create(AgentType at, Object[] arr) throws IllegalArgumentException, UnsupportedMessageException {
List<Class<? extends Tag>> allTags = new ArrayList<>();
String rootNameRegExp = null;
Object rootNameFn = null;
Object sourceFilterFn = null;
if (arr != null && arr.length > 2) {
Object config = arr[2];
final InteropLibrary iop = InteropLibrary.getFactory().getUncached();
Map<String, Object> map = new LinkedHashMap<>();
if (iop.hasHashEntries(config)) {
Object it = iop.getHashEntriesIterator(config);
while (iop.hasIteratorNextElement(it)) {
try {
Object keyAndValue = iop.getIteratorNextElement(it);
Object key;
Object value;
try {
key = iop.readArrayElement(keyAndValue, 0);
value = iop.readArrayElement(keyAndValue, 1);
} catch (InvalidArrayIndexException ex) {
throw CompilerDirectives.shouldNotReachHere(ex);
}
String type = iop.asString(key);
map.put(type, value);
} catch (StopIterationException ex) {
break;
}
}
} else {
Object allMembers = iop.getMembers(config, false);
long allMembersSize = iop.getArraySize(allMembers);
for (int i = 0; i < allMembersSize; i++) {
Object atI;
try {
atI = iop.readArrayElement(allMembers, i);
} catch (InvalidArrayIndexException ex) {
continue;
}
String type = iop.asString(atI);
Object value;
try {
value = iop.readMember(config, type);
} catch (UnknownIdentifierException ex) {
continue;
}
map.put(type, value);
}
}
for (Map.Entry<String, Object> entry : map.entrySet()) {
String type = entry.getKey();
switch(type) {
case "expressions":
if (isSet(iop, map, "expressions")) {
allTags.add(StandardTags.ExpressionTag.class);
}
break;
case "statements":
if (isSet(iop, map, "statements")) {
allTags.add(StandardTags.StatementTag.class);
}
break;
case "roots":
if (isSet(iop, map, "roots")) {
allTags.add(StandardTags.RootBodyTag.class);
}
break;
case "rootNameFilter":
{
Object fn = map.get("rootNameFilter");
if (fn != null && !iop.isNull(fn)) {
if (iop.isString(fn)) {
rootNameRegExp = iop.asString(fn);
} else {
if (!iop.isExecutable(fn)) {
throw new IllegalArgumentException("rootNameFilter should be a string, a regular expression!");
}
rootNameFn = fn;
}
}
break;
}
case "sourceFilter":
{
Object fn = map.get("sourceFilter");
if (fn != null && !iop.isNull(fn)) {
if (!iop.isExecutable(fn)) {
throw new IllegalArgumentException("sourceFilter has to be a function!");
}
sourceFilterFn = fn;
}
break;
}
default:
throw InsightException.unknownAttribute(type);
}
}
}
if (allTags.isEmpty()) {
throw new IllegalArgumentException("No elements specified to listen to for execution listener. Need to specify at least one element kind: expressions, statements or roots.");
}
allTags.sort((c1, c2) -> c1.getName().compareTo(c2.getName()));
InsightFilter filter = new InsightFilter(allTags, rootNameRegExp, rootNameFn != null, sourceFilterFn != null);
return new Data(at, filter, arr[1], rootNameFn, sourceFilterFn);
}
Aggregations