forked from AssemblyScript/assemblyscript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrunner.js
117 lines (104 loc) · 3.4 KB
/
runner.js
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
export default function runner(exports, runs, allocs) {
const alloc = exports["heap_alloc"];
const free = exports["heap_free"];
const reset = exports["heap_reset"];
const fill = exports["memory_fill"];
const ptrs = [];
function randomAlloc(maxSize) {
if (!maxSize) maxSize = 8192;
let size = ((Math.random() * maxSize) >>> 0) + 1;
size = (size + 3) & ~3;
let ptr = alloc(size, 0);
if (!ptr) throw Error();
if ((ptr & 15) != 0) throw Error("invalid alignment: " + (ptr & 15) + " on " + ptr);
if (ptrs.indexOf(ptr) >= 0) throw Error("duplicate pointer");
if (fill) fill(ptr, ptr % 16, size);
ptrs.push(ptr);
return ptr;
}
function preciseFree(ptr) {
let idx = ptrs.indexOf(ptr);
if (idx < 0) throw Error("unknown pointer");
ptr = ptrs[idx];
ptrs.splice(idx, 1);
if (typeof ptr !== "number") throw Error();
free(ptr);
}
function randomFree() {
let idx = (Math.random() * ptrs.length) >>> 0;
let ptr = ptrs[idx];
if (typeof ptr !== "number") throw Error();
ptrs.splice(idx, 1);
free(ptr);
}
// remember the smallest possible memory address
let base = alloc(64, 0);
console.log("base: " + base);
try {
reset();
} catch (e) {
free(base);
}
let currentMem = exports.memory.buffer.byteLength;
console.log("mem initial: " + currentMem);
function testMemChanged() {
let actualMem = exports.memory.buffer.byteLength;
if (actualMem > currentMem) {
console.log("mem changed: " + currentMem + " -> " + actualMem);
currentMem = actualMem;
}
}
try {
for (let j = 0; j < runs; ++j) {
console.log("run " + (j + 1) + " (" + allocs + " allocations) ...");
for (let i = 0; i < allocs; ++i) {
let ptr = randomAlloc();
testMemChanged();
// immediately free every 4th
if (!(i % 4)) preciseFree(ptr);
// occasionally free random blocks
else if (ptrs.length && Math.random() < 0.33) randomFree();
// ^ sums up to clearing about half the blocks half-way
}
// free the rest, randomly
while (ptrs.length) randomFree();
try {
reset();
let ptr = alloc(64, 0);
if (ptr !== base) throw Error("expected " + base + " but got " + ptr);
reset();
} catch (e) {
// should now be possible to reuse the entire memory
// just try a large portion of the memory here, for example because of
// SL+1 for allocations in TLSF
let size = ((exports.memory.buffer.byteLength - base) * 9 / 10) >>> 0;
let ptr = alloc(size, 0);
// if (fill) fill(ptr, 0xac, size);
if (ptr !== base) throw Error("expected " + base + " but got " + ptr);
free(ptr);
}
testMemChanged();
}
} finally {
// mem(exports.memory, 0, 0x800);
}
}
/* function mem(memory, offset, count) {
if (!offset) offset = 0;
if (!count) count = 1024;
let mem = new Uint8Array(memory.buffer, offset);
// let stackTop = new Uint32Array(memory.buffer, 4, 1)[0];
let hex = [];
for (let i = 0; i < count; ++i) {
let o = (offset + i).toString(16);
while (o.length < 4) o = "0" + o;
if ((i & 15) === 0) {
hex.push("\n" + o + ":");
}
let h = mem[i].toString(16);
if (h.length < 2) h = "0" + h;
hex.push(h);
}
console.log(hex.join(" ") + " ...");
} */
if (typeof module === "object" && typeof exports === "object") module.exports = runner;