Garbage collect the intern symbol table

Symbols created by the compiler, or that are hard-coded as class
constants now use SymbolTerm.intern() to cache the SymbolTerm and
try to reuse the same instance across all locations that use it.
Strings are interned using the Java interning system, ensuring at
most 1 copy of the String object exists in the heap.

Symbols created dynamically on the fly by builtin predicates are
allocated directly and not stored in the cache. This slows down
any evaluation, as the symbol must be compared one character at
a time, however String.equals() should be faster here than doing
the HashMap lookup on each wrapping of a String into a SymbolTerm.

To reduce the risk of leaks, the symbol table now uses WeakReferences
to hold onto the cached SymbolTerm and SymbolTerm.gc() is invoked
cleaning out any dead references whenever the interpreter stops
goal evaluation.
50 files changed