Several Memory Related Performance Improvements

1) reuse working memory. Each hash algorithm has a buffer of working
memory that they process data in. Since javascript is single threaded
and this operation is sync, we only need one buffer for the class, not per thread.
This saves a lot of time allocating memory.

2) add Hash.init() method to reinitialize a hash algorithm.
This makes it possible to reuse an instance again, so there is less objects
created and less GC. This makes a difference in iterated hashing (i.e. pbkdf2)
Although, this doesn't make such a big difference after 1), it's still measurable.

3) pooling hash instances. Save created hash instances in an array, and when the user
is finished, keep it for next time. This makes a difference to the crypto-bench/bench-hash
benchmark, which was going very weirdly... doing lots of large hashes after each other
was slow, but just doing the largest hash was 3x faster??? now performance is same
no matter how many large hashes you do.
I'm still seeing a little bit of wobble there. maybe it's related to the encoding stage?
2.1.0