[cost] write ObjC's NSCollection model separately and refactor

Summary:
When implementing iterator, we find out that because some semantics of inferbo is Java-specific, we cannot simply use Java's `Collection` model for `NSCollection`.
So this diff writing `NSCollection` model separately.

This diff also extracts the common parts of `NSCollection` and `Collection` into `AbstractCollection` to combine the duplicate the parts.

Reviewed By: ezgicicek

Differential Revision: D22975159

fbshipit-source-id: daed3f99f
master
Qianyi Shu 4 years ago committed by Facebook GitHub Bot
parent 12189f4c4e
commit a7ff42069c

@ -41,6 +41,8 @@ let java_list_files_length = mk "java.list_files_length" Typ.(int)
let is_java_collection_internal_array fn = Fieldname.equal fn java_collection_internal_array let is_java_collection_internal_array fn = Fieldname.equal fn java_collection_internal_array
let objc_collection_internal_array = mk "nscollection.elements" Typ.(mk_array void)
let c_strlen () = let c_strlen () =
if Language.curr_language_is Java then mk "length" Typ.uint else mk "c.strlen" Typ.uint if Language.curr_language_is Java then mk "length" Typ.uint else mk "c.strlen" Typ.uint

@ -47,6 +47,9 @@ val is_cpp_vector_elem : Fieldname.t -> bool
val is_java_collection_internal_array : Fieldname.t -> bool val is_java_collection_internal_array : Fieldname.t -> bool
(** Check if the field is for Java collection's elements *) (** Check if the field is for Java collection's elements *)
val objc_collection_internal_array : Fieldname.t
(** Field for ObjC's collection's elements *)
(** {2 Field domain constructor} *) (** {2 Field domain constructor} *)
type field_typ = Typ.t option type field_typ = Typ.t option

@ -783,11 +783,15 @@ module JavaInteger = struct
{exec; check= no_check} {exec; check= no_check}
end end
(* Java's Collections are represented like arrays. But we don't care about the elements. module type Lang = sig
val collection_internal_array_field : Fieldname.t
end
(* Abstract Collections are represented like arrays. But we don't care about the elements.
- when they are constructed, we set the size to 0 - when they are constructed, we set the size to 0
- each time we add an element, we increase the length of the array - each time we add an element, we increase the length of the array
- each time we delete an element, we decrease the length of the array *) - each time we delete an element, we decrease the length of the array *)
module Collection = struct module AbstractCollection (Lang : Lang) = struct
let create_collection {pname; node_hash; location} ~ret:(id, _) mem ~length = let create_collection {pname; node_hash; location} ~ret:(id, _) mem ~length =
let represents_multiple_values = true in let represents_multiple_values = true in
let traces = Trace.(Set.singleton location ArrayDeclaration) in let traces = Trace.(Set.singleton location ArrayDeclaration) in
@ -803,9 +807,7 @@ module Collection = struct
Dom.Val.of_java_array_alloc allocsite ~length ~traces Dom.Val.of_java_array_alloc allocsite ~length ~traces
in in
let coll_loc = Loc.of_allocsite coll_allocsite in let coll_loc = Loc.of_allocsite coll_allocsite in
let internal_array_loc = let internal_array_loc = Loc.append_field coll_loc Lang.collection_internal_array_field in
Loc.append_field coll_loc BufferOverrunField.java_collection_internal_array
in
mem mem
|> Dom.Mem.add_heap internal_array_loc internal_array |> Dom.Mem.add_heap internal_array_loc internal_array
|> Dom.Mem.add_stack (Loc.of_id id) (coll_loc |> PowLoc.singleton |> Dom.Val.of_pow_loc ~traces) |> Dom.Mem.add_stack (Loc.of_id id) (coll_loc |> PowLoc.singleton |> Dom.Val.of_pow_loc ~traces)
@ -825,14 +827,12 @@ module Collection = struct
let eval_collection_internal_array_locs coll_exp mem = let eval_collection_internal_array_locs coll_exp mem =
Sem.eval_locs coll_exp mem Sem.eval_locs coll_exp mem |> PowLoc.append_field ~fn:Lang.collection_internal_array_field
|> PowLoc.append_field ~fn:BufferOverrunField.java_collection_internal_array
let get_collection_internal_array_locs coll_id mem = let get_collection_internal_array_locs coll_id mem =
let coll = Dom.Mem.find (Loc.of_id coll_id) mem in let coll = Dom.Mem.find (Loc.of_id coll_id) mem in
Dom.Val.get_pow_loc coll Dom.Val.get_pow_loc coll |> PowLoc.append_field ~fn:Lang.collection_internal_array_field
|> PowLoc.append_field ~fn:BufferOverrunField.java_collection_internal_array
let get_collection_internal_elements_locs coll_id mem = let get_collection_internal_elements_locs coll_id mem =
@ -1031,14 +1031,49 @@ module Collection = struct
{exec; check= check_index ~last_included:false coll_id index_exp} {exec; check= check_index ~last_included:false coll_id index_exp}
end end
module Collection = AbstractCollection (struct
let collection_internal_array_field = BufferOverrunField.java_collection_internal_array
end)
module NSCollection = struct module NSCollection = struct
include AbstractCollection (struct
let collection_internal_array_field = BufferOverrunField.objc_collection_internal_array
end)
let create_collection {pname; node_hash; location; integer_type_widths} ~ret:(coll_id, _) mem
~size_exp =
let represents_multiple_values = true in
let _, stride, length0, _ = get_malloc_info size_exp in
let length = Sem.eval integer_type_widths length0 mem in
let traces = Trace.(Set.add_elem location ArrayDeclaration) (Dom.Val.get_traces length) in
let internal_array =
let allocsite =
Allocsite.make pname ~node_hash ~inst_num:1 ~dimension:1 ~path:None
~represents_multiple_values
in
let offset, size = (Itv.zero, Dom.Val.get_itv length) in
Dom.Val.of_c_array_alloc allocsite ~stride ~offset ~size ~traces
in
let coll_allocsite =
Allocsite.make pname ~node_hash ~inst_num:0 ~dimension:1 ~path:None
~represents_multiple_values
in
let coll_loc = Loc.of_allocsite coll_allocsite in
let internal_array_loc =
Loc.append_field coll_loc BufferOverrunField.objc_collection_internal_array
in
mem
|> Dom.Mem.add_heap internal_array_loc internal_array
|> Dom.Mem.add_stack (Loc.of_id coll_id)
(coll_loc |> PowLoc.singleton |> Dom.Val.of_pow_loc ~traces)
(** Creates a new array from the given c array by copying the first X elements. *) (** Creates a new array from the given c array by copying the first X elements. *)
let create_from_array src_exp size_exp = let create_from_array src_exp size_exp =
let exec ({integer_type_widths} as model_env) ~ret:((id, _) as ret) mem = let exec model_env ~ret:((id, _) as ret) mem =
let size_v = Sem.eval integer_type_widths size_exp mem |> Dom.Val.get_itv in
let src_arr_v = Dom.Mem.find_set (Sem.eval_locs src_exp mem) mem in let src_arr_v = Dom.Mem.find_set (Sem.eval_locs src_exp mem) mem in
let mem = Collection.create_collection model_env ~ret mem ~length:size_v in let mem = create_collection model_env ~ret mem ~size_exp in
let dest_arr_loc = Collection.get_collection_internal_elements_locs id mem in let dest_arr_loc = get_collection_internal_elements_locs id mem in
Dom.Mem.update_mem dest_arr_loc src_arr_v mem Dom.Mem.update_mem dest_arr_loc src_arr_v mem
and check {location; integer_type_widths} mem cond_set = and check {location; integer_type_widths} mem cond_set =
BoUtils.Check.lindex integer_type_widths ~array_exp:src_exp ~index_exp:size_exp BoUtils.Check.lindex integer_type_widths ~array_exp:src_exp ~index_exp:size_exp
@ -1047,11 +1082,27 @@ module NSCollection = struct
{exec; check} {exec; check}
let new_collection =
let exec = create_collection ~size_exp:Exp.zero in
{exec; check= no_check}
let get_first coll_id = get_at_index coll_id Exp.zero
let of_list list =
let exec env ~ret:((id, _) as ret) mem =
let mem = new_collection.exec env ~ret mem in
List.fold_left list ~init:mem ~f:(fun acc {exp= elem_exp} ->
(add id elem_exp).exec env ~ret acc )
in
{exec; check= no_check}
let copy coll_id src_exp = let copy coll_id src_exp =
let exec model_env ~ret:((id, _) as ret) mem = let exec model_env ~ret:((id, _) as ret) mem =
let coll = Dom.Mem.find_stack (Loc.of_id coll_id) mem in let coll = Dom.Mem.find_stack (Loc.of_id coll_id) mem in
let set_length = Collection.eval_collection_length src_exp mem |> Dom.Val.get_itv in let set_length = eval_collection_length src_exp mem |> Dom.Val.get_itv in
Collection.change_size_by ~size_f:(fun _ -> set_length) coll_id model_env ~ret mem change_size_by ~size_f:(fun _ -> set_length) coll_id model_env ~ret mem
|> model_by_value coll id |> model_by_value coll id
in in
{exec; check= no_check} {exec; check= no_check}
@ -1378,11 +1429,12 @@ module NSString = struct
let concat = JavaString.concat let concat = JavaString.concat
let split exp = let split exp =
let exec model_env ~ret mem = let exec model_env ~ret:((coll_id, _) as ret) mem =
let itv = let to_add_length =
ArrObjCommon.eval_size model_env exp ~fn mem |> JavaString.range_itv_one_max_one_mone ArrObjCommon.eval_size model_env exp ~fn mem |> JavaString.range_itv_one_max_one_mone
in in
Collection.create_collection ~length:itv model_env ~ret mem NSCollection.create_collection ~size_exp:Exp.zero model_env ~ret mem
|> NSCollection.change_size_by ~size_f:(Itv.plus to_add_length) coll_id model_env ~ret
in in
{exec; check= no_check} {exec; check= no_check}
@ -1404,7 +1456,7 @@ let objc_malloc exp =
let exec ({tenv} as model) ~ret mem = let exec ({tenv} as model) ~ret mem =
match exp with match exp with
| Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSArray" tenv (Typ.to_string typ) -> | Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSArray" tenv (Typ.to_string typ) ->
Collection.new_collection.exec model ~ret mem NSCollection.new_collection.exec model ~ret mem
| Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSString" tenv (Typ.to_string typ) | Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSString" tenv (Typ.to_string typ)
-> ->
(NSString.create_with_c_string (Exp.Const (Const.Cstr ""))).exec model ~ret mem (NSString.create_with_c_string (Exp.Const (Const.Cstr ""))).exec model ~ret mem
@ -1555,32 +1607,36 @@ module Call = struct
; -"CFArrayCreate" <>$ any_arg $+ capt_exp $+ capt_exp ; -"CFArrayCreate" <>$ any_arg $+ capt_exp $+ capt_exp
$+...$--> NSCollection.create_from_array $+...$--> NSCollection.create_from_array
; -"CFArrayCreateCopy" <>$ any_arg $+ capt_exp $!--> create_copy_array ; -"CFArrayCreateCopy" <>$ any_arg $+ capt_exp $!--> create_copy_array
; -"CFArrayGetCount" <>$ capt_exp $!--> Collection.size ; -"CFArrayGetCount" <>$ capt_exp $!--> NSCollection.size
; -"CFArrayGetValueAtIndex" <>$ capt_var_exn $+ capt_exp $!--> Collection.get_at_index ; -"CFArrayGetValueAtIndex" <>$ capt_var_exn $+ capt_exp $!--> NSCollection.get_at_index
; -"CFDictionaryGetCount" <>$ capt_exp $!--> Collection.size ; -"CFDictionaryGetCount" <>$ capt_exp $!--> NSCollection.size
; -"MCFArrayGetCount" <>$ capt_exp $!--> Collection.size ; -"MCFArrayGetCount" <>$ capt_exp $!--> NSCollection.size
; +PatternMatch.ObjectiveC.implements "NSArray" &:: "init" <>$ capt_exp $--> id ; +PatternMatch.ObjectiveC.implements "NSArray" &:: "init" <>$ capt_exp $--> id
; +PatternMatch.ObjectiveC.implements "NSArray" &:: "array" <>--> Collection.new_collection ; +PatternMatch.ObjectiveC.implements "NSArray" &:: "array" <>--> NSCollection.new_collection
; +PatternMatch.ObjectiveC.implements "NSArray"
&:: "firstObject" <>$ capt_var_exn $!--> NSCollection.get_first
; +PatternMatch.ObjectiveC.implements "NSArray" ; +PatternMatch.ObjectiveC.implements "NSArray"
&:: "initWithArray:" <>$ capt_var_exn $+ capt_exp $--> NSCollection.copy &:: "initWithArray:" <>$ capt_var_exn $+ capt_exp $--> NSCollection.copy
; +PatternMatch.ObjectiveC.implements "NSArray" ; +PatternMatch.ObjectiveC.implements "NSArray"
&:: "initWithArray:copyItems:" <>$ capt_var_exn $+ capt_exp $+ any_arg &:: "initWithArray:copyItems:" <>$ capt_var_exn $+ capt_exp $+ any_arg
$--> NSCollection.copy $--> NSCollection.copy
; +PatternMatch.ObjectiveC.implements "NSArray" &:: "count" <>$ capt_exp $!--> Collection.size
; +PatternMatch.ObjectiveC.implements "NSArray" ; +PatternMatch.ObjectiveC.implements "NSArray"
&:: "objectAtIndexedSubscript:" <>$ capt_var_exn $+ capt_exp $!--> Collection.get_at_index &:: "count" <>$ capt_exp $!--> NSCollection.size
; +PatternMatch.ObjectiveC.implements "NSArray"
&:: "objectAtIndexedSubscript:" <>$ capt_var_exn $+ capt_exp $!--> NSCollection.get_at_index
; +PatternMatch.ObjectiveC.implements "NSArray" ; +PatternMatch.ObjectiveC.implements "NSArray"
&:: "arrayWithObjects:count:" <>$ capt_exp $+ capt_exp $--> NSCollection.create_from_array &:: "arrayWithObjects:count:" <>$ capt_exp $+ capt_exp $--> NSCollection.create_from_array
; +PatternMatch.ObjectiveC.implements "NSArray" &:: "arrayWithObjects" &++> Collection.of_list ; +PatternMatch.ObjectiveC.implements "NSArray"
&:: "arrayWithObjects" &++> NSCollection.of_list
; +PatternMatch.ObjectiveC.implements "NSDictionary" ; +PatternMatch.ObjectiveC.implements "NSDictionary"
&:: "dictionaryWithObjects:forKeys:count:" <>$ any_arg $+ capt_exp $+ capt_exp &:: "dictionaryWithObjects:forKeys:count:" <>$ any_arg $+ capt_exp $+ capt_exp
$--> NSCollection.create_from_array $--> NSCollection.create_from_array
; +PatternMatch.ObjectiveC.implements "NSDictionary" ; +PatternMatch.ObjectiveC.implements "NSDictionary"
&:: "objectForKeyedSubscript:" <>$ capt_var_exn $+ capt_exp $--> Collection.get_at_index &:: "objectForKeyedSubscript:" <>$ capt_var_exn $+ capt_exp $--> NSCollection.get_at_index
; +PatternMatch.ObjectiveC.implements "NSDictionary" ; +PatternMatch.ObjectiveC.implements "NSDictionary"
&:: "objectForKey:" <>$ capt_var_exn $+ capt_exp $--> Collection.get_at_index &:: "objectForKey:" <>$ capt_var_exn $+ capt_exp $--> NSCollection.get_at_index
; +PatternMatch.ObjectiveC.implements "NSDictionary" ; +PatternMatch.ObjectiveC.implements "NSDictionary"
&:: "count" <>$ capt_exp $--> Collection.size &:: "count" <>$ capt_exp $--> NSCollection.size
; +PatternMatch.ObjectiveC.implements "NSDictionary" ; +PatternMatch.ObjectiveC.implements "NSDictionary"
&:: "allKeys" <>$ capt_exp $--> create_copy_array &:: "allKeys" <>$ capt_exp $--> create_copy_array
; +PatternMatch.ObjectiveC.implements "NSDictionary" ; +PatternMatch.ObjectiveC.implements "NSDictionary"

@ -36,6 +36,11 @@ module Collection : sig
(** Evaluate length of Java collection *) (** Evaluate length of Java collection *)
end end
module NSCollection : sig
val eval_collection_length : Exp.t -> BufferOverrunDomain.Mem.t -> BufferOverrunDomain.Val.t
(** Evaluate length of ObjC collection *)
end
module NSString : sig module NSString : sig
val get_length : val get_length :
BufferOverrunUtils.ModelEnv.model_env BufferOverrunUtils.ModelEnv.model_env

@ -156,6 +156,20 @@ module NSString = struct
let substring_from_index = JavaString.substring_no_end let substring_from_index = JavaString.substring_no_end
end end
module NSCollection = struct
let get_length str ~of_function {location} ~ret:_ mem =
let itv =
BufferOverrunModels.NSCollection.eval_collection_length str mem
|> BufferOverrunDomain.Val.get_itv
in
CostUtils.of_itv ~itv ~degree_kind:Polynomials.DegreeKind.Linear ~of_function location
let op_on_two_coll cost_op ~of_function coll1 coll2 model_env ~ret mem =
let get_length coll = get_length coll ~of_function model_env ~ret mem in
cost_op (get_length coll1) (get_length coll2)
end
module ImmutableSet = struct module ImmutableSet = struct
let construct = linear ~of_function:"ImmutableSet.construct" let construct = linear ~of_function:"ImmutableSet.construct"
@ -200,6 +214,13 @@ module Call = struct
&:: "componentsSeparatedByString:" <>$ capt_exp $+ capt_exp &:: "componentsSeparatedByString:" <>$ capt_exp $+ capt_exp
$--> NSString.op_on_two_str BasicCost.mult $--> NSString.op_on_two_str BasicCost.mult
~of_function:"NSString.componentsSeparatedByString:" ~of_function:"NSString.componentsSeparatedByString:"
; -"NSArray" &:: "initWithArray:" <>$ any_arg $+ capt_exp
$--> NSCollection.get_length ~of_function:"NSArray.initWithArray:"
; -"NSArray" &:: "isEqualToArray:" <>$ capt_exp $+ capt_exp
$--> NSCollection.op_on_two_coll BasicCost.min_default_left
~of_function:"NSArray.isEqualToArray:"
; -"NSArray" &:: "containsObject:" <>$ capt_exp $+ any_arg
$--> NSCollection.get_length ~of_function:"NSArray.containsObject:"
; +PatternMatch.Java.implements_collections ; +PatternMatch.Java.implements_collections
&:: "sort" $ capt_exp &:: "sort" $ capt_exp
$+...$--> BoundsOfCollection.n_log_n_length ~of_function:"Collections.sort" $+...$--> BoundsOfCollection.n_log_n_length ~of_function:"Collections.sort"

@ -77,6 +77,12 @@ NSArray* nsarray_add_objects_from_array_linear_FN(NSArray* append_array) {
// query element // query element
void nsarray_get_first_constant() {
NSArray* array = @[ @1, @2 ];
for (int i = 0; i < [[array firstObject] integerValue]; i++) {
}
}
void nsarray_access_constant() { void nsarray_access_constant() {
NSArray* array = @[ @1.0f, @2.0f, @3.0f, @4.0f, @5.0f, @6.0f, @7.0f, @8.0f ]; NSArray* array = @[ @1.0f, @2.0f, @3.0f, @4.0f, @5.0f, @6.0f, @7.0f, @8.0f ];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
@ -103,7 +109,7 @@ void nsarray_find_linear(NSArray* array) {
} }
} }
void nsarray_contains_object_linear_FN(NSArray* array) { void nsarray_contains_object_linear(NSArray* array) {
[array containsObject:@1]; [array containsObject:@1];
} }
@ -163,8 +169,7 @@ void nsarray_next_object_linear_FN(NSArray* array) {
} }
// compare array // compare array
boolean_t nsarray_is_equal_to_array_linear_FN(NSArray* array1, boolean_t nsarray_is_equal_to_array_linear(NSArray* array1, NSArray* array2) {
NSArray* array2) {
return [array1 isEqualToArray:array2]; return [array1 isEqualToArray:array2];
} }

@ -1,21 +1,22 @@
codetoanalyze/objc/performance/NSArray.m, nsarray_access_constant, 50, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_access_constant, 50, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_access_linear, 3 + 7 ⋅ array.length.ub + 3 ⋅ (array.length.ub + 1), OnUIThread:false, [{array.length.ub + 1},Loop,{array.length.ub},Loop] codetoanalyze/objc/performance/NSArray.m, nsarray_access_linear, 3 + 7 ⋅ array->elements.length.ub + 3 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSArray.m, nsarray_add_object_constant, 8, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_add_object_constant, 8, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_add_objects_from_array_linear_FN, 8, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_add_objects_from_array_linear_FN, 8, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_array_with_objects_constant, 27, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_array_with_objects_constant, 27, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_binary_search_log_FN, 10, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_binary_search_log_FN, 10, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_contains_object_linear_FN, 4, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_contains_object_linear, 3 + array->elements.length.ub, OnUIThread:false, [{array->elements.length.ub},Modeled call to NSArray.containsObject:]
codetoanalyze/objc/performance/NSArray.m, nsarray_count_bounded_linear, 3 + 3 ⋅ array.length.ub + 3 ⋅ (array.length.ub + 1), OnUIThread:false, [{array.length.ub + 1},Loop,{array.length.ub},Loop] codetoanalyze/objc/performance/NSArray.m, nsarray_count_bounded_linear, 3 + 3 ⋅ array->elements.length.ub + 3 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSArray.m, nsarray_empty_array_constant, 8, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_empty_array_constant, 8, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_enumerator_linear_FN, 14, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_enumerator_linear_FN, 14, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_find_linear, 4 + 9 ⋅ array.length.ub + 3 ⋅ (array.length.ub + 1), OnUIThread:false, [{array.length.ub + 1},Loop,{array.length.ub},Loop] codetoanalyze/objc/performance/NSArray.m, nsarray_find_linear, 4 + 9 ⋅ array->elements.length.ub + 3 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSArray.m, nsarray_first_object_constant, 4, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_first_object_constant, 4, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_get_first_constant, 27, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_init_constant, 9, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_init_constant, 9, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_constant, 15, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_constant, 14, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_copy_linear, 7 + 3 ⋅ array.length.ub + 3 ⋅ (array.length.ub + 1), OnUIThread:false, [{array.length.ub + 1},Loop,{array.length.ub},Loop] codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_copy_linear, 7 + 3 ⋅ array->elements.length.ub + 3 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_linear, 7 + 3 ⋅ array.length.ub + 3 ⋅ (array.length.ub + 1), OnUIThread:false, [{array.length.ub + 1},Loop,{array.length.ub},Loop] codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_linear, 6 + 3 ⋅ array->elements.length.ub + array->elements.length.ub + 3 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Modeled call to NSArray.initWithArray:,{array->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_objects_constant, 39, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_objects_constant, 39, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_is_equal_to_array_linear_FN, 5, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_is_equal_to_array_linear, 4 + array1->elements.length.ub, OnUIThread:false, [{array1->elements.length.ub},Modeled call to NSArray.isEqualToArray:]
codetoanalyze/objc/performance/NSArray.m, nsarray_iterate_linear_FN, 14, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_iterate_linear_FN, 14, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_last_object_constant, 4, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_last_object_constant, 4, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_next_object_linear_FN, 10, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_next_object_linear_FN, 10, OnUIThread:false, []
@ -23,9 +24,9 @@ codetoanalyze/objc/performance/NSArray.m, nsarray_object_at_indexed_constant, 34
codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_constant, 34, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_constant, 34, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_nlogn_FN, 10, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_nlogn_FN, 10, OnUIThread:false, []
codetoanalyze/objc/performance/NSArray.m, objc_blocknsarray_binary_search_log_FN_1, 5, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, objc_blocknsarray_binary_search_log_FN_1, 5, OnUIThread:false, []
codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_keys_linear1, 3 + 3 ⋅ dict.length.ub + 4 ⋅ (dict.length.ub + 1), OnUIThread:false, [{dict.length.ub + 1},Loop,{dict.length.ub},Loop] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_keys_linear1, 3 + 3 ⋅ dict->elements.length.ub + 4 ⋅ (dict->elements.length.ub + 1), OnUIThread:false, [{dict->elements.length.ub + 1},Loop,{dict->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_keys_linear2, 6 + 3 ⋅ dict.length.ub + 3 ⋅ (dict.length.ub + 1), OnUIThread:false, [{dict.length.ub + 1},Loop,{dict.length.ub},Loop] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_keys_linear2, 6 + 3 ⋅ dict->elements.length.ub + 3 ⋅ (dict->elements.length.ub + 1), OnUIThread:false, [{dict->elements.length.ub + 1},Loop,{dict->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_values_linear, 3 + 3 ⋅ dict.length.ub + 4 ⋅ (dict.length.ub + 1), OnUIThread:false, [{dict.length.ub + 1},Loop,{dict.length.ub},Loop] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_values_linear, 3 + 3 ⋅ dict->elements.length.ub + 4 ⋅ (dict->elements.length.ub + 1), OnUIThread:false, [{dict->elements.length.ub + 1},Loop,{dict->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_dictionary_with_objects_linear, 14 + 15 ⋅ n_entries + 3 ⋅ n_entries + 2 ⋅ (1+max(0, n_entries)) + 4 ⋅ (1+max(0, n_entries)), OnUIThread:false, [{1+max(0, n_entries)},Loop,{1+max(0, n_entries)},Loop,{n_entries},Loop,{n_entries},Loop] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_dictionary_with_objects_linear, 14 + 15 ⋅ n_entries + 3 ⋅ n_entries + 2 ⋅ (1+max(0, n_entries)) + 4 ⋅ (1+max(0, n_entries)), OnUIThread:false, [{1+max(0, n_entries)},Loop,{1+max(0, n_entries)},Loop,{n_entries},Loop,{n_entries},Loop]
codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_enumerate_constant, 52, OnUIThread:false, [] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_enumerate_constant, 52, OnUIThread:false, []
codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_enumerator_linear_FN, 10, OnUIThread:false, [] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_enumerator_linear_FN, 10, OnUIThread:false, []
@ -46,7 +47,7 @@ codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_init_with_capacity_con
codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_constant, 15, OnUIThread:false, [] codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_constant, 15, OnUIThread:false, []
codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_in_loop_constant, 92, OnUIThread:false, [] codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_in_loop_constant, 92, OnUIThread:false, []
codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_in_loop_constant, 18, OnUIThread:false, [] codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_in_loop_constant, 18, OnUIThread:false, []
codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_linear, 3 + 11 ⋅ array.length.ub + 3 ⋅ (array.length.ub + 1), OnUIThread:false, [{array.length.ub + 1},Loop,{array.length.ub},Loop] codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_linear, 3 + 11 ⋅ array->elements.length.ub + 3 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Loop]
codetoanalyze/objc/performance/NSMutableDictionary.m, nsmutabledictionary_set_element_in_loop_linear_FN, 14, OnUIThread:false, [] codetoanalyze/objc/performance/NSMutableDictionary.m, nsmutabledictionary_set_element_in_loop_linear_FN, 14, OnUIThread:false, []
codetoanalyze/objc/performance/NSMutableString.m, nsmstring_append_string_constant, 14 + 3 ⋅ (str.length.ub + 5) + 3 ⋅ (str.length.ub + 6), OnUIThread:false, [{str.length.ub + 6},Loop,{str.length.ub + 5},Loop] codetoanalyze/objc/performance/NSMutableString.m, nsmstring_append_string_constant, 14 + 3 ⋅ (str.length.ub + 5) + 3 ⋅ (str.length.ub + 6), OnUIThread:false, [{str.length.ub + 6},Loop,{str.length.ub + 5},Loop]
codetoanalyze/objc/performance/NSMutableString.m, nsmstring_append_string_linear, 5 + str2.length.ub + 3 ⋅ (str2.length.ub + str1.length.ub) + 3 ⋅ (str2.length.ub + str1.length.ub + 1), OnUIThread:false, [{str2.length.ub + str1.length.ub + 1},Loop,{str2.length.ub + str1.length.ub},Loop,{str2.length.ub},Modeled call to NSMutableString.appendString:] codetoanalyze/objc/performance/NSMutableString.m, nsmstring_append_string_linear, 5 + str2.length.ub + 3 ⋅ (str2.length.ub + str1.length.ub) + 3 ⋅ (str2.length.ub + str1.length.ub + 1), OnUIThread:false, [{str2.length.ub + str1.length.ub + 1},Loop,{str2.length.ub + str1.length.ub},Loop,{str2.length.ub},Modeled call to NSMutableString.appendString:]
@ -80,10 +81,10 @@ codetoanalyze/objc/performance/block.m, objc_blockblock_multiply_array_linear_FN
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_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, 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] 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]
codetoanalyze/objc/performance/cf.m, array_count_linear, 6 + 3 ⋅ arr.length.ub + 2 ⋅ (arr.length.ub + 1), OnUIThread:false, [{arr.length.ub + 1},Loop,{arr.length.ub},Loop] codetoanalyze/objc/performance/cf.m, array_count_linear, 6 + 3 ⋅ arr->elements.length.ub + 2 ⋅ (arr->elements.length.ub + 1), OnUIThread:false, [{arr->elements.length.ub + 1},Loop,{arr->elements.length.ub},Loop]
codetoanalyze/objc/performance/cf.m, cf_array_create_copy_linear, 8 + 3 ⋅ arrayValues.length + 2 ⋅ (arrayValues.length + 1), OnUIThread:false, [{arrayValues.length + 1},Loop,{arrayValues.length},Loop] codetoanalyze/objc/performance/cf.m, cf_array_create_copy_linear, 8 + 3 ⋅ arrayValues.elements.length + 2 ⋅ (arrayValues.elements.length + 1), OnUIThread:false, [{arrayValues.elements.length + 1},Loop,{arrayValues.elements.length},Loop]
codetoanalyze/objc/performance/cf.m, cf_array_create_linear, 11 + 3 ⋅ x + 2 ⋅ (1+max(0, x)), OnUIThread:false, [{1+max(0, x)},Loop,{x},Loop] codetoanalyze/objc/performance/cf.m, cf_array_create_linear, 11 + 3 ⋅ x + 2 ⋅ (1+max(0, x)), OnUIThread:false, [{1+max(0, x)},Loop,{x},Loop]
codetoanalyze/objc/performance/cf.m, dict_count_linear, 6 + 3 ⋅ dict.length.ub + 2 ⋅ (dict.length.ub + 1), OnUIThread:false, [{dict.length.ub + 1},Loop,{dict.length.ub},Loop] codetoanalyze/objc/performance/cf.m, dict_count_linear, 6 + 3 ⋅ dict->elements.length.ub + 2 ⋅ (dict->elements.length.ub + 1), OnUIThread:false, [{dict->elements.length.ub + 1},Loop,{dict->elements.length.ub},Loop]
codetoanalyze/objc/performance/compound_loop_guard.m, compound_while, 7 + 3 ⋅ m + 4 ⋅ (1+max(0, m)), OnUIThread:false, [{1+max(0, m)},Loop,{m},Loop] codetoanalyze/objc/performance/compound_loop_guard.m, compound_while, 7 + 3 ⋅ m + 4 ⋅ (1+max(0, m)), OnUIThread:false, [{1+max(0, m)},Loop,{m},Loop]
codetoanalyze/objc/performance/compound_loop_guard.m, nested_while_and_or_constant, 20, OnUIThread:false, [] codetoanalyze/objc/performance/compound_loop_guard.m, nested_while_and_or_constant, 20, OnUIThread:false, []
codetoanalyze/objc/performance/compound_loop_guard.m, simplified_simulated_while_with_and_constant, 605, OnUIThread:false, [] codetoanalyze/objc/performance/compound_loop_guard.m, simplified_simulated_while_with_and_constant, 605, OnUIThread:false, []

Loading…
Cancel
Save