https://github.com/AssemblyScript/assemblyscript/blob/master/std/assembly/map.ts#L61
Memory leak here at Map#clear
Proposed fix:
clear(): void {
const bucketsSize = INITIAL_CAPACITY * <i32>BUCKET_SIZE;
// check to see if buckets exists and free it before setting it to a new array buffer
if (this.buckets != null) memory.free(changetype<usize>(this.buckets));
this.buckets = new ArrayBuffer(bucketsSize);
this.bucketsMask = INITIAL_CAPACITY - 1;
const entriesSize = INITIAL_CAPACITY * <i32>ENTRY_SIZE<K,V>();
// check to see if entries exists and free it before setting it to a new array buffer
if (this.entries!= null) memory.free(changetype<usize>(this.entries));
this.entries = new ArrayBuffer(entriesSize, true);
this.entriesCapacity = INITIAL_CAPACITY;
this.entriesOffset = 0;
this.entriesCount = 0;
}
I don't want to submit a new pull request without making sure I know what I'm talking about. Any ideas?
Current stdlib anticipates the presence of GC, and ArrayBuffer is a managed object so is cleared by GC, not manually. Have you tried using ITCM with manual gc.collect() calls?
@dcodeIO I'm at a complete loss for how to do this sort of thing. I don't know what ITCM is, or how the gc works. Is there documentation on this?
I'm guessing this is something I need to learn and I don't know where to find this information.
To use the GC, do:
import "allocator/tlsf";
import "collector/itcm";
and whenever you need to free memory (this can only be done manually currently), do
gc.collect();
I've imported the gc as you have suggested, and now I run into a runtime error. It looks like there's a problem within the step() function inside the gc. Is there something I'm missing?
index.js:210 Uncaught (in promise) RuntimeError: function signature mismatch
at ~lib/collector/itcm/step (wasm-function[37]:172)
at ~lib/collector/itcm/__gc_allocate (wasm-function[38]:15)
at ~lib/array/Array<i32>#constructor (wasm-function[77]:53)
at assembly/primitives/CanvasMap/CanvasRenderingContext2DInitializer#getOptimized (wasm-function[99]:93)
at assembly/example/init (wasm-function[102]:8)
at Object.wrap [as init] (http://localhost:1234/demo-src.e31bb0bc.js:4437:12)
at _callee$ (http://localhost:1234/demo-src.e31bb0bc.js:4727:50)
at tryCatch (http://localhost:1234/demo-src.e31bb0bc.js:152:40)
at Generator.invoke [as _invoke] (http://localhost:1234/demo-src.e31bb0bc.js:378:22)
at Generator.prototype.(anonymous function) [as next] (http://localhost:1234/demo-src.e31bb0bc.js:204:21)
I notice that it's calling ~lib/array/Array<i32>#constructor, and I'm definitely not constructing an Array<i32>. I assume that's because it's trying to initialize an array of references. Are there pitfalls I need to avoid, or is there a bug here?
The source starts here on this line:
https://github.com/jtenner/canvas-as/blob/master/assembly/primitives/CanvasMap.ts#L19
It's not well tested, yet, so there might be issues. What about the array at public used: string[] = new Array<string>(0);?
I don't think so, because the error occurs when I call getOptimized() like it suggests in the stack trace. It's saying that an array is being constructed in a function that isn't even constructing an array:
at ~lib/array/Array<i32>#constructor (:1234/wasm-function[70]:36)
at assembly/primitives/CanvasMap/CanvasRenderingContext2DInitializer#getOptimized (:1234/wasm-function[98]:196)
at assembly/example/init (:1234/wasm-function[101]:8)
Edit: Just to make sure, I commented out the property and the if statements that use the string array. It looks like it's not related.
The untouched wat file shows construction of an Array
https://github.com/jtenner/canvas-as/blob/master/build/untouched.wat#L5532
Looks like those might be the culprits.
GC itself doesn't construct managed objects, so it must be something else. For example OptimizedCanvasRenderingContext2D, which is instantiated there, contains a lot of arrays on its private properties that, since OptimizedCanvasRenderingContext2D doesn't have a constructor, are constructed and assigned on new OptimizedCanvasRenderingContext2D.
When it generates an Array<enum> it would be generating an Array<i32> as a consequence. It must be one of those. You are right. I just can't seem to replicate the problem on wasm studio as an example.
Edit: Yes it's inlining the "default" constructor because no constructor exists.
Closing this issue for now as it hasn't received any replies recently. Feel free to reopen it if necessary!
Most helpful comment
I don't want to submit a new pull request without making sure I know what I'm talking about. Any ideas?