Refactor `dill` logic
Refactor the `dill` logic to make it easier to maintain (and fix some issues along the way)

It makes the following improvements to the serialization API:
* consistent order of a `dict`'s keys
* support for hashing `torch.compile`-ed modules and functions
* deprecates `datasets.fingerprint.hashregister` as the `hashregister`-ed reducers are never invoked anyways (does not support nested data as `pickle`/`dill` do)


~~TODO: optimize hashing of `pa.Table` and `datasets.table.Table`~~ The `pa_array.to_string` approach is faster for large arrays because it outputs the first 10 and last 10 elements (by default). The problem is that this can produce identical hashes for non-identical arrays if their differing elements get ellipsed...
 
Fix https://github.com/huggingface/datasets/issues/6440, fix https://github.com/huggingface/datasets/issues/5839