[inferbo] Add model for `String.valueOf(char[])`

Reviewed By: skcho

Differential Revision: D24396467

fbshipit-source-id: 0ddd7b727
master
Ezgi Çiçek 4 years ago committed by Facebook GitHub Bot
parent 2a28ebfeb4
commit 2679bb0b61

@ -1395,11 +1395,7 @@ module JavaString = struct
{exec; check= no_check} {exec; check= no_check}
let create_with_length {pname; node_hash; location; integer_type_widths} ~ret:(id, _) ~begin_idx let create_with_length {pname; node_hash; location} ~ret:(id, _) ~length_itv mem =
~end_v mem =
let begin_itv = Sem.eval integer_type_widths begin_idx mem |> Dom.Val.get_itv in
let end_itv = Dom.Val.get_itv end_v in
let length_itv = Itv.minus end_itv begin_itv in
let arr_loc = let arr_loc =
Allocsite.make pname ~node_hash ~inst_num:0 ~dimension:1 ~path:None Allocsite.make pname ~node_hash ~inst_num:0 ~dimension:1 ~path:None
~represents_multiple_values:false ~represents_multiple_values:false
@ -1416,17 +1412,34 @@ module JavaString = struct
let substring_no_end exp begin_idx = let substring_no_end exp begin_idx =
let exec model_env ~ret mem = let exec ({integer_type_widths} as model_env) ~ret mem =
create_with_length model_env ~ret ~begin_idx ~end_v:(get_length model_env exp mem) mem let begin_itv = Sem.eval integer_type_widths begin_idx mem |> Dom.Val.get_itv in
let end_itv = get_length model_env exp mem |> Dom.Val.get_itv in
let length_itv = Itv.minus end_itv begin_itv in
create_with_length model_env ~ret ~length_itv mem
in in
{exec; check= no_check} {exec; check= no_check}
let substring begin_idx end_idx = let substring begin_idx end_idx =
let exec ({integer_type_widths} as model_env) ~ret mem = let exec ({integer_type_widths} as model_env) ~ret mem =
create_with_length model_env ~ret ~begin_idx let begin_itv = Sem.eval integer_type_widths begin_idx mem |> Dom.Val.get_itv in
~end_v:(Sem.eval integer_type_widths end_idx mem) let end_itv = Sem.eval integer_type_widths end_idx mem |> Dom.Val.get_itv in
mem let length_itv = Itv.minus end_itv begin_itv in
create_with_length model_env ~ret ~length_itv mem
in
{exec; check= no_check}
let create_from_short_arr exp =
let exec ({integer_type_widths} as model_env) ~ret mem =
let mem = create_with_length model_env ~ret ~length_itv:Itv.zero mem in
let deref_of_tgt =
Dom.Mem.find_stack (Loc.of_id (fst ret)) mem
|> Dom.Val.get_pow_loc |> PowLoc.append_field ~fn
in
let src_arr_locs = Dom.Val.get_all_locs (Sem.eval_arr integer_type_widths exp mem) in
Dom.Mem.update_mem deref_of_tgt (Dom.Mem.find_set src_arr_locs mem) mem
in in
{exec; check= no_check} {exec; check= no_check}
@ -1439,8 +1452,8 @@ module NSString = struct
let create_with_c_string src_exp = let create_with_c_string src_exp =
let exec model_env ~ret mem = let exec model_env ~ret mem =
let v = Sem.eval_string_len src_exp mem in let length_itv = Sem.eval_string_len src_exp mem |> Dom.Val.get_itv in
JavaString.create_with_length model_env ~ret ~begin_idx:Exp.zero ~end_v:v mem JavaString.create_with_length model_env ~ret ~length_itv mem
in in
{exec; check= no_check} {exec; check= no_check}
@ -1607,7 +1620,9 @@ module Call = struct
let open ProcnameDispatcher.Call in let open ProcnameDispatcher.Call in
let int_typ = Typ.mk (Typ.Tint Typ.IInt) in let int_typ = Typ.mk (Typ.Tint Typ.IInt) in
let char_typ = Typ.mk (Typ.Tint Typ.IChar) in let char_typ = Typ.mk (Typ.Tint Typ.IChar) in
let short_typ = Typ.mk (Typ.Tint Typ.IUShort) in
let char_ptr = Typ.mk (Typ.Tptr (char_typ, Pk_pointer)) in let char_ptr = Typ.mk (Typ.Tptr (char_typ, Pk_pointer)) in
let short_array = Typ.mk (Typ.Tptr (Typ.mk_array short_typ, Pk_pointer)) in
let match_builtin builtin _ s = String.equal s (Procname.get_method builtin) in let match_builtin builtin _ s = String.equal s (Procname.get_method builtin) in
make_dispatcher make_dispatcher
[ (* Clang common models *) [ (* Clang common models *)
@ -1925,6 +1940,8 @@ module Call = struct
&:: "<init>" <>$ capt_exp $--> JavaString.empty_constructor &:: "<init>" <>$ capt_exp $--> JavaString.empty_constructor
; +PatternMatch.Java.implements_lang "String" ; +PatternMatch.Java.implements_lang "String"
&:: "concat" <>$ capt_exp $+ capt_exp $+...$--> JavaString.concat &:: "concat" <>$ capt_exp $+ capt_exp $+...$--> JavaString.concat
; +PatternMatch.Java.implements_lang "String"
&:: "valueOf" <>$ capt_exp_of_prim_typ short_array $--> JavaString.create_from_short_arr
; +PatternMatch.Java.implements_lang "String" ; +PatternMatch.Java.implements_lang "String"
&:: "indexOf" <>$ capt_exp $+ any_arg $+...$--> JavaString.indexOf &:: "indexOf" <>$ capt_exp $+ any_arg $+...$--> JavaString.indexOf
; +PatternMatch.Java.implements_lang "String" ; +PatternMatch.Java.implements_lang "String"

@ -112,4 +112,15 @@ class StringTest {
void class_get_canonical_name_constant(Integer a) { void class_get_canonical_name_constant(Integer a) {
for (int i = 0; i < a.getClass().getCanonicalName().length(); i++) {} for (int i = 0; i < a.getClass().getCanonicalName().length(); i++) {}
} }
void string_valueOf_linear(char[] input) {
String s = String.valueOf(input);
for (int i = 0; i < s.length(); i++) {}
}
void string_valueOf_constant() {
char[] input = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
String s = String.valueOf(input);
for (int i = 0; i < s.length(); i++) {}
}
} }

@ -343,6 +343,8 @@ codetoanalyze/java/performance/StringTest.java, StringTest.split_with_limit_line
codetoanalyze/java/performance/StringTest.java, StringTest.startsWith_constant():java.lang.String, 18, OnUIThread:false, [] codetoanalyze/java/performance/StringTest.java, StringTest.startsWith_constant():java.lang.String, 18, OnUIThread:false, []
codetoanalyze/java/performance/StringTest.java, StringTest.string_constructor_constant():void, 45, OnUIThread:false, [] codetoanalyze/java/performance/StringTest.java, StringTest.string_constructor_constant():void, 45, OnUIThread:false, []
codetoanalyze/java/performance/StringTest.java, StringTest.string_constructor_linear(java.lang.String):void, 9 + 5 ⋅ s.length + 3 ⋅ (s.length + 1), OnUIThread:false, [{s.length + 1},Loop,{s.length},Loop] codetoanalyze/java/performance/StringTest.java, StringTest.string_constructor_linear(java.lang.String):void, 9 + 5 ⋅ s.length + 3 ⋅ (s.length + 1), OnUIThread:false, [{s.length + 1},Loop,{s.length},Loop]
codetoanalyze/java/performance/StringTest.java, StringTest.string_valueOf_constant():void, 85, OnUIThread:false, []
codetoanalyze/java/performance/StringTest.java, StringTest.string_valueOf_linear(char[]):void, 8 + 5 ⋅ input.length + 3 ⋅ (input.length + 1), OnUIThread:false, [{input.length + 1},Loop,{input.length},Loop]
codetoanalyze/java/performance/StringTest.java, StringTest.substring_linear(java.lang.String,int,int):void, 13 + 8 ⋅ (-x + y), OnUIThread:false, [{-x + y},Loop] codetoanalyze/java/performance/StringTest.java, StringTest.substring_linear(java.lang.String,int,int):void, 13 + 8 ⋅ (-x + y), OnUIThread:false, [{-x + y},Loop]
codetoanalyze/java/performance/StringTest.java, StringTest.substring_no_end_linear(java.lang.String,int):void, 12 + 8 ⋅ (-x + s.length), OnUIThread:false, [{-x + s.length},Loop] codetoanalyze/java/performance/StringTest.java, StringTest.substring_no_end_linear(java.lang.String,int):void, 12 + 8 ⋅ (-x + s.length), OnUIThread:false, [{-x + s.length},Loop]
codetoanalyze/java/performance/Switch.java, codetoanalyze.java.performance.Switch.<init>(), 3, OnUIThread:false, [] codetoanalyze/java/performance/Switch.java, codetoanalyze.java.performance.Switch.<init>(), 3, OnUIThread:false, []

Loading…
Cancel
Save