koffi 1.1.5 → 1.2.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,15 @@
1
- // This program is free software: you can redistribute it and/or modify
2
- // it under the terms of the GNU Affero General Public License as published by
3
- // the Free Software Foundation, either version 3 of the License, or
4
- // (at your option) any later version.
5
- //
6
- // This program is distributed in the hope that it will be useful,
7
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
8
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9
- // GNU Affero General Public License for more details.
10
- //
11
- // You should have received a copy of the GNU Affero General Public License
12
- // along with this program. If not, see https://www.gnu.org/licenses/.
1
+ # This program is free software: you can redistribute it and/or modify
2
+ # it under the terms of the GNU Affero General Public License as published by
3
+ # the Free Software Foundation, either version 3 of the License, or
4
+ # (at your option) any later version.
5
+ #
6
+ # This program is distributed in the hope that it will be useful,
7
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9
+ # GNU Affero General Public License for more details.
10
+ #
11
+ # You should have received a copy of the GNU Affero General Public License
12
+ # along with this program. If not, see https://www.gnu.org/licenses/.
13
13
 
14
14
  #ifdef __APPLE__
15
15
  #define SYMBOL(Symbol) _ ## Symbol
@@ -17,19 +17,23 @@
17
17
  #define SYMBOL(Symbol) Symbol
18
18
  #endif
19
19
 
20
- // These three are the same, but they differ (in the C side) by their return type.
21
- // Unlike the three next functions, these ones don't forward XMM argument registers.
20
+ # Forward
21
+ # ----------------------------
22
+
23
+ # These three are the same, but they differ (in the C side) by their return type.
24
+ # Unlike the three next functions, these ones don't forward XMM argument registers.
22
25
  .global SYMBOL(ForwardCallGG)
23
26
  .global SYMBOL(ForwardCallF)
24
27
  .global SYMBOL(ForwardCallDDDD)
25
28
 
26
- // The X variants are slightly slower, and are used when XMM arguments must be forwarded.
29
+ # The X variants are slightly slower, and are used when XMM arguments must be forwarded.
27
30
  .global SYMBOL(ForwardCallXGG)
28
31
  .global SYMBOL(ForwardCallXF)
29
32
  .global SYMBOL(ForwardCallXDDDD)
30
33
 
31
- // Copy function pointer to r9, in order to save it through argument forwarding.
32
- // Save RSP in r29 (non-volatile), and use carefully assembled stack provided by caller.
34
+ # Copy function pointer to r9, in order to save it through argument forwarding.
35
+ # Also make a copy of the SP to CallData::old_sp because the callback system might need it.
36
+ # Save RSP in r29 (non-volatile), and use carefully assembled stack provided by caller.
33
37
  .macro prologue
34
38
  .cfi_startproc
35
39
  stp x29, x30, [sp, -16]!
@@ -38,13 +42,14 @@
38
42
  .cfi_offset 30, 8
39
43
  mov x29, sp
40
44
  .cfi_def_cfa x29, 16
45
+ str x29, [x2, 0]
41
46
  mov x9, x0
42
47
  add sp, x1, #136
43
48
  .endm
44
49
 
45
- // Call native function.
46
- // Once done, restore normal stack pointer and return.
47
- // The return value is passed untouched through r0, r1, v0 and/or v1.
50
+ # Call native function.
51
+ # Once done, restore normal stack pointer and return.
52
+ # The return value is passed untouched through r0, r1, v0 and/or v1.
48
53
  .macro epilogue
49
54
  blr x9
50
55
  mov sp, x29
@@ -57,29 +62,21 @@
57
62
  .cfi_endproc
58
63
  .endm
59
64
 
60
- // Prepare general purpose argument registers from array passed by caller.
65
+ # Prepare general purpose argument registers from array passed by caller.
61
66
  .macro forward_int
62
67
  ldr x8, [x1, 64]
63
- ldr x7, [x1, 56]
64
- ldr x6, [x1, 48]
65
- ldr x5, [x1, 40]
66
- ldr x4, [x1, 32]
67
- ldr x3, [x1, 24]
68
- ldr x2, [x1, 16]
69
- ldr x0, [x1, 0]
70
- ldr x1, [x1, 8]
68
+ ldp x6, x7, [x1, 48]
69
+ ldp x4, x5, [x1, 32]
70
+ ldp x2, x3, [x1, 16]
71
+ ldp x0, x1, [x1, 0]
71
72
  .endm
72
73
 
73
- // Prepare vector argument registers from array passed by caller.
74
+ # Prepare vector argument registers from array passed by caller.
74
75
  .macro forward_vec
75
- ldr d7, [x1, 128]
76
- ldr d6, [x1, 120]
77
- ldr d5, [x1, 112]
78
- ldr d4, [x1, 104]
79
- ldr d3, [x1, 96]
80
- ldr d2, [x1, 88]
81
- ldr d1, [x1, 80]
82
- ldr d0, [x1, 72]
76
+ ldp d6, d7, [x1, 120]
77
+ ldp d4, d5, [x1, 104]
78
+ ldp d2, d3, [x1, 88]
79
+ ldp d0, d1, [x1, 72]
83
80
  .endm
84
81
 
85
82
  SYMBOL(ForwardCallGG):
@@ -114,3 +111,204 @@ SYMBOL(ForwardCallXDDDD):
114
111
  forward_vec
115
112
  forward_int
116
113
  epilogue
114
+
115
+ # Callback trampolines
116
+ # ----------------------------
117
+
118
+ .global SYMBOL(Trampoline0)
119
+ .global SYMBOL(Trampoline1)
120
+ .global SYMBOL(Trampoline2)
121
+ .global SYMBOL(Trampoline3)
122
+ .global SYMBOL(Trampoline4)
123
+ .global SYMBOL(Trampoline5)
124
+ .global SYMBOL(Trampoline6)
125
+ .global SYMBOL(Trampoline7)
126
+ .global SYMBOL(Trampoline8)
127
+ .global SYMBOL(Trampoline9)
128
+ .global SYMBOL(Trampoline10)
129
+ .global SYMBOL(Trampoline11)
130
+ .global SYMBOL(Trampoline12)
131
+ .global SYMBOL(Trampoline13)
132
+ .global SYMBOL(Trampoline14)
133
+ .global SYMBOL(Trampoline15)
134
+ .global SYMBOL(TrampolineX0)
135
+ .global SYMBOL(TrampolineX1)
136
+ .global SYMBOL(TrampolineX2)
137
+ .global SYMBOL(TrampolineX3)
138
+ .global SYMBOL(TrampolineX4)
139
+ .global SYMBOL(TrampolineX5)
140
+ .global SYMBOL(TrampolineX6)
141
+ .global SYMBOL(TrampolineX7)
142
+ .global SYMBOL(TrampolineX8)
143
+ .global SYMBOL(TrampolineX9)
144
+ .global SYMBOL(TrampolineX10)
145
+ .global SYMBOL(TrampolineX11)
146
+ .global SYMBOL(TrampolineX12)
147
+ .global SYMBOL(TrampolineX13)
148
+ .global SYMBOL(TrampolineX14)
149
+ .global SYMBOL(TrampolineX15)
150
+ .global SYMBOL(RelayCallBack)
151
+ .global SYMBOL(CallSwitchStack)
152
+
153
+ # First, make a copy of the GPR argument registers (x0 to x7).
154
+ # Then call the C function RelayCallBack with the following arguments:
155
+ # static trampoline ID, a pointer to the saved GPR array, a pointer to the stack
156
+ # arguments of this call, and a pointer to a struct that will contain the result registers.
157
+ # After the call, simply load these registers from the output struct.
158
+ .macro trampoline id
159
+ .cfi_startproc
160
+ stp x29, x30, [sp, -16]!
161
+ .cfi_def_cfa sp, 16
162
+ .cfi_offset 29, 16
163
+ .cfi_offset 30, 8
164
+ sub sp, sp, #192
165
+ .cfi_def_cfa sp, 208
166
+ stp x0, x1, [sp, 0]
167
+ stp x2, x3, [sp, 16]
168
+ stp x4, x5, [sp, 32]
169
+ stp x6, x7, [sp, 48]
170
+ str x8, [sp, 64]
171
+ mov x0, \id
172
+ mov x1, sp
173
+ add x2, sp, #208
174
+ add x3, sp, #136
175
+ bl SYMBOL(RelayCallBack)
176
+ ldp x0, x1, [sp, 136]
177
+ add sp, sp, #192
178
+ .cfi_def_cfa sp, 16
179
+ ldp x29, x30, [sp], 16
180
+ .cfi_def_cfa sp, 0
181
+ .cfi_restore 30
182
+ .cfi_restore 29
183
+ ret
184
+ .cfi_endproc
185
+ .endm
186
+
187
+ # Same thing, but also forwards the floating-point argument registers and loads them at the end.
188
+ .macro trampoline_vec id
189
+ .cfi_startproc
190
+ stp x29, x30, [sp, -16]!
191
+ .cfi_def_cfa sp, 16
192
+ .cfi_offset 29, 16
193
+ .cfi_offset 30, 8
194
+ sub sp, sp, #192
195
+ .cfi_def_cfa sp, 208
196
+ stp x0, x1, [sp, 0]
197
+ stp x2, x3, [sp, 16]
198
+ stp x4, x5, [sp, 32]
199
+ stp x6, x7, [sp, 48]
200
+ str x8, [sp, 64]
201
+ stp d0, d1, [sp, 72]
202
+ stp d2, d3, [sp, 88]
203
+ stp d4, d5, [sp, 104]
204
+ stp d6, d7, [sp, 120]
205
+ mov x0, \id
206
+ mov x1, sp
207
+ add x2, sp, #208
208
+ add x3, sp, #136
209
+ bl SYMBOL(RelayCallBack)
210
+ ldp x0, x1, [sp, 136]
211
+ ldp d0, d1, [sp, 152]
212
+ ldp d2, d3, [sp, 168]
213
+ add sp, sp, #192
214
+ .cfi_def_cfa sp, 16
215
+ ldp x29, x30, [sp], 16
216
+ .cfi_def_cfa sp, 0
217
+ .cfi_restore 30
218
+ .cfi_restore 29
219
+ ret
220
+ .cfi_endproc
221
+ .endm
222
+
223
+ SYMBOL(Trampoline0):
224
+ trampoline 0
225
+ SYMBOL(Trampoline1):
226
+ trampoline 1
227
+ SYMBOL(Trampoline2):
228
+ trampoline 2
229
+ SYMBOL(Trampoline3):
230
+ trampoline 3
231
+ SYMBOL(Trampoline4):
232
+ trampoline 4
233
+ SYMBOL(Trampoline5):
234
+ trampoline 5
235
+ SYMBOL(Trampoline6):
236
+ trampoline 6
237
+ SYMBOL(Trampoline7):
238
+ trampoline 7
239
+ SYMBOL(Trampoline8):
240
+ trampoline 8
241
+ SYMBOL(Trampoline9):
242
+ trampoline 9
243
+ SYMBOL(Trampoline10):
244
+ trampoline 10
245
+ SYMBOL(Trampoline11):
246
+ trampoline 11
247
+ SYMBOL(Trampoline12):
248
+ trampoline 12
249
+ SYMBOL(Trampoline13):
250
+ trampoline 13
251
+ SYMBOL(Trampoline14):
252
+ trampoline 14
253
+ SYMBOL(Trampoline15):
254
+ trampoline 15
255
+
256
+ SYMBOL(TrampolineX0):
257
+ trampoline_vec 0
258
+ SYMBOL(TrampolineX1):
259
+ trampoline_vec 1
260
+ SYMBOL(TrampolineX2):
261
+ trampoline_vec 2
262
+ SYMBOL(TrampolineX3):
263
+ trampoline_vec 3
264
+ SYMBOL(TrampolineX4):
265
+ trampoline_vec 4
266
+ SYMBOL(TrampolineX5):
267
+ trampoline_vec 5
268
+ SYMBOL(TrampolineX6):
269
+ trampoline_vec 6
270
+ SYMBOL(TrampolineX7):
271
+ trampoline_vec 7
272
+ SYMBOL(TrampolineX8):
273
+ trampoline_vec 8
274
+ SYMBOL(TrampolineX9):
275
+ trampoline_vec 9
276
+ SYMBOL(TrampolineX10):
277
+ trampoline_vec 10
278
+ SYMBOL(TrampolineX11):
279
+ trampoline_vec 11
280
+ SYMBOL(TrampolineX12):
281
+ trampoline_vec 12
282
+ SYMBOL(TrampolineX13):
283
+ trampoline_vec 13
284
+ SYMBOL(TrampolineX14):
285
+ trampoline_vec 14
286
+ SYMBOL(TrampolineX15):
287
+ trampoline_vec 15
288
+
289
+ # When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
290
+ # The propblem is that we're still running on the separate Koffi stack, and V8 will
291
+ # preobably misdetect this as a "stack overflow". We have to restore the old
292
+ # stack pointer, call Node.js/V8 and go back to ours.
293
+ # The first three parameters (x0, x1, x2) are passed through untouched.
294
+ SYMBOL(CallSwitchStack):
295
+ .cfi_startproc
296
+ stp x29, x30, [sp, -16]!
297
+ .cfi_def_cfa sp, 16
298
+ .cfi_offset 29, 16
299
+ .cfi_offset 30, 8
300
+ mov x29, sp
301
+ ldr x9, [x4, 0]
302
+ sub x9, sp, x9
303
+ and x9, x9, #-16
304
+ str x9, [x4, 8]
305
+ mov sp, x3
306
+ blr x5
307
+ mov sp, x29
308
+ .cfi_def_cfa sp, 16
309
+ ldp x29, x30, [sp], 16
310
+ .cfi_def_cfa sp, 0
311
+ .cfi_restore 30
312
+ .cfi_restore 29
313
+ ret
314
+ .cfi_endproc
@@ -13,6 +13,20 @@
13
13
 
14
14
  AREA |.text|, CODE
15
15
 
16
+ ; Forward
17
+ ; ----------------------------
18
+
19
+ ; These three are the same, but they differ (in the C side) by their return type.
20
+ ; Unlike the three next functions, these ones don't forward XMM argument registers.
21
+ EXPORT ForwardCallGG
22
+ EXPORT ForwardCallF
23
+ EXPORT ForwardCallDDDD
24
+
25
+ ; The X variants are slightly slower, and are used when XMM arguments must be forwarded.
26
+ EXPORT ForwardCallXGG
27
+ EXPORT ForwardCallXF
28
+ EXPORT ForwardCallXDDDD
29
+
16
30
  ; Copy function pointer to r9, in order to save it through argument forwarding.
17
31
  ; Save RSP in r29 (non-volatile), and use carefully assembled stack provided by caller.
18
32
  MACRO
@@ -41,28 +55,20 @@
41
55
  forward_int
42
56
 
43
57
  ldr x8, [x1, 64]
44
- ldr x7, [x1, 56]
45
- ldr x6, [x1, 48]
46
- ldr x5, [x1, 40]
47
- ldr x4, [x1, 32]
48
- ldr x3, [x1, 24]
49
- ldr x2, [x1, 16]
50
- ldr x0, [x1, 0]
51
- ldr x1, [x1, 8]
58
+ ldp x6, x7, [x1, 48]
59
+ ldp x4, x5, [x1, 32]
60
+ ldp x2, x3, [x1, 16]
61
+ ldp x0, x1, [x1, 0]
52
62
  MEND
53
63
 
54
64
  ; Prepare vector argument registers from array passed by caller.
55
65
  MACRO
56
66
  forward_vec
57
67
 
58
- ldr d7, [x1, 128]
59
- ldr d6, [x1, 120]
60
- ldr d5, [x1, 112]
61
- ldr d4, [x1, 104]
62
- ldr d3, [x1, 96]
63
- ldr d2, [x1, 88]
64
- ldr d1, [x1, 80]
65
- ldr d0, [x1, 72]
68
+ ldp d6, d7, [x1, 120]
69
+ ldp d4, d5, [x1, 104]
70
+ ldp d2, d3, [x1, 88]
71
+ ldp d0, d1, [x1, 72]
66
72
  MEND
67
73
 
68
74
  ForwardCallGG PROC
@@ -104,4 +110,214 @@ ForwardCallXDDDD PROC
104
110
  epilogue
105
111
  ENDP
106
112
 
113
+ ; Callback trampolines
114
+ ; ----------------------------
115
+
116
+ EXPORT Trampoline0
117
+ EXPORT Trampoline1
118
+ EXPORT Trampoline2
119
+ EXPORT Trampoline3
120
+ EXPORT Trampoline4
121
+ EXPORT Trampoline5
122
+ EXPORT Trampoline6
123
+ EXPORT Trampoline7
124
+ EXPORT Trampoline8
125
+ EXPORT Trampoline9
126
+ EXPORT Trampoline10
127
+ EXPORT Trampoline11
128
+ EXPORT Trampoline12
129
+ EXPORT Trampoline13
130
+ EXPORT Trampoline14
131
+ EXPORT Trampoline15
132
+ EXPORT TrampolineX0
133
+ EXPORT TrampolineX1
134
+ EXPORT TrampolineX2
135
+ EXPORT TrampolineX3
136
+ EXPORT TrampolineX4
137
+ EXPORT TrampolineX5
138
+ EXPORT TrampolineX6
139
+ EXPORT TrampolineX7
140
+ EXPORT TrampolineX8
141
+ EXPORT TrampolineX9
142
+ EXPORT TrampolineX10
143
+ EXPORT TrampolineX11
144
+ EXPORT TrampolineX12
145
+ EXPORT TrampolineX13
146
+ EXPORT TrampolineX14
147
+ EXPORT TrampolineX15
148
+ EXPORT RelayCallBack
149
+ EXTERN RelayCallBack
150
+ EXPORT CallSwitchStack
151
+
152
+ ; First, make a copy of the GPR argument registers (x0 to x7).
153
+ ; Then call the C function RelayCallBack with the following arguments:
154
+ ; static trampoline ID, a pointer to the saved GPR array, a pointer to the stack
155
+ ; arguments of this call, and a pointer to a struct that will contain the result registers.
156
+ ; After the call, simply load these registers from the output struct.
157
+ MACRO
158
+ trampoline $ID
159
+
160
+ stp x29, x30, [sp, -16]!
161
+ sub sp, sp, #192
162
+ stp x0, x1, [sp, 0]
163
+ stp x2, x3, [sp, 16]
164
+ stp x4, x5, [sp, 32]
165
+ stp x6, x7, [sp, 48]
166
+ str x8, [sp, 64]
167
+ mov x0, $ID
168
+ mov x1, sp
169
+ add x2, sp, #208
170
+ add x3, sp, #136
171
+ bl RelayCallBack
172
+ ldp x0, x1, [sp, 136]
173
+ add sp, sp, #192
174
+ ldp x29, x30, [sp], 16
175
+ ret
176
+ MEND
177
+
178
+ ; Same thing, but also forwards the floating-point argument registers and loads them at the end.
179
+ MACRO
180
+ trampoline_vec $ID
181
+
182
+ stp x29, x30, [sp, -16]!
183
+ sub sp, sp, #192
184
+ stp x0, x1, [sp, 0]
185
+ stp x2, x3, [sp, 16]
186
+ stp x4, x5, [sp, 32]
187
+ stp x6, x7, [sp, 48]
188
+ str x8, [sp, 64]
189
+ stp d0, d1, [sp, 72]
190
+ stp d2, d3, [sp, 88]
191
+ stp d4, d5, [sp, 104]
192
+ stp d6, d7, [sp, 120]
193
+ mov x0, $ID
194
+ mov x1, sp
195
+ add x2, sp, #208
196
+ add x3, sp, #136
197
+ bl RelayCallBack
198
+ ldp x0, x1, [sp, 136]
199
+ ldp d0, d1, [sp, 152]
200
+ ldp d2, d3, [sp, 168]
201
+ add sp, sp, #192
202
+ ldp x29, x30, [sp], 16
203
+ ret
204
+ MEND
205
+
206
+ Trampoline0 PROC
207
+ trampoline 0
208
+ ENDP
209
+ Trampoline1 PROC
210
+ trampoline 1
211
+ ENDP
212
+ Trampoline2 PROC
213
+ trampoline 2
214
+ ENDP
215
+ Trampoline3 PROC
216
+ trampoline 3
217
+ ENDP
218
+ Trampoline4 PROC
219
+ trampoline 4
220
+ ENDP
221
+ Trampoline5 PROC
222
+ trampoline 5
223
+ ENDP
224
+ Trampoline6 PROC
225
+ trampoline 6
226
+ ENDP
227
+ Trampoline7 PROC
228
+ trampoline 7
229
+ ENDP
230
+ Trampoline8 PROC
231
+ trampoline 8
232
+ ENDP
233
+ Trampoline9 PROC
234
+ trampoline 9
235
+ ENDP
236
+ Trampoline10 PROC
237
+ trampoline 10
238
+ ENDP
239
+ Trampoline11 PROC
240
+ trampoline 11
241
+ ENDP
242
+ Trampoline12 PROC
243
+ trampoline 12
244
+ ENDP
245
+ Trampoline13 PROC
246
+ trampoline 13
247
+ ENDP
248
+ Trampoline14 PROC
249
+ trampoline 14
250
+ ENDP
251
+ Trampoline15 PROC
252
+ trampoline 15
253
+ ENDP
254
+
255
+ TrampolineX0 PROC
256
+ trampoline_vec 0
257
+ ENDP
258
+ TrampolineX1 PROC
259
+ trampoline_vec 1
260
+ ENDP
261
+ TrampolineX2 PROC
262
+ trampoline_vec 2
263
+ ENDP
264
+ TrampolineX3 PROC
265
+ trampoline_vec 3
266
+ ENDP
267
+ TrampolineX4 PROC
268
+ trampoline_vec 4
269
+ ENDP
270
+ TrampolineX5 PROC
271
+ trampoline_vec 5
272
+ ENDP
273
+ TrampolineX6 PROC
274
+ trampoline_vec 6
275
+ ENDP
276
+ TrampolineX7 PROC
277
+ trampoline_vec 7
278
+ ENDP
279
+ TrampolineX8 PROC
280
+ trampoline_vec 8
281
+ ENDP
282
+ TrampolineX9 PROC
283
+ trampoline_vec 9
284
+ ENDP
285
+ TrampolineX10 PROC
286
+ trampoline_vec 10
287
+ ENDP
288
+ TrampolineX11 PROC
289
+ trampoline_vec 11
290
+ ENDP
291
+ TrampolineX12 PROC
292
+ trampoline_vec 12
293
+ ENDP
294
+ TrampolineX13 PROC
295
+ trampoline_vec 13
296
+ ENDP
297
+ TrampolineX14 PROC
298
+ trampoline_vec 14
299
+ ENDP
300
+ TrampolineX15 PROC
301
+ trampoline_vec 15
302
+ ENDP
303
+
304
+ ; When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
305
+ ; The propblem is that we're still running on the separate Koffi stack, and V8 will
306
+ ; preobably misdetect this as a "stack overflow". We have to restore the old
307
+ ; stack pointer, call Node.js/V8 and go back to ours.
308
+ ; The first three parameters (x0, x1, x2) are passed through untouched.
309
+ CallSwitchStack PROC
310
+ stp x29, x30, [sp, -16]!
311
+ mov x29, sp
312
+ ldr x9, [x4, 0]
313
+ sub x9, sp, x9
314
+ and x9, x9, #-16
315
+ str x9, [x4, 8]
316
+ mov sp, x3
317
+ blr x5
318
+ mov sp, x29
319
+ ldp x29, x30, [sp], 16
320
+ ret
321
+ ENDP
322
+
107
323
  END