-
Notifications
You must be signed in to change notification settings - Fork 0
/
mem-utils.js
102 lines (88 loc) · 2.89 KB
/
mem-utils.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
const assert = require("assert");
const { LRUMap } = require("lru_map");
const utf8Encoder = new TextEncoder("utf-8");
const utf8Decoder = new TextDecoder("utf-8");
module.exports = function(memory, wasmInstance) {
const memViews = {
int8: new Int8Array(memory.buffer),
uint8: new Uint8Array(memory.buffer),
uint8Clamped: new Uint8ClampedArray(memory.buffer),
int16: new Int16Array(memory.buffer),
uint16: new Uint16Array(memory.buffer),
int32: new Int32Array(memory.buffer),
uint32: new Uint32Array(memory.buffer),
float32: new Float32Array(memory.buffer),
float64: new Float64Array(memory.buffer)
};
const { _malloc, _sizeof_unsigned_long } = wasmInstance.exports;
const wordSize = _sizeof_unsigned_long();
const memWordView = memViews[`uint${wordSize * 8}`];
const memSwordView = memViews[`int${wordSize * 8}`];
const wordLimit = Math.pow(2, wordSize * 8);
const registerSize = 16;
const numRegisters = 8;
const registersBeginPtr = _malloc(registerSize * numRegisters);
const initRegister = Symbol("initRegister");
const clearRegister = Symbol("clearRegister");
const registersObjMap = new LRUMap(numRegisters);
registersObjMap.assign([...Array(numRegisters).keys()].map(n => [n, null]));
registersObjMap.shift = function shift() {
const [n, obj] = LRUMap.prototype.shift.call(this);
if (obj != null) {
obj[clearRegister](getRegisterPtr(n));
objsRegisterNumMap.delete(obj);
}
return [n, obj];
};
const objsRegisterNumMap = new WeakMap();
function getRegisterPtr(n) {
assert(
Number.isInteger(n) && n >= 0 && n < numRegisters,
`invalid register number ${n}`
);
return registersBeginPtr + n * registerSize;
}
function ensureRegister(obj) {
let registerPtr;
if (objsRegisterNumMap.has(obj)) {
n = objsRegisterNumMap.get(obj);
assert(
registersObjMap.get(n) === obj,
`wrong object found in register ${n}`
);
registerPtr = getRegisterPtr(n);
} else {
n = registersObjMap.shift()[0];
registerPtr = getRegisterPtr(n);
registersObjMap.set(n, obj);
objsRegisterNumMap.set(obj, n);
obj[initRegister](registerPtr);
}
return registerPtr;
}
return {
isWord(n) {
return Number.isInteger(n) && n >= 0 && n < wordLimit;
},
isSword(n) {
return Number.isInteger(n) && n * 2 >= -wordLimit && n * 2 < wordLimit;
},
ensureRegister,
initRegister,
clearRegister,
registerSize,
memViews,
stringToNewCStr(str) {
const b = utf8Encoder.encode(str);
const ptr = _malloc(b.length + 1);
memViews.uint8.set(b, ptr);
memViews.uint8[ptr + b.length] = 0;
return ptr;
},
cstrToString(ptr) {
let length;
for (length = 0; memViews.uint8[ptr + length] !== 0; ++length);
return utf8Decoder.decode(new DataView(memory.buffer, ptr, length));
}
};
};