In my simulator, I definitely had to cache this, because it's checked so many times per turn. I got at least a 2x speedup when I did.
My strategy: check if there's a cached value for gainsToEndGame, and return it if so. Otherwise, calculate it and put it in the cache. Whenever a card is gained or returned to the Supply, clear the cached value.
(I clear the value instead of recalculating it right then, because multiple cards could be gained in quick succession, with no need to calculate gainsToEndGame in between.)