avoid WeakKeyDict, since it causes finalizer-order confusion in Julia