diff --git a/infer/src/cost/cost.ml b/infer/src/cost/cost.ml index 745f3c5ea..c32d7631d 100644 --- a/infer/src/cost/cost.ml +++ b/infer/src/cost/cost.ml @@ -106,19 +106,22 @@ module InstrBasicCostWithReason = struct |> Option.value ~default:(Option.value callee_cost_opt ~default:BasicCostWithReason.zero) - let dispatch_autoreleasepool_func_ptr_call {inferbo_invariant_map; integer_type_widths} instr_node - fun_exp = + let dispatch_func_ptr_call {inferbo_invariant_map; integer_type_widths} instr_node fun_exp = BufferOverrunAnalysis.extract_pre (InstrCFG.Node.id instr_node) inferbo_invariant_map - |> Option.value_map ~default:BasicCostWithReason.zero ~f:(fun inferbo_mem -> + |> Option.bind ~f:(fun inferbo_mem -> let func_ptrs = BufferOverrunSemantics.eval integer_type_widths fun_exp inferbo_mem |> BufferOverrunDomain.Val.get_func_ptrs in match FuncPtr.Set.is_singleton_or_more func_ptrs with | Singleton (Path path) -> - BasicCost.of_func_ptr path |> BasicCostWithReason.of_basic_cost + let symbolic_cost = + BasicCost.of_func_ptr path |> BasicCostWithReason.of_basic_cost + in + Some (CostDomain.construct ~f:(fun _ -> symbolic_cost)) | _ -> - BasicCostWithReason.zero ) + None ) + |> Option.value ~default:CostDomain.unit_cost_atomic_operation let get_instr_cost_record tenv extras cfg instr_node instr = @@ -186,14 +189,7 @@ module InstrBasicCostWithReason = struct | Sil.Call (_, Exp.Const (Const.Cfun _), _, _, _) -> CostDomain.zero_record | Sil.Call (_, fun_exp, _, _location, _) -> - CostDomain.construct ~f:(fun kind -> - match kind with - | OperationCost -> - BasicCostWithReason.one () - | AllocationCost -> - BasicCostWithReason.zero - | AutoreleasepoolSize -> - dispatch_autoreleasepool_func_ptr_call extras instr_node fun_exp ) + dispatch_func_ptr_call extras instr_node fun_exp | Sil.Load {id= lhs_id} when Ident.is_none lhs_id -> (* dummy deref inserted by frontend--don't count as a step. In JDK 11, dummy deref disappears and causes cost differences diff --git a/infer/tests/codetoanalyze/c/performance/cost-issues.exp b/infer/tests/codetoanalyze/c/performance/cost-issues.exp index 4d35d9f70..e10572694 100644 --- a/infer/tests/codetoanalyze/c/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/c/performance/cost-issues.exp @@ -64,7 +64,7 @@ codetoanalyze/c/performance/loops.c, if_out_loop, 515, OnUIThread:false, [] codetoanalyze/c/performance/loops.c, larger_state_FN, 1005, OnUIThread:false, [] codetoanalyze/c/performance/loops.c, loop_use_global_vars, 4 + 4 ⋅ x + 2 ⋅ (1+max(0, x)), OnUIThread:false, [{1+max(0, x)},Loop,{x},Loop] codetoanalyze/c/performance/loops.c, ptr_cmp, 5 + 5 ⋅ size + 2 ⋅ (2+max(-1, size)), OnUIThread:false, [{2+max(-1, size)},Loop,{size},Loop] -codetoanalyze/c/performance/purity.c, loop, 7007, OnUIThread:false, [] +codetoanalyze/c/performance/purity.c, loop, 6007 + 1000 ⋅ |fun_ptr|, OnUIThread:false, [] codetoanalyze/c/performance/switch_continue.c, test_switch_FN, 601, OnUIThread:false, [] codetoanalyze/c/performance/switch_continue.c, unroll_loop, 16 + (n - 1) + 11 ⋅ (max(1, n)), OnUIThread:false, [{max(1, n)},Loop,{n - 1},Loop] codetoanalyze/c/performance/two_loops_symbolic.c, nop, 2, OnUIThread:false, [] diff --git a/infer/tests/codetoanalyze/objc/performance/block.m b/infer/tests/codetoanalyze/objc/performance/block.m index f95ade3d3..f79e0176f 100644 --- a/infer/tests/codetoanalyze/objc/performance/block.m +++ b/infer/tests/codetoanalyze/objc/performance/block.m @@ -38,3 +38,11 @@ void doBlockA_direct_block_linear(int a) { loop_linear(a); }); } + +void wrapper_runBlockA(BlockA block) { runBlockA(block); } + +void call_wrapper_runBlockA_linear(int a) { + wrapper_runBlockA(^{ + loop_linear(a); + }); +} diff --git a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp index 051fcaf96..4cd748049 100644 --- a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp @@ -95,15 +95,19 @@ codetoanalyze/objc/performance/araii.m, Araii.initWithBuffer, 15, OnUIThread:fa codetoanalyze/objc/performance/araii.m, Araii.setBuffer:, 4, OnUIThread:false, [] codetoanalyze/objc/performance/araii.m, memory_leak_raii_main, 18, OnUIThread:false, [] codetoanalyze/objc/performance/block.m, block_multiply_array_linear, 13 + 5 ⋅ array->elements.length.ub + 4 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Call to objc_blockblock_multiply_array_linear_1,Loop,{array->elements.length.ub},Call to objc_blockblock_multiply_array_linear_1,Loop] +codetoanalyze/objc/performance/block.m, call_wrapper_runBlockA_linear, 11 + 3 ⋅ a + 2 ⋅ (1+max(0, a)), OnUIThread:false, [{1+max(0, a)},Call to loop_linear,Loop,{a},Call to loop_linear,Loop] codetoanalyze/objc/performance/block.m, doBlockA_direct_block_linear, 10 + 3 ⋅ a + 2 ⋅ (1+max(0, a)), OnUIThread:false, [{1+max(0, a)},Call to runBlockA[objc_blockdoBlockA_direct_block_linear_3],Call to objc_blockdoBlockA_direct_block_linear_3,Call to loop_linear,Loop,{a},Call to runBlockA[objc_blockdoBlockA_direct_block_linear_3],Call to objc_blockdoBlockA_direct_block_linear_3,Call to loop_linear,Loop] codetoanalyze/objc/performance/block.m, doBlockA_linear, 12 + 3 ⋅ a + 2 ⋅ (1+max(0, a)), OnUIThread:false, [{1+max(0, a)},Call to runBlockA[objc_blockdoBlockA_linear_2],Call to objc_blockdoBlockA_linear_2,Call to loop_linear,Loop,{a},Call to runBlockA[objc_blockdoBlockA_linear_2],Call to objc_blockdoBlockA_linear_2,Call to loop_linear,Loop] codetoanalyze/objc/performance/block.m, loop_linear, 3 + 3 ⋅ x + 2 ⋅ (1+max(0, x)), OnUIThread:false, [{1+max(0, x)},Loop,{x},Loop] codetoanalyze/objc/performance/block.m, objc_blockblock_multiply_array_linear_1, 8 + 5 ⋅ array->elements.length.ub + 4 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Loop] +codetoanalyze/objc/performance/block.m, objc_blockcall_wrapper_runBlockA_linear_4, 5 + 3 ⋅ a + 2 ⋅ (1+max(0, a)), OnUIThread:false, [{1+max(0, a)},Call to loop_linear,Loop,{a},Call to loop_linear,Loop] codetoanalyze/objc/performance/block.m, objc_blockdoBlockA_direct_block_linear_3, 5 + 3 ⋅ a + 2 ⋅ (1+max(0, a)), OnUIThread:false, [{1+max(0, a)},Call to loop_linear,Loop,{a},Call to loop_linear,Loop] codetoanalyze/objc/performance/block.m, objc_blockdoBlockA_linear_2, 5 + 3 ⋅ a + 2 ⋅ (1+max(0, a)), OnUIThread:false, [{1+max(0, a)},Call to loop_linear,Loop,{a},Call to loop_linear,Loop] -codetoanalyze/objc/performance/block.m, runBlockA, 3, OnUIThread:false, [] +codetoanalyze/objc/performance/block.m, runBlockA, 2 + |block|, OnUIThread:false, [] codetoanalyze/objc/performance/block.m, runBlockA[objc_blockdoBlockA_direct_block_linear_3], 8 + 3 ⋅ a[doBlockA_direct_block_linear()] + 2 ⋅ (1+max(0, a[doBlockA_direct_block_linear()])), OnUIThread:false, [{1+max(0, a[doBlockA_direct_block_linear()])},Call to objc_blockdoBlockA_direct_block_linear_3,Call to loop_linear,Loop,{a[doBlockA_direct_block_linear()]},Call to objc_blockdoBlockA_direct_block_linear_3,Call to loop_linear,Loop] codetoanalyze/objc/performance/block.m, runBlockA[objc_blockdoBlockA_linear_2], 8 + 3 ⋅ a[doBlockA_linear()] + 2 ⋅ (1+max(0, a[doBlockA_linear()])), OnUIThread:false, [{1+max(0, a[doBlockA_linear()])},Call to objc_blockdoBlockA_linear_2,Call to loop_linear,Loop,{a[doBlockA_linear()]},Call to objc_blockdoBlockA_linear_2,Call to loop_linear,Loop] +codetoanalyze/objc/performance/block.m, wrapper_runBlockA, 4 + |block|, OnUIThread:false, [] +codetoanalyze/objc/performance/block.m, wrapper_runBlockA[objc_blockcall_wrapper_runBlockA_linear_4], 4 + |block|, OnUIThread:false, [] codetoanalyze/objc/performance/break.m, break_constant_FP, 8 + 5 ⋅ p + 2 ⋅ (1+max(0, p)), OnUIThread:false, [{1+max(0, p)},Call to break_loop,Loop,{p},Call to break_loop,Loop] codetoanalyze/objc/performance/break.m, break_loop, 5 + 5 ⋅ p + 2 ⋅ (1+max(0, p)), OnUIThread:false, [{1+max(0, p)},Loop,{p},Loop] codetoanalyze/objc/performance/break.m, break_loop_with_t, 7 + 5 ⋅ p + 2 ⋅ (1+max(0, p)), OnUIThread:false, [{1+max(0, p)},Loop,{p},Loop] @@ -202,7 +206,7 @@ codetoanalyze/objc/performance/mutable_copy_test.m, MyMutableObj.mutableCopyWith codetoanalyze/objc/performance/mutable_copy_test.m, MyMutableObj.objects, 7, OnUIThread:false, [] codetoanalyze/objc/performance/mutable_copy_test.m, MyMutableObj.setMObjects:, 4, OnUIThread:false, [] codetoanalyze/objc/performance/mutable_copy_test.m, loop_over_mutable_copy_linear, 36 + 3 ⋅ b->_mObjects->elements.length.ub + 3 ⋅ (b->_mObjects->elements.length.ub + 1), OnUIThread:false, [{b->_mObjects->elements.length.ub + 1},Loop,{b->_mObjects->elements.length.ub},Loop] -codetoanalyze/objc/performance/purity.m, loop, 7007, OnUIThread:false, [] +codetoanalyze/objc/performance/purity.m, loop, 6007 + 1000 ⋅ |fun_ptr|, OnUIThread:false, [] codetoanalyze/objc/performance/switch_continue.m, test_switch_FN, 601, OnUIThread:false, [] codetoanalyze/objc/performance/switch_continue.m, unroll_loop, 16 + (n - 1) + 11 ⋅ (max(1, n)), OnUIThread:false, [{max(1, n)},Loop,{n - 1},Loop] codetoanalyze/objc/performance/two_loops_symbolic.m, nop, 2, OnUIThread:false, []