@ebowwa/bun-native-page 0.2.0

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.
@@ -0,0 +1,334 @@
1
+ /**
2
+ * High-level allocator classes: PageArena and BufferPool
3
+ */
4
+
5
+ import { getPageSize, alignToPage, allocPageAligned, mmapAnonymous, type AllocatedBuffer, type MappedRegion } from './index.js';
6
+ import { PageSizeError } from './errors.js';
7
+
8
+ // ============================================================================
9
+ // PageArena
10
+ // ============================================================================
11
+
12
+ export interface ArenaOptions {
13
+ /** Initial size in bytes */
14
+ initialSize?: number;
15
+ /** Growth factor when arena is full (default: 2) */
16
+ growthFactor?: number;
17
+ /** Maximum size in bytes (default: 4GB) */
18
+ maxSize?: number;
19
+ /** Use huge pages if available (Linux only) */
20
+ useHugePages?: boolean;
21
+ /** Lock pages in memory (prevent swap) */
22
+ lockMemory?: boolean;
23
+ /** Use mmap instead of malloc (for large arenas) */
24
+ useMmap?: boolean;
25
+ }
26
+
27
+ /**
28
+ * A bump-allocator arena backed by page-aligned memory
29
+ */
30
+ export class PageArena {
31
+ private _capacity: number;
32
+ private _used: number;
33
+ private _growthFactor: number;
34
+ private _maxSize: number;
35
+ private _buffer: AllocatedBuffer | MappedRegion | null;
36
+ private _useMmap: boolean;
37
+ private _destroyed: boolean;
38
+ private _allocations: Array<{ offset: number; size: number }>;
39
+
40
+ constructor(options: ArenaOptions = {}) {
41
+ const pageSize = getPageSize();
42
+ const initialSize = alignToPage(options.initialSize ?? pageSize.size * 4);
43
+ this._growthFactor = options.growthFactor ?? 2;
44
+ this._maxSize = options.maxSize ?? 4 * 1024 * 1024 * 1024; // 4GB
45
+ this._useMmap = options.useMmap ?? initialSize >= 1024 * 1024; // mmap for >= 1MB
46
+ this._capacity = initialSize;
47
+ this._used = 0;
48
+ this._destroyed = false;
49
+ this._allocations = [];
50
+
51
+ // Allocate initial buffer
52
+ if (this._useMmap) {
53
+ this._buffer = mmapAnonymous(initialSize, 'read-write');
54
+ if (options.lockMemory) {
55
+ this._buffer.lock();
56
+ }
57
+ } else {
58
+ this._buffer = allocPageAligned(initialSize);
59
+ }
60
+ }
61
+
62
+ /** Current capacity in bytes */
63
+ get capacity(): number {
64
+ return this._capacity;
65
+ }
66
+
67
+ /** Bytes used */
68
+ get used(): number {
69
+ return this._used;
70
+ }
71
+
72
+ /** Bytes available */
73
+ get available(): number {
74
+ return this._capacity - this._used;
75
+ }
76
+
77
+ /** Get ArrayBuffer view of entire arena */
78
+ get buffer(): ArrayBuffer {
79
+ this._checkDestroyed();
80
+ return this._buffer!.buffer;
81
+ }
82
+
83
+ /**
84
+ * Allocate bytes, returns offset from arena start
85
+ */
86
+ alloc(size: number, alignment: number = 8): number {
87
+ this._checkDestroyed();
88
+
89
+ if (size <= 0) {
90
+ throw new PageSizeError('Allocation size must be positive');
91
+ }
92
+
93
+ // Align offset to requested alignment (not page size - arena is already page-aligned)
94
+ const currentOffset = this._used;
95
+ const alignedOffset = Math.ceil(currentOffset / alignment) * alignment;
96
+
97
+ // Check if we need to grow
98
+ if (alignedOffset + size > this._capacity) {
99
+ this._grow(alignedOffset + size);
100
+ }
101
+
102
+ this._used = alignedOffset + size;
103
+ this._allocations.push({ offset: alignedOffset, size });
104
+
105
+ return alignedOffset;
106
+ }
107
+
108
+ /**
109
+ * Get slice at offset
110
+ */
111
+ slice(offset: number, length: number): ArrayBuffer {
112
+ this._checkDestroyed();
113
+ return this._buffer!.buffer.slice(offset, offset + length);
114
+ }
115
+
116
+ /**
117
+ * Reset arena (does not free memory, allows reuse)
118
+ */
119
+ reset(): void {
120
+ this._checkDestroyed();
121
+ this._used = 0;
122
+ this._allocations = [];
123
+ }
124
+
125
+ /**
126
+ * Grow arena by at least additionalBytes
127
+ */
128
+ grow(additionalBytes: number): void {
129
+ this._checkDestroyed();
130
+ this._grow(this._used + additionalBytes);
131
+ }
132
+
133
+ private _grow(requiredSize: number): void {
134
+ if (requiredSize > this._maxSize) {
135
+ throw new PageSizeError(`Arena would exceed max size of ${this._maxSize} bytes`);
136
+ }
137
+
138
+ // Calculate new size with growth factor
139
+ const alignedRequired = alignToPage(requiredSize);
140
+ const newSize = Math.min(
141
+ Math.max(alignedRequired, alignToPage(this._capacity * this._growthFactor)),
142
+ this._maxSize
143
+ );
144
+
145
+ // Allocate new buffer
146
+ let newBuffer: AllocatedBuffer | MappedRegion;
147
+ if (this._useMmap) {
148
+ newBuffer = mmapAnonymous(newSize, 'read-write');
149
+ } else {
150
+ const buf = allocPageAligned(newSize);
151
+ if (!buf) {
152
+ throw new PageSizeError(`Failed to grow arena to ${newSize} bytes`);
153
+ }
154
+ newBuffer = buf;
155
+ }
156
+
157
+ // Copy existing data to new buffer
158
+ if (this._used > 0 && this._buffer) {
159
+ const oldView = new Uint8Array(this._buffer.buffer);
160
+ const newView = new Uint8Array(newBuffer.buffer);
161
+ newView.set(oldView.subarray(0, this._used));
162
+ }
163
+
164
+ // Free old buffer
165
+ if (this._buffer) {
166
+ if ('unmap' in this._buffer) {
167
+ this._buffer.unmap();
168
+ } else {
169
+ this._buffer.free();
170
+ }
171
+ }
172
+
173
+ // Update references
174
+ this._buffer = newBuffer;
175
+ this._capacity = newSize;
176
+ }
177
+
178
+ /**
179
+ * Free all memory
180
+ */
181
+ destroy(): void {
182
+ if (this._destroyed) return;
183
+ this._destroyed = true;
184
+
185
+ if (this._buffer) {
186
+ if ('unmap' in this._buffer) {
187
+ this._buffer.unmap();
188
+ } else {
189
+ this._buffer.free();
190
+ }
191
+ this._buffer = null;
192
+ }
193
+ }
194
+
195
+ private _checkDestroyed(): void {
196
+ if (this._destroyed) {
197
+ throw new PageSizeError('Arena has been destroyed');
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Create arena from existing options
203
+ */
204
+ static from(options: ArenaOptions): PageArena {
205
+ return new PageArena(options);
206
+ }
207
+ }
208
+
209
+ // ============================================================================
210
+ // BufferPool
211
+ // ============================================================================
212
+
213
+ /**
214
+ * A pool of fixed-size page-aligned buffers
215
+ */
216
+ export class BufferPool {
217
+ private _bufferSize: number;
218
+ private _buffers: AllocatedBuffer[];
219
+ private _available: AllocatedBuffer[];
220
+ private _inUse: Set<AllocatedBuffer>;
221
+ private _destroyed: boolean;
222
+
223
+ constructor(bufferSize: number, initialCount: number = 4) {
224
+ const pageSize = getPageSize();
225
+ this._bufferSize = alignToPage(bufferSize);
226
+ this._buffers = [];
227
+ this._available = [];
228
+ this._inUse = new Set();
229
+ this._destroyed = false;
230
+
231
+ // Pre-allocate initial buffers
232
+ for (let i = 0; i < initialCount; i++) {
233
+ const buffer = allocPageAligned(this._bufferSize);
234
+ if (buffer) {
235
+ this._buffers.push(buffer);
236
+ this._available.push(buffer);
237
+ }
238
+ }
239
+ }
240
+
241
+ /** Individual buffer size */
242
+ get bufferSize(): number {
243
+ return this._bufferSize;
244
+ }
245
+
246
+ /** Total buffers in pool */
247
+ get totalCount(): number {
248
+ return this._buffers.length;
249
+ }
250
+
251
+ /** Available buffers */
252
+ get availableCount(): number {
253
+ return this._available.length;
254
+ }
255
+
256
+ /** In-use buffers */
257
+ get inUseCount(): number {
258
+ return this._inUse.size;
259
+ }
260
+
261
+ /**
262
+ * Acquire a buffer from the pool
263
+ */
264
+ acquire(): AllocatedBuffer {
265
+ this._checkDestroyed();
266
+
267
+ let buffer: AllocatedBuffer | undefined;
268
+
269
+ if (this._available.length > 0) {
270
+ buffer = this._available.pop();
271
+ } else {
272
+ // Grow pool
273
+ buffer = allocPageAligned(this._bufferSize);
274
+ if (!buffer) {
275
+ throw new PageSizeError('Failed to allocate buffer from pool');
276
+ }
277
+ this._buffers.push(buffer);
278
+ }
279
+
280
+ this._inUse.add(buffer!);
281
+ return buffer!;
282
+ }
283
+
284
+ /**
285
+ * Return a buffer to the pool
286
+ */
287
+ release(buffer: AllocatedBuffer): void {
288
+ this._checkDestroyed();
289
+
290
+ if (!this._inUse.has(buffer)) {
291
+ throw new PageSizeError('Buffer does not belong to this pool or already released');
292
+ }
293
+
294
+ this._inUse.delete(buffer);
295
+ this._available.push(buffer);
296
+ }
297
+
298
+ /**
299
+ * Grow pool by count
300
+ */
301
+ grow(count: number): void {
302
+ this._checkDestroyed();
303
+
304
+ for (let i = 0; i < count; i++) {
305
+ const buffer = allocPageAligned(this._bufferSize);
306
+ if (buffer) {
307
+ this._buffers.push(buffer);
308
+ this._available.push(buffer);
309
+ }
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Destroy pool and free all memory
315
+ */
316
+ destroy(): void {
317
+ if (this._destroyed) return;
318
+ this._destroyed = true;
319
+
320
+ for (const buffer of this._buffers) {
321
+ buffer.free();
322
+ }
323
+
324
+ this._buffers = [];
325
+ this._available = [];
326
+ this._inUse.clear();
327
+ }
328
+
329
+ private _checkDestroyed(): void {
330
+ if (this._destroyed) {
331
+ throw new PageSizeError('BufferPool has been destroyed');
332
+ }
333
+ }
334
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Error types for @ebowwa/bun-native-page
3
+ */
4
+ export declare class PageSizeError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ export declare class AllocationError extends PageSizeError {
8
+ size: number;
9
+ constructor(size: number, reason: string);
10
+ }
11
+ export declare class MapError extends PageSizeError {
12
+ size: number;
13
+ constructor(size: number, reason: string);
14
+ }
15
+ export declare class UnmapError extends PageSizeError {
16
+ constructor(reason: string);
17
+ }
18
+ export declare class ProtectionError extends PageSizeError {
19
+ constructor(reason: string);
20
+ }
21
+ export declare class LockError extends PageSizeError {
22
+ constructor(reason: string);
23
+ }
24
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,aAAa;IAEvC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM;CAKjB;AAED,qBAAa,QAAS,SAAQ,aAAa;IAEhC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM;CAKjB;AAED,qBAAa,UAAW,SAAQ,aAAa;gBAC/B,MAAM,EAAE,MAAM;CAI3B;AAED,qBAAa,eAAgB,SAAQ,aAAa;gBACpC,MAAM,EAAE,MAAM;CAI3B;AAED,qBAAa,SAAU,SAAQ,aAAa;gBAC9B,MAAM,EAAE,MAAM;CAI3B"}
package/dist/errors.js ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Error types for @ebowwa/bun-native-page
3
+ */
4
+ export class PageSizeError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'PageSizeError';
8
+ }
9
+ }
10
+ export class AllocationError extends PageSizeError {
11
+ size;
12
+ constructor(size, reason) {
13
+ super(`Failed to allocate ${size} bytes: ${reason}`);
14
+ this.size = size;
15
+ this.name = 'AllocationError';
16
+ }
17
+ }
18
+ export class MapError extends PageSizeError {
19
+ size;
20
+ constructor(size, reason) {
21
+ super(`Failed to map ${size} bytes: ${reason}`);
22
+ this.size = size;
23
+ this.name = 'MapError';
24
+ }
25
+ }
26
+ export class UnmapError extends PageSizeError {
27
+ constructor(reason) {
28
+ super(`Failed to unmap memory: ${reason}`);
29
+ this.name = 'UnmapError';
30
+ }
31
+ }
32
+ export class ProtectionError extends PageSizeError {
33
+ constructor(reason) {
34
+ super(`Failed to change protection: ${reason}`);
35
+ this.name = 'ProtectionError';
36
+ }
37
+ }
38
+ export class LockError extends PageSizeError {
39
+ constructor(reason) {
40
+ super(`Failed to lock memory: ${reason}`);
41
+ this.name = 'LockError';
42
+ }
43
+ }
44
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,aAAa;IAEvC;IADT,YACS,IAAY,EACnB,MAAc;QAEd,KAAK,CAAC,sBAAsB,IAAI,WAAW,MAAM,EAAE,CAAC,CAAC;QAH9C,SAAI,GAAJ,IAAI,CAAQ;QAInB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,aAAa;IAEhC;IADT,YACS,IAAY,EACnB,MAAc;QAEd,KAAK,CAAC,iBAAiB,IAAI,WAAW,MAAM,EAAE,CAAC,CAAC;QAHzC,SAAI,GAAJ,IAAI,CAAQ;QAInB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,aAAa;IAC3C,YAAY,MAAc;QACxB,KAAK,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,aAAa;IAChD,YAAY,MAAc;QACxB,KAAK,CAAC,gCAAgC,MAAM,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,aAAa;IAC1C,YAAY,MAAc;QACxB,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF"}
package/dist/errors.ts ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Error types for @ebowwa/bun-native-page
3
+ */
4
+
5
+ export class PageSizeError extends Error {
6
+ constructor(message: string) {
7
+ super(message);
8
+ this.name = 'PageSizeError';
9
+ }
10
+ }
11
+
12
+ export class AllocationError extends PageSizeError {
13
+ constructor(
14
+ public size: number,
15
+ reason: string
16
+ ) {
17
+ super(`Failed to allocate ${size} bytes: ${reason}`);
18
+ this.name = 'AllocationError';
19
+ }
20
+ }
21
+
22
+ export class MapError extends PageSizeError {
23
+ constructor(
24
+ public size: number,
25
+ reason: string
26
+ ) {
27
+ super(`Failed to map ${size} bytes: ${reason}`);
28
+ this.name = 'MapError';
29
+ }
30
+ }
31
+
32
+ export class UnmapError extends PageSizeError {
33
+ constructor(reason: string) {
34
+ super(`Failed to unmap memory: ${reason}`);
35
+ this.name = 'UnmapError';
36
+ }
37
+ }
38
+
39
+ export class ProtectionError extends PageSizeError {
40
+ constructor(reason: string) {
41
+ super(`Failed to change protection: ${reason}`);
42
+ this.name = 'ProtectionError';
43
+ }
44
+ }
45
+
46
+ export class LockError extends PageSizeError {
47
+ constructor(reason: string) {
48
+ super(`Failed to lock memory: ${reason}`);
49
+ this.name = 'LockError';
50
+ }
51
+ }
package/dist/ffi.d.ts ADDED
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Bun FFI bindings to page_native library
3
+ */
4
+ import { ptr, toArrayBuffer } from 'bun:ffi';
5
+ export declare const ffi: {
6
+ getSize: {
7
+ (): bigint;
8
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
9
+ };
10
+ is4k: {
11
+ (): number;
12
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
13
+ };
14
+ is16k: {
15
+ (): number;
16
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
17
+ };
18
+ getHugePageSize: {
19
+ (): bigint;
20
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
21
+ };
22
+ getPlatform: {
23
+ (): number;
24
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
25
+ };
26
+ alignSize: {
27
+ (args_0: number | bigint): bigint;
28
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
29
+ };
30
+ truncateSize: {
31
+ (args_0: number | bigint): bigint;
32
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
33
+ };
34
+ isAligned: {
35
+ (args_0: number | bigint): number;
36
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
37
+ };
38
+ alloc: {
39
+ (args_0: number | bigint): import("bun:ffi").Pointer;
40
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
41
+ };
42
+ allocPtr: {
43
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString): import("bun:ffi").Pointer;
44
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
45
+ };
46
+ allocSize: {
47
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString): bigint;
48
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
49
+ };
50
+ free: {
51
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString): undefined;
52
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
53
+ };
54
+ mmapAnonymous: {
55
+ (args_0: number | bigint, args_1: number): import("bun:ffi").Pointer;
56
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
57
+ };
58
+ mmapFile: {
59
+ (args_0: number, args_1: number | bigint, args_2: number | bigint, args_3: number): import("bun:ffi").Pointer;
60
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
61
+ };
62
+ mmapHuge: {
63
+ (args_0: number | bigint): import("bun:ffi").Pointer;
64
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
65
+ };
66
+ mmapPtr: {
67
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString): import("bun:ffi").Pointer;
68
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
69
+ };
70
+ mmapSize: {
71
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString): bigint;
72
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
73
+ };
74
+ munmap: {
75
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString): number;
76
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
77
+ };
78
+ madvise: {
79
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString, args_1: number | bigint, args_2: number): number;
80
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
81
+ };
82
+ mprotect: {
83
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString, args_1: number | bigint, args_2: number): number;
84
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
85
+ };
86
+ mlock: {
87
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString, args_1: number | bigint): number;
88
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
89
+ };
90
+ munlock: {
91
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString, args_1: number | bigint): number;
92
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
93
+ };
94
+ zero: {
95
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString, args_1: number | bigint): undefined;
96
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
97
+ };
98
+ copy: {
99
+ (args_0: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString, args_1: NodeJS.TypedArray<ArrayBufferLike> | import("bun:ffi").Pointer | import("bun:ffi").CString, args_2: number | bigint): undefined;
100
+ __ffi_function_callable: typeof import("bun:ffi").FFIFunctionCallableSymbol;
101
+ };
102
+ };
103
+ export { ptr, toArrayBuffer };
104
+ //# sourceMappingURL=ffi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffi.d.ts","sourceRoot":"","sources":["ffi.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAkB,GAAG,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAgF7D,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCf,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC"}
package/dist/ffi.js ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Bun FFI bindings to page_native library
3
+ */
4
+ import { dlopen, ptr, toArrayBuffer } from 'bun:ffi';
5
+ // Platform detection
6
+ const platform = process.platform;
7
+ const arch = process.arch;
8
+ // Resolve native library path
9
+ function getNativePath() {
10
+ const platformMap = {
11
+ 'darwin-arm64': 'darwin-arm64',
12
+ 'darwin-x64': 'darwin-x64',
13
+ 'linux-x64': 'linux-x64',
14
+ 'linux-x86': 'linux-x86',
15
+ 'linux-arm64': 'linux-arm64',
16
+ 'linux-arm': 'linux-arm',
17
+ 'win32-x64': 'windows-x64',
18
+ 'win32-x86': 'windows-x86',
19
+ 'win32-arm64': 'windows-arm64',
20
+ };
21
+ const key = `${platform}-${arch}`;
22
+ const platformDir = platformMap[key];
23
+ if (!platformDir) {
24
+ throw new Error(`Unsupported platform: ${key}`);
25
+ }
26
+ const libName = platform === 'win32' ? 'page_native.dll' : `libpage_native.dylib`;
27
+ return import.meta.dir + `/../native/${platformDir}/${libName}`;
28
+ }
29
+ // FFI symbol definitions
30
+ const symbols = {
31
+ // Page size
32
+ page_get_size: { returns: 'usize' },
33
+ page_is_4k: { returns: 'i32' },
34
+ page_is_16k: { returns: 'i32' },
35
+ page_get_huge_page_size: { returns: 'usize' },
36
+ page_get_platform: { returns: 'i32' },
37
+ page_align_size: { args: ['usize'], returns: 'usize' },
38
+ page_truncate_size: { args: ['usize'], returns: 'usize' },
39
+ page_is_aligned: { args: ['usize'], returns: 'i32' },
40
+ // Allocation
41
+ page_alloc: { args: ['usize'], returns: 'pointer' },
42
+ page_alloc_ptr: { args: ['pointer'], returns: 'pointer' },
43
+ page_alloc_size: { args: ['pointer'], returns: 'usize' },
44
+ page_free: { args: ['pointer'], returns: 'void' },
45
+ // mmap
46
+ page_mmap_anonymous: { args: ['usize', 'i32'], returns: 'pointer' },
47
+ page_mmap_file: { args: ['i32', 'usize', 'i64', 'i32'], returns: 'pointer' },
48
+ page_mmap_huge: { args: ['usize'], returns: 'pointer' },
49
+ page_mmap_ptr: { args: ['pointer'], returns: 'pointer' },
50
+ page_mmap_size: { args: ['pointer'], returns: 'usize' },
51
+ page_munmap: { args: ['pointer'], returns: 'i32' },
52
+ page_madvise: { args: ['ptr', 'usize', 'i32'], returns: 'i32' },
53
+ page_mprotect: { args: ['ptr', 'usize', 'i32'], returns: 'i32' },
54
+ page_mlock: { args: ['ptr', 'usize'], returns: 'i32' },
55
+ page_munlock: { args: ['ptr', 'usize'], returns: 'i32' },
56
+ // Utility
57
+ page_zero: { args: ['ptr', 'usize'], returns: 'void' },
58
+ page_copy: { args: ['ptr', 'ptr', 'usize'], returns: 'void' },
59
+ };
60
+ // Load the library
61
+ let lib;
62
+ try {
63
+ lib = dlopen(getNativePath(), symbols);
64
+ }
65
+ catch (e) {
66
+ throw new Error(`Failed to load page_native library for ${platform}-${arch}. ` +
67
+ `Make sure the native library is built for your platform. ` +
68
+ `Error: ${e}`);
69
+ }
70
+ // Export the FFI functions
71
+ export const ffi = {
72
+ // Page size
73
+ getSize: lib.symbols.page_get_size,
74
+ is4k: lib.symbols.page_is_4k,
75
+ is16k: lib.symbols.page_is_16k,
76
+ getHugePageSize: lib.symbols.page_get_huge_page_size,
77
+ getPlatform: lib.symbols.page_get_platform,
78
+ alignSize: lib.symbols.page_align_size,
79
+ truncateSize: lib.symbols.page_truncate_size,
80
+ isAligned: lib.symbols.page_is_aligned,
81
+ // Allocation
82
+ alloc: lib.symbols.page_alloc,
83
+ allocPtr: lib.symbols.page_alloc_ptr,
84
+ allocSize: lib.symbols.page_alloc_size,
85
+ free: lib.symbols.page_free,
86
+ // mmap
87
+ mmapAnonymous: lib.symbols.page_mmap_anonymous,
88
+ mmapFile: lib.symbols.page_mmap_file,
89
+ mmapHuge: lib.symbols.page_mmap_huge,
90
+ mmapPtr: lib.symbols.page_mmap_ptr,
91
+ mmapSize: lib.symbols.page_mmap_size,
92
+ munmap: lib.symbols.page_munmap,
93
+ madvise: lib.symbols.page_madvise,
94
+ mprotect: lib.symbols.page_mprotect,
95
+ mlock: lib.symbols.page_mlock,
96
+ munlock: lib.symbols.page_munlock,
97
+ // Utility
98
+ zero: lib.symbols.page_zero,
99
+ copy: lib.symbols.page_copy,
100
+ };
101
+ export { ptr, toArrayBuffer };
102
+ //# sourceMappingURL=ffi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffi.js","sourceRoot":"","sources":["ffi.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAU,GAAG,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7D,qBAAqB;AACrB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;AAClC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;AAE1B,8BAA8B;AAC9B,SAAS,aAAa;IACpB,MAAM,WAAW,GAA2B;QAC1C,cAAc,EAAE,cAAc;QAC9B,YAAY,EAAE,YAAY;QAC1B,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,WAAW;QACxB,aAAa,EAAE,aAAa;QAC5B,WAAW,EAAE,WAAW;QACxB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,aAAa;QAC1B,aAAa,EAAE,eAAe;KAC/B,CAAC;IAEF,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,sBAAsB,CAAC;IAClF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,cAAc,WAAW,IAAI,OAAO,EAAE,CAAC;AAClE,CAAC;AAED,yBAAyB;AACzB,MAAM,OAAO,GAAG;IACd,YAAY;IACZ,aAAa,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE;IACnC,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;IAC9B,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;IAC/B,uBAAuB,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE;IAC7C,iBAAiB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;IACrC,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;IACtD,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;IACzD,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IAEpD,aAAa;IACb,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE;IACnD,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE;IACzD,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;IACxD,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;IAEjD,OAAO;IACP,mBAAmB,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE;IACnE,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE;IAC5E,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE;IACvD,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE;IACxD,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;IACvD,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IAClD,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IAC/D,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IAChE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IACtD,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IAExD,UAAU;IACV,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;IACtD,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;CACrD,CAAC;AAEX,mBAAmB;AACnB,IAAI,GAA8C,CAAC;AAEnD,IAAI,CAAC;IACH,GAAG,GAAG,MAAM,CAAC,aAAa,EAAE,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAAC,OAAO,CAAC,EAAE,CAAC;IACX,MAAM,IAAI,KAAK,CACb,0CAA0C,QAAQ,IAAI,IAAI,IAAI;QAC9D,2DAA2D;QAC3D,UAAU,CAAC,EAAE,CACd,CAAC;AACJ,CAAC;AAED,2BAA2B;AAC3B,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,YAAY;IACZ,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa;IAClC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU;IAC5B,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW;IAC9B,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,uBAAuB;IACpD,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,iBAAiB;IAC1C,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,eAAe;IACtC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,kBAAkB;IAC5C,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,eAAe;IAEtC,aAAa;IACb,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU;IAC7B,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc;IACpC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,eAAe;IACtC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS;IAE3B,OAAO;IACP,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,mBAAmB;IAC9C,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc;IACpC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc;IACpC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa;IAClC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc;IACpC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW;IAC/B,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY;IACjC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa;IACnC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU;IAC7B,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY;IAEjC,UAAU;IACV,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS;IAC3B,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS;CAC5B,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC"}