Replace the CCoinsViewCache interface with mostly just AccessCoins and ModifyCoins methods (see individual commits), and maintain metadata about cached entries.
This allows us to know when a transaction is fully spent before it is flushed, allowing us to forget about it entirely and never have it touch disk at all.
With this, I can -reindex the main chain until the last checkpoint with around 2GB (without any chainstate write to disk) of RSS. The final dump of the result to LevelDB takes 700MB extra.
Note that this is just a memory usage improvement, and not a performance optimization as such: it doesn't attempt to keep modified non-dirty entries in memory, or do negative caching.
This builds upon #4822, which may be simpler to review.