Skip to content

Commit b5ffaf3

Browse files
committed
Portable not-so-smart Heap
1 parent d0b189b commit b5ffaf3

File tree

4 files changed

+54
-13
lines changed

4 files changed

+54
-13
lines changed

portable-assembly.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ declare function select<T>(ifTrue: T, ifFalse: T, condition: bool): T;
4141
declare function sqrt<T = f32 | f64>(value: T): T;
4242
/** Rounds to the nearest integer towards zero of a 32-bit or 64-bit float. */
4343
declare function trunc<T = f32 | f64>(value: T): T;
44+
/** Loads a value of the specified type from memory. Type must be `u8`. */
45+
declare function load<T = u8>(offset: usize): T;
46+
/** Stores a value of the specified type to memory. Type must be `u8`. */
47+
declare function store<T = u8>(offset: usize, value: T): void;
4448
/** Emits an unreachable operation that results in a runtime error when executed. */
4549
declare function unreachable(): any; // sic
4650

src/glue/js.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
require("../../portable-assembly"); // not inherited from tsconfig by ts-node otherwise :(
1+
require("../../portable-assembly");
22

33
// Copy Binaryen exports to global scope
44
var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self;
@@ -13,9 +13,17 @@ for (var key in binaryen)
1313
globalScope[key] = binaryen[key];
1414

1515
// Use Binaryen's heap
16-
Object.defineProperties(globalScope['Heap'] = {
17-
allocate: binaryen._malloc,
18-
dispose: binaryen._free
16+
Object.defineProperties(globalScope["Heap"] = {
17+
allocate: function allocate(size) {
18+
if (!size) return 0; // should be safe in our case
19+
return binaryen._malloc(size);
20+
},
21+
dispose: function dispose(ptr) {
22+
if (ptr) binaryen._free(ptr);
23+
},
24+
copy: function copy(dest, src, n) {
25+
return binaryen._memcpy(dest, src, n);
26+
}
1927
}, {
2028
free: { get: function() { return binaryen.HEAPU8.length; } },
2129
used: { get: function() { return 0; } },
@@ -24,7 +32,7 @@ Object.defineProperties(globalScope['Heap'] = {
2432
globalScope["store"] = function store(ptr, val) {
2533
binaryen.HEAPU8[ptr] = val;
2634
};
27-
globalScope["load"] = function load_u8(ptr) {
35+
globalScope["load"] = function load(ptr) {
2836
return binaryen.HEAPU8[ptr];
2937
};
3038

std/assembly/heap.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ let HEAP_OFFSET: usize = HEAP_START; // HEAP_START is a constant generated by th
99
class Heap {
1010

1111
static allocate(size: usize): usize {
12+
if (!size) return 0;
13+
const len: i32 = current_memory();
14+
if (HEAP_OFFSET + size > <usize>len << 16)
15+
if(grow_memory(max<i32>(<i32>ceil<f64>(<f64>size / 65536), len * 2 - len)) < 0)
16+
unreachable();
1217
const ptr: usize = HEAP_OFFSET;
13-
assert(ptr + size <= (<usize>current_memory() << 16));
14-
if (((HEAP_OFFSET += size) & ALIGN_MASK) != 0) // align next offset
18+
if ((HEAP_OFFSET += size) & ALIGN_MASK) // align next offset
1519
HEAP_OFFSET = (HEAP_OFFSET | ALIGN_MASK) + 1;
1620
return ptr;
1721
}

std/portable/heap.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
11
var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self;
22

3-
globalScope["Heap"] = {
4-
allocate: function() { throw new Error("not implemented"); },
5-
dispose: function() { throw new Error("not implemented"); },
6-
used: 0,
7-
free: 0,
8-
size: 0
3+
var HEAP = new Uint8Array(65536);
4+
var HEAP_OFFSET = 0;
5+
6+
Object.defineProperties(globalScope["Heap"] = {
7+
allocate: function allocate(size) {
8+
if (!size) return 0;
9+
if (HEAP_OFFSET + size > HEAP.length) {
10+
var oldHeap = HEAP;
11+
HEAP = new Uint8Array(Math.max(HEAP.length + size, HEAP.length * 2));
12+
HEAP.set(oldHeap);
13+
}
14+
var ptr = HEAP_OFFSET;
15+
if ((HEAP_OFFSET += size) & 7)
16+
HEAP_OFFSET = (HEAP_OFFSET | 7) + 1;
17+
return ptr;
18+
},
19+
dispose: function dispose() { },
20+
copy: function copy(dest, src, n) {
21+
HEAP.set(HEAP.subarray(src, src + n), dest);
22+
return dest;
23+
}
24+
}, {
25+
used: { get: function get_used() { return HEAP_OFFSET; } },
26+
free: { get: function get_free() { return HEAP.length - HEAP_OFFSET; } },
27+
size: { get: function get_size() { return HEAP.length; } }
28+
});
29+
globalScope["store"] = function store(ptr, val) {
30+
binaryen.HEAPU8[ptr] = val;
31+
};
32+
globalScope["load"] = function load(ptr) {
33+
return binaryen.HEAPU8[ptr];
934
};

0 commit comments

Comments
 (0)