move the dispatch table to be per-instance

visitors are not shared among threads, so any mutations to the cache
should be OK.  The cache is also pre-populated on construction, but we
should pull that out so we can share the cache among visitors in the
future.