[Cost] Add invariant analysis

Reviewed By: mbouaziz

Differential Revision: D8381787

fbshipit-source-id: dcd93e6
master
Ezgi Çiçek 7 years ago committed by Facebook Github Bot
parent ea734a3e77
commit cf1c2acb54

@ -22,7 +22,18 @@ module L = Logging
module VarSet = AbstractDomain.FiniteSet (Var)
module CFG = ProcCfg.Normal
module ControlDepSet = AbstractDomain.FiniteSet (Var)
module LoopHead = Procdesc.Node
(* For each CV, track the loop head where it is originating from. This
is needed for invariant analysis. *)
module CVar = struct
type t = {cvar: Var.t; loop_head: LoopHead.t} [@@deriving compare]
let pp fmt {cvar; loop_head} =
F.fprintf fmt "(cvar : %a; loop_head : %a)" Var.pp cvar LoopHead.pp loop_head
end
module ControlDepSet = AbstractDomain.FiniteSet (CVar)
module GuardNodes = AbstractDomain.FiniteSet (Procdesc.Node)
module LoopHeads = Procdesc.NodeSet
@ -44,28 +55,31 @@ module TransferFunctionsControlDeps (CFG : ProcCfg.S) = struct
type extras = loop_control_maps
let collect_vars_in_exp exp =
let collect_vars_in_exp exp loop_head =
Var.get_all_vars_in_exp exp
|> Sequence.fold ~init:ControlDepSet.empty ~f:(fun acc cvar -> ControlDepSet.add cvar acc)
|> Sequence.fold ~init:ControlDepSet.empty ~f:(fun acc cvar ->
ControlDepSet.add {cvar; loop_head} acc )
let find_vars_in_decl id _ = function
let find_vars_in_decl id loop_head _ = function
| Sil.Load (lhs_id, exp, _, _) when Ident.equal lhs_id id ->
collect_vars_in_exp exp |> Option.some
collect_vars_in_exp exp loop_head |> Option.some
| Sil.Call ((lhs_id, _), _, arg_list, _, _) when Ident.equal lhs_id id ->
List.fold_left arg_list ~init:ControlDepSet.empty ~f:(fun deps (exp, _) ->
collect_vars_in_exp exp |> ControlDepSet.union deps )
collect_vars_in_exp exp loop_head |> ControlDepSet.union deps )
|> Option.some
| _ ->
None
let get_vars_in_exp exp prune_node =
let get_vars_in_exp exp prune_node loop_head =
assert (Exp.program_vars exp |> Sequence.is_empty) ;
(* We should never have program variables in prune nodes *)
Exp.free_vars exp
|> Sequence.fold ~init:ControlDepSet.empty ~f:(fun acc id ->
match Procdesc.Node.find_in_node_or_preds prune_node ~f:(find_vars_in_decl id) with
match
Procdesc.Node.find_in_node_or_preds prune_node ~f:(find_vars_in_decl id loop_head)
with
| Some deps ->
ControlDepSet.union deps acc
| None ->
@ -75,7 +89,7 @@ module TransferFunctionsControlDeps (CFG : ProcCfg.S) = struct
(* extract vars from the prune instructions in the node *)
let get_control_vars loop_nodes =
let get_control_vars loop_nodes loop_head =
GuardNodes.fold
(fun prune_node acc ->
let instrs = Procdesc.Node.get_instrs prune_node in
@ -83,7 +97,7 @@ module TransferFunctionsControlDeps (CFG : ProcCfg.S) = struct
~f:(fun astate instr ->
match instr with
| Sil.Prune (exp, _, _, _) ->
Domain.union (get_vars_in_exp exp prune_node) astate
Domain.union (get_vars_in_exp exp prune_node loop_head) astate
| _ ->
(* prune nodes include other instructions like REMOVE_TEMPS or loads *)
astate )
@ -92,7 +106,8 @@ module TransferFunctionsControlDeps (CFG : ProcCfg.S) = struct
(* Each time we pass through
- a loop header, add control variables of its guard nodes,
- a loop header, add control variables(CVs) of its guard nodes,
along with the loop header that CV is originating from
- a loop exit node, remove control variables of its guard nodes
This is correct because the CVs are only going to be temporaries. *)
let exec_instr astate {ProcData.extras= {exit_map; loop_head_to_guard_nodes}} (node: CFG.Node.t)
@ -101,7 +116,7 @@ module TransferFunctionsControlDeps (CFG : ProcCfg.S) = struct
let astate' =
match LoopHeadToGuardNodes.find_opt node loop_head_to_guard_nodes with
| Some loop_nodes ->
Domain.union astate (get_control_vars loop_nodes)
Domain.union astate (get_control_vars loop_nodes node)
| _ ->
astate
in
@ -116,7 +131,7 @@ module TransferFunctionsControlDeps (CFG : ProcCfg.S) = struct
L.(debug Analysis Medium)
"@\n>>>Exit node %a, Loop head %a, guard nodes=%a @\n\n" Procdesc.Node.pp node
Procdesc.Node.pp loop_head GuardNodes.pp guard_nodes ;
get_control_vars guard_nodes |> Domain.diff astate_acc
get_control_vars guard_nodes loop_head |> Domain.diff astate_acc
| _ ->
(* Every loop head must have a guard node *)
assert false )
@ -135,7 +150,20 @@ end
module ControlDepAnalyzer = AbstractInterpreter.Make (CFG) (TransferFunctionsControlDeps)
let compute_control_vars control_invariant_map node =
(* Filter CVs which are invariant in the loop where the CV originated from *)
let remove_invariant_vars control_vars loop_inv_map =
ControlDepSet.fold
(fun {cvar; loop_head} acc ->
match LoopInvariant.LoopHeadToInvVars.find_opt loop_head loop_inv_map with
| Some inv_vars ->
if LoopInvariant.InvariantVars.mem cvar inv_vars then acc else VarSet.add cvar acc
| _ ->
(* Each cvar is always attached to a loop head *)
assert false )
control_vars VarSet.empty
let compute_control_vars control_invariant_map loop_inv_map node =
let node_id = CFG.Node.id node in
let deps = VarSet.empty in
ControlDepAnalyzer.extract_post node_id control_invariant_map
@ -144,5 +172,5 @@ let compute_control_vars control_invariant_map node =
L.(debug Analysis Medium)
"@\n>>> Control dependencies of node %a : %a @\n" Procdesc.Node.pp node ControlDepSet.pp
control_deps ;
control_deps )
remove_invariant_vars control_deps loop_inv_map )
|> Option.value ~default:deps

@ -144,7 +144,7 @@ module BoundMap = struct
false
let compute_upperbound_map node_cfg inferbo_invariant_map control_invariant_map =
let compute_upperbound_map node_cfg inferbo_invariant_map control_invariant_map loop_inv_map =
let pname = Procdesc.get_proc_name node_cfg in
let formal_pvars =
Procdesc.get_formals node_cfg |> List.map ~f:(fun (m, _) -> Pvar.mk m pname)
@ -162,7 +162,9 @@ module BoundMap = struct
match exit_state_opt with
| Some entry_mem ->
(* compute control vars, i.e. set of variables that affect the execution count *)
let control_vars = Control.compute_control_vars control_invariant_map node in
let control_vars =
Control.compute_control_vars control_invariant_map loop_inv_map node
in
L.(debug Analysis Medium)
"@\n>>> All dependencies for node = %a : %a @\n\n" Procdesc.Node.pp node
Control.VarSet.pp control_vars ;
@ -988,8 +990,14 @@ let checker ({Callbacks.tenv; proc_desc} as callback_args) : Summary.t =
BufferOverrunChecker.compute_invariant_map_and_check callback_args
in
let node_cfg = NodeCFG.from_pdesc proc_desc in
let proc_data = ProcData.make_default proc_desc tenv in
(* computes reaching defs: node -> (var -> node set) *)
let reaching_defs_invariant_map =
ReachingDefs.Analyzer.exec_cfg node_cfg proc_data ~initial:ReachingDefs.ReachingDefsMap.empty
~debug:true
in
(* collect all prune nodes that occur in loop guards, needed for ControlDepAnalyzer *)
let control_maps = Loop_control.get_control_maps node_cfg in
let control_maps, loop_head_to_loop_nodes = Loop_control.get_control_maps node_cfg in
(* computes the control dependencies: node -> var set *)
let control_dep_invariant_map =
let proc_data = ProcData.make proc_desc tenv control_maps in
@ -1003,9 +1011,14 @@ let checker ({Callbacks.tenv; proc_desc} as callback_args) : Summary.t =
AnalyzerNodesBasicCost.exec_cfg instr_cfg proc_data ~initial:NodesBasicCostDomain.empty
~debug:true
in
(* compute loop invariant map for control var analysis *)
let loop_inv_map =
LoopInvariant.get_loop_inv_var_map reaching_defs_invariant_map loop_head_to_loop_nodes
in
(* given the semantics computes the upper bound on the number of times a node could be executed *)
let bound_map =
BoundMap.compute_upperbound_map node_cfg inferbo_invariant_map control_dep_invariant_map
loop_inv_map
in
let pp_extra, get_node_nb_exec =
let equalities = ConstraintSolver.collect_constraints node_cfg in

@ -0,0 +1,127 @@
(*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module L = Logging
module InvariantVars = AbstractDomain.FiniteSet (Var)
module LoopNodes = AbstractDomain.FiniteSet (Procdesc.Node)
(** Map loop header node -> all nodes in the loop *)
module LoopHeadToLoopNodes = Procdesc.NodeMap
let is_defined_outside loop_nodes reaching_defs var =
ReachingDefs.ReachingDefsMap.find_opt var reaching_defs
|> Option.map ~f:(fun def_nodes -> LoopNodes.inter def_nodes loop_nodes |> LoopNodes.is_empty)
|> Option.value ~default:true
(* check if the def of var is unique and satisfies function f_exp *)
let is_def_unique_and_satisfy var (loop_nodes: LoopNodes.t) f_exp =
(* Use O(1) is_singleton check *)
(* tedious parameter wrangling to make IContainer's fold interface happy *)
IContainer.is_singleton
~fold:(fun s ~init ~f -> LoopNodes.fold (fun acc x -> f x acc) s init)
loop_nodes
&& LoopNodes.for_all
(fun node ->
Procdesc.Node.get_instrs node
|> Instrs.exists ~f:(function
| Sil.Load (id, exp_rhs, _, _) when Var.equal (Var.of_id id) var && f_exp exp_rhs ->
true
| Sil.Store (exp_lhs, _, exp_rhs, _)
when Exp.equal exp_lhs (Var.to_exp var) && f_exp exp_rhs ->
true (* function calls are ignored at the moment *)
| _ ->
false ) )
loop_nodes
let is_exp_invariant inv_vars loop_nodes reaching_defs exp =
Var.get_all_vars_in_exp exp
|> Sequence.for_all ~f:(fun var ->
InvariantVars.mem var inv_vars || is_defined_outside loop_nodes reaching_defs var )
let get_vars_in_loop loop_nodes =
LoopNodes.fold
(fun node acc ->
Procdesc.Node.get_instrs node
|> Instrs.fold
~f:(fun acc instr ->
match instr with
| Sil.Load (id, exp_rhs, _, _) ->
Var.get_all_vars_in_exp exp_rhs
|> Sequence.fold
~init:(InvariantVars.add (Var.of_id id) acc)
~f:(fun acc var -> InvariantVars.add var acc)
| Sil.Store (exp_lhs, _, exp_rhs, _) ->
Var.get_all_vars_in_exp exp_rhs
|> Sequence.append (Var.get_all_vars_in_exp exp_lhs)
|> Sequence.fold ~init:acc ~f:(fun acc var -> InvariantVars.add var acc)
(* function calls are ignored at the moment *)
| _ ->
acc )
~init:acc )
loop_nodes InvariantVars.empty
(* A variable is invariant if
- its reaching definition is outside of the loop
- o.w. its definition is constant or invariant itself *)
let get_inv_vars_in_loop reaching_defs_invariant_map loop_head loop_nodes =
let process_var_once var inv_vars =
(* if a variable is marked invariant once, it can't be invalidated
(i.e. invariance is monotonic) *)
if InvariantVars.mem var inv_vars then (inv_vars, false)
else
let loop_head_id = Procdesc.Node.get_id loop_head in
ReachingDefs.Analyzer.extract_post loop_head_id reaching_defs_invariant_map
|> Option.map ~f:(fun reaching_defs ->
ReachingDefs.ReachingDefsMap.find_opt var reaching_defs
|> Option.map ~f:(fun def_nodes ->
let in_loop_defs = LoopNodes.inter loop_nodes def_nodes in
(* reaching definition is outside of the loop *)
if LoopNodes.is_empty in_loop_defs then (InvariantVars.add var inv_vars, true)
else if
(* its definition is unique and invariant *)
is_def_unique_and_satisfy var in_loop_defs
(is_exp_invariant inv_vars loop_nodes reaching_defs)
then (InvariantVars.add var inv_vars, true)
else (inv_vars, false) )
|> Option.value (* if a var is not declared, it must be invariant *)
~default:(InvariantVars.add var inv_vars, true) )
|> Option.value ~default:(inv_vars, false)
in
let vars_in_loop = get_vars_in_loop loop_nodes in
(* until there are no changes to inv_vars, keep repeatedly
processing all the variables that occur in the loop nodes *)
let rec find_fixpoint inv_vars =
let inv_vars', modified =
InvariantVars.fold
(fun var (inv_vars, is_mod) ->
let inv_vars', is_mod' = process_var_once var inv_vars in
(inv_vars', is_mod || is_mod') )
vars_in_loop (inv_vars, false)
in
if modified then find_fixpoint inv_vars' else inv_vars'
in
find_fixpoint InvariantVars.empty
(** Map loop head -> invariant vars in loop *)
module LoopHeadToInvVars = Procdesc.NodeMap
let get_loop_inv_var_map reaching_defs_invariant_map loop_head_to_loop_nodes =
LoopHeadToLoopNodes.fold
(fun loop_head loop_nodes inv_map ->
let inv_vars_in_loop =
get_inv_vars_in_loop reaching_defs_invariant_map loop_head loop_nodes
in
L.(debug Analysis Medium)
"@\n>>> loop head: %a --> inv vars: %a @\n" Procdesc.Node.pp loop_head InvariantVars.pp
inv_vars_in_loop ;
LoopHeadToInvVars.add loop_head inv_vars_in_loop inv_map )
loop_head_to_loop_nodes LoopHeadToInvVars.empty

@ -109,7 +109,8 @@ let get_control_maps cfg =
loop_head_to_source_list )
in
Procdesc.NodeMap.fold
(fun loop_head source_list Control.({exit_map; loop_head_to_guard_nodes}) ->
(fun loop_head source_list
(Control.({exit_map; loop_head_to_guard_nodes}), loop_head_to_loop_nodes) ->
L.(debug Analysis Medium)
"Back-edge source list : [%a] --> loop_head: %i \n" (Pp.comma_seq Procdesc.Node.pp)
source_list (nid_int loop_head) ;
@ -140,8 +141,20 @@ let get_control_maps cfg =
Some guard_prune_nodes)
loop_head_to_guard_nodes
in
Control.{exit_map= exit_map'; loop_head_to_guard_nodes= loop_head_to_guard_nodes'} )
let loop_head_to_loop_nodes' =
LoopInvariant.LoopHeadToLoopNodes.update loop_head
(function
| Some existing_loop_nodes ->
Some (LoopInvariant.LoopNodes.union existing_loop_nodes loop_nodes)
| None ->
Some loop_nodes)
loop_head_to_loop_nodes
in
let open Control in
( {exit_map= exit_map'; loop_head_to_guard_nodes= loop_head_to_guard_nodes'}
, loop_head_to_loop_nodes' ) )
loop_head_to_source_nodes_map
Control.
( (let open Control in
{ exit_map= Control.ExitNodeToLoopHeads.empty
; loop_head_to_guard_nodes= Control.LoopHeadToGuardNodes.empty }
; loop_head_to_guard_nodes= Control.LoopHeadToGuardNodes.empty })
, LoopInvariant.LoopHeadToLoopNodes.empty )

@ -0,0 +1,59 @@
(*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
(** The node in which the reaching definition x := e is defined.
A definition x :=e, declared at node N, reaches the current node
if there is a path from node N to the current node such that x is
not modified along the path **)
module Defs = AbstractDomain.FiniteSet (Procdesc.Node)
(* even though we only add singletons (defs), the set is needed for joins *)
(** Map var -> its reaching definition **)
module ReachingDefsMap = AbstractDomain.Map (Var) (Defs)
(* forward transfer function for reaching definitions *)
module TransferFunctionsReachingDefs (CFG : ProcCfg.S) = struct
module CFG = CFG
module Domain = ReachingDefsMap
type extras = ProcData.no_extras
(* for each x := e at node n, remove x's definitions and introduce x -> n *)
let exec_instr astate _ (node: CFG.Node.t) instr =
let node = CFG.Node.underlying_node node in
let strong_update_def astate var = Domain.add var (Defs.singleton node) astate in
let weak_update_def astate var =
Domain.update var
(function Some defs -> Some (Defs.add node defs) | None -> Some (Defs.singleton node))
astate
in
match instr with
| Sil.Load (lhs_id, _, _, _) when Ident.is_none lhs_id ->
(* dummy deref inserted by frontend--don't count as a read *)
astate
| Sil.Load (id, _, _, _) | Sil.Call ((id, _), _, _, _, _) ->
strong_update_def astate (Var.of_id id)
(* only strong update for assigning to a pvar *)
| Sil.Store (Lvar pvar, _, _, _) ->
strong_update_def astate (Var.of_pvar pvar)
(* by default use weak update *)
| Sil.Store (exp_lhs, _, _, _) ->
let vars = Var.get_all_vars_in_exp exp_lhs in
Sequence.fold ~init:astate ~f:weak_update_def vars
| _ ->
astate
let pp_session_name node fmt =
F.fprintf fmt "reaching defs analysis %a" CFG.Node.pp_id (CFG.Node.id node)
end
module Analyzer = AbstractInterpreter.Make (ProcCfg.Normal) (TransferFunctionsReachingDefs)

@ -17,6 +17,8 @@ let singleton_or_more ~fold t =
match acc with Empty -> Singleton item | _ -> return More ) )
let is_singleton ~fold t = match singleton_or_more ~fold t with Singleton _ -> true | _ -> false
let mem_nth ~fold t index =
With_return.with_return (fun {return} ->
let _ : int =

@ -13,6 +13,10 @@ type 'a singleton_or_more = Empty | Singleton of 'a | More
val singleton_or_more :
fold:('t, 'a, 'a singleton_or_more) Container.fold -> 't -> 'a singleton_or_more
(* O(1) *)
val is_singleton : fold:('t, 'a, 'a singleton_or_more) Container.fold -> 't -> bool
val mem_nth : fold:('t, _, int) Container.fold -> 't -> int -> bool
val forto : (int, int, 'accum) Container.fold

@ -4,9 +4,63 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* We get quadratic bound for this example but we should get linear bound */
/* Depending on whether p is positive, the program might loop forever */
int while_unique_def_FN(int p) {
int j = 0;
while (j < 10) {
if (p > 0) {
j = 500;
} else {
j = -1;
}
}
return 0;
}
/* Theta(n) */
void do_k_times(int n) {
int k = n;
for (int i = 0; i < k; i++) {
}
}
/* Theta(n) */
void do_k_times_array(int n) {
int k = n;
int a[10];
for (int i = 0; i < k; i++) {
a[k] = 4 + k;
}
}
/* Expected Theta(n * m), but can't handle nested loops over symbols yet */
void do_n_m_times_nested_FP(int n, int m) {
int k = n;
int p = m;
for (int i = 0; i < k; i++) {
for (int j = 0; j < p; j++) {
}
}
}
/* Expected Theta(m) but can't handle nested loops over symbols yet.
Also inner loop will have t as invariant */
void two_loops_nested_invariant_FP(int p) {
int t = 0;
int m = p;
for (int i = 0; i < m; i++) {
t = 3;
for (int j = 0; j < t; j++) {
}
}
}
/* since the guard i is invariant, we will remove it from control
variables, and hence the total cost will be constant, but the
program diverges */
int while_infinite_FN() {
int i = 0;
while (i < 10) {
}
return 0;
}

@ -77,8 +77,13 @@ codetoanalyze/c/performance/instantiate.c, do_m2_times, 1, EXPENSIVE_EXECUTION_T
codetoanalyze/c/performance/instantiate.c, do_m2_times, 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 10 * s$1 + 6 * s$1^2]
codetoanalyze/c/performance/instantiate.c, do_n_times, 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 6 * s$1]
codetoanalyze/c/performance/instantiate.c, do_n_times, 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 3 + 6 * s$1]
codetoanalyze/c/performance/invariant.c, do_k_times, 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 5 * s$1^2]
codetoanalyze/c/performance/invariant.c, do_k_times, 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 5 * s$1^2]
codetoanalyze/c/performance/invariant.c, do_k_times, 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 5 * s$1]
codetoanalyze/c/performance/invariant.c, do_k_times, 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 5 * s$1]
codetoanalyze/c/performance/invariant.c, do_k_times_array, 3, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 8 * s$1]
codetoanalyze/c/performance/invariant.c, do_k_times_array, 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 8 * s$1]
codetoanalyze/c/performance/invariant.c, do_n_m_times_nested_FP, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/invariant.c, two_loops_nested_invariant_FP, 0, INFINITE_EXECUTION_TIME_CALL, no_bucket, ERROR, []
codetoanalyze/c/performance/invariant.c, while_infinite_FN, 2, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, []
codetoanalyze/c/performance/jump_inside_loop.c, jump_inside_loop, 7, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2002]
codetoanalyze/c/performance/jump_inside_loop.c, jump_inside_loop, 9, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2002]
codetoanalyze/c/performance/jump_inside_loop.c, jump_inside_loop, 11, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2004]

@ -2,8 +2,8 @@ codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(i
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 4, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 882]
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 882]
codetoanalyze/java/performance/ArrayCost.java, boolean ArrayCost.isPowOfTwo_FP(int), 12, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 889]
codetoanalyze/java/performance/ArrayCost.java, void ArrayCost.ArrayCost(int[]), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 5 * u$7^2]
codetoanalyze/java/performance/ArrayCost.java, void ArrayCost.ArrayCost(int[]), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 6 + 5 * u$7^2]
codetoanalyze/java/performance/ArrayCost.java, void ArrayCost.ArrayCost(int[]), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 5 + 5 * u$7]
codetoanalyze/java/performance/ArrayCost.java, void ArrayCost.ArrayCost(int[]), 5, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 6 + 5 * u$7]
codetoanalyze/java/performance/Break.java, int Break.break_constant(int), 2, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 8 + 7 * s$1]
codetoanalyze/java/performance/Break.java, int Break.break_loop(int,int), 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 1 + 7 * s$1]
codetoanalyze/java/performance/Break.java, int Break.break_loop(int,int), 1, EXPENSIVE_EXECUTION_TIME_CALL, no_bucket, ERROR, [with estimated cost 2 + 7 * s$1]

Loading…
Cancel
Save