Mercurial > hg > truffle
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); |