aboutsummaryrefslogtreecommitdiffhomepage
path: root/targets/wasm_exec.js
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2020-04-06 23:12:41 +0200
committerRon Evans <[email protected]>2020-04-12 18:41:34 +0200
commit5674c35e1477e21eaafab3a51241d84e47a679dd (patch)
tree61f0e3de2998e0163af6f976c7dd67523ea757a7 /targets/wasm_exec.js
parent0f9038ad2e8609e173a9a9916915cb4e982a5836 (diff)
downloadtinygo-5674c35e1477e21eaafab3a51241d84e47a679dd.tar.gz
tinygo-5674c35e1477e21eaafab3a51241d84e47a679dd.zip
wasm: backport "garbage collect references to JavaScript values"
See commit: https://github.com/golang/go/commit/54e6ba6724dfde355070238f9abc16362cac2e3d Warning: this will drop support for Go 1.13 for WebAssembly targets! I have modified the integration tests to specifically blacklist Go 1.13 instead of whitelisting any other version, to avoid accidentally not testing WebAssembly.
Diffstat (limited to 'targets/wasm_exec.js')
-rw-r--r--targets/wasm_exec.js40
1 files changed, 27 insertions, 13 deletions
diff --git a/targets/wasm_exec.js b/targets/wasm_exec.js
index 85f147cd0..4c8790667 100644
--- a/targets/wasm_exec.js
+++ b/targets/wasm_exec.js
@@ -202,26 +202,31 @@
return;
}
- let ref = this._refs.get(v);
- if (ref === undefined) {
- ref = this._values.length;
- this._values.push(v);
- this._refs.set(v, ref);
+ let id = this._ids.get(v);
+ if (id === undefined) {
+ id = this._idPool.pop();
+ if (id === undefined) {
+ id = this._values.length;
+ }
+ this._values[id] = v;
+ this._goRefCounts[id] = 0;
+ this._ids.set(v, id);
}
- let typeFlag = 0;
+ this._goRefCounts[id]++;
+ let typeFlag = 1;
switch (typeof v) {
case "string":
- typeFlag = 1;
+ typeFlag = 2;
break;
case "symbol":
- typeFlag = 2;
+ typeFlag = 3;
break;
case "function":
- typeFlag = 3;
+ typeFlag = 4;
break;
}
mem().setUint32(addr + 4, nanHead | typeFlag, true);
- mem().setUint32(addr, ref, true);
+ mem().setUint32(addr, id, true);
}
const loadSlice = (array, len, cap) => {
@@ -284,6 +289,13 @@
setTimeout(this._inst.exports.go_scheduler, timeout);
},
+ // func finalizeRef(v ref)
+ "syscall/js.finalizeRef": (sp) => {
+ // Note: TinyGo does not support finalizers so this should never be
+ // called.
+ console.error('syscall/js.finalizeRef not implemented');
+ },
+
// func stringVal(value string) ref
"syscall/js.stringVal": (ret_ptr, value_ptr, value_len) => {
const s = loadString(value_ptr, value_len);
@@ -405,7 +417,7 @@
async run(instance) {
this._inst = instance;
- this._values = [ // TODO: garbage collection
+ this._values = [ // JS values that Go currently has references to, indexed by reference id
NaN,
0,
null,
@@ -414,8 +426,10 @@
global,
this,
];
- this._refs = new Map();
- this.exited = false;
+ this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
+ this._ids = new Map(); // mapping from JS values to reference ids
+ this._idPool = []; // unused ids that have been garbage collected
+ this.exited = false; // whether the Go program has exited
const mem = new DataView(this._inst.exports.memory.buffer)