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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
#define HAS_ARGUMENTS
// This file is part of Bun!
// You can find the original source:
// https://github.com/Jarred-Sumner/bun/blob/main/src/javascript/jsc/api/FFI.h#L2
//
// clang-format off
// This file is only compatible with 64 bit CPUs
// It must be kept in sync with JSCJSValue.h
// https://github.com/Jarred-Sumner/WebKit/blob/72c2052b781cbfd4af867ae79ac9de460e392fba/Source/JavaScriptCore/runtime/JSCJSValue.h#L455-L458
#ifdef IS_CALLBACK
// #define INJECT_BEFORE printf("bun_call %p cachedJSContext %p cachedCallbackFunction %p\n", &bun_call, cachedJSContext, cachedCallbackFunction);
#endif
#define IS_BIG_ENDIAN 0
#define USE_JSVALUE64 1
#define USE_JSVALUE32_64 0
// #include <stdint.h>
#ifdef INJECT_BEFORE
// #include <stdio.h>
#endif
// #include <tcclib.h>
// // /* 7.18.1.1 Exact-width integer types */
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef uint64_t size_t;
typedef long intptr_t;
typedef uint64_t uintptr_t;
typedef _Bool bool;
#define true 1
#define false 0
#ifdef USES_FLOAT
// https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c
double trunc(double x);
double trunc(double x)
{
union {double f; uint64_t i;} u = {x};
int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12;
uint64_t m;
if (e >= 52 + 12)
return x;
if (e < 12)
e = 1;
m = -1ULL >> e;
if ((u.i & m) == 0)
return x;
x + 0x1p120f;
u.i &= ~m;
return u.f;
}
#endif
// This value is 2^49, used to encode doubles such that the encoded value will
// begin with a 15-bit pattern within the range 0x0002..0xFFFC.
#define DoubleEncodeOffsetBit 49
#define DoubleEncodeOffset (1ll << DoubleEncodeOffsetBit)
#define OtherTag 0x2
#define BoolTag 0x4
#define UndefinedTag 0x8
#define TagValueFalse (OtherTag | BoolTag | false)
#define TagValueTrue (OtherTag | BoolTag | true)
#define TagValueUndefined (OtherTag | UndefinedTag)
#define TagValueNull (OtherTag)
// If all bits in the mask are set, this indicates an integer number,
// if any but not all are set this value is a double precision number.
#define NumberTag 0xfffe000000000000ll
typedef void* JSCell;
typedef union EncodedJSValue {
int64_t asInt64;
#if USE_JSVALUE32_64
double asDouble;
#elif USE_JSVALUE64
JSCell *ptr;
#endif
#if IS_BIG_ENDIAN
struct {
int32_t tag;
int32_t payload;
} asBits;
#else
struct {
int32_t payload;
int32_t tag;
} asBits;
#endif
void* asPtr;
} EncodedJSValue;
EncodedJSValue ValueUndefined = { TagValueUndefined };
EncodedJSValue ValueTrue = { TagValueTrue };
typedef void* JSContext;
#define LOAD_ARGUMENTS_FROM_CALL_FRAME EncodedJSValue* args = (EncodedJSValue*)((size_t*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
#ifdef IS_CALLBACK
extern int64_t bun_call(JSContext, void* func, void* thisValue, size_t len, const EncodedJSValue args[], void* exception);
JSContext cachedJSContext;
void* cachedCallbackFunction;
#endif
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) __attribute__((__always_inline__));
static EncodedJSValue DOUBLE_TO_JSVALUE(double val) __attribute__((__always_inline__));
static EncodedJSValue FLOAT_TO_JSVALUE(float val) __attribute__((__always_inline__));
static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) __attribute__((__always_inline__));
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__));
static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
static void* JSVALUE_TO_PTR(EncodedJSValue val) {
// must be a double
return (void*)(val.asInt64 - DoubleEncodeOffset);
}
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) {
EncodedJSValue val;
val.asInt64 = (int64_t)ptr + DoubleEncodeOffset;
return val;
}
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
return val.asInt64;
}
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
EncodedJSValue res;
res.asInt64 = NumberTag | (uint32_t)val;
return res;
}
static EncodedJSValue DOUBLE_TO_JSVALUE(double val) {
EncodedJSValue res;
#ifdef USES_FLOAT
res.asInt64 = trunc(val) == val ? val : val - DoubleEncodeOffset;
#else
// should never get here
res.asInt64 = 0xa;
#endif
return res;
}
static EncodedJSValue FLOAT_TO_JSVALUE(float val) {
return DOUBLE_TO_JSVALUE(val);
}
static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) {
EncodedJSValue res;
res.asInt64 = val ? TagValueTrue : TagValueFalse;
return res;
}
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) {
return val.asInt64 + DoubleEncodeOffset;
}
static float JSVALUE_TO_FLOAT(EncodedJSValue val) {
return (float)JSVALUE_TO_DOUBLE(val);
}
static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
return val.asInt64 == TagValueTrue;
}
#define arg(i) ((EncodedJSValue*)args)[i]
void* JSFunctionCall(void* globalObject, void* callFrame);
// int64_t JSFunctionCall(void* globalObject, void* callFrame) {
// EncodedJSValue* args = (EncodedJSValue*)((unsigned char*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
// }
// --- Generated Code ---
/* --- The Function To Call */
void callback(void* arg0);
/* ---- Your Wrapper Function ---- */
void* JSFunctionCall(void* globalObject, void* callFrame) {
#ifdef HAS_ARGUMENTS
LOAD_ARGUMENTS_FROM_CALL_FRAME;
#endif
#ifdef INJECT_BEFORE
//Bun_FFI_PointerOffsetToArgumentsList: 6
//Bun_FFI_PointerOffsetToArgumentsCount: 0
#endif
callback( JSVALUE_TO_PTR(arg(0)));
return ValueUndefined.asPtr;
}
|