Introduce dynamic heap management

* improves the memory footprint and does not increase execution time.
* heapSize doubles every time we are running out of space after a GC
  or allocated a too big chunk (>= 10%) outside of the _baseBlock.
* allocations when the heap is too filled are done with regular malloc,
  and promptly freed after as we request a GC.
* --min-memory and --max-memory are respected.
* allow to run 2 gc consecutively. This happens when we need to change
  the heap size. As the only reliable measurement is the activeMemory,
  which is only available after a GC, and we need to do another GC
  to transfer the heap to the bigger block.
Guess the next active size when doing an allocation outside of the base block

* Avoids the double GC pattern for huge allocations.
  It was especially bad since it most likely meant
  doing another extra allocation during the first GC.