comparison truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java @ 22219:1c0f490984d5

Merge with f47b601edbc626dcfe8b3636933b4834c89f7779
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Wed, 16 Sep 2015 15:36:22 -0700
parents dc83cc1f94f2 3aad794eec0e
children c9681cd54d90
comparison
equal deleted inserted replaced
22160:0599e2df6a9f 22219:1c0f490984d5
22 * or visit www.oracle.com if you need additional information or have any 22 * or visit www.oracle.com if you need additional information or have any
23 * questions. 23 * questions.
24 */ 24 */
25 package com.oracle.truffle.api.debug; 25 package com.oracle.truffle.api.debug;
26 26
27 import java.io.Closeable;
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.List;
33
27 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 34 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
28 import com.oracle.truffle.api.Truffle; 35 import com.oracle.truffle.api.Truffle;
29 import com.oracle.truffle.api.TruffleLanguage; 36 import com.oracle.truffle.api.TruffleLanguage;
30 import com.oracle.truffle.api.frame.FrameInstance; 37 import com.oracle.truffle.api.frame.FrameInstance;
31 import com.oracle.truffle.api.frame.FrameInstanceVisitor; 38 import com.oracle.truffle.api.frame.FrameInstanceVisitor;
33 import com.oracle.truffle.api.impl.Accessor; 40 import com.oracle.truffle.api.impl.Accessor;
34 import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener; 41 import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
35 import com.oracle.truffle.api.instrument.AdvancedInstrumentRoot; 42 import com.oracle.truffle.api.instrument.AdvancedInstrumentRoot;
36 import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory; 43 import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
37 import com.oracle.truffle.api.instrument.Instrument; 44 import com.oracle.truffle.api.instrument.Instrument;
45 import com.oracle.truffle.api.instrument.Instrumenter;
38 import com.oracle.truffle.api.instrument.KillException; 46 import com.oracle.truffle.api.instrument.KillException;
39 import com.oracle.truffle.api.instrument.Probe; 47 import com.oracle.truffle.api.instrument.Probe;
40 import com.oracle.truffle.api.instrument.StandardSyntaxTag; 48 import com.oracle.truffle.api.instrument.StandardSyntaxTag;
41 import com.oracle.truffle.api.instrument.SyntaxTag; 49 import com.oracle.truffle.api.instrument.SyntaxTag;
42 import com.oracle.truffle.api.instrument.SyntaxTagTrap; 50 import com.oracle.truffle.api.instrument.SyntaxTagTrap;
43 import com.oracle.truffle.api.nodes.Node; 51 import com.oracle.truffle.api.nodes.Node;
44 import com.oracle.truffle.api.source.LineLocation; 52 import com.oracle.truffle.api.source.LineLocation;
45 import com.oracle.truffle.api.source.Source; 53 import com.oracle.truffle.api.source.Source;
46 import java.io.Closeable;
47 import java.io.IOException;
48 import java.io.PrintStream;
49 import java.util.ArrayList;
50 import java.util.Collection;
51 import java.util.List;
52 54
53 /** 55 /**
54 * Represents debugging related state of a {@link com.oracle.truffle.api.vm.TruffleVM}. Instance of 56 * Represents debugging related state of a {@link com.oracle.truffle.api.vm.TruffleVM}. Instance of
55 * this class is delivered via {@link SuspendedEvent#getDebugger()} and 57 * this class is delivered via {@link SuspendedEvent#getDebugger()} and
56 * {@link ExecutionEvent#getDebugger()} events, once {@link com.oracle.truffle.api.debug debugging 58 * {@link ExecutionEvent#getDebugger()} events, once {@link com.oracle.truffle.api.debug debugging
58 */ 60 */
59 @SuppressWarnings("javadoc") 61 @SuppressWarnings("javadoc")
60 public final class Debugger { 62 public final class Debugger {
61 63
62 private static final boolean TRACE = false; 64 private static final boolean TRACE = false;
63 private static final String TRACE_PREFIX = "DEBUG ENGINE: "; 65 private static final String TRACE_PREFIX = "Debugger: ";
64 66
65 private static final PrintStream OUT = System.out; 67 private static final PrintStream OUT = System.out;
66 68
67 private static final SyntaxTag STEPPING_TAG = StandardSyntaxTag.STATEMENT; 69 private static final SyntaxTag STEPPING_TAG = StandardSyntaxTag.STATEMENT;
68 private static final SyntaxTag CALL_TAG = StandardSyntaxTag.CALL; 70 private static final SyntaxTag CALL_TAG = StandardSyntaxTag.CALL;
71 if (TRACE) { 73 if (TRACE) {
72 OUT.println(TRACE_PREFIX + String.format(format, args)); 74 OUT.println(TRACE_PREFIX + String.format(format, args));
73 } 75 }
74 } 76 }
75 77
78 private final Instrumenter instrumenter;
76 private final Object vm; 79 private final Object vm;
77 private Source lastSource; 80 private Source lastSource;
78 81
79 interface BreakpointCallback { 82 interface BreakpointCallback {
80 83
90 * Logs a warning that is kept until the start of the next execution. 93 * Logs a warning that is kept until the start of the next execution.
91 */ 94 */
92 void addWarning(String warning); 95 void addWarning(String warning);
93 } 96 }
94 97
98 private final BreakpointCallback breakpointCallback;
99 private final WarningLog warningLog;
100
95 /** 101 /**
96 * Implementation of line-oriented breakpoints. 102 * Implementation of line-oriented breakpoints.
97 */ 103 */
98 private final LineBreakpointFactory lineBreaks; 104 private final LineBreakpointFactory lineBreaks;
99 105
105 /** 111 /**
106 * Head of the stack of executions. 112 * Head of the stack of executions.
107 */ 113 */
108 private DebugExecutionContext debugContext; 114 private DebugExecutionContext debugContext;
109 115
110 Debugger(Object vm) { 116 Debugger(Object vm, Instrumenter instrumenter) {
111 this.vm = vm; 117 this.vm = vm;
112 118 this.instrumenter = instrumenter;
113 Source.setFileCaching(true); 119 Source.setFileCaching(true);
114 120
115 // Initialize execution context stack 121 // Initialize execution context stack
116 debugContext = new DebugExecutionContext(null, null); 122 debugContext = new DebugExecutionContext(null, null);
117 prepareContinue(); 123 prepareContinue();
118 debugContext.contextTrace("START EXEC DEFAULT"); 124 debugContext.contextTrace("START EXEC DEFAULT");
119 125
120 final BreakpointCallback breakpointCallback = new BreakpointCallback() { 126 breakpointCallback = new BreakpointCallback() {
121 127
122 @TruffleBoundary 128 @TruffleBoundary
123 public void haltedAt(Node astNode, MaterializedFrame mFrame, String haltReason) { 129 public void haltedAt(Node astNode, MaterializedFrame mFrame, String haltReason) {
124 debugContext.halt(astNode, mFrame, true, haltReason); 130 debugContext.halt(astNode, mFrame, true, haltReason);
125 } 131 }
126 }; 132 };
127 133
128 final WarningLog warningLog = new WarningLog() { 134 warningLog = new WarningLog() {
129 135
130 public void addWarning(String warning) { 136 public void addWarning(String warning) {
131 assert debugContext != null; 137 assert debugContext != null;
132 debugContext.logWarning(warning); 138 debugContext.logWarning(warning);
133 } 139 }
134 }; 140 };
135 141
136 this.lineBreaks = new LineBreakpointFactory(this, breakpointCallback, warningLog); 142 this.lineBreaks = new LineBreakpointFactory(this, breakpointCallback, warningLog);
137 this.tagBreaks = new TagBreakpointFactory(this, breakpointCallback, warningLog); 143 this.tagBreaks = new TagBreakpointFactory(this, breakpointCallback, warningLog);
138 }
139
140 Object vm() {
141 return vm;
142 } 144 }
143 145
144 /** 146 /**
145 * Sets a breakpoint to halt at a source line. 147 * Sets a breakpoint to halt at a source line.
146 * 148 *
267 throw new IllegalArgumentException(); 269 throw new IllegalArgumentException();
268 } 270 }
269 debugContext.setStrategy(new StepOver(stepCount)); 271 debugContext.setStrategy(new StepOver(stepCount));
270 } 272 }
271 273
274 // TODO (mlvdv) used by the breakpoint factories; to be deprecated/replaced.
272 /** 275 /**
273 * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot} 276 * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
274 * that, when executed, computes the result of a textual expression in the language; used to 277 * that, when executed, computes the result of a textual expression in the language; used to
275 * create an 278 * create an
276 * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String) 279 * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
282 * @throws IOException if the factory cannot be created, for example if the expression is badly 285 * @throws IOException if the factory cannot be created, for example if the expression is badly
283 * formed. 286 * formed.
284 */ 287 */
285 @SuppressWarnings("rawtypes") 288 @SuppressWarnings("rawtypes")
286 AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Probe probe, String expr, AdvancedInstrumentResultListener resultListener) throws IOException { 289 AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Probe probe, String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
287 try { 290 Class<? extends TruffleLanguage> languageClass = ACCESSOR.findLanguage(probe);
288 Class<? extends TruffleLanguage> langugageClass = ACCESSOR.findLanguage(probe); 291 return ACCESSOR.createAdvancedInstrumentRootFactory(vm, languageClass, expr, resultListener);
289 TruffleLanguage.Env env = ACCESSOR.findLanguage(vm, langugageClass); 292 }
290 TruffleLanguage<?> l = ACCESSOR.findLanguage(env); 293
291 DebugSupportProvider dsp = ACCESSOR.getDebugSupport(l); 294 Instrumenter getInstrumenter() {
292 return dsp.createAdvancedInstrumentRootFactory(expr, resultListener); 295 return instrumenter;
293 } catch (DebugSupportException ex) {
294 throw new IOException(ex);
295 }
296 } 296 }
297 297
298 /** 298 /**
299 * A mode of user navigation from a current code location to another, e.g "step in" vs. 299 * A mode of user navigation from a current code location to another, e.g "step in" vs.
300 * "step over". 300 * "step over".
414 this.unfinishedStepCount = stepCount; 414 this.unfinishedStepCount = stepCount;
415 } 415 }
416 416
417 @Override 417 @Override
418 protected void setStrategy(final int stackDepth) { 418 protected void setStrategy(final int stackDepth) {
419 Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) { 419 instrumenter.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
420 @TruffleBoundary 420 @TruffleBoundary
421 @Override 421 @Override
422 public void tagTrappedAt(Node node, MaterializedFrame mFrame) { 422 public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
423 // HALT: just before statement 423 // HALT: just before statement
424 --unfinishedStepCount; 424 --unfinishedStepCount;
428 halt(node, mFrame, true); 428 halt(node, mFrame, true);
429 } 429 }
430 strategyTrace("RESUME BEFORE", ""); 430 strategyTrace("RESUME BEFORE", "");
431 } 431 }
432 }); 432 });
433 Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) { 433 instrumenter.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
434 @TruffleBoundary 434 @TruffleBoundary
435 @Override 435 @Override
436 public void tagTrappedAt(Node node, MaterializedFrame mFrame) { 436 public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
437 --unfinishedStepCount; 437 --unfinishedStepCount;
438 strategyTrace(null, "TRAP AFTER unfinished steps=%d", unfinishedStepCount); 438 strategyTrace(null, "TRAP AFTER unfinished steps=%d", unfinishedStepCount);
447 }); 447 });
448 } 448 }
449 449
450 @Override 450 @Override
451 protected void unsetStrategy() { 451 protected void unsetStrategy() {
452 Probe.setBeforeTagTrap(null); 452 instrumenter.setBeforeTagTrap(null);
453 Probe.setAfterTagTrap(null); 453 instrumenter.setAfterTagTrap(null);
454 } 454 }
455 } 455 }
456 456
457 /** 457 /**
458 * Strategy: execution to nearest enclosing call site. 458 * Strategy: execution to nearest enclosing call site.
471 */ 471 */
472 private final class StepOut extends StepStrategy { 472 private final class StepOut extends StepStrategy {
473 473
474 @Override 474 @Override
475 protected void setStrategy(final int stackDepth) { 475 protected void setStrategy(final int stackDepth) {
476 Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) { 476 instrumenter.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
477 477
478 @TruffleBoundary 478 @TruffleBoundary
479 @Override 479 @Override
480 public void tagTrappedAt(Node node, MaterializedFrame mFrame) { 480 public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
481 // HALT: 481 // HALT:
489 }); 489 });
490 } 490 }
491 491
492 @Override 492 @Override
493 protected void unsetStrategy() { 493 protected void unsetStrategy() {
494 Probe.setAfterTagTrap(null); 494 instrumenter.setAfterTagTrap(null);
495 } 495 }
496 } 496 }
497 497
498 /** 498 /**
499 * Strategy: per-statement stepping, so long as not nested in method calls (i.e. at original 499 * Strategy: per-statement stepping, so long as not nested in method calls (i.e. at original
515 this.unfinishedStepCount = stepCount; 515 this.unfinishedStepCount = stepCount;
516 } 516 }
517 517
518 @Override 518 @Override
519 protected void setStrategy(final int stackDepth) { 519 protected void setStrategy(final int stackDepth) {
520 Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) { 520 instrumenter.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
521 @TruffleBoundary 521 @TruffleBoundary
522 @Override 522 @Override
523 public void tagTrappedAt(Node node, MaterializedFrame mFrame) { 523 public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
524 final int currentStackDepth = currentStackDepth(); 524 final int currentStackDepth = currentStackDepth();
525 if (currentStackDepth <= stackDepth) { 525 if (currentStackDepth <= stackDepth) {
540 } 540 }
541 strategyTrace("RESUME BEFORE", ""); 541 strategyTrace("RESUME BEFORE", "");
542 } 542 }
543 }); 543 });
544 544
545 Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) { 545 instrumenter.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
546 @TruffleBoundary 546 @TruffleBoundary
547 @Override 547 @Override
548 public void tagTrappedAt(Node node, MaterializedFrame mFrame) { 548 public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
549 final int currentStackDepth = currentStackDepth(); 549 final int currentStackDepth = currentStackDepth();
550 if (currentStackDepth < stackDepth) { 550 if (currentStackDepth < stackDepth) {
561 }); 561 });
562 } 562 }
563 563
564 @Override 564 @Override
565 protected void unsetStrategy() { 565 protected void unsetStrategy() {
566 Probe.setBeforeTagTrap(null); 566 instrumenter.setBeforeTagTrap(null);
567 Probe.setAfterTagTrap(null); 567 instrumenter.setAfterTagTrap(null);
568 } 568 }
569 } 569 }
570 570
571 /** 571 /**
572 * Strategy: per-statement stepping, not into method calls, in effect while at increased stack 572 * Strategy: per-statement stepping, not into method calls, in effect while at increased stack
590 this.startStackDepth = startStackDepth; 590 this.startStackDepth = startStackDepth;
591 } 591 }
592 592
593 @Override 593 @Override
594 protected void setStrategy(final int stackDepth) { 594 protected void setStrategy(final int stackDepth) {
595 Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) { 595 instrumenter.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
596 @TruffleBoundary 596 @TruffleBoundary
597 @Override 597 @Override
598 public void tagTrappedAt(Node node, MaterializedFrame mFrame) { 598 public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
599 final int currentStackDepth = currentStackDepth(); 599 final int currentStackDepth = currentStackDepth();
600 if (currentStackDepth <= startStackDepth) { 600 if (currentStackDepth <= startStackDepth) {
611 }); 611 });
612 } 612 }
613 613
614 @Override 614 @Override
615 protected void unsetStrategy() { 615 protected void unsetStrategy() {
616 Probe.setBeforeTagTrap(null); 616 instrumenter.setBeforeTagTrap(null);
617 } 617 }
618 } 618 }
619 619
620 /** 620 /**
621 * Information and debugging state for a single Truffle execution (which make take place over 621 * Information and debugging state for a single Truffle execution (which make take place over
811 private static final class AccessorDebug extends Accessor { 811 private static final class AccessorDebug extends Accessor {
812 @Override 812 @Override
813 protected Closeable executionStart(Object vm, Debugger[] fillIn, Source s) { 813 protected Closeable executionStart(Object vm, Debugger[] fillIn, Source s) {
814 final Debugger d; 814 final Debugger d;
815 if (fillIn[0] == null) { 815 if (fillIn[0] == null) {
816 d = fillIn[0] = new Debugger(vm); 816 final Instrumenter instrumenter = ACCESSOR.getInstrumenter(vm);
817 d = fillIn[0] = new Debugger(vm, instrumenter);
817 } else { 818 } else {
818 d = fillIn[0]; 819 d = fillIn[0];
819 } 820 }
820 d.executionStarted(s); 821 d.executionStarted(s);
821 return new Closeable() { 822 return new Closeable() {
840 protected TruffleLanguage<?> findLanguage(TruffleLanguage.Env env) { 841 protected TruffleLanguage<?> findLanguage(TruffleLanguage.Env env) {
841 return super.findLanguage(env); 842 return super.findLanguage(env);
842 } 843 }
843 844
844 @Override 845 @Override
845 protected DebugSupportProvider getDebugSupport(TruffleLanguage<?> l) { 846 protected Instrumenter getInstrumenter(Object vm) {
846 return super.getDebugSupport(l); 847 return super.getInstrumenter(vm);
848 }
849
850 @Override
851 protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Object vm, Class<? extends TruffleLanguage> languageClass, String expr,
852 AdvancedInstrumentResultListener resultListener) throws IOException {
853 return super.createAdvancedInstrumentRootFactory(vm, languageClass, expr, resultListener);
847 } 854 }
848 855
849 @Override 856 @Override
850 protected void dispatchEvent(Object vm, Object event) { 857 protected void dispatchEvent(Object vm, Object event) {
851 super.dispatchEvent(vm, event); 858 super.dispatchEvent(vm, event);