-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathInstrumentation.v3
126 lines (124 loc) · 4.27 KB
/
Instrumentation.v3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright 2023 Ben L. Titzer. All rights reserved.
// See LICENSE for details of Apache 2.0 license.
// Provides a common entrypoint to the engine's instrumentation capabilities, including
// the insertion/removal of probes, as well as firing probes during execution.
component Instrumentation {
def probes = ProbeList.new(); // probes on the global interpreter loop
// Reset the instrumentation to the default, i.e. only tracing probes.
def reset() { // TODO: only used in testing.
probes.clear();
BasicTracing.reset(); // TODO: engine depends on tracing in util
}
// Insert a probe into the global interpreter loop.
def insertGlobalProbe(p: Probe) {
if (FeatureDisable.emptyProbes) p = EMPTY_PROBE;
probes.add(p);
}
// Remove a probe from the global interpreter loop.
def removeGlobalProbe(p: Probe) {
if (FeatureDisable.emptyProbes) p = EMPTY_PROBE;
probes.remove(p);
}
// Insert a probe into the entry of a specific function.
def insertFuncEntryProbe(module: Module, func_id: int, p: Probe) {
insertLocalProbe(module, func_id, 0, p);
}
// Insert a probe a specific offset in a specific function.
def insertLocalProbe(module: Module, func_id: int, offset: int, p: Probe) {
if (FeatureDisable.emptyProbes) p = EMPTY_PROBE;
if (module.probes == null) module.probes = Array.new(module.functions.length);
if (func_id >= module.probes.length) module.probes = Arrays.grow(module.probes, func_id + 1);
var map = module.probes[func_id];
var func = module.functions[func_id];
if (func.orig_bytecode == null) return;
if (map == null) map = module.probes[func_id] = Array.new(func.orig_bytecode.length);
var probe = map[offset];
match (probe) {
l: ProbeList => {
l.add(p);
func.activateProbingAt(offset, InternalOpcode.PROBE.code);
Execute.tiering.onFuncProbeInsertN(module, func, offset, p);
}
null => {
map[offset] = p;
func.activateProbingAt(offset,
if (WhammProbe.?(p) && FastIntTuning.enableWhammProbeTrampoline,
InternalOpcode.WHAMM_PROBE.code,
InternalOpcode.PROBE.code));
Execute.tiering.onFuncProbeInsert1(module, func, offset, p);
}
_ => {
var list = ProbeList.new();
list.add(probe);
list.add(p);
map[offset] = list;
func.activateProbingAt(offset, InternalOpcode.PROBE.code);
Execute.tiering.onFuncProbeInsert1(module, func, offset, p);
}
}
}
// Insert a probe a specific offset in a specific function.
def removeLocalProbe(module: Module, func_id: int, offset: int, p: Probe) {
if (module.probes == null) return;
var map = module.probes[func_id];
if (map == null) return;
var probe = map[offset];
match (probe) {
null => return;
l: ProbeList => {
l.remove(p);
if (l.elem == null) {
map[offset] = null;
var func = module.functions[func_id];
func.deactiveProbingAt(offset);
Execute.tiering.onFuncProbeRemove(module, func, offset);
}
}
_ => if (probe == p) {
map[offset] = null;
var func = module.functions[func_id];
func.deactiveProbingAt(offset);
Execute.tiering.onFuncProbeRemove(module, func, offset);
}
}
}
// Get the probe, if any, at the given {offset}.
def getLocalProbe(module: Module, func_id: int, offset: int) -> Probe {
var probes = module.probes;
if (probes == null) return null;
var map = probes[func_id];
if (map == null) return null;
return map[offset];
}
// Called by the engine to fire probes on the global interpreter loop.
def fireGlobalProbes(dynamicLoc: DynamicLoc) -> Throwable {
Metrics.probe_fires.val++;
var r = probes.fire(dynamicLoc);
return resume(r);
}
// Called by the engine to fire probes on a specific dynamic location (instruction).
def fireLocalProbes(dynamicLoc: DynamicLoc) -> Throwable {
var func = dynamicLoc.func;
var pc = dynamicLoc.pc;
var probes = func.instance.module.probes;
if (probes == null) return null;
var map = probes[func.decl.func_index];
if (map == null) return null;
var probe = map[pc];
if (probe == null) return null;
Metrics.probe_fires.val++;
var r = probe.fire(dynamicLoc);
return resume(r);
}
private def resume(r: Resumption) -> Throwable {
match (r) {
Continue => {
return null;
}
Trap(reason, trace) => { // TODO: add exception backtrace
return Trap.new(reason, null, null);
}
}
}
}
def EMPTY_PROBE = Probe.new();