Rework how HHBBC analyzes public static properties
commit48bbf465e32e4b1387af23632ad6bccc5c2a0787
authorRick Lavoie <rlavoie@fb.com>
Fri, 11 Jan 2019 17:09:35 +0000 (11 09:09 -0800)
committerHhvm Bot <hhvm-bot@users.noreply.github.com>
Fri, 11 Jan 2019 17:16:01 +0000 (11 09:16 -0800)
tree1f846313b8b28d8e0c1dff60817f8a58d7bfefb5
parent9963b7c1ae08076af891c237b1409011d2d92d92
Rework how HHBBC analyzes public static properties

Summary:
HHBBC analyzes public static properties differently than private
static/non-static properties (public non-static properties aren't analyzed at
all). Those can be analyzed from Bottom to a fixed point while doing class
analysis because its guaranteed all of their accesses will be within that
class. No such guarantee exists for a public static property.

Instead the analysis is performed closer to that of a function's return
value. That is, the type starts out as TGen in the Index, and it is refined as a
result of the accesses seen during the analysis round. Like anything out in the
Index, this guarantees that the type is always correct (we don't have to reach a
fixed point).

HHBBC performs one full set of analysis rounds knowing nothing about public
static property types (the Index returns TGen). Then it performs a single
analysis round (not a full set), gathering all of the mutations of public static
properties. These mutations then refine the types in the Index, and another full
set of analysis rounds are performed, using the updated public static
information in the Index.

This all works, but its inefficient. First of all, we have to perform an extra
single analysis round over all of the functions. Then, we have to perform an
extra full set of analysis. This is because we do not record any dependencies of
which functions are actually using the public static property information, so we
have to schedule everything. This second full set convergences relatively
quickly, but the first round still takes a while. Finally, all this extra work
is of little benefit because we only iterate on the public static property
information once.

Let's do this a bit differently. First of all, record dependencies between
functions and the public static property information they query. This involves
adding a new type dependency representing a public static property name. Discard
the separate public static property pass. Instead every function analysis round
always records the public static property mutations it sees in its
FuncAnalysis. The Index stores the gathered mutations for each function. As the
analysis is completed, the Index is updated with the mutations from the
FuncAnalysis. If a function hasn't been analyzed in the current round, its
gathered set of mutations will persist from when it was last analyzed. Once all
functions have been such processed, we refine the public static property
information in the Index by unioning together all the mutations for each
property. Any property which has a type refined will reschedule any function
with a dependency on it.

With this change we only need to perform one full set of analysis and we'll
continue until all the public static properties stop refining. This exposed a
bug in that we weren't recording possible public static property mutations when
updating base information in interp-minstr.cpp which we probably only got away
with because we only iterated once. Fix that.

Reviewed By: markw65

Differential Revision: D13620784

fbshipit-source-id: 6151b13fd54a0faf1f4bc7a6adc6cd8972f2dbb5
16 files changed:
hphp/hhbbc/analyze.cpp
hphp/hhbbc/analyze.h
hphp/hhbbc/dce.cpp
hphp/hhbbc/debug.cpp
hphp/hhbbc/emit.cpp
hphp/hhbbc/index.cpp
hphp/hhbbc/index.h
hphp/hhbbc/interp-minstr.cpp
hphp/hhbbc/interp-state.cpp
hphp/hhbbc/interp-state.h
hphp/hhbbc/interp.cpp
hphp/hhbbc/main.cpp
hphp/hhbbc/optimize.cpp
hphp/hhbbc/options.h
hphp/hhbbc/stats.cpp
hphp/hhbbc/whole-program.cpp