From 7fbe04f7012a52834760afacaaddf95bfd553a7a Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Wed, 22 Apr 2020 02:32:34 -0700 Subject: [PATCH] [cost] Suppress cost issues on lambda and auto-generated procedures Summary: This diff suppresses cost issues on lambda and auto-generated procedures, since they were too noisy. Reviewed By: ezgicicek Differential Revision: D21153619 fbshipit-source-id: 65ad6dcc3 --- infer/src/IR/Procname.ml | 8 ++++++ infer/src/IR/Procname.mli | 4 +++ infer/src/IR/Typ.ml | 15 ++++++++-- infer/src/IR/Typ.mli | 3 ++ infer/src/backend/Differential.ml | 7 +---- infer/src/cost/cost.ml | 6 +++- .../java/performance/LambdaTest.java | 28 +++++++++++++++++++ .../codetoanalyze/java/performance/issues.exp | 2 +- 8 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 infer/tests/codetoanalyze/java/performance/LambdaTest.java diff --git a/infer/src/IR/Procname.ml b/infer/src/IR/Procname.ml index e57383eb5..3b5cf5617 100644 --- a/infer/src/IR/Procname.ml +++ b/infer/src/IR/Procname.ml @@ -158,6 +158,10 @@ module Java = struct Typ.Name.Java.is_anonymous_inner_class_name_exn class_name + let is_anonymous_inner_class_method {class_name} = + Option.value ~default:false (Typ.Name.Java.is_anonymous_inner_class_name_opt class_name) + + let is_static {kind} = match kind with Static -> true | _ -> false let is_lambda {method_name} = String.is_prefix ~prefix:"lambda$" method_name @@ -424,6 +428,10 @@ let is_java_access_method = is_java_lift Java.is_access_method let is_java_class_initializer = is_java_lift Java.is_class_initializer +let is_java_anonymous_inner_class_method = is_java_lift Java.is_anonymous_inner_class_method + +let is_java_autogen_method = is_java_lift Java.is_autogen_method + let is_objc_method procname = match procname with ObjC_Cpp name -> ObjC_Cpp.is_objc_method name | _ -> false diff --git a/infer/src/IR/Procname.mli b/infer/src/IR/Procname.mli index a61404600..d450ab6c2 100644 --- a/infer/src/IR/Procname.mli +++ b/infer/src/IR/Procname.mli @@ -218,6 +218,10 @@ val is_java_access_method : t -> bool val is_java_class_initializer : t -> bool +val is_java_anonymous_inner_class_method : t -> bool + +val is_java_autogen_method : t -> bool + val is_objc_method : t -> bool module Hash : Caml.Hashtbl.S with type key = t diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 34b6026de..ea20d6645 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -465,11 +465,15 @@ module Name = struct let java_lang_string = from_string "java.lang.String" + let get_java_class_name_opt typename = + match typename with JavaClass java_class_name -> Some java_class_name | _ -> None + + let get_java_class_name_exn typename = - match typename with - | JavaClass java_class_name -> + match get_java_class_name_opt typename with + | Some java_class_name -> java_class_name - | _ -> + | None -> L.die InternalError "Tried to split a non-java class name into a java split type@." @@ -478,6 +482,11 @@ module Name = struct JavaClassName.is_anonymous_inner_class_name java_class_name + let is_anonymous_inner_class_name_opt class_name = + get_java_class_name_opt class_name + |> Option.map ~f:JavaClassName.is_anonymous_inner_class_name + + let is_external t = get_java_class_name_exn t |> JavaClassName.package |> Option.exists ~f:Config.java_package_is_external diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 1600afd03..3caac57b4 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -233,6 +233,9 @@ module Name : sig val is_anonymous_inner_class_name_exn : t -> bool (** Throws if it is not a Java class *) + val is_anonymous_inner_class_name_opt : t -> bool option + (** return None if it is not a Java class *) + val java_lang_object : t val java_io_serializable : t diff --git a/infer/src/backend/Differential.ml b/infer/src/backend/Differential.ml index 3d429b7c8..d0a213045 100644 --- a/infer/src/backend/Differential.ml +++ b/infer/src/backend/Differential.ml @@ -267,12 +267,7 @@ let issue_of_cost kind CostIssues.{complexity_increase_issue; unreachable_issue; else if String.equal method_name Procname.Java.class_initializer_method_name then Format.pp_print_string f "class initializer" else - Format.fprintf f "%t%a" - (fun f -> - if Procname.Java.is_autogen_method_name method_name then - Format.pp_print_string f "auto-generated method " ) - (MarkupFormatter.wrap_monospaced Format.pp_print_string) - method_name + Format.fprintf f "%a" (MarkupFormatter.wrap_monospaced Format.pp_print_string) method_name in Format.asprintf "%s of %t has %a from %a to %a. %s %a" (CostKind.to_complexity_string kind) diff --git a/infer/src/cost/cost.ml b/infer/src/cost/cost.ml index 6746a0f4e..39c8ea982 100644 --- a/infer/src/cost/cost.ml +++ b/infer/src/cost/cost.ml @@ -285,7 +285,11 @@ module Check = struct let check_and_report ~is_on_ui_thread WorstCaseCost.{costs; reports} proc_desc summary = let pname = Procdesc.get_proc_name proc_desc in let proc_loc = Procdesc.get_loc proc_desc in - if not (Procname.is_java_access_method pname) then ( + if + (not (Procname.is_java_access_method pname)) + && (not (Procname.is_java_anonymous_inner_class_method pname)) + && not (Procname.is_java_autogen_method pname) + then ( CostIssues.CostKindMap.iter2 CostIssues.enabled_cost_map reports ~f:(fun _kind (CostIssues.{name; threshold} as kind_spec) -> function | ThresholdReports.Threshold _ | ThresholdReports.NoReport -> diff --git a/infer/tests/codetoanalyze/java/performance/LambdaTest.java b/infer/tests/codetoanalyze/java/performance/LambdaTest.java new file mode 100644 index 000000000..692c766f7 --- /dev/null +++ b/infer/tests/codetoanalyze/java/performance/LambdaTest.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +interface LambdaTestI { + void abstractFun(int x); +} + +class LambdaTest { + void call_lambda(int x) { + /* Three methods are auto-generated here: + - LambdaTest.callsite_LambdaTest$Lambda$_2_0 + - LambdaTest.access_LambdaTest$Lambda$_2_0 + - LambdaTest$Lambda$_2_0. + and one method is newly defined here: + - LambdaTest$Lambda$_2_0.abstractFun */ + LambdaTestI fobj = + (int y) -> { + /* One method is auto-generated here: + - lambda$call_lambda$0 */ + for (int i = 0; i < y; i++) {} + }; + fobj.abstractFun(x); + } +} diff --git a/infer/tests/codetoanalyze/java/performance/issues.exp b/infer/tests/codetoanalyze/java/performance/issues.exp index 175cb3ba1..84816eaa6 100644 --- a/infer/tests/codetoanalyze/java/performance/issues.exp +++ b/infer/tests/codetoanalyze/java/performance/issues.exp @@ -60,7 +60,6 @@ codetoanalyze/java/performance/CantHandle.java, CantHandle.square_root_FP(int):v codetoanalyze/java/performance/CantHandle.java, CantHandle.square_root_FP(int):void, 3, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [,Assignment,Binary operation: ([0, +oo] + 1):signed32] codetoanalyze/java/performance/CantHandle.java, CantHandle.square_root_variant_FP(int):void, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 25] codetoanalyze/java/performance/CantHandle.java, CantHandle.square_root_variant_FP(int):void, 3, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [,Parameter `x`,Binary operation: ([0, +oo] + 1):signed32] -codetoanalyze/java/performance/CollectionTest.java, CollectionTest$MyEnumType$1.(), 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 88] codetoanalyze/java/performance/CollectionTest.java, CollectionTest$MyEnumType$1.(), 4, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [,Assignment,Binary operation: ([0, +oo] + 1):signed32] codetoanalyze/java/performance/CollectionTest.java, CollectionTest$MyEnumType.():void, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to CollectionTest$MyEnumType$1.(),Unbounded loop,Loop at line 88] codetoanalyze/java/performance/CollectionTest.java, CollectionTest.ensure_call(CollectionTest$MyCollection):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 11 + 5 ⋅ list.length, O(list.length), degree = 1,{list.length},call to void CollectionTest.iterate_over_mycollection(CollectionTest$MyCollection),Loop at line 17] @@ -154,6 +153,7 @@ codetoanalyze/java/performance/JsonUtils.java, libraries.marauder.analytics.util codetoanalyze/java/performance/JsonUtils.java, libraries.marauder.analytics.utils.json.JsonUtils.escape(java.lang.StringBuilder,java.lang.String):void, 1, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [,Assignment,Binary operation: ([0, +oo] + 1):signed32] codetoanalyze/java/performance/JsonUtils.java, libraries.marauder.analytics.utils.json.JsonUtils.serialize(java.lang.String):java.lang.StringBuilder, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to void JsonUtils.serialize(StringBuilder,String),Call to void JsonUtils.escape(StringBuilder,String),Unbounded loop,Loop at line 13] codetoanalyze/java/performance/JsonUtils.java, libraries.marauder.analytics.utils.json.JsonUtils.serialize(java.lang.StringBuilder,java.lang.String):void, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to void JsonUtils.escape(StringBuilder,String),Unbounded loop,Loop at line 13] +codetoanalyze/java/performance/LambdaTest.java, LambdaTest.call_lambda(int):void, 13, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 21 + 5 ⋅ x, O(x), degree = 1,{x},call to void LambdaTest$Lambda$_2_0.abstractFun(int),call to void LambdaTest.access_LambdaTest$Lambda$_2_0(int),call to void LambdaTest.lambda$call_lambda$0(int),Loop at line 24] codetoanalyze/java/performance/ListTest.java, ListTest.asList_linear(java.lang.String[]):void, 2, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 7 + 8 ⋅ array.length + 3 ⋅ (array.length + 1), O(array.length), degree = 1,{array.length + 1},Loop at line 42,{array.length},Loop at line 42] codetoanalyze/java/performance/ListTest.java, ListTest.call_iterate_elements_linear(java.util.List,java.util.List):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 26 + 5 ⋅ (l2.length + l1.length) + 3 ⋅ (l2.length + l1.length + 1), O((l2.length + l1.length)), degree = 1,{l2.length + l1.length + 1},call to void ListTest.iterate_elements_linear(List),Loop at line 59,{l2.length + l1.length},call to void ListTest.iterate_elements_linear(List),Loop at line 59] codetoanalyze/java/performance/ListTest.java, ListTest.indexOfImpl_linear(java.util.List,java.lang.Object):int, 2, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 4 + 11 ⋅ list.length + 3 ⋅ (list.length + 1), O(list.length), degree = 1,{list.length + 1},Loop at line 18,{list.length},Loop at line 18]