Fixing memory leaks due to Anonymous String Objects

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Fixing memory leaks due to Anonymous String Objects

phayter
For my ‘Project 13’, I decided to address what I believe to be a Jack language design weakness, specifically memory leakage due to Anonymous String Objects.

Anonymous String Objects (ASOs) are instantiated while compiling a subroutineCall’s expressionList which contains string constants. Since the ASOs are unnamed, there is no client technique for disposing of them and the OS has no garbage collection, hence the ASOs accumulate as memory leaks. In the compileTerm method of the CompilationEngine, only the compilation of a stringConstant allocates memory. So a stringConstant are the only anonymous objects instantiated by the compiler.

The approach to solving this memory leakage is based on extending the OS classes of Memory and String, as well as a few additions to the JackCompiler, which essentially extends the Jack OS. The basic strategy is to add ASO pointers to a list maintained by the extended Jack OS, and then dispose those ASOs upon a subroutine return using the pointers in the list. Adding ASO pointers is done when the string constants are instantiated but keeping (assigned) named strings off the list. In addition, the compiler does not permit returns from any OS calls to impact the list since OS calls are used to maintain the list (and OS subroutines do not have any ASOs in them anyway).

The extended String Class addresses the situation of an appendChar call exceeding its current maximum string length. The book leaves the resolution of this condition up to the OS programmer. The extension allocates more character memory to accommodate the appendChar call. Since the Jack language is not hard-typed, a string object can be used as a list or stack of pointers. To ease list / stack support an additional String method named lastChar, which returns top of stack (ie, a stack ‘peek’), has been added to the extended String Class.

The extended Memory Class uses a string named anonList, initialized in Memory.init, to hold ASO pointers. Memory Class extensions include anonListAdd, anonListRelease, and removeASO functions. Where, anonListAdd function adds a string pointer to the anonList. Where, anonListRelease function disposes the strings in the anonList. And where, removeASO function removes a specific string pointer from the anonList (such as a named / assigned string).

Compiler modifications invoke calls to the Memory Class extensions. All instantiated stringConstants are added to the anonList (by calling anonListAdd function). If that stringConstant is then assigned with a let statment,  then the pointer for that stringConstant is removed from the anonList (by calling the removeASO function). Just prior to return (after return values have been pushed onto the Hack stack) and if the subroutine is not an OS subroutine, the compiler inserts a call to anonListRelease so that ASOs are disposed.
Reply | Threaded
Open this post in threaded view
|

Re: Fixing memory leaks due to Anonymous String Objects

WBahn
Administrator
I agree that this is a weakness, particularly as it can occur with functions that are called in a loop.

Your approach sounds pretty nice, but one thing confuses me (I may just not be thinking things through correctly). Let's say that you call a subroutine with an string constant and then that function calls another subroutine with a string constant. It sounds like when the second function returns that it will release all of the ASOs, including the one that the first function may still be using?
Reply | Threaded
Open this post in threaded view
|

Re: Fixing memory leaks due to Anonymous String Objects

phayter
Thanks for the feedback. You are right, my solution does not handle this (rather obvious) case. Other test cases including recursion with different ASOs did pass, but that matters little...

To achieve a complete solution the anonList needs to be managed as a stack and not as a list. There are sufficient methods in my String class to manage a stack. I would add a sentinel so that each return only releases the ASOs for that subroutine.