6666import com .oracle .truffle .api .instrumentation .ExecuteSourceListener ;
6767import com .oracle .truffle .api .instrumentation .ExecutionEventNode ;
6868import com .oracle .truffle .api .instrumentation .ExecutionEventNodeFactory ;
69+ import com .oracle .truffle .api .instrumentation .Instrumenter ;
6970import com .oracle .truffle .api .instrumentation .LoadSourceSectionEvent ;
7071import com .oracle .truffle .api .instrumentation .LoadSourceSectionListener ;
7172import com .oracle .truffle .api .instrumentation .SourceFilter ;
@@ -198,7 +199,7 @@ public enum Kind {
198199
199200 private final AtomicReference <EventBinding <?>> sourceBinding = new AtomicReference <>();
200201 private final List <EventBinding <? extends ExecutionEventNodeFactory >> execBindings = new ArrayList <>();
201- private LocationsInExecutedSources locationsInExecutedSources ;
202+ private volatile LocationsInExecutedSources locationsInExecutedSources ;
202203 private volatile boolean breakpointBindingReady ;
203204
204205 Breakpoint (BreakpointLocation key , SuspendAnchor suspendAnchor ) {
@@ -273,6 +274,7 @@ public boolean isEnabled() {
273274 */
274275 public void setEnabled (boolean enabled ) {
275276 boolean doInstall = false ;
277+ Debugger d ;
276278 synchronized (this ) {
277279 if (disposed ) {
278280 // cannot enable disposed breakpoints
@@ -284,10 +286,13 @@ public void setEnabled(boolean enabled) {
284286 }
285287 this .enabled = enabled ;
286288 }
289+ d = debugger ;
287290 }
288291 if (doInstall ) {
289292 if (enabled ) {
290- install ();
293+ if (d != null ) {
294+ installInstrumentation (d .getInstrumenter ());
295+ } // else when debugger == null, the breakpoint was disposed.
291296 } else {
292297 uninstall ();
293298 }
@@ -371,9 +376,9 @@ public void dispose() {
371376 DebuggerSession [] breakpointSessions = null ;
372377 Debugger breakpointDebugger = null ;
373378 LocationsInExecutedSources locations = null ;
379+ setEnabled (false );
374380 synchronized (this ) {
375381 if (!disposed ) {
376- setEnabled (false );
377382 breakpointSessions = sessions .toArray (new DebuggerSession [sessions .size ()]);
378383 breakpointDebugger = debugger ;
379384 debugger = null ;
@@ -511,6 +516,7 @@ synchronized void installGlobal(Debugger d) {
511516 }
512517
513518 private void install (Debugger d ) {
519+ assert d != null ;
514520 assert Thread .holdsLock (this );
515521 if (this .debugger != null && this .debugger != d ) {
516522 throw new IllegalStateException ("Breakpoint is already installed in a different Debugger instance." );
@@ -542,18 +548,19 @@ boolean install(DebuggerSession d, boolean failOnError) {
542548 install (d .getDebugger ());
543549 }
544550 if (enabled ) {
545- install ( );
551+ installInstrumentation ( d . getDebugger (). getInstrumenter () );
546552 }
547553 return true ;
548554 }
549555
550- private void install ( ) {
556+ private void installInstrumentation ( Instrumenter instrumenter ) {
551557 EventBinding <?> binding = sourceBinding .get ();
552558 if (binding == null || binding .isDisposed ()) {
553559 BreakpointLocation .LocationFilters filters = locationKey .createLocationFilters (suspendAnchor );
554560 if (locationKey .isLoadBindingNeeded ()) {
555- locationsInExecutedSources = new LocationsInExecutedSources ();
556- EventBinding <?> loadBinding = debugger .getInstrumenter ().createLoadSourceSectionBinding (filters .nearestFilter , filters .sectionFilter , locationsInExecutedSources , true );
561+ LocationsInExecutedSources locations = new LocationsInExecutedSources ();
562+ locationsInExecutedSources = locations ;
563+ EventBinding <?> loadBinding = instrumenter .createLoadSourceSectionBinding (filters .nearestFilter , filters .sectionFilter , locations , true );
557564 if (sourceBinding .compareAndSet (null , loadBinding )) {
558565 try {
559566 loadBinding .attach ();
@@ -569,7 +576,7 @@ private void install() {
569576 }
570577 if (needExecBinding ) {
571578 EventBinding <? extends ExecutionEventNodeFactory > execBinding ;
572- execBinding = debugger . getInstrumenter () .attachExecutionEventFactory (filters .nearestFilter , filters .sectionFilter , new BreakpointNodeFactory ());
579+ execBinding = instrumenter .attachExecutionEventFactory (filters .nearestFilter , filters .sectionFilter , new BreakpointNodeFactory ());
573580 execBindingAdded (execBinding );
574581 }
575582 }
@@ -591,6 +598,10 @@ public void onLoad(LoadSourceSectionEvent event) {
591598 boolean doAssign ;
592599 EventBinding <?> execBinding = null ;
593600 synchronized (this ) {
601+ if (debugger == null ) {
602+ // disposed
603+ return ;
604+ }
594605 if (!(doAssign = executedSources .contains (source ))) {
595606 SourceSection oldSection = loadedSections .put (source , section );
596607 if (oldSection == null ) {
0 commit comments