[COREVM-82] Refactor dynamic object heap

Currently `dynamic_object_heap` uses `std::unordered_map` internally to keep track of a mapping of object IDs to dynamic objects. However, this raises the problem of "hole" left among ID the entire range (please refer to COREVM-72 for more details). The problem can be fixed by refactoring, or reimplementing the underlying internal structure of the object heap. The heap can be refactored so that it directly talks to the allocator and uses the addresses of objects as IDs, and provides an iterator interface to iterate through all the active objects on the allocator.

The new underlying storage for dynamic objects is the `dynamic_object_container`, which was added in #20.