Skip to content

Commit

Permalink
[flow] cache vals in Ssa_val.simplify_val
Browse files Browse the repository at this point in the history
Summary:
We can cache the ssa IDs that are simplified per file to avoid duplicate work.

Changelog: [internal]

Reviewed By: gkz

Differential Revision: D62327411

fbshipit-source-id: 3ce4efe0ce86f29c16ca82b22dd26661ef4dfe84
  • Loading branch information
panagosg7 authored and facebook-github-bot committed Sep 7, 2024
1 parent f75d454 commit e9870c4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 45 deletions.
9 changes: 5 additions & 4 deletions src/analysis/env_builder/name_resolver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,7 @@ module Make (Context : C) (FlowAPIUtils : F with type cx = Context.t) :
(Error_message.EBindingError (Error_message.ENameAlreadyBound, loc, name, def_loc))
| _ -> ()
in
let val_simplify = Val.simplify ~cache:(ref IMap.empty) in

let enable_enums = Context.enable_enums cx in
object (this)
Expand Down Expand Up @@ -1121,7 +1122,7 @@ module Make (Context : C) (FlowAPIUtils : F with type cx = Context.t) :
method values : Env_api.values =
L.LMap.map
(fun { def_loc; value; val_binding_kind; name } ->
Val.simplify def_loc val_binding_kind name value)
val_simplify def_loc val_binding_kind name value)
env_state.values

method refinement_invalidation_info = env_state.refinement_invalidation_info
Expand Down Expand Up @@ -3876,7 +3877,7 @@ module Make (Context : C) (FlowAPIUtils : F with type cx = Context.t) :

let { val_ref; _ } = this#env_read maybe_exhaustively_checked_var_name in
let { Env_api.write_locs; _ } =
Val.simplify None Val.InternalBinding None !val_ref
val_simplify None Val.InternalBinding None !val_ref
in
let (locs, undeclared) =
Base.List.fold
Expand Down Expand Up @@ -3996,7 +3997,7 @@ module Make (Context : C) (FlowAPIUtils : F with type cx = Context.t) :

let { val_ref; _ } = this#env_read maybe_exhaustively_checked_var_name in
let { Env_api.write_locs; _ } =
Val.simplify None Val.InternalBinding None !val_ref
val_simplify None Val.InternalBinding None !val_ref
in
let (locs, undeclared) =
Base.List.fold
Expand Down Expand Up @@ -5666,7 +5667,7 @@ module Make (Context : C) (FlowAPIUtils : F with type cx = Context.t) :
else
!val_ref
in
let v = Val.simplify def_loc (Val.SourceLevelBinding kind) (Some name) v in
let v = val_simplify def_loc (Val.SourceLevelBinding kind) (Some name) v in
v

method! declare_module _loc ({ Ast.Statement.DeclareModule.id = _; body; _ } as m) =
Expand Down
88 changes: 48 additions & 40 deletions src/analysis/env_builder/ssa_val.ml
Original file line number Diff line number Diff line change
Expand Up @@ -297,44 +297,52 @@ let providers locs =
locs
)

let rec simplify_val t =
let vals = normalize t.write_state in
Base.List.map
~f:(function
| Uninitialized l
when WriteSet.for_all
(function
| IllegalWrite _
| Uninitialized _ ->
true
| _ -> false)
vals ->
Env_api.Uninitialized (mk_reason RUninitialized l)
| Undefined r -> Env_api.Undefined r
| Number r -> Env_api.Number r
| DeclaredFunction l -> Env_api.DeclaredFunction l
| Undeclared (name, loc)
| DeclaredButSkipped (name, loc) ->
Env_api.Undeclared (name, loc)
| Uninitialized l -> Env_api.Uninitialized (mk_reason RPossiblyUninitialized l)
| Projection loc -> Env_api.Projection loc
| FunctionThis r -> Env_api.FunctionThis r
| GlobalThis r -> Env_api.GlobalThis r
| IllegalThis r -> Env_api.IllegalThis r
| ClassInstanceThis r -> Env_api.ClassInstanceThis r
| ClassStaticThis r -> Env_api.ClassStaticThis r
| ClassInstanceSuper r -> Env_api.ClassInstanceSuper r
| ClassStaticSuper r -> Env_api.ClassStaticSuper r
| Loc r -> Env_api.Write r
| EmptyArray { reason; arr_providers } -> Env_api.EmptyArray { reason; arr_providers }
| IllegalWrite r -> Env_api.IllegalWrite r
| Refinement { refinement_id; val_t } ->
Env_api.Refinement { writes = simplify_val val_t; refinement_id; write_id = Some val_t.id }
| ModuleScoped name -> Env_api.ModuleScoped name
| Global name -> Env_api.Global name
| PHI _ ->
raise Env_api.(Env_invariant (None, Impossible "A normalized value cannot be a PHI")))
(WriteSet.elements vals)
let rec simplify_val cache t =
match IMap.find_opt t.id !cache with
| Some v -> v
| None ->
let vals = normalize t.write_state in
let result =
Base.List.map
~f:(function
| Uninitialized l
when WriteSet.for_all
(function
| IllegalWrite _
| Uninitialized _ ->
true
| _ -> false)
vals ->
Env_api.Uninitialized (mk_reason RUninitialized l)
| Undefined r -> Env_api.Undefined r
| Number r -> Env_api.Number r
| DeclaredFunction l -> Env_api.DeclaredFunction l
| Undeclared (name, loc)
| DeclaredButSkipped (name, loc) ->
Env_api.Undeclared (name, loc)
| Uninitialized l -> Env_api.Uninitialized (mk_reason RPossiblyUninitialized l)
| Projection loc -> Env_api.Projection loc
| FunctionThis r -> Env_api.FunctionThis r
| GlobalThis r -> Env_api.GlobalThis r
| IllegalThis r -> Env_api.IllegalThis r
| ClassInstanceThis r -> Env_api.ClassInstanceThis r
| ClassStaticThis r -> Env_api.ClassStaticThis r
| ClassInstanceSuper r -> Env_api.ClassInstanceSuper r
| ClassStaticSuper r -> Env_api.ClassStaticSuper r
| Loc r -> Env_api.Write r
| EmptyArray { reason; arr_providers } -> Env_api.EmptyArray { reason; arr_providers }
| IllegalWrite r -> Env_api.IllegalWrite r
| Refinement { refinement_id; val_t } ->
Env_api.Refinement
{ writes = simplify_val cache val_t; refinement_id; write_id = Some val_t.id }
| ModuleScoped name -> Env_api.ModuleScoped name
| Global name -> Env_api.Global name
| PHI _ ->
raise Env_api.(Env_invariant (None, Impossible "A normalized value cannot be a PHI")))
(WriteSet.elements vals)
in
cache := IMap.add t.id result !cache;
result

type val_binding_kind =
(* A source level binding is something we can point to a user and say that the definition
Expand All @@ -345,8 +353,8 @@ type val_binding_kind =
| InternalBinding

(* Simplification converts a Val.t to a list of locations. *)
let simplify def_loc val_binding_kind name value =
let write_locs = simplify_val value in
let simplify ~cache def_loc val_binding_kind name value =
let write_locs = simplify_val cache value in
let val_kind =
match val_binding_kind with
| SourceLevelBinding (Bindings.Type { imported; type_only_namespace }) ->
Expand Down
8 changes: 7 additions & 1 deletion src/analysis/env_builder/ssa_val.mli
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,13 @@ type val_binding_kind =
| SourceLevelBinding of Bindings.kind
| InternalBinding

val simplify : ALoc.t option -> val_binding_kind -> string option -> t -> Env_api.read
val simplify :
cache:Env_api.write_locs IMap.t ref ->
ALoc.t option ->
val_binding_kind ->
string option ->
t ->
Env_api.read

val id_of_val : t -> int

Expand Down

0 comments on commit e9870c4

Please sign in to comment.