# HG changeset patch # User Michael Van De Vanter # Date 1447357122 28800 # Node ID 07e5178604d46dd2da59c262fae0c25ebeb3a0fd # Parent 9a6f0c689576e8018c19e76a03abc351e6ce8168# Parent a647534602a6b70deb64b9d96c2798d7e36e1e0e Merge with a647534602a6b70deb64b9d96c2798d7e36e1e0e diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java --- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java Thu Nov 12 11:38:42 2015 -0800 @@ -65,6 +65,7 @@ return null; } + @Deprecated public ForeignAccess getForeignAccessFactory() { return ForeignAccess.create(new com.oracle.truffle.api.interop.ForeignAccess.Factory() { @@ -77,4 +78,13 @@ } }); } + + /** + * Create a {@link ForeignAccess} to access a specific {@link DynamicObject}. + * + * @param object the object to be accessed + */ + public ForeignAccess getForeignAccessFactory(DynamicObject object) { + return getForeignAccessFactory(); + } } diff -r 9a6f0c689576 -r 07e5178604d4 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 Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/EvalInstrumentTest.java Thu Nov 12 11:38:42 2015 -0800 @@ -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 9a6f0c689576 -r 07e5178604d4 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 Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java Thu Nov 12 11:38:42 2015 -0800 @@ -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 9a6f0c689576 -r 07e5178604d4 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 Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/LineBreakpointFactory.java Thu Nov 12 11:38:42 2015 -0800 @@ -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 9a6f0c689576 -r 07e5178604d4 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 Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/TagBreakpointFactory.java Thu Nov 12 11:38:42 2015 -0800 @@ -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 9a6f0c689576 -r 07e5178604d4 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 Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Thu Nov 12 11:38:42 2015 -0800 @@ -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 9a6f0c689576 -r 07e5178604d4 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 Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumenter.java Thu Nov 12 11:38:42 2015 -0800 @@ -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 9a6f0c689576 -r 07e5178604d4 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 Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeInstrument.java Thu Nov 12 11:38:42 2015 -0800 @@ -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); } diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Thu Nov 12 11:38:42 2015 -0800 @@ -59,6 +59,7 @@ public static final String GraphVisualizerAddress = "127.0.0.1"; public static final int GraphVisualizerPort = 4444; + private static final String DEFAULT_GRAPH_NAME = "truffle tree"; private Map nodeMap; private List edgeList; @@ -481,7 +482,7 @@ public GraphPrintVisitor visit(Object node) { if (openGraphCount == 0) { - beginGraph("truffle tree"); + beginGraph(DEFAULT_GRAPH_NAME); } // if node is visited once again, skip @@ -502,6 +503,10 @@ } public GraphPrintVisitor visit(Object node, GraphPrintHandler handler) { + if (openGraphCount == 0) { + beginGraph(DEFAULT_GRAPH_NAME); + } + handler.visit(node, new GraphPrintAdapter()); return this; diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java Thu Nov 12 11:38:42 2015 -0800 @@ -22,20 +22,74 @@ */ package com.oracle.truffle.object; -import com.oracle.truffle.object.debug.JSONShapeVisitor; +import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; +import java.nio.file.Paths; import java.util.Collection; +import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; +import com.oracle.truffle.api.nodes.GraphPrintVisitor; +import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.api.object.Property; +import com.oracle.truffle.object.debug.GraphvizShapeVisitor; +import com.oracle.truffle.object.debug.IGVShapeVisitor; +import com.oracle.truffle.object.debug.JSONShapeVisitor; +import com.oracle.truffle.object.debug.ShapeProfiler; + class Debug { private static Collection allShapes; - static void registerShape(ShapeImpl newShape) { + static void trackShape(ShapeImpl newShape) { allShapes.add(newShape); } + static void trackObject(DynamicObject obj) { + ShapeProfiler.getInstance().track(obj); + } + + static Iterable getAllShapes() { + return allShapes; + } + + static String dumpObject(DynamicObject object, int level, int levelStop) { + List properties = object.getShape().getPropertyListInternal(true); + StringBuilder sb = new StringBuilder(properties.size() * 10); + sb.append("{\n"); + for (Property property : properties) { + indent(sb, level + 1); + + sb.append(property.getKey()); + sb.append('[').append(property.getLocation()).append(']'); + Object value = property.get(object, false); + if (value instanceof DynamicObject) { + if (level < levelStop) { + value = dumpObject((DynamicObject) value, level + 1, levelStop); + } else { + value = value.toString(); + } + } + sb.append(": "); + sb.append(value); + if (property != properties.get(properties.size() - 1)) { + sb.append(","); + } + sb.append("\n"); + } + indent(sb, level); + sb.append("}"); + return sb.toString(); + } + + private static StringBuilder indent(StringBuilder sb, int level) { + for (int i = 0; i < level; i++) { + sb.append(' '); + } + return sb; + } + static { if (ObjectStorageOptions.DumpShapes) { allShapes = new ConcurrentLinkedQueue<>(); @@ -44,10 +98,36 @@ if (ObjectStorageOptions.DumpShapes) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { public void run() { - try (PrintWriter out = new PrintWriter("shapes.json", "UTF-8")) { + try { + if (ObjectStorageOptions.DumpShapesDOT) { + dumpDOT(); + } + if (ObjectStorageOptions.DumpShapesJSON) { + dumpJSON(); + } + if (ObjectStorageOptions.DumpShapesIGV) { + dumpIGV(); + } + } catch (FileNotFoundException | UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + private void dumpDOT() throws FileNotFoundException, UnsupportedEncodingException { + try (PrintWriter out = new PrintWriter(getOutputFile("dot"), "UTF-8")) { + GraphvizShapeVisitor visitor = new GraphvizShapeVisitor(); + for (ShapeImpl shape : getAllShapes()) { + shape.accept(visitor); + } + out.println(visitor); + } + } + + private void dumpJSON() throws FileNotFoundException, UnsupportedEncodingException { + try (PrintWriter out = new PrintWriter(getOutputFile("json"), "UTF-8")) { out.println("{\"shapes\": ["); boolean first = true; - for (ShapeImpl shape : allShapes) { + for (ShapeImpl shape : getAllShapes()) { if (!first) { out.println(","); } @@ -58,9 +138,37 @@ out.println(); } out.println("]}"); - } catch (FileNotFoundException | UnsupportedEncodingException e) { - throw new RuntimeException(e); + } + } + + private void dumpIGV() { + GraphPrintVisitor printer = new GraphPrintVisitor(); + printer.beginGroup("shapes"); + IGVShapeVisitor visitor = new IGVShapeVisitor(printer); + for (ShapeImpl shape : getAllShapes()) { + if (isRootShape(shape)) { + printer.beginGraph(DebugShapeVisitor.getId(shape)); + shape.accept(visitor); + printer.endGraph(); + } } + printer.beginGraph("all shapes"); + for (ShapeImpl shape : getAllShapes()) { + if (isRootShape(shape)) { + shape.accept(visitor); + } + } + printer.endGraph(); + printer.endGroup(); + printer.printToNetwork(false); + } + + private boolean isRootShape(ShapeImpl shape) { + return shape.getParent() == null; + } + + private File getOutputFile(String extension) { + return Paths.get(ObjectStorageOptions.DumpShapesPath, "shapes." + extension).toFile(); } })); } diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java Thu Nov 12 11:38:42 2015 -0800 @@ -29,8 +29,6 @@ import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.object.Locations.ValueLocation; -import com.oracle.truffle.object.debug.ShapeProfiler; -import java.util.List; public abstract class DynamicObjectImpl extends DynamicObject implements Cloneable { private ShapeImpl shape; @@ -43,7 +41,7 @@ setShape(shape); if (ObjectStorageOptions.Profile) { - trackObject(this); + Debug.trackObject(this); } } @@ -207,39 +205,7 @@ } public String debugDump(int level, int levelStop) { - List properties = this.getShape().getPropertyListInternal(true); - StringBuilder sb = new StringBuilder(properties.size() * 10); - sb.append("{\n"); - for (Property property : properties) { - indent(sb, level + 1); - - sb.append(property.getKey()); - sb.append('[').append(property.getLocation()).append(']'); - Object value = property.get(this, false); - if (value instanceof DynamicObjectImpl) { - if (level < levelStop) { - value = ((DynamicObjectImpl) value).debugDump(level + 1, levelStop); - } else { - value = value.toString(); - } - } - sb.append(": "); - sb.append(value); - if (property != properties.get(properties.size() - 1)) { - sb.append(","); - } - sb.append("\n"); - } - indent(sb, level); - sb.append("}"); - return sb.toString(); - } - - private static StringBuilder indent(StringBuilder sb, int level) { - for (int i = 0; i < level; i++) { - sb.append(' '); - } - return sb; + return Debug.dumpObject(this, level, levelStop); } @Override @@ -333,10 +299,6 @@ return getShape().getLayout().getStrategy().updateShape(this); } - private static void trackObject(DynamicObject obj) { - ShapeProfiler.getInstance().track(obj); - } - @Override public final DynamicObject copy(Shape currentShape) { return cloneWithShape(currentShape); @@ -344,6 +306,6 @@ @Override public ForeignAccess getForeignAccess() { - return getShape().getForeignAccessFactory(); + return getShape().getForeignAccessFactory(this); } } diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java Thu Nov 12 11:38:42 2015 -0800 @@ -40,7 +40,11 @@ // Debug options (should be final) public static final boolean DebugCounters = booleanOption(OPTION_PREFIX + "DebugCounters", true); public static final boolean TraceReshape = booleanOption(OPTION_PREFIX + "TraceReshape", false); - public static final boolean DumpShapes = booleanOption(OPTION_PREFIX + "DumpShapes", false); + public static final boolean DumpShapesDOT = booleanOption(OPTION_PREFIX + "DumpShapesDOT", false); + public static final boolean DumpShapesJSON = booleanOption(OPTION_PREFIX + "DumpShapesJSON", false); + public static final boolean DumpShapesIGV = booleanOption(OPTION_PREFIX + "DumpShapesIGV", false); + public static final boolean DumpShapes = DumpShapesDOT || DumpShapesJSON || DumpShapesIGV; + public static final String DumpShapesPath = System.getProperty(OPTION_PREFIX + "DumpShapesPath", ""); public static final boolean Profile = booleanOption(OPTION_PREFIX + "Profile", false); public static final int ProfileTopResults = Integer.getInteger(OPTION_PREFIX + "ProfileTopResults", -1); diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Thu Nov 12 11:38:42 2015 -0800 @@ -154,7 +154,9 @@ this.extraData = objectType.createShapeData(this); shapeCount.inc(); - debugRegisterShape(this); + if (ObjectStorageOptions.DumpShapes) { + Debug.trackShape(this); + } } protected ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) { @@ -1126,12 +1128,6 @@ } } - private static void debugRegisterShape(ShapeImpl newShape) { - if (ObjectStorageOptions.DumpShapes) { - Debug.registerShape(newShape); - } - } - /** * Match all filter. */ @@ -1152,7 +1148,7 @@ private static final DebugCounter shapeCacheHitCount = DebugCounter.create("Shape cache hits"); private static final DebugCounter shapeCacheMissCount = DebugCounter.create("Shape cache misses"); - public ForeignAccess getForeignAccessFactory() { - return getObjectType().getForeignAccessFactory(); + public ForeignAccess getForeignAccessFactory(DynamicObject object) { + return getObjectType().getForeignAccessFactory(object); } } diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java --- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java Thu Nov 12 11:38:42 2015 -0800 @@ -42,7 +42,7 @@ @Override public GraphvizShapeVisitor visitShape(Shape shape, Map transitions) { if (!drawn.add(shape)) { - return null; + return this; } String prefix = "s"; diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/IGVShapeVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/IGVShapeVisitor.java Thu Nov 12 11:38:42 2015 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 2015, 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.object.debug; + +import java.util.Map; +import java.util.Map.Entry; + +import com.oracle.truffle.api.nodes.GraphPrintVisitor; +import com.oracle.truffle.api.nodes.GraphPrintVisitor.GraphPrintAdapter; +import com.oracle.truffle.api.nodes.GraphPrintVisitor.GraphPrintHandler; +import com.oracle.truffle.api.object.Shape; +import com.oracle.truffle.object.DebugShapeVisitor; +import com.oracle.truffle.object.ShapeImpl; +import com.oracle.truffle.object.Transition; + +public class IGVShapeVisitor extends DebugShapeVisitor { + private final GraphPrintVisitor graphPrinter; + + public IGVShapeVisitor(GraphPrintVisitor printer) { + this.graphPrinter = printer; + } + + @Override + public IGVShapeVisitor visitShape(final Shape shape, final Map transitions) { + graphPrinter.visit(shape, new GraphPrintHandler() { + public void visit(Object node, GraphPrintAdapter printer) { + if (!printer.visited(node)) { + Shape s = (Shape) node; + printer.createElementForNode(s); + String name = s.getLastProperty() == null ? "ROOT" : s.getLastProperty().toString(); + printer.setNodeProperty(s, "name", name); + printer.setNodeProperty(s, "valid", s.isValid()); + printer.setNodeProperty(s, "identityHashCode", Integer.toHexString(System.identityHashCode(s))); + printer.setNodeProperty(s, "objectType", s.getObjectType()); + + for (Entry entry : transitions.entrySet()) { + Shape dst = entry.getValue(); + ((ShapeImpl) dst).accept(IGVShapeVisitor.this); + assert printer.visited(dst); + printer.connectNodes(s, dst, entry.getKey().getShortName()); + } + } + } + }); + + return this; + } +} diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Thu Nov 12 11:38:42 2015 -0800 @@ -50,6 +50,7 @@ import java.util.List; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; @@ -185,7 +186,7 @@ */ /* - * + * *

Tools:
The use of some of Truffle's support for developer tools (based on the * Truffle {@linkplain Instrumenter Instrumentation Framework}) are demonstrated in this file, for * example:

  • a {@linkplain NodeExecCounter counter for node executions}, tabulated by node @@ -419,6 +420,7 @@ failed[0] = e; } return new CallTarget() { + @TruffleBoundary @Override public Object call(Object... arguments) { if (failed[0] instanceof RuntimeException) { diff -r 9a6f0c689576 -r 07e5178604d4 truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java Thu Nov 12 11:35:19 2015 -0800 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLObjectType.java Thu Nov 12 11:38:42 2015 -0800 @@ -60,7 +60,7 @@ } @Override - public ForeignAccess getForeignAccessFactory() { + public ForeignAccess getForeignAccessFactory(DynamicObject obj) { return access; }