Defered_decl global mutable state
commit0d267c6165c90c1aa0811bd27c20bf01a9d85f13
authorLucian Wischik <ljw@fb.com>
Wed, 11 Dec 2019 06:46:22 +0000 (10 22:46 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 11 Dec 2019 06:51:50 +0000 (10 22:51 -0800)
tree878e895bde50bde196473917a51b4fd71bde5495
parenta84647cb574284b175395aca818e897a2d640937
Defered_decl global mutable state

Summary:
My goal is that, when we typecheck, we can count how many decls needed to be fetched. I want to count that both for bulk typechecking invoked by `serverTypeCheck.do_typechecking` where it already happens (it invokes `Typing_check_service.go_with_interrupt` > `process_files`, or `process_in_parallel` > `process_files`). And also in `Provider_utils.compute_tast_and_errors_unquarantined` which is used by serverless-IDE and by hh_server to answer several smaller queries here and there.

Defered_decls uses a bunch of mutable global state which makes this tricky -- e.g. can we reliably be working with that mutable state within `process_files`, and then handle an interrupt that wants its own decl counter, and then resume?

The answer is a fragile "yes we can" because of the invariant that each `process_file` call never itself gets interrupted, and `Deferred_decl.reset` gets called at the start of each `process_file`, and the state is never read after the end before being reset by the next `process_file`. But I don't want to be fragile.

Hence this diff.

First, it introduces the API `Deferred_decl.restore_state`. The idea is that anyone who wants to do some local work can call `Deferred_decl.reset` as normal. But now it returns the previous global-mutable-state. Thus, when you've finished your local work, you can call `Deferred_decl.restore_state` so that other work can continue fine.

In this way we can locally enforce the non-interference, rather than relying on a fragile global invariant.

Second, this diff moves `threshold`. Previously it was being fetched by `typing_classes_heap` out of the global mutable variable `GlobalNamingOptions.opt`, and was being fetched each time a decl needed to be fetched. But for my purposes I wanted the local typecheck to never have a threshold. Therefore I'm making it so it's a part of the Deferred-decl state.

Reviewed By: 2BitSalute

Differential Revision: D18879092

fbshipit-source-id: bdfeb0dcd90ae5bd16f2804528418f8501b21fe8
hphp/hack/src/typing/deferred_decl.ml
hphp/hack/src/typing/typing_check_service.ml
hphp/hack/src/typing/typing_classes_heap.ml
hphp/hack/test/unit/server_tests.ml