1 package experimental
2
3 import (
4 "context"
5
6 "github.com/tetratelabs/wazero/api"
7 )
8
9
10
11
12
13
14
15 type StackIterator interface {
16
17
18 Next() bool
19
20 Function() InternalFunction
21
22
23 ProgramCounter() ProgramCounter
24 }
25
26
27
28
29 type FunctionListenerFactoryKey struct{}
30
31
32
33 type FunctionListenerFactory interface {
34
35
36 NewFunctionListener(api.FunctionDefinition) FunctionListener
37
38
39
40 }
41
42
43
44 type FunctionListener interface {
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, stackIterator StackIterator)
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 After(ctx context.Context, mod api.Module, def api.FunctionDefinition, results []uint64)
81
82
83
84
85
86
87
88
89
90
91
92
93
94 Abort(ctx context.Context, mod api.Module, def api.FunctionDefinition, err error)
95 }
96
97
98
99
100
101
102
103
104
105 type FunctionListenerFunc func(context.Context, api.Module, api.FunctionDefinition, []uint64, StackIterator)
106
107
108 func (f FunctionListenerFunc) Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, stackIterator StackIterator) {
109 f(ctx, mod, def, params, stackIterator)
110 }
111
112
113
114 func (f FunctionListenerFunc) After(context.Context, api.Module, api.FunctionDefinition, []uint64) {
115 }
116
117
118
119 func (f FunctionListenerFunc) Abort(context.Context, api.Module, api.FunctionDefinition, error) {
120 }
121
122
123
124
125 type FunctionListenerFactoryFunc func(api.FunctionDefinition) FunctionListener
126
127
128 func (f FunctionListenerFactoryFunc) NewFunctionListener(def api.FunctionDefinition) FunctionListener {
129 return f(def)
130 }
131
132
133
134
135
136
137
138
139
140
141
142
143 func MultiFunctionListenerFactory(factories ...FunctionListenerFactory) FunctionListenerFactory {
144 multi := make(multiFunctionListenerFactory, len(factories))
145 copy(multi, factories)
146 return multi
147 }
148
149 type multiFunctionListenerFactory []FunctionListenerFactory
150
151 func (multi multiFunctionListenerFactory) NewFunctionListener(def api.FunctionDefinition) FunctionListener {
152 var lstns []FunctionListener
153 for _, factory := range multi {
154 if lstn := factory.NewFunctionListener(def); lstn != nil {
155 lstns = append(lstns, lstn)
156 }
157 }
158 switch len(lstns) {
159 case 0:
160 return nil
161 case 1:
162 return lstns[0]
163 default:
164 return &multiFunctionListener{lstns: lstns}
165 }
166 }
167
168 type multiFunctionListener struct {
169 lstns []FunctionListener
170 stack stackIterator
171 }
172
173 func (multi *multiFunctionListener) Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, si StackIterator) {
174 multi.stack.base = si
175 for _, lstn := range multi.lstns {
176 multi.stack.index = -1
177 lstn.Before(ctx, mod, def, params, &multi.stack)
178 }
179 }
180
181 func (multi *multiFunctionListener) After(ctx context.Context, mod api.Module, def api.FunctionDefinition, results []uint64) {
182 for _, lstn := range multi.lstns {
183 lstn.After(ctx, mod, def, results)
184 }
185 }
186
187 func (multi *multiFunctionListener) Abort(ctx context.Context, mod api.Module, def api.FunctionDefinition, err error) {
188 for _, lstn := range multi.lstns {
189 lstn.Abort(ctx, mod, def, err)
190 }
191 }
192
193 type stackIterator struct {
194 base StackIterator
195 index int
196 pcs []uint64
197 fns []InternalFunction
198 }
199
200 func (si *stackIterator) Next() bool {
201 if si.base != nil {
202 si.pcs = si.pcs[:0]
203 si.fns = si.fns[:0]
204
205 for si.base.Next() {
206 si.pcs = append(si.pcs, uint64(si.base.ProgramCounter()))
207 si.fns = append(si.fns, si.base.Function())
208 }
209
210 si.base = nil
211 }
212 si.index++
213 return si.index < len(si.pcs)
214 }
215
216 func (si *stackIterator) ProgramCounter() ProgramCounter {
217 return ProgramCounter(si.pcs[si.index])
218 }
219
220 func (si *stackIterator) Function() InternalFunction {
221 return si.fns[si.index]
222 }
223
224
225 type StackFrame struct {
226 Function api.Function
227 Params []uint64
228 Results []uint64
229 PC uint64
230 SourceOffset uint64
231 }
232
233 type internalFunction struct {
234 definition api.FunctionDefinition
235 sourceOffset uint64
236 }
237
238 func (f internalFunction) Definition() api.FunctionDefinition {
239 return f.definition
240 }
241
242 func (f internalFunction) SourceOffsetForPC(pc ProgramCounter) uint64 {
243 return f.sourceOffset
244 }
245
246
247
248 type stackFrameIterator struct {
249 index int
250 stack []StackFrame
251 fndef []api.FunctionDefinition
252 }
253
254 func (si *stackFrameIterator) Next() bool {
255 si.index++
256 return si.index < len(si.stack)
257 }
258
259 func (si *stackFrameIterator) Function() InternalFunction {
260 return internalFunction{
261 definition: si.fndef[si.index],
262 sourceOffset: si.stack[si.index].SourceOffset,
263 }
264 }
265
266 func (si *stackFrameIterator) ProgramCounter() ProgramCounter {
267 return ProgramCounter(si.stack[si.index].PC)
268 }
269
270
271
272 func NewStackIterator(stack ...StackFrame) StackIterator {
273 si := &stackFrameIterator{
274 index: -1,
275 stack: make([]StackFrame, len(stack)),
276 fndef: make([]api.FunctionDefinition, len(stack)),
277 }
278 for i := range stack {
279 si.stack[i] = stack[len(stack)-(i+1)]
280 }
281
282
283
284
285
286 for i, frame := range stack {
287 si.fndef[i] = frame.Function.Definition()
288 }
289 return si
290 }
291
292
293
294
295
296
297
298
299
300 func BenchmarkFunctionListener(n int, module api.Module, stack []StackFrame, listener FunctionListener) {
301 if len(stack) == 0 {
302 panic("cannot benchmark function listener with an empty stack")
303 }
304
305 ctx := context.Background()
306 def := stack[0].Function.Definition()
307 params := stack[0].Params
308 results := stack[0].Results
309 stackIterator := &stackIterator{base: NewStackIterator(stack...)}
310
311 for i := 0; i < n; i++ {
312 stackIterator.index = -1
313 listener.Before(ctx, module, def, params, stackIterator)
314 listener.After(ctx, module, def, results)
315 }
316 }
317
318
319
320
321
322
323
View as plain text