Detecting if methods annotated with @PerformanceCritical transitively call methods annotated with @Expensive

Summary: public
Just works by running the analysis bottom-up and promoting any method as virtually annotated with `Expensive` whenever one of its callee is annotated with `Expensive`

Reviewed By: cristianoc

Differential Revision: D2635242

fb-gh-sync-id: 4401be6
master
jrm 9 years ago committed by facebook-github-bot-1
parent 8636aa1f70
commit 6b6b4d1949

@ -112,6 +112,11 @@ let verify_annotation = "com.facebook.infer.annotation.Verify"
let expensive = "Expensive" let expensive = "Expensive"
let performance_critical = "PerformanceCritical" let performance_critical = "PerformanceCritical"
let expensive_annotation = {
Sil.class_name = expensive;
Sil.parameters = []
}
let ia_is_nullable ia = let ia_is_nullable ia =
ia_ends_with ia nullable ia_ends_with ia nullable
@ -163,7 +168,6 @@ let ia_is ann ia = match ann with
| Nullable -> ia_is_nullable ia | Nullable -> ia_is_nullable ia
| Present -> ia_is_present ia | Present -> ia_is_present ia
(** Get a method signature with annotations from a proc_attributes. *) (** Get a method signature with annotations from a proc_attributes. *)
let get_annotated_signature proc_attributes : annotated_signature = let get_annotated_signature proc_attributes : annotated_signature =
let method_annotation = proc_attributes.ProcAttributes.method_annotation in let method_annotation = proc_attributes.ProcAttributes.method_annotation in

@ -14,6 +14,8 @@ val suppressLint : string
val expensive : string val expensive : string
val performance_critical : string val performance_critical : string
val expensive_annotation : Sil.annotation
type annotation = type annotation =
| Nullable | Nullable
| Present | Present

@ -33,10 +33,18 @@ let search_expensive_call checked_pnames expensive_callee (pname, _) =
end end
let is_performance_critical attributes = let check_attributes check attributes =
let annotated_signature = Annotations.get_annotated_signature attributes in let annotated_signature = Annotations.get_annotated_signature attributes in
let ret_annotation, _ = annotated_signature.Annotations.ret in let ret_annotation, _ = annotated_signature.Annotations.ret in
Annotations.ia_is_performance_critical ret_annotation check ret_annotation
let is_performance_critical attributes =
check_attributes Annotations.ia_is_performance_critical attributes
let is_expensive attributes =
check_attributes Annotations.ia_is_expensive attributes
let callback_performance_checker _ _ _ tenv pname pdesc : unit = let callback_performance_checker _ _ _ tenv pname pdesc : unit =
@ -58,4 +66,11 @@ let callback_performance_checker _ _ _ tenv pname pdesc : unit =
Annotations.expensive in Annotations.expensive in
Checkers.ST.report_error Checkers.ST.report_error
pname pdesc calls_expensive_method (Cfg.Procdesc.get_loc pdesc) description pname pdesc calls_expensive_method (Cfg.Procdesc.get_loc pdesc) description
| Some _ -> () | Some _ when not (is_expensive attributes) ->
let ret_annot, param_annot = attributes.ProcAttributes.method_annotation in
let updated_method_annot =
(Annotations.expensive_annotation, true) :: ret_annot, param_annot in
let updated_attributes =
{ attributes with ProcAttributes.method_annotation = updated_method_annot } in
AttributesTable.store_attributes updated_attributes
| Some _ -> () (* Nothing to do if method already annotated with @Expensive *)

@ -16,14 +16,30 @@ public class ExpensiveCallExample {
Object mObject; Object mObject;
void nonExpensiveMethod() {}
@Expensive @Expensive
void expensiveMethod() { void expensiveMethod() {
mObject = new Object(); mObject = new Object();
} }
void methodWrapper() {
expensiveMethod();
}
@PerformanceCritical
void notCallingExpensiveMethod() {
nonExpensiveMethod();
}
@PerformanceCritical @PerformanceCritical
void shouldReportExpensiveCallWarning() { void directlyCallingExpensiveMethod() {
expensiveMethod(); expensiveMethod();
} }
@PerformanceCritical
void indirectlyCallingExpensiveMethod() {
methodWrapper();
}
} }

@ -39,7 +39,8 @@ public class ExpensiveCallTest {
public void matchErrors() public void matchErrors()
throws IOException, InterruptedException, InferException { throws IOException, InterruptedException, InferException {
String[] methods = { String[] methods = {
"shouldReportExpensiveCallWarning", "directlyCallingExpensiveMethod",
"indirectlyCallingExpensiveMethod"
}; };
assertThat( assertThat(
"Results should contain " + CALLS_EXPENSIVE_METHOD, "Results should contain " + CALLS_EXPENSIVE_METHOD,

Loading…
Cancel
Save