From cebf95afc4e3452bcebacfca1a77e7603df804be Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Thu, 17 Sep 2020 03:52:24 -0700 Subject: [PATCH] [cost] Select autorelease trace with bigger polynomial Summary: This diff selects an autorelease trace that has a bigger polynomial. Reviewed By: ezgicicek Differential Revision: D23731155 fbshipit-source-id: 243591583 --- infer/src/bufferoverrun/polynomials.ml | 33 +++++++++++++------ .../objc/autoreleasepool/basic.m | 8 +++++ .../objc/autoreleasepool/cost-issues.exp | 1 + 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/infer/src/bufferoverrun/polynomials.ml b/infer/src/bufferoverrun/polynomials.ml index 45335ef0d..0f2c26c05 100644 --- a/infer/src/bufferoverrun/polynomials.ml +++ b/infer/src/bufferoverrun/polynomials.ml @@ -222,7 +222,18 @@ module MakePolynomial (S : NonNegativeSymbolWithDegreeKind) = struct let get_autoreleasepool_trace {autoreleasepool_trace} = autoreleasepool_trace - let join_autoreleasepool_trace x y = Option.first_some x y + let rec degree_poly {terms} = + M.fold + (fun t p cur_max -> + let degree_term = Degree.succ (S.degree_kind t) (degree_poly p) in + if Degree.compare degree_term cur_max > 0 then degree_term else cur_max ) + terms Degree.zero + + + let join_autoreleasepool_trace poly_x poly_y x y = + Option.merge x y ~f:(fun x y -> + if Degree.compare (degree_poly poly_x) (degree_poly poly_y) >= 0 then x else y ) + let poly_of_non_negative_int : NonNegativeInt.t -> poly = fun const -> {const; terms= M.empty} @@ -269,7 +280,8 @@ module MakePolynomial (S : NonNegativeSymbolWithDegreeKind) = struct fun p1 p2 -> { poly= plus_poly p1.poly p2.poly ; autoreleasepool_trace= - join_autoreleasepool_trace p1.autoreleasepool_trace p2.autoreleasepool_trace } + join_autoreleasepool_trace p1.poly p2.poly p1.autoreleasepool_trace p2.autoreleasepool_trace + } let rec mult_const_positive : poly -> PositiveInt.t -> poly = @@ -324,7 +336,8 @@ module MakePolynomial (S : NonNegativeSymbolWithDegreeKind) = struct let poly = mult_poly p1.poly p2.poly in let autoreleasepool_trace = if is_zero_poly poly then None - else join_autoreleasepool_trace p1.autoreleasepool_trace p2.autoreleasepool_trace + else + join_autoreleasepool_trace p1.poly p2.poly p1.autoreleasepool_trace p2.autoreleasepool_trace in {poly; autoreleasepool_trace} @@ -446,8 +459,7 @@ module MakePolynomial (S : NonNegativeSymbolWithDegreeKind) = struct match subst_poly poly eval_sym with | poly -> let autoreleasepool_trace = - Option.map autoreleasepool_trace ~f:(fun autoreleasepool_trace -> - Bounds.BoundTrace.call ~callee_pname ~location autoreleasepool_trace ) + Option.map autoreleasepool_trace ~f:(Bounds.BoundTrace.call ~callee_pname ~location) in Val {poly; autoreleasepool_trace} | exception ReturnTop s_trace -> @@ -464,9 +476,10 @@ module MakePolynomial (S : NonNegativeSymbolWithDegreeKind) = struct let degree_term = (Degree.succ (S.degree_kind t) d, mult_symb p' t) in if [%compare: Degree.t * t] degree_term cur_max > 0 then degree_term else cur_max ) terms - (Degree.zero, one ?autoreleasepool_trace ()) + (Degree.zero, one ()) in - degree_with_term_poly poly + let d, p = degree_with_term_poly poly in + (d, {p with autoreleasepool_trace}) let degree p = fst (degree_with_term p) @@ -534,9 +547,9 @@ module MakePolynomial (S : NonNegativeSymbolWithDegreeKind) = struct let polynomial_traces ?(is_autoreleasepool_trace = false) p = let traces = get_symbols p |> List.map ~f:S.make_err_trace_symbol in if is_autoreleasepool_trace then - get_autoreleasepool_trace p - |> Option.value_map ~default:traces ~f:(fun trace -> - traces @ [("autorelease", Bounds.BoundTrace.make_err_trace ~depth:0 trace)] ) + traces + @ Option.value_map (get_autoreleasepool_trace p) ~default:[] ~f:(fun trace -> + [("autorelease", Bounds.BoundTrace.make_err_trace ~depth:0 trace)] ) else traces end diff --git a/infer/tests/codetoanalyze/objc/autoreleasepool/basic.m b/infer/tests/codetoanalyze/objc/autoreleasepool/basic.m index ebacae10e..f869e568d 100644 --- a/infer/tests/codetoanalyze/objc/autoreleasepool/basic.m +++ b/infer/tests/codetoanalyze/objc/autoreleasepool/basic.m @@ -102,4 +102,12 @@ } } +- (void)multiple_autorelease_constants:(int)n { + [self call_autorelease_constant]; + for (int i = 0; i < n; i++) { + [self call_autorelease_constant]; + } + [self call_autorelease_constant]; +} + @end diff --git a/infer/tests/codetoanalyze/objc/autoreleasepool/cost-issues.exp b/infer/tests/codetoanalyze/objc/autoreleasepool/cost-issues.exp index b822ae1d9..4f32fd95d 100644 --- a/infer/tests/codetoanalyze/objc/autoreleasepool/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/autoreleasepool/cost-issues.exp @@ -19,6 +19,7 @@ codetoanalyze/objc/autoreleasepool/basic.m, Basic.call_autorelease_constant, 1, codetoanalyze/objc/autoreleasepool/basic.m, Basic.call_no_autorelease_zero, 0, OnUIThread:false, [] codetoanalyze/objc/autoreleasepool/basic.m, Basic.dealloc, 0, OnUIThread:false, [] codetoanalyze/objc/autoreleasepool/basic.m, Basic.loop_in_autoreleasepool_zero:, 0, OnUIThread:false, [] +codetoanalyze/objc/autoreleasepool/basic.m, Basic.multiple_autorelease_constants:, 2 + n, OnUIThread:false, [{n},Loop,autorelease,Call to Basic.call_autorelease_constant,Modeled call to autorelease] codetoanalyze/objc/autoreleasepool/basic.m, Basic.no_autoreleased_in_loop_zero:, 0, OnUIThread:false, [] codetoanalyze/objc/autoreleasepool/no_arc_callee.m, NoArcCallee.allocObject, 0, OnUIThread:false, [] codetoanalyze/objc/autoreleasepool/no_arc_callee.m, NoArcCallee.copyObject:, 0, OnUIThread:false, []