[backend] try not to re-allocate too much when normalizing props

Summary:
The goal is not to end up with a deep copy when nothing has changed, as this
puts lots of pressure on the memory.

Reviewed By: mbouaziz

Differential Revision: D7113976

fbshipit-source-id: 1b85ecd
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent 1f04a5eda0
commit 8df15e2f00

@ -1078,7 +1078,7 @@ module Normalize = struct
in in
let e' = eval e in let e' = eval e in
(* L.d_str "sym_eval "; Sil.d_exp e; L.d_str" --> "; Sil.d_exp e'; L.d_ln (); *) (* L.d_str "sym_eval "; Sil.d_exp e; L.d_str" --> "; Sil.d_exp e'; L.d_ln (); *)
e' if Exp.equal e e' then e else e'
let exp_normalize ?destructive tenv sub exp = let exp_normalize ?destructive tenv sub exp =
@ -1089,9 +1089,12 @@ module Normalize = struct
let texp_normalize tenv sub (exp: Exp.t) : Exp.t = let texp_normalize tenv sub (exp: Exp.t) : Exp.t =
match exp with match exp with
| Sizeof ({dynamic_length} as sizeof_data) -> | Sizeof {dynamic_length= None} ->
Sizeof exp
{sizeof_data with dynamic_length= Option.map ~f:(exp_normalize tenv sub) dynamic_length} | Sizeof ({dynamic_length= Some dyn_len} as sizeof_data) ->
let dyn_len' = exp_normalize tenv sub dyn_len in
if phys_equal dyn_len dyn_len' then exp
else Sizeof {sizeof_data with dynamic_length= Some dyn_len'}
| _ -> | _ ->
exp_normalize tenv sub exp exp_normalize tenv sub exp
@ -1282,25 +1285,30 @@ module Normalize = struct
| _ -> | _ ->
(e1, e2, false) (e1, e2, false)
in in
let handle_boolean_operation from_equality e1 e2 : Sil.atom = let handle_boolean_operation orig_a from_equality e1 e2 : Sil.atom =
let ne1 = exp_normalize tenv sub e1 in let ne1 = exp_normalize tenv sub e1 in
let ne2 = exp_normalize tenv sub e2 in let ne2 = exp_normalize tenv sub e2 in
let ne1', ne2', op_negated = handle_unary_negation ne1 ne2 in let ne1', ne2', op_negated = handle_unary_negation ne1 ne2 in
let e1', e2' = normalize_eq (ne1', ne2') in let e1', e2' = normalize_eq (ne1', ne2') in
let e1'', e2'' = exp_reorder e1' e2' in let e1'', e2'' = exp_reorder e1' e2' in
let use_equality = if op_negated then not from_equality else from_equality in let use_equality = if op_negated then not from_equality else from_equality in
if use_equality then Aeq (e1'', e2'') else Aneq (e1'', e2'') if Bool.equal use_equality from_equality && phys_equal e1 e1'' && phys_equal e2 e2'' then
orig_a
else if use_equality then Aeq (e1'', e2'')
else Aneq (e1'', e2'')
in in
let a' : Sil.atom = let a' : Sil.atom =
match a with match a with
| Aeq (e1, e2) -> | Aeq (e1, e2) ->
handle_boolean_operation true e1 e2 handle_boolean_operation a true e1 e2
| Aneq (e1, e2) -> | Aneq (e1, e2) ->
handle_boolean_operation false e1 e2 handle_boolean_operation a false e1 e2
| Apred (a, es) -> | Apred (tag, es) ->
Apred (a, List.map ~f:(fun e -> exp_normalize tenv sub e) es) let es' = IList.map_changed es ~equal:Exp.equal ~f:(fun e -> exp_normalize tenv sub e) in
| Anpred (a, es) -> if phys_equal es es' then a else Apred (tag, es')
Anpred (a, List.map ~f:(fun e -> exp_normalize tenv sub e) es) | Anpred (tag, es) ->
let es' = IList.map_changed es ~equal:Exp.equal ~f:(fun e -> exp_normalize tenv sub e) in
if phys_equal es es' then a else Anpred (tag, es')
in in
if atom_is_inequality a' then inequality_normalize tenv a' else a' if atom_is_inequality a' then inequality_normalize tenv a' else a'
@ -1325,15 +1333,24 @@ module Normalize = struct
let rec strexp_normalize tenv sub (se: Sil.strexp) : Sil.strexp = let rec strexp_normalize tenv sub (se: Sil.strexp) : Sil.strexp =
match se with match se with
| Eexp (e, inst) -> | Eexp (e, inst) ->
Eexp (exp_normalize tenv sub e, inst) let e' = exp_normalize tenv sub e in
if phys_equal e e' then se else Eexp (e', inst)
| Estruct (fld_cnts, inst) -> ( | Estruct (fld_cnts, inst) -> (
match fld_cnts with match fld_cnts with
| [] -> | [] ->
se se
| _ -> | _ :: _ ->
let fld_cnts' = let fld_cnts' =
List.map ~f:(fun (fld, cnt) -> (fld, strexp_normalize tenv sub cnt)) fld_cnts IList.map_changed fld_cnts
in ~equal:[%compare.equal : Typ.Fieldname.t * Sil.strexp]
~f:(fun ((fld, cnt) as x) ->
let cnt' = strexp_normalize tenv sub cnt in
if phys_equal cnt cnt' then x else (fld, cnt') )
in
if phys_equal fld_cnts fld_cnts'
&& List.is_sorted ~compare:[%compare : Typ.Fieldname.t * Sil.strexp] fld_cnts
then se
else
let fld_cnts'' = List.sort ~cmp:[%compare : Typ.Fieldname.t * Sil.strexp] fld_cnts' in let fld_cnts'' = List.sort ~cmp:[%compare : Typ.Fieldname.t * Sil.strexp] fld_cnts' in
Estruct (fld_cnts'', inst) ) Estruct (fld_cnts'', inst) )
| Earray (len, idx_cnts, inst) -> | Earray (len, idx_cnts, inst) ->
@ -1341,14 +1358,19 @@ module Normalize = struct
match idx_cnts with match idx_cnts with
| [] -> | [] ->
if Exp.equal len len' then se else Earray (len', idx_cnts, inst) if Exp.equal len len' then se else Earray (len', idx_cnts, inst)
| _ -> | _ :: _ ->
let idx_cnts' = let idx_cnts' =
List.map IList.map_changed idx_cnts
~f:(fun (idx, cnt) -> ~equal:[%compare.equal : Exp.t * Sil.strexp]
~f:(fun ((idx, cnt) as x) ->
let idx' = exp_normalize tenv sub idx in let idx' = exp_normalize tenv sub idx in
(idx', strexp_normalize tenv sub cnt) ) let cnt' = strexp_normalize tenv sub cnt in
idx_cnts if phys_equal idx idx' && phys_equal cnt cnt' then x else (idx', cnt') )
in in
if phys_equal idx_cnts idx_cnts'
&& List.is_sorted ~compare:[%compare : Exp.t * Sil.strexp] idx_cnts
then se
else
let idx_cnts'' = List.sort ~cmp:[%compare : Exp.t * Sil.strexp] idx_cnts' in let idx_cnts'' = List.sort ~cmp:[%compare : Exp.t * Sil.strexp] idx_cnts' in
Earray (len', idx_cnts'', inst) Earray (len', idx_cnts'', inst)

Loading…
Cancel
Save