Skip to content

Commit

Permalink
[GR-18794] Using FrameLibrary to access Frame values effectively.
Browse files Browse the repository at this point in the history
PullRequest: graal/5615
  • Loading branch information
Jaroslav Tulach committed Mar 16, 2020
2 parents a044f5c + cfe72f6 commit 689dc19
Show file tree
Hide file tree
Showing 9 changed files with 461 additions and 62 deletions.
1 change: 1 addition & 0 deletions tools/ci.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ toolsGateLite : ${toolsCommon} {
run : [
["mx", "build" ],
["mx", "unittest", "--verbose" ]
["mx", "sigtest" ]
]
}

Expand Down
1 change: 1 addition & 0 deletions tools/mx.tools/mx_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ def _tools_gate_runner(args, tasks):
dependencies=['Truffle'],
truffle_jars=['tools:AGENTSCRIPT'],
support_distributions=['tools:AGENTSCRIPT_GRAALVM_SUPPORT'],
priority=10,
include_by_default=True,
))

Expand Down
2 changes: 1 addition & 1 deletion tools/mx.tools/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@
},
"AGENTSCRIPT_GRAALVM_SUPPORT" : {
"native" : True,
"description" : "Script driven tracing and instrumentation Agentfor the GraalVM",
"description" : "Script driven tracing and instrumentation Agent for the GraalVM",
"layout" : {
"native-image.properties" : "file:mx.tools/tools-agentscript.properties",
},
Expand Down
136 changes: 136 additions & 0 deletions tools/src/com.oracle.truffle.tools.agentscript/snapshot.sigtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#Signature file v4.1
#Version

CLSS public abstract interface !annotation com.oracle.truffle.api.library.GenerateLibrary
anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[TYPE])
innr public abstract interface static !annotation Abstract
innr public abstract interface static !annotation DefaultExport
intf java.lang.annotation.Annotation
meth public abstract !hasdefault boolean defaultExportLookupEnabled()
meth public abstract !hasdefault boolean dynamicDispatchEnabled()
meth public abstract !hasdefault java.lang.Class<? extends com.oracle.truffle.api.library.Library> assertions()
meth public abstract !hasdefault java.lang.Class<?> receiverType()

CLSS public abstract interface static !annotation com.oracle.truffle.api.library.GenerateLibrary$DefaultExport
outer com.oracle.truffle.api.library.GenerateLibrary
anno 0 java.lang.annotation.Repeatable(java.lang.Class<? extends java.lang.annotation.Annotation> value=class com.oracle.truffle.api.library.GenerateLibrary$DefaultExport$Repeat)
anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=CLASS)
anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[TYPE])
innr public abstract interface static !annotation Repeat
intf java.lang.annotation.Annotation
meth public abstract java.lang.Class<?> value()

CLSS public abstract com.oracle.truffle.api.library.Library
cons protected init()
meth public abstract boolean accepts(java.lang.Object)
supr com.oracle.truffle.api.nodes.Node

CLSS public abstract com.oracle.truffle.api.nodes.Node
cons protected init()
innr public abstract interface static !annotation Child
innr public abstract interface static !annotation Children
intf com.oracle.truffle.api.nodes.NodeInterface
intf java.lang.Cloneable
meth protected final <%0 extends com.oracle.truffle.api.TruffleLanguage> com.oracle.truffle.api.TruffleLanguage$LanguageReference<{%%0}> lookupLanguageReference(java.lang.Class<{%%0}>)
meth protected final <%0 extends com.oracle.truffle.api.nodes.Node> {%%0} insert({%%0})
meth protected final <%0 extends com.oracle.truffle.api.nodes.Node> {%%0}[] insert({%%0}[])
meth protected final <%0 extends java.lang.Object, %1 extends com.oracle.truffle.api.TruffleLanguage<{%%0}>> com.oracle.truffle.api.TruffleLanguage$ContextReference<{%%0}> lookupContextReference(java.lang.Class<{%%1}>)
meth protected final java.util.concurrent.locks.Lock getLock()
meth protected final void notifyInserted(com.oracle.truffle.api.nodes.Node)
meth protected final void reportPolymorphicSpecialize()
meth protected void onReplace(com.oracle.truffle.api.nodes.Node,java.lang.CharSequence)
meth public boolean isAdoptable()
meth public com.oracle.truffle.api.nodes.Node copy()
meth public com.oracle.truffle.api.nodes.Node deepCopy()
meth public com.oracle.truffle.api.nodes.NodeCost getCost()
meth public com.oracle.truffle.api.source.SourceSection getEncapsulatingSourceSection()
meth public com.oracle.truffle.api.source.SourceSection getSourceSection()
meth public final <%0 extends com.oracle.truffle.api.nodes.Node> {%%0} replace({%%0})
meth public final <%0 extends com.oracle.truffle.api.nodes.Node> {%%0} replace({%%0},java.lang.CharSequence)
meth public final <%0 extends java.lang.Object> {%%0} atomic(java.util.concurrent.Callable<{%%0}>)
meth public final boolean isSafelyReplaceableBy(com.oracle.truffle.api.nodes.Node)
meth public final com.oracle.truffle.api.nodes.Node getParent()
meth public final com.oracle.truffle.api.nodes.RootNode getRootNode()
meth public final java.lang.Iterable<com.oracle.truffle.api.nodes.Node> getChildren()
meth public final void accept(com.oracle.truffle.api.nodes.NodeVisitor)
meth public final void adoptChildren()
meth public final void atomic(java.lang.Runnable)
meth public java.lang.String getDescription()
meth public java.lang.String toString()
meth public java.util.Map<java.lang.String,java.lang.Object> getDebugProperties()
supr java.lang.Object
hfds GIL_LOCK,UNCACHED_CONTEXT_REFERENCES,UNCACHED_LANGUAGE_REFERENCES,parent

CLSS public abstract interface com.oracle.truffle.api.nodes.NodeInterface

CLSS public abstract interface com.oracle.truffle.tools.agentscript.AgentScript
fld public final static java.lang.String ID = "agentscript"
fld public final static java.lang.String VERSION = "0.4"
meth public void registerAgentScript(com.oracle.truffle.api.source.Source)

CLSS public abstract com.oracle.truffle.tools.agentscript.FrameLibrary
cons public init()
innr public final static Query
meth public java.lang.Object readMember(com.oracle.truffle.tools.agentscript.FrameLibrary$Query,java.lang.String) throws com.oracle.truffle.api.interop.UnknownIdentifierException
meth public static com.oracle.truffle.tools.agentscript.FrameLibrary getUncached()
meth public void collectNames(com.oracle.truffle.tools.agentscript.FrameLibrary$Query,java.util.Set<java.lang.String>) throws com.oracle.truffle.api.interop.InteropException
supr com.oracle.truffle.api.library.Library
hcls UncachedDefault

CLSS public final static com.oracle.truffle.tools.agentscript.FrameLibrary$Query
outer com.oracle.truffle.tools.agentscript.FrameLibrary
meth public com.oracle.truffle.api.frame.Frame frame()
meth public java.lang.Iterable<com.oracle.truffle.api.Scope> findLocalScopes()
supr java.lang.Object
hfds env,frame,where

CLSS public abstract interface java.lang.Cloneable

CLSS public java.lang.Object
cons public init()
meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
meth protected void finalize() throws java.lang.Throwable
meth public boolean equals(java.lang.Object)
meth public final java.lang.Class<?> getClass()
meth public final void notify()
meth public final void notifyAll()
meth public final void wait() throws java.lang.InterruptedException
meth public final void wait(long) throws java.lang.InterruptedException
meth public final void wait(long,int) throws java.lang.InterruptedException
meth public int hashCode()
meth public java.lang.String toString()

CLSS public abstract interface java.lang.annotation.Annotation
meth public abstract boolean equals(java.lang.Object)
meth public abstract int hashCode()
meth public abstract java.lang.Class<? extends java.lang.annotation.Annotation> annotationType()
meth public abstract java.lang.String toString()

CLSS public abstract interface !annotation java.lang.annotation.Documented
anno 0 java.lang.annotation.Documented()
anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
intf java.lang.annotation.Annotation

CLSS public abstract interface !annotation java.lang.annotation.Repeatable
anno 0 java.lang.annotation.Documented()
anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
intf java.lang.annotation.Annotation
meth public abstract java.lang.Class<? extends java.lang.annotation.Annotation> value()

CLSS public abstract interface !annotation java.lang.annotation.Retention
anno 0 java.lang.annotation.Documented()
anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
intf java.lang.annotation.Annotation
meth public abstract java.lang.annotation.RetentionPolicy value()

CLSS public abstract interface !annotation java.lang.annotation.Target
anno 0 java.lang.annotation.Documented()
anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
intf java.lang.annotation.Annotation
meth public abstract java.lang.annotation.ElementType[] value()

Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* Copyright (c) 2020, 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.tools.agentscript;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Scope;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
import com.oracle.truffle.api.interop.InteropException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnknownIdentifierException;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.GenerateLibrary;
import com.oracle.truffle.api.library.Library;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.tools.agentscript.impl.AccessorFrameLibrary;
import com.oracle.truffle.tools.agentscript.impl.DefaultFrameLibrary;
import java.util.Set;

/**
* Encapsulating access to execution frames.
* <a href="https://github.com/oracle/graal/blob/master/tools/docs/T-Trace.md">T-Trace</a> scripts
* can access local variables of the dynamically <a href=
* "https://github.com/oracle/graal/blob/master/tools/docs/T-Trace-Manual.md#inspecting-values">
* instrumented source code</a>. This library handles such accesses. {@linkplain ExportLibrary
* Implement your own} to respond to various messages (like
* {@link #readMember(com.oracle.truffle.tools.agentscript.FrameLibrary.Query, java.lang.String) })
* in a different way - for example by exposing more than it is in their {@linkplain Frame frames}
* for some specific languages.
* <p>
* It is expected more messages appear in this library during its evolution. Such messages will be
* provided with their appropriate {@link #getUncached() default} implementation.
*
* @since 20.1
*/
@GenerateLibrary(defaultExportLookupEnabled = true)
@GenerateLibrary.DefaultExport(DefaultFrameLibrary.class)
public abstract class FrameLibrary extends Library {
/**
* Default constructor.
*
* @since 20.1
*/
protected FrameLibrary() {
}

/**
* Default implementation of the {@code FrameLibrary}. Provides the same view of local variables
* as available to debugger.
*
* @return a shared instance of the library
* @since 20.1
*/
public static FrameLibrary getUncached() {
return UncachedDefault.DEFAULT;
}

/**
* Reads a value of a local variable.
*
* @param env location, environment, etc. to read values from
* @param member the name of the variable to read
* @return value of the variable
* @throws UnknownIdentifierException thrown when the member is unknown
* @since 20.1
*/
public Object readMember(
Query env,
String member) throws UnknownIdentifierException {
return getUncached().readMember(env, member);
}

/**
* Collect names of local variables.
*
* @param env location, environment, etc. to read values from
* @param names collection to add the names to
* @throws InteropException thrown when something goes wrong
* @since 20.1
*/
public void collectNames(
Query env,
Set<String> names) throws InteropException {
getUncached().collectNames(env, names);
}

/**
* Holds location, environment, etc. Used to provide necessary information for implementation of
* individual {@link FrameLibrary} messages like
* {@link FrameLibrary#collectNames(com.oracle.truffle.tools.agentscript.FrameLibrary.Query, java.util.Set)}
* and co.
*
* @since 20.1
*/
public final class Query {
private final Node where;
private final Frame frame;
private final TruffleInstrument.Env env;

Query(Node where, Frame frame, TruffleInstrument.Env env) {
this.where = where;
this.frame = frame;
this.env = env;
}

/**
* Access to current and enclosing {@link Scope}.
*
* @return iterable providing access to the frames.
* @since 20.1
*/
public Iterable<Scope> findLocalScopes() {
return env.findLocalScopes(where, frame);
}

/**
* Currently active frame to read values from.
*
* @return the currently active frame
* @since 20.1
*/
public Frame frame() {
return frame;
}
}

static {
AccessorFrameLibrary accessor = new AccessorFrameLibrary() {
@Override
protected Query create(Node where, Frame frame, TruffleInstrument.Env env) {
return UncachedDefault.DEFAULT.new Query(where, frame, env);
}
};
assert AccessorFrameLibrary.DEFAULT == accessor;
}

private static final class UncachedDefault extends FrameLibrary {
static final FrameLibrary DEFAULT = new UncachedDefault();

private UncachedDefault() {
}

@CompilerDirectives.TruffleBoundary
@Override
public Object readMember(Query env, String member) throws UnknownIdentifierException {
InteropLibrary iop = InteropLibrary.getFactory().getUncached();
for (Scope scope : env.findLocalScopes()) {
if (scope == null) {
continue;
}
if (member.equals(scope.getReceiverName())) {
return scope.getReceiver();
}
Object variable = readMemberImpl(member, scope.getVariables(), iop);
if (variable != null) {
return variable;
}
Object argument = readMemberImpl(member, scope.getArguments(), iop);
if (argument != null) {
return argument;
}
}
throw UnknownIdentifierException.create(member);
}

@CompilerDirectives.TruffleBoundary
@Override
public void collectNames(Query env, Set<String> names) throws InteropException {
InteropLibrary iop = InteropLibrary.getFactory().getUncached();
for (Scope scope : env.findLocalScopes()) {
if (scope == null) {
continue;
}
final String receiverName = scope.getReceiverName();
if (receiverName != null) {
names.add(receiverName);
}
readMemberNames(names, scope.getVariables(), iop);
readMemberNames(names, scope.getArguments(), iop);
}
}

@Override
public boolean accepts(Object receiver) {
return receiver instanceof Query;
}

static Object readMemberImpl(String name, Object map, InteropLibrary iop) {
if (map != null && iop.hasMembers(map)) {
try {
return iop.readMember(map, name);
} catch (InteropException e) {
return null;
}
}
return null;
}

static void readMemberNames(Set<String> names, Object map, InteropLibrary iop) throws InteropException {
if (map != null && iop.hasMembers(map)) {
Object members = iop.getMembers(map);
long size = iop.getArraySize(members);
for (long i = 0; i < size; i++) {
Object at = iop.readArrayElement(members, i);
if (at instanceof String) {
names.add((String) at);
}
}
}
}
}
}
Loading

0 comments on commit 689dc19

Please sign in to comment.