0
# Instrumentation and Debugging
1
2
Truffle's instrumentation framework provides comprehensive debugging, profiling, and tooling infrastructure for language development and runtime analysis. It enables dynamic attachment of execution listeners, breakpoints, and profiling tools without modifying language implementations.
3
4
## Capabilities
5
6
### Instrument Implementation
7
8
Core framework for implementing debugging and profiling tools.
9
10
```java { .api }
11
/**
12
* Base class for implementing Truffle instruments
13
*/
14
public abstract class TruffleInstrument {
15
16
/**
17
* Called when instrument is created
18
* @param env Instrument environment
19
*/
20
protected abstract void onCreate(Env env);
21
22
/**
23
* Called when instrument is finalized
24
* @param env Instrument environment
25
*/
26
protected void onFinalize(Env env) {
27
// Default implementation
28
}
29
30
/**
31
* Called when instrument is disposed
32
* @param env Instrument environment
33
*/
34
protected void onDispose(Env env) {
35
// Default implementation
36
}
37
38
/**
39
* Instrument registration annotation
40
*/
41
@Retention(RetentionPolicy.RUNTIME)
42
@Target(ElementType.TYPE)
43
public @interface Registration {
44
45
/**
46
* Instrument identifier
47
* @return Instrument ID
48
*/
49
String id();
50
51
/**
52
* Instrument name
53
* @return Display name
54
*/
55
String name();
56
57
/**
58
* Instrument version
59
* @return Version string
60
*/
61
String version() default "";
62
63
/**
64
* Whether instrument is internal
65
* @return true if internal
66
*/
67
boolean internal() default false;
68
69
/**
70
* Services provided by instrument
71
* @return Array of service classes
72
*/
73
Class<?>[] services() default {};
74
}
75
76
/**
77
* Instrument environment providing access to instrumentation services
78
*/
79
public static final class Env {
80
81
/**
82
* Get instrumenter for attaching listeners
83
* @return Instrumenter instance
84
*/
85
public Instrumenter getInstrumenter();
86
87
/**
88
* Get logger for this instrument
89
* @param loggerName Logger name
90
* @return TruffleLogger instance
91
*/
92
public TruffleLogger getLogger(String loggerName);
93
94
/**
95
* Register service for other instruments/languages
96
* @param service Service object
97
*/
98
public void registerService(Object service);
99
100
/**
101
* Look up service from other instruments/languages
102
* @param type Service type
103
* @return Service instance or null
104
*/
105
public <T> T lookup(Class<T> type);
106
107
/**
108
* Get instrument options
109
* @return OptionValues instance
110
*/
111
public OptionValues getOptions();
112
113
/**
114
* Get input stream for instrument
115
* @return InputStream
116
*/
117
public InputStream in();
118
119
/**
120
* Get output stream for instrument
121
* @return OutputStream
122
*/
123
public OutputStream out();
124
125
/**
126
* Get error stream for instrument
127
* @return OutputStream
128
*/
129
public OutputStream err();
130
}
131
}
132
```
133
134
**Usage Example:**
135
136
```java
137
@TruffleInstrument.Registration(
138
id = "myProfiler",
139
name = "My Profiler",
140
version = "1.0"
141
)
142
public class MyProfiler extends TruffleInstrument {
143
144
@Override
145
protected void onCreate(Env env) {
146
Instrumenter instrumenter = env.getInstrumenter();
147
148
// Attach execution listener to all source sections
149
instrumenter.attachExecutionEventListener(
150
SourceSectionFilter.ANY,
151
new ExecutionEventListener() {
152
@Override
153
public void onEnter(EventContext context, VirtualFrame frame) {
154
// Record entry time
155
recordEntry(context.getInstrumentedSourceSection());
156
}
157
158
@Override
159
public void onReturnValue(EventContext context, VirtualFrame frame, Object result) {
160
// Record exit time and result
161
recordExit(context.getInstrumentedSourceSection(), result);
162
}
163
}
164
);
165
}
166
167
private void recordEntry(SourceSection section) {
168
// Profiling logic
169
}
170
171
private void recordExit(SourceSection section, Object result) {
172
// Profiling logic
173
}
174
}
175
```
176
177
### Execution Event System
178
179
Framework for monitoring and intercepting AST node execution.
180
181
```java { .api }
182
/**
183
* Main interface for attaching execution listeners and instruments
184
*/
185
public abstract class Instrumenter {
186
187
/**
188
* Attach execution event listener
189
* @param filter Filter for source sections to instrument
190
* @param listener Execution event listener
191
* @return Event binding for management
192
*/
193
public abstract EventBinding<ExecutionEventListener> attachExecutionEventListener(
194
SourceSectionFilter filter, ExecutionEventListener listener);
195
196
/**
197
* Attach execution event factory
198
* @param filter Filter for source sections to instrument
199
* @param factory Factory for creating event nodes
200
* @return Event binding for management
201
*/
202
public abstract <T extends ExecutionEventNodeFactory> EventBinding<T> attachExecutionEventFactory(
203
SourceSectionFilter filter, T factory);
204
205
/**
206
* Attach load source listener
207
* @param filter Filter for sources to monitor
208
* @param listener Source load listener
209
* @param includeExistingSources Whether to notify for existing sources
210
* @return Event binding for management
211
*/
212
public abstract EventBinding<LoadSourceListener> attachLoadSourceListener(
213
SourceFilter filter, LoadSourceListener listener, boolean includeExistingSources);
214
215
/**
216
* Attach load source section listener
217
* @param filter Filter for source sections to monitor
218
* @param listener Source section load listener
219
* @param includeExistingSections Whether to notify for existing sections
220
* @return Event binding for management
221
*/
222
public abstract EventBinding<LoadSourceSectionListener> attachLoadSourceSectionListener(
223
SourceSectionFilter filter, LoadSourceSectionListener listener, boolean includeExistingSections);
224
225
/**
226
* Get allocation reporter for memory tracking
227
* @return AllocationReporter instance
228
*/
229
public abstract AllocationReporter getAllocationReporter();
230
231
/**
232
* Visit loaded source sections
233
* @param filter Filter for sections to visit
234
* @param visitor Section visitor
235
*/
236
public abstract void visitLoadedSourceSections(SourceSectionFilter filter, LoadSourceSectionListener visitor);
237
}
238
239
/**
240
* Listener interface for execution events
241
*/
242
public interface ExecutionEventListener {
243
244
/**
245
* Called when entering instrumented node
246
* @param context Event context
247
* @param frame Execution frame
248
*/
249
default void onEnter(EventContext context, VirtualFrame frame) {
250
// Default implementation
251
}
252
253
/**
254
* Called when exiting with return value
255
* @param context Event context
256
* @param frame Execution frame
257
* @param result Return value
258
*/
259
default void onReturnValue(EventContext context, VirtualFrame frame, Object result) {
260
// Default implementation
261
}
262
263
/**
264
* Called when exiting with exception
265
* @param context Event context
266
* @param frame Execution frame
267
* @param exception Exception thrown
268
*/
269
default void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
270
// Default implementation
271
}
272
}
273
274
/**
275
* Factory interface for creating execution event nodes
276
*/
277
public interface ExecutionEventNodeFactory {
278
279
/**
280
* Create execution event node
281
* @param context Event context
282
* @return ExecutionEventNode instance
283
*/
284
ExecutionEventNode create(EventContext context);
285
}
286
287
/**
288
* Base class for execution event nodes
289
*/
290
public abstract class ExecutionEventNode extends Node {
291
292
/**
293
* Called when entering instrumented node
294
* @param frame Execution frame
295
*/
296
protected void onEnter(VirtualFrame frame) {
297
// Default implementation
298
}
299
300
/**
301
* Called when exiting with return value
302
* @param frame Execution frame
303
* @param result Return value
304
*/
305
protected void onReturnValue(VirtualFrame frame, Object result) {
306
// Default implementation
307
}
308
309
/**
310
* Called when exiting with exception
311
* @param frame Execution frame
312
* @param exception Exception thrown
313
*/
314
protected void onReturnExceptional(VirtualFrame frame, Throwable exception) {
315
// Default implementation
316
}
317
318
/**
319
* Called when node is disposed
320
*/
321
protected void onDispose(VirtualFrame frame) {
322
// Default implementation
323
}
324
325
/**
326
* Get event context
327
* @return EventContext instance
328
*/
329
protected final EventContext getEventContext() {
330
// Implementation details
331
return null;
332
}
333
}
334
335
/**
336
* Context information for execution events
337
*/
338
public abstract class EventContext {
339
340
/**
341
* Get instrumented source section
342
* @return SourceSection instance
343
*/
344
public abstract SourceSection getInstrumentedSourceSection();
345
346
/**
347
* Get instrumented node
348
* @return Node instance
349
*/
350
public abstract Node getInstrumentedNode();
351
352
/**
353
* Check if node has tag
354
* @param tag Tag class to check
355
* @return true if node has tag
356
*/
357
public abstract boolean hasTag(Class<? extends Tag> tag);
358
359
/**
360
* Get node object for debugging
361
* @param frame Execution frame
362
* @return Debug node object
363
*/
364
public abstract Object getNodeObject(VirtualFrame frame);
365
366
/**
367
* Create unwind throwable for non-local control flow
368
* @param info Unwind information
369
* @return Unwind throwable
370
*/
371
public abstract RuntimeException createUnwind(Object info);
372
373
/**
374
* Create error throwable
375
* @param exception Exception to wrap
376
* @return Error throwable
377
*/
378
public abstract RuntimeException createError(RuntimeException exception);
379
}
380
```
381
382
### Source Filtering System
383
384
Comprehensive filtering system for targeting specific source code regions for instrumentation.
385
386
```java { .api }
387
/**
388
* Filter for selecting source sections to instrument
389
*/
390
public final class SourceSectionFilter {
391
392
/**
393
* Filter matching any source section
394
*/
395
public static final SourceSectionFilter ANY = newBuilder().build();
396
397
/**
398
* Create new filter builder
399
* @return Builder instance
400
*/
401
public static Builder newBuilder() {
402
return new Builder();
403
}
404
405
/**
406
* Builder for creating source section filters
407
*/
408
public static final class Builder {
409
410
/**
411
* Filter by tag classes
412
* @param tags Tag classes to match
413
* @return Builder instance
414
*/
415
public Builder tagIs(Class<?>... tags) {
416
return this;
417
}
418
419
/**
420
* Filter by tag classes (any match)
421
* @param tags Tag classes to match
422
* @return Builder instance
423
*/
424
public Builder tagIsOneOf(Class<?>... tags) {
425
return this;
426
}
427
428
/**
429
* Filter by source sections
430
* @param sections Source sections to match
431
* @return Builder instance
432
*/
433
public Builder sourceSectionEquals(SourceSection... sections) {
434
return this;
435
}
436
437
/**
438
* Filter by line range
439
* @param startLine Start line (inclusive)
440
* @param endLine End line (inclusive)
441
* @return Builder instance
442
*/
443
public Builder lineIn(int startLine, int endLine) {
444
return this;
445
}
446
447
/**
448
* Filter by specific line
449
* @param line Line number
450
* @return Builder instance
451
*/
452
public Builder lineIs(int line) {
453
return this;
454
}
455
456
/**
457
* Filter by column range
458
* @param startColumn Start column (inclusive)
459
* @param endColumn End column (inclusive)
460
* @return Builder instance
461
*/
462
public Builder columnIn(int startColumn, int endColumn) {
463
return this;
464
}
465
466
/**
467
* Filter by MIME type
468
* @param mimeTypes MIME types to match
469
* @return Builder instance
470
*/
471
public Builder mimeTypeIs(String... mimeTypes) {
472
return this;
473
}
474
475
/**
476
* Filter by source name pattern
477
* @param namePattern Name pattern (regex)
478
* @return Builder instance
479
*/
480
public Builder sourceIs(String namePattern) {
481
return this;
482
}
483
484
/**
485
* Filter by root name pattern
486
* @param namePattern Root name pattern (regex)
487
* @return Builder instance
488
*/
489
public Builder rootNameIs(String namePattern) {
490
return this;
491
}
492
493
/**
494
* Include internal sources
495
* @return Builder instance
496
*/
497
public Builder includeInternal(boolean includeInternal) {
498
return this;
499
}
500
501
/**
502
* Build the filter
503
* @return SourceSectionFilter instance
504
*/
505
public SourceSectionFilter build() {
506
return new SourceSectionFilter();
507
}
508
}
509
}
510
511
/**
512
* Filter for selecting sources to monitor
513
*/
514
public final class SourceFilter {
515
516
/**
517
* Filter matching any source
518
*/
519
public static final SourceFilter ANY = newBuilder().build();
520
521
/**
522
* Create new filter builder
523
* @return Builder instance
524
*/
525
public static Builder newBuilder() {
526
return new Builder();
527
}
528
529
/**
530
* Builder for creating source filters
531
*/
532
public static final class Builder {
533
534
/**
535
* Filter by MIME type
536
* @param mimeTypes MIME types to match
537
* @return Builder instance
538
*/
539
public Builder mimeTypeIs(String... mimeTypes) {
540
return this;
541
}
542
543
/**
544
* Filter by source name pattern
545
* @param namePattern Name pattern (regex)
546
* @return Builder instance
547
*/
548
public Builder sourceIs(String namePattern) {
549
return this;
550
}
551
552
/**
553
* Include internal sources
554
* @return Builder instance
555
*/
556
public Builder includeInternal(boolean includeInternal) {
557
return this;
558
}
559
560
/**
561
* Build the filter
562
* @return SourceFilter instance
563
*/
564
public SourceFilter build() {
565
return new SourceFilter();
566
}
567
}
568
}
569
```
570
571
### Allocation Tracking
572
573
System for monitoring memory allocations in Truffle languages.
574
575
```java { .api }
576
/**
577
* Reports memory allocations to registered listeners
578
*/
579
public abstract class AllocationReporter {
580
581
/**
582
* Add allocation listener
583
* @param listener Allocation listener
584
*/
585
public abstract void addListener(AllocationListener listener);
586
587
/**
588
* Remove allocation listener
589
* @param listener Allocation listener
590
*/
591
public abstract void removeListener(AllocationListener listener);
592
593
/**
594
* Report object allocation
595
* @param newObject Newly allocated object
596
*/
597
public abstract void onEnter(Object newObject);
598
599
/**
600
* Report allocation with size
601
* @param newObject Newly allocated object
602
* @param size Allocation size in bytes
603
*/
604
public abstract void onEnter(Object newObject, long size);
605
606
/**
607
* Report allocation with language and size
608
* @param newObject Newly allocated object
609
* @param size Allocation size in bytes
610
* @param language Allocating language
611
*/
612
public abstract void onEnter(Object newObject, long size, TruffleLanguage<?> language);
613
}
614
615
/**
616
* Listener interface for allocation events
617
*/
618
public interface AllocationListener {
619
620
/**
621
* Called when object is allocated
622
* @param event Allocation event
623
*/
624
void onAllocation(AllocationEvent event);
625
}
626
627
/**
628
* Event representing an object allocation
629
*/
630
public abstract class AllocationEvent {
631
632
/**
633
* Get allocated object
634
* @return Allocated object
635
*/
636
public abstract Object getAllocatedObject();
637
638
/**
639
* Get allocation size
640
* @return Size in bytes
641
*/
642
public abstract long getSize();
643
644
/**
645
* Get allocating language
646
* @return TruffleLanguage instance
647
*/
648
public abstract TruffleLanguage<?> getLanguage();
649
650
/**
651
* Get allocation stack trace
652
* @return Array of stack trace elements
653
*/
654
public abstract StackTraceElement[] getStackTrace();
655
}
656
```
657
658
### Event Binding Management
659
660
System for managing and controlling instrumentation bindings.
661
662
```java { .api }
663
/**
664
* Represents a binding between instrument and instrumented code
665
* @param <T> Bound element type
666
*/
667
public abstract class EventBinding<T> {
668
669
/**
670
* Check if binding is disposed
671
* @return true if disposed
672
*/
673
public abstract boolean isDisposed();
674
675
/**
676
* Dispose this binding
677
*/
678
public abstract void dispose();
679
680
/**
681
* Get bound element
682
* @return Bound element
683
*/
684
public abstract T getElement();
685
686
/**
687
* Check if binding is attached to specific instrumented node
688
* @param node Node to check
689
* @return true if attached
690
*/
691
public abstract boolean isAttached(Node node);
692
}
693
```
694
695
### Node Tagging System
696
697
System for marking AST nodes with semantic tags for targeted instrumentation.
698
699
```java { .api }
700
/**
701
* Base class for node tags
702
*/
703
public abstract class Tag {
704
// Base tag class
705
}
706
707
/**
708
* Standard tags for common language constructs
709
*/
710
public final class StandardTags {
711
712
/**
713
* Tag for expression nodes
714
*/
715
public static final class ExpressionTag extends Tag {
716
private ExpressionTag() {}
717
}
718
719
/**
720
* Tag for statement nodes
721
*/
722
public static final class StatementTag extends Tag {
723
private StatementTag() {}
724
}
725
726
/**
727
* Tag for function call nodes
728
*/
729
public static final class CallTag extends Tag {
730
private CallTag() {}
731
}
732
733
/**
734
* Tag for root nodes
735
*/
736
public static final class RootTag extends Tag {
737
private RootTag() {}
738
}
739
740
/**
741
* Tag for root body nodes
742
*/
743
public static final class RootBodyTag extends Tag {
744
private RootBodyTag() {}
745
}
746
747
/**
748
* Tag for read variable nodes
749
*/
750
public static final class ReadVariableTag extends Tag {
751
private ReadVariableTag() {}
752
}
753
754
/**
755
* Tag for write variable nodes
756
*/
757
public static final class WriteVariableTag extends Tag {
758
private WriteVariableTag() {}
759
}
760
}
761
762
/**
763
* Marks nodes as instrumentable
764
*/
765
@Retention(RetentionPolicy.RUNTIME)
766
@Target(ElementType.TYPE)
767
public @interface Instrumentable {
768
769
/**
770
* Factory class for creating wrappers
771
* @return Wrapper factory class
772
*/
773
Class<? extends ProvidedTags> factory();
774
}
775
776
/**
777
* Tags provided by an instrumentable node
778
*/
779
public abstract class ProvidedTags {
780
781
/**
782
* Get provided tag classes
783
* @return Array of tag classes
784
*/
785
public abstract Class<?>[] getProvidedTags();
786
}
787
788
/**
789
* Generates wrapper nodes for instrumentation
790
*/
791
@Retention(RetentionPolicy.CLASS)
792
@Target(ElementType.TYPE)
793
public @interface GenerateWrapper {
794
795
/**
796
* Delegate factory class
797
* @return Factory class
798
*/
799
Class<?> delegateTo();
800
}
801
```
802
803
### Source Load Monitoring
804
805
System for monitoring source code loading and compilation.
806
807
```java { .api }
808
/**
809
* Listener interface for source loading events
810
*/
811
public interface LoadSourceListener {
812
813
/**
814
* Called when source is loaded
815
* @param event Source load event
816
*/
817
void onLoad(LoadSourceEvent event);
818
}
819
820
/**
821
* Listener interface for source section loading events
822
*/
823
public interface LoadSourceSectionListener {
824
825
/**
826
* Called when source section is loaded
827
* @param event Source section load event
828
*/
829
void onLoad(LoadSourceSectionEvent event);
830
}
831
832
/**
833
* Event representing source loading
834
*/
835
public abstract class LoadSourceEvent {
836
837
/**
838
* Get loaded source
839
* @return Source instance
840
*/
841
public abstract Source getSource();
842
}
843
844
/**
845
* Event representing source section loading
846
*/
847
public abstract class LoadSourceSectionEvent {
848
849
/**
850
* Get loaded source section
851
* @return SourceSection instance
852
*/
853
public abstract SourceSection getSourceSection();
854
855
/**
856
* Get associated node
857
* @return Node instance
858
*/
859
public abstract Node getNode();
860
}
861
```
862
863
## Types
864
865
### Debugging Infrastructure Types
866
867
```java { .api }
868
/**
869
* Options for instrumentation configuration
870
*/
871
public final class OptionValues {
872
873
/**
874
* Get option value
875
* @param key Option key
876
* @return Option value
877
*/
878
public <T> T get(OptionKey<T> key) {
879
return null;
880
}
881
882
/**
883
* Check if option has value
884
* @param key Option key
885
* @return true if has value
886
*/
887
public boolean hasBeenSet(OptionKey<?> key) {
888
return false;
889
}
890
}
891
892
/**
893
* Key for accessing option values
894
* @param <T> Option value type
895
*/
896
public final class OptionKey<T> {
897
898
/**
899
* Get default value
900
* @return Default value
901
*/
902
public T getDefaultValue() {
903
return null;
904
}
905
}
906
907
/**
908
* Descriptor for option definitions
909
*/
910
public final class OptionDescriptor {
911
912
/**
913
* Get option name
914
* @return Option name
915
*/
916
public String getName() {
917
return null;
918
}
919
920
/**
921
* Get option help text
922
* @return Help text
923
*/
924
public String getHelp() {
925
return null;
926
}
927
928
/**
929
* Get option key
930
* @return OptionKey instance
931
*/
932
public OptionKey<?> getKey() {
933
return null;
934
}
935
}
936
```