[Java frontend]Javalib's lambda rewritting is making his way through Infer

Reviewed By: ngorogiannis

Differential Revision: D19970219

fbshipit-source-id: b14bb36a4
master
David Pichardie 5 years ago committed by Facebook Github Bot
parent 865691b535
commit 64289cde4d

@ -128,7 +128,13 @@ let proc_inline_synthetic_methods cfg pdesc : unit =
let attributes = Procdesc.get_attributes pd in
let is_synthetic = attributes.is_synthetic_method in
let is_bridge = attributes.is_bridge_method in
if is_access || is_bridge || is_synthetic then
let is_generated_for_lambda =
String.is_substring ~substring:"$Lambda$" (Procname.get_method pn)
in
(* this is a temporary hack in order to stop synthetic inlining on
methods that are generated for lambda rewritting *)
if is_generated_for_lambda then instr
else if is_access || is_bridge || is_synthetic then
inline_synthetic_method ret_id_typ etl pd loc |> Option.value ~default:instr
else instr
| exception (Caml.Not_found | Not_found_s _) ->

@ -255,9 +255,12 @@ let get_classpath_channel program = program.classpath.channel
let get_models program = program.models
(* this string should characterize the methods we generate for lambda rewriting *)
let lambda_str = "$Lambda$"
let add_class cn jclass program =
(* [prefix] must be a fresh class name *)
let prefix = JBasics.cn_name cn ^ "$Lambda$" in
let prefix = JBasics.cn_name cn ^ lambda_str in
(* we rewrite each class to replace invokedynamic (closure construction)
with equivalent old-style Java code that implements a suitable Java interface *)
let rewritten_jclass, new_classes = Javalib.remove_invokedynamics jclass ~prefix in
@ -265,7 +268,9 @@ let add_class cn jclass program =
(* the rewrite will generate new classes and we add them to the program *)
JBasics.ClassMap.iter
(fun cn jcl -> program.classmap <- JBasics.ClassMap.add cn jcl program.classmap)
new_classes
new_classes ;
rewritten_jclass
let set_callee_translated program pname = Procname.Hash.replace program.callees pname Translated
@ -286,7 +291,7 @@ let lookup_node cn program =
with Caml.Not_found -> (
try
let jclass = javalib_get_class (get_classpath_channel program) cn in
add_class cn jclass program ; Some jclass
Some (add_class cn jclass program)
with
| JBasics.No_class_found _ ->
(* TODO T28155039 Figure out when and what to log *)

@ -217,10 +217,12 @@ let get_bytecode cm =
L.(die InternalError)
"native method %s found in %s@." (JBasics.ms_name ms) (JBasics.cn_name cn)
| Javalib.Java t ->
(* Sawja doesn't handle invokedynamic, and it will crash with a Match_failure if we give it
bytecode with this instruction. hack around this problem by converting all invokedynamic's
to invokestatic's that call a method with the same signature as the lambda on
java.lang.Object. this isn't great, but it's a lot better than crashing *)
(* Java frontend doesn't know how to translate Sawja invokedynamics, but most
of them will be rewritten by Javalib before arriving to Sawja. For the
remainings we (still) use this hack that convert an invokedynamic
into an invokestatic that calls a method with the same signature as the lambda.
But the objective is to never have to do that and hope Javalib rewriting
is complete enough *)
let bytecode = Lazy.force t in
let c_code =
Array.map

@ -9,6 +9,7 @@ package codetoanalyze.java.infer;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
public class InvokeDynamic {
@ -32,7 +33,8 @@ public class InvokeDynamic {
});
}
// we won't get this one because we don't actually translate the invocation of the lambda
// we still don't get this one (even with Javalib lambda rewriting)
// because Collections.sort is skipped
void FN_npeViaCaptureBad(List<String> list) {
String s = null;
Collections.sort(
@ -41,4 +43,15 @@ public class InvokeDynamic {
return s.compareTo(a);
});
}
Integer npeViaSimpleCapture() {
String s = null;
Function<String, Integer> f = (s1) -> s.length();
return f.apply(null);
}
Integer npeViaSimpleParamPassing() {
Function<String, Integer> f = (s) -> s.length();
return f.apply(null);
}
}

@ -100,6 +100,8 @@ codetoanalyze/java/infer/HashMapExample.java, codetoanalyze.java.infer.HashMapEx
codetoanalyze/java/infer/IntegerExample.java, codetoanalyze.java.infer.IntegerExample.testIntegerEqualsBad():void, 5, NULL_DEREFERENCE, B1, ERROR, [start of procedure testIntegerEqualsBad(),Taking true branch]
codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.invokeDynamicThenNpeBad(java.util.List):void, 6, NULL_DEREFERENCE, B1, ERROR, [start of procedure invokeDynamicThenNpeBad(...),start of procedure callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_3_3(),return from a call to Comparator InvokeDynamic.callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_3_3(),Skipping sort(...): unknown method]
codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.lambda$npeInLambdaBad$1(java.lang.String,java.lang.String):int, 1, NULL_DEREFERENCE, B1, ERROR, [start of procedure lambda$npeInLambdaBad$1(...)]
codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.npeViaSimpleCapture():java.lang.Integer, 2, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure npeViaSimpleCapture(),start of procedure callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_10_3(...),return from a call to Function InvokeDynamic.callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_10_3(String)]
codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.npeViaSimpleParamPassing():java.lang.Integer, 1, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure npeViaSimpleParamPassing(),start of procedure callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_11_0(),return from a call to Function InvokeDynamic.callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_11_0()]
codetoanalyze/java/infer/JunitAssertion.java, codetoanalyze.java.infer.JunitAssertion.consistentAssertion(codetoanalyze.java.infer.JunitAssertion$A):void, 0, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure consistentAssertion(...),Taking false branch]
codetoanalyze/java/infer/JunitAssertion.java, codetoanalyze.java.infer.JunitAssertion.inconsistentAssertion(codetoanalyze.java.infer.JunitAssertion$A):void, 1, NULL_DEREFERENCE, B5, ERROR, [start of procedure inconsistentAssertion(...),Taking false branch]
codetoanalyze/java/infer/Lists.java, codetoanalyze.java.infer.Lists.clearCausesEmptinessNPE(java.util.List,int):void, 4, NULL_DEREFERENCE, B1, ERROR, [start of procedure clearCausesEmptinessNPE(...),Taking true branch,Taking true branch]

Loading…
Cancel
Save