forked from oracle/graal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GR-18794] Using FrameLibrary to access Frame values effectively.
PullRequest: graal/5615
- Loading branch information
Showing
9 changed files
with
461 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 136 additions & 0 deletions
136
tools/src/com.oracle.truffle.tools.agentscript/snapshot.sigtest
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
|
234 changes: 234 additions & 0 deletions
234
...acle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/FrameLibrary.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.