Java 8 suport enhancements, mostly to model lambdas compiled to
invokedynamic
This commit is contained in:
parent
f760672215
commit
671bd98977
@ -470,12 +470,12 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site) {
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site, BootstrapMethod bootstrap) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site) {
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site, BootstrapMethod bootstrap) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@ -605,11 +605,6 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
|
||||
return new SetPrototype(iindex, object, prototype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSAInstruction InvokeInstruction(int i, int[] js, int j, CallSiteReference site, BootstrapMethod bootstrap) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ package lambda;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class SortingExample {
|
||||
public class SortingExample {
|
||||
private final String[] strings;
|
||||
|
||||
public SortingExample(int n) {
|
||||
@ -12,24 +12,43 @@ public class SortingExample {
|
||||
strings[i] = "str" + i;
|
||||
}
|
||||
}
|
||||
|
||||
private String[] sort(Comparator<String> c) {
|
||||
|
||||
private String[] sort(Comparator<String> c) {
|
||||
String[] strs = strings.clone();
|
||||
Arrays.sort(strs, c);
|
||||
return strs;
|
||||
}
|
||||
|
||||
public String[] sortForward() {
|
||||
return sort( (String l, String r) -> l.compareTo(r));
|
||||
private static int id1(int x) { return x; }
|
||||
|
||||
public String[] sortForward() {
|
||||
return sort( (String l, String r) -> id1(l.compareTo(r)));
|
||||
}
|
||||
|
||||
private static int id2(int x) { return x; }
|
||||
|
||||
public String[] sort(int v) {
|
||||
return sort( (String l, String r) -> id2(l.compareTo(r) * v));
|
||||
}
|
||||
|
||||
private int id3(int x) { return x; }
|
||||
|
||||
public String[] sort(String v) {
|
||||
return sort( (String l, String r) -> id3(l.compareTo(v) + v.compareTo(r)));
|
||||
}
|
||||
|
||||
private static int id4(int x) { return x; }
|
||||
|
||||
public String[] sortBackward() {
|
||||
return sort( (String l, String r) -> r.compareTo(l));
|
||||
return sort( (String l, String r) -> id4(r.compareTo(l)));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SortingExample x = new SortingExample(10);
|
||||
System.err.println( Arrays.toString( x.sortForward() ));
|
||||
System.err.println( Arrays.toString( x.sort(1) ));
|
||||
System.err.println( Arrays.toString( x.sortBackward() ));
|
||||
System.err.println( Arrays.toString( x.sort(-1) ));
|
||||
System.err.println( Arrays.toString( x.sort( "something" ) ));
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAPropagationCallGraphBuilder;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||
@ -75,7 +76,7 @@ public class CallGraphTestUtil {
|
||||
S.start();
|
||||
}
|
||||
|
||||
CallGraphBuilder builder = Util.makeZeroCFABuilder(options, cache, cha, scope);
|
||||
SSAPropagationCallGraphBuilder builder = Util.makeZeroCFABuilder(options, cache, cha, scope);
|
||||
CallGraph cg = builder.makeCallGraph(options, null);
|
||||
if (testPAtoString) {
|
||||
builder.getPointerAnalysis().toString();
|
||||
|
||||
@ -11,13 +11,10 @@
|
||||
package com.ibm.wala.core.tests.callGraph;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.core.tests.util.TestConstants;
|
||||
import com.ibm.wala.core.tests.util.WalaTestCase;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
@ -26,7 +23,6 @@ import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.AllApplicationEntrypoints;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2006 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.core.tests.callGraph;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.core.tests.util.TestConstants;
|
||||
import com.ibm.wala.core.tests.util.WalaTestCase;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
/**
|
||||
* Check properties of a call to clone() in RTA
|
||||
*/
|
||||
public class LambdaTest extends WalaTestCase {
|
||||
|
||||
@Test public void testSortingExample() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
|
||||
|
||||
AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(TestConstants.WALA_TESTDATA, CallGraphTestUtil.REGRESSION_EXCLUSIONS);
|
||||
ClassHierarchy cha = ClassHierarchy.make(scope);
|
||||
Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha,
|
||||
"Llambda/SortingExample");
|
||||
AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints);
|
||||
|
||||
CallGraph cg = CallGraphTestUtil.buildZeroCFA(options, new AnalysisCache(), cha, scope, false);
|
||||
|
||||
// Find compareTo
|
||||
TypeReference str = TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Ljava/lang/String");
|
||||
MethodReference ct = MethodReference.findOrCreate(str, Atom.findOrCreateUnicodeAtom("compareTo"), Descriptor.findOrCreateUTF8("(Ljava/lang/String;)I"));
|
||||
Set<CGNode> ctnodes = cg.getNodes(ct);
|
||||
|
||||
checkCompareToCalls(cg, ctnodes, "id1", 1);
|
||||
checkCompareToCalls(cg, ctnodes, "id2", 1);
|
||||
checkCompareToCalls(cg, ctnodes, "id3", 2);
|
||||
checkCompareToCalls(cg, ctnodes, "id4", 1);
|
||||
}
|
||||
|
||||
protected void checkCompareToCalls(CallGraph cg, Set<CGNode> ctnodes, String x, int expected) {
|
||||
// Find node corresponding to id1
|
||||
TypeReference tid1 = TypeReference.findOrCreate(ClassLoaderReference.Application, "Llambda/SortingExample");
|
||||
MethodReference mid1 = MethodReference.findOrCreate(tid1, x, "(I)I");
|
||||
Assert.assertTrue("expect " + x + " node", cg.getNodes(mid1).iterator().hasNext());
|
||||
CGNode id1node = cg.getNodes(mid1).iterator().next();
|
||||
|
||||
// caller of id1 is dynamic from sortForward, and has 1 compareTo
|
||||
CGNode sfnode = cg.getPredNodes(id1node).next();
|
||||
int count = 0;
|
||||
for(Iterator<CallSiteReference> sites = sfnode.iterateCallSites(); sites.hasNext(); ) {
|
||||
if (ctnodes.containsAll(cg.getPossibleTargets(sfnode, sites.next()))) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("expected one call to compareTo", expected, count);
|
||||
System.err.println("found " + count + " compareTo calls in " + sfnode);
|
||||
}
|
||||
}
|
||||
@ -265,7 +265,7 @@ public abstract class AbstractReflectionInterpreter implements SSAContextInterpr
|
||||
int[] params = new int[1];
|
||||
params[0] = alloc;
|
||||
int exc = getExceptionsForType(t);
|
||||
SSAInvokeInstruction s = insts.InvokeInstruction(allInstructions.size(), params, exc, site);
|
||||
SSAInvokeInstruction s = insts.InvokeInstruction(allInstructions.size(), params, exc, site, null);
|
||||
calls.add(s);
|
||||
allInstructions.add(s);
|
||||
}
|
||||
|
||||
@ -176,7 +176,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
|
||||
int[] params = new int[2];
|
||||
params[0] = 1;
|
||||
params[1] = retValue;
|
||||
SSAInvokeInstruction S = insts.InvokeInstruction(statements.size(), params, exceptionValue, ARRAYCOPY_SITE);
|
||||
SSAInvokeInstruction S = insts.InvokeInstruction(statements.size(), params, exceptionValue, ARRAYCOPY_SITE, null);
|
||||
statements.add(S);
|
||||
} else {
|
||||
// copy the fields over, one by one.
|
||||
|
||||
@ -490,7 +490,7 @@ public class FactoryBypassInterpreter extends AbstractReflectionInterpreter {
|
||||
int[] params = new int[1];
|
||||
params[0] = alloc;
|
||||
int exc = getExceptionsForType(T);
|
||||
SSAInvokeInstruction s = insts.InvokeInstruction(allInstructions.size(), params, exc, site);
|
||||
SSAInvokeInstruction s = insts.InvokeInstruction(allInstructions.size(), params, exc, site, null);
|
||||
calls.add(s);
|
||||
allInstructions.add(s);
|
||||
}
|
||||
@ -558,7 +558,7 @@ public class FactoryBypassInterpreter extends AbstractReflectionInterpreter {
|
||||
CallSiteReference site = CallSiteReference.make(getCallSiteForType(T), init, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
int[] params = new int[1];
|
||||
params[0] = i;
|
||||
SSAInvokeInstruction s = insts.InvokeInstruction(allInstructions.size(), params, getExceptionsForType(T), site);
|
||||
SSAInvokeInstruction s = insts.InvokeInstruction(allInstructions.size(), params, getExceptionsForType(T), site, null);
|
||||
calls.add(s);
|
||||
allInstructions.add(s);
|
||||
}
|
||||
|
||||
@ -201,17 +201,17 @@ public class ReflectiveInvocationInterpreter extends AbstractReflectionInterpret
|
||||
// emit the dispatch and return instructions
|
||||
if (method.getReference().equals(CTOR_NEW_INSTANCE)) {
|
||||
m.addInstruction(null, insts.InvokeInstruction(m.allInstructions.size(), args, exceptions, CallSiteReference.make(pc++, target.getReference(),
|
||||
IInvokeInstruction.Dispatch.SPECIAL)), false);
|
||||
IInvokeInstruction.Dispatch.SPECIAL), null), false);
|
||||
m.addInstruction(null, insts.ReturnInstruction(m.allInstructions.size(), args[0], false), false);
|
||||
} else {
|
||||
Dispatch d = target.isStatic() ? Dispatch.STATIC : Dispatch.VIRTUAL;
|
||||
if (target.getReturnType().equals(TypeReference.Void)) {
|
||||
m.addInstruction(null, insts.InvokeInstruction(m.allInstructions.size(), args, exceptions, CallSiteReference.make(pc++, target.getReference(), d)),
|
||||
m.addInstruction(null, insts.InvokeInstruction(m.allInstructions.size(), args, exceptions, CallSiteReference.make(pc++, target.getReference(), d), null),
|
||||
false);
|
||||
} else {
|
||||
result = nextLocal++;
|
||||
m.addInstruction(null, insts.InvokeInstruction(m.allInstructions.size(), result, args, exceptions, CallSiteReference.make(pc++,
|
||||
target.getReference(), d)), false);
|
||||
target.getReference(), d), null), false);
|
||||
m.addInstruction(null, insts.ReturnInstruction(m.allInstructions.size(), result, false), false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +272,7 @@ public class MethodHandles {
|
||||
params[i] = i+3;
|
||||
}
|
||||
CallSiteReference site = CallSiteReference.make(nargs+1, ref, isStatic? Dispatch.STATIC: Dispatch.SPECIAL);
|
||||
code.addStatement(insts.InvokeInstruction(code.getNextProgramCounter(), 2*nargs+3, params, 2*nargs+4, site));
|
||||
code.addStatement(insts.InvokeInstruction(code.getNextProgramCounter(), 2*nargs+3, params, 2*nargs+4, site, null));
|
||||
code.addStatement(insts.ReturnInstruction(code.getNextProgramCounter(), 2*nargs+3, false));
|
||||
} else {
|
||||
int nargs = node.getMethod().getNumberOfParameters();
|
||||
|
||||
@ -228,44 +228,57 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site) {
|
||||
return new SSAInvokeInstruction(iindex, result, params, exception, site) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
if (!isStatic()) {
|
||||
return getNullPointerException();
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site, BootstrapMethod bootstrap) {
|
||||
if (bootstrap != null) {
|
||||
return new SSAInvokeDynamicInstruction(iindex, result, params, exception, site, bootstrap) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
if (!isStatic()) {
|
||||
return getNullPointerException();
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public SSAInvokeDynamicInstruction InvokeInstruction(int result, int[] params, int exception, CallSiteReference site, BootstrapMethod bootstrap) {
|
||||
return new SSAInvokeDynamicInstruction(result, params, exception, site, bootstrap) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
if (!isStatic()) {
|
||||
return getNullPointerException();
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
};
|
||||
} else {
|
||||
return new SSAInvokeInstruction(iindex, result, params, exception, site) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
if (!isStatic()) {
|
||||
return getNullPointerException();
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site) {
|
||||
return new SSAInvokeInstruction(iindex, params, exception, site) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
if (!isStatic()) {
|
||||
return getNullPointerException();
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
public SSAInvokeInstruction InvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site, BootstrapMethod bootstrap) {
|
||||
if (bootstrap != null) {
|
||||
return new SSAInvokeDynamicInstruction(iindex, params, exception, site, bootstrap) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
if (!isStatic()) {
|
||||
return getNullPointerException();
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
} else {
|
||||
return new SSAInvokeInstruction(iindex, params, exception, site) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
if (!isStatic()) {
|
||||
return getNullPointerException();
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -137,9 +137,9 @@ public abstract class AbstractRootMethod extends SyntheticMethod {
|
||||
CallSiteReference newSite = CallSiteReference.make(statements.size(), site.getDeclaredTarget(), site.getInvocationCode());
|
||||
SSAInvokeInstruction s = null;
|
||||
if (newSite.getDeclaredTarget().getReturnType().equals(TypeReference.Void)) {
|
||||
s = insts.InvokeInstruction(statements.size(), params, nextLocal++, newSite);
|
||||
s = insts.InvokeInstruction(statements.size(), params, nextLocal++, newSite, null);
|
||||
} else {
|
||||
s = insts.InvokeInstruction(statements.size(), nextLocal++, params, nextLocal++, newSite);
|
||||
s = insts.InvokeInstruction(statements.size(), nextLocal++, params, nextLocal++, newSite, null);
|
||||
}
|
||||
statements.add(s);
|
||||
cache.invalidate(this, Everywhere.EVERYWHERE);
|
||||
|
||||
@ -38,6 +38,7 @@ import com.ibm.wala.ipa.callgraph.propagation.rta.BasicRTABuilder;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.ipa.summaries.BypassClassTargetSelector;
|
||||
import com.ibm.wala.ipa.summaries.BypassMethodTargetSelector;
|
||||
import com.ibm.wala.ipa.summaries.LambdaMethodTargetSelector;
|
||||
import com.ibm.wala.ipa.summaries.XMLMethodSummaryReader;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
@ -76,7 +77,7 @@ public class Util {
|
||||
if (options == null) {
|
||||
throw new IllegalArgumentException("options is null");
|
||||
}
|
||||
options.setSelector(new ClassHierarchyMethodTargetSelector(cha));
|
||||
options.setSelector(new LambdaMethodTargetSelector(new ClassHierarchyMethodTargetSelector(cha)));
|
||||
options.setSelector(new ClassHierarchyClassTargetSelector(cha));
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2007 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.ipa.summaries;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.Language;
|
||||
import com.ibm.wala.classLoader.NewSiteReference;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.MethodTargetSelector;
|
||||
import com.ibm.wala.shrikeCT.BootstrapMethodsReader.BootstrapMethod;
|
||||
import com.ibm.wala.ssa.SSAInstructionFactory;
|
||||
import com.ibm.wala.ssa.SSAInvokeDynamicInstruction;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
public class LambdaMethodTargetSelector implements MethodTargetSelector {
|
||||
|
||||
private final WeakHashMap<BootstrapMethod, SummarizedMethod> summaries = new WeakHashMap<BootstrapMethod, SummarizedMethod>();
|
||||
|
||||
private final MethodTargetSelector base;
|
||||
|
||||
public LambdaMethodTargetSelector(MethodTargetSelector base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) {
|
||||
if (! site.getDeclaredTarget().getName().equals(MethodReference.clinitName) &&
|
||||
caller.getClassHierarchy().lookupClass(TypeReference.LambdaMetaFactory) != null &&
|
||||
caller.getClassHierarchy().lookupClass(TypeReference.LambdaMetaFactory).equals(
|
||||
caller.getClassHierarchy().lookupClass(site.getDeclaredTarget().getDeclaringClass())))
|
||||
{
|
||||
SSAInvokeDynamicInstruction invoke = (SSAInvokeDynamicInstruction)caller.getIR().getCalls(site)[0];
|
||||
|
||||
if (!summaries.containsKey(invoke.getBootstrap())) {
|
||||
String cls = caller.getMethod().getDeclaringClass().getName().toString().replace("/", "$").substring(1);
|
||||
int bootstrapIndex = invoke.getBootstrap().getIndexInClassFile();
|
||||
MethodReference ref =
|
||||
MethodReference.findOrCreate(
|
||||
site.getDeclaredTarget().getDeclaringClass(),
|
||||
Atom.findOrCreateUnicodeAtom(site.getDeclaredTarget().getName().toString() +"$" + cls + "$" + bootstrapIndex),
|
||||
site.getDeclaredTarget().getDescriptor());
|
||||
|
||||
MethodSummary summary = new MethodSummary(ref);
|
||||
|
||||
if (site.isStatic()) {
|
||||
summary.setStatic(true);
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
int v = site.getDeclaredTarget().getNumberOfParameters() + 2;
|
||||
IClass lambda = LambdaSummaryClass.findOrCreate(caller, invoke);
|
||||
SSAInstructionFactory insts = Language.JAVA.instructionFactory();
|
||||
summary.addStatement(insts.NewInstruction(index, v, NewSiteReference.make(index, lambda.getReference())));
|
||||
index++;
|
||||
for(int i = 0; i < site.getDeclaredTarget().getNumberOfParameters(); i++) {
|
||||
summary.addStatement(
|
||||
insts.PutInstruction(index++, v, i+1, lambda.getField(Atom.findOrCreateUnicodeAtom("c" + i)).getReference()));
|
||||
}
|
||||
summary.addStatement(insts.ReturnInstruction(index++, v, false));
|
||||
|
||||
summaries.put(invoke.getBootstrap(), new SummarizedMethod(ref, summary, caller.getClassHierarchy().lookupClass(site.getDeclaredTarget().getDeclaringClass())));
|
||||
}
|
||||
|
||||
return summaries.get(invoke.getBootstrap());
|
||||
|
||||
} else {
|
||||
return base.getCalleeTarget(caller, site, receiver);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,304 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.ipa.summaries;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.SyntheticClass;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction.Dispatch;
|
||||
import com.ibm.wala.shrikeCT.BootstrapMethodsReader.BootstrapMethod;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.ssa.SSAInstructionFactory;
|
||||
import com.ibm.wala.ssa.SSAInvokeDynamicInstruction;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
public class LambdaSummaryClass extends SyntheticClass {
|
||||
|
||||
private static WeakHashMap<BootstrapMethod, LambdaSummaryClass> summaries = new WeakHashMap<BootstrapMethod, LambdaSummaryClass>();
|
||||
|
||||
public static LambdaSummaryClass findOrCreate(CGNode caller, SSAInvokeDynamicInstruction inst) {
|
||||
if (! summaries.containsKey(inst.getBootstrap())) {
|
||||
String bootstrapCls = caller.getMethod().getDeclaringClass().getName().toString().replace("/", "$").substring(1);
|
||||
int bootstrapIndex = inst.getBootstrap().getIndexInClassFile();
|
||||
TypeReference ref = TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Lwala/lambda" + "$" + bootstrapCls + "$" + bootstrapIndex);
|
||||
LambdaSummaryClass cls = new LambdaSummaryClass(ref, caller.getClassHierarchy(), inst);
|
||||
caller.getClassHierarchy().addClass(cls);
|
||||
summaries.put(inst.getBootstrap(), cls);
|
||||
}
|
||||
|
||||
return summaries.get(inst.getBootstrap());
|
||||
}
|
||||
|
||||
private final SSAInvokeDynamicInstruction invoke;
|
||||
|
||||
private final Map<Atom,IField> fields;
|
||||
|
||||
private final Map<Selector,IMethod> methods;
|
||||
|
||||
public LambdaSummaryClass(TypeReference T, IClassHierarchy cha, SSAInvokeDynamicInstruction invoke) {
|
||||
super(T, cha);
|
||||
this.invoke = invoke;
|
||||
this.fields = makeFields();
|
||||
this.methods = Collections.singletonMap(trampoline().getSelector(), makeTrampoline());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPublic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrivate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModifiers() throws UnsupportedOperationException {
|
||||
return Constants.ACC_FINAL | Constants.ACC_SUPER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClass getSuperclass() {
|
||||
return getClassHierarchy().getRootClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends IClass> getDirectInterfaces() {
|
||||
return Collections.singleton(getClassHierarchy().lookupClass(invoke.getDeclaredResultType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IClass> getAllImplementedInterfaces() {
|
||||
IClass iface = getClassHierarchy().lookupClass(invoke.getDeclaredResultType());
|
||||
Set<IClass> result = HashSetFactory.make(iface.getAllImplementedInterfaces());
|
||||
result.add(iface);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMethod getMethod(Selector selector) {
|
||||
return methods.get(selector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IField getField(Atom name) {
|
||||
return fields.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMethod getClassInitializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IMethod> getDeclaredMethods() {
|
||||
return methods.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getAllInstanceFields() {
|
||||
return fields.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getAllStaticFields() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getAllFields() {
|
||||
return getAllInstanceFields();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IMethod> getAllMethods() {
|
||||
return methods.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
return fields.values();
|
||||
}
|
||||
|
||||
private Map<Atom,IField> makeFields() {
|
||||
Map<Atom,IField> result = HashMapFactory.make();
|
||||
for(int i = 0; i < invoke.getNumberOfParameters(); i++) {
|
||||
final int yuck = i;
|
||||
result.put(Atom.findOrCreateUnicodeAtom("c" + yuck), new IField() {
|
||||
@Override
|
||||
public IClass getDeclaringClass() {
|
||||
return LambdaSummaryClass.this;
|
||||
}
|
||||
@Override
|
||||
public Atom getName() {
|
||||
return Atom.findOrCreateUnicodeAtom("c" + yuck);
|
||||
}
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@Override
|
||||
public IClassHierarchy getClassHierarchy() {
|
||||
return LambdaSummaryClass.this.getClassHierarchy();
|
||||
}
|
||||
@Override
|
||||
public TypeReference getFieldTypeReference() {
|
||||
return invoke.getDeclaredTarget().getParameterType(yuck);
|
||||
}
|
||||
@Override
|
||||
public FieldReference getReference() {
|
||||
return FieldReference.findOrCreate(LambdaSummaryClass.this.getReference(), getName(), getFieldTypeReference());
|
||||
}
|
||||
@Override
|
||||
public boolean isFinal() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrivate() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isProtected() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isPublic() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isVolatile() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private MethodReference trampoline() {
|
||||
try {
|
||||
return MethodReference.findOrCreate(LambdaSummaryClass.this.getReference(), invoke.getDeclaredTarget().getName(), Descriptor.findOrCreateUTF8(getLambdaDeclaredSignature()));
|
||||
} catch (IllegalArgumentException | InvalidClassFileException e) {
|
||||
assert false : e;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getLambdaCalleeClass() throws IllegalArgumentException, InvalidClassFileException {
|
||||
int cpIndex = invoke.getBootstrap().callArgumentIndex(1);
|
||||
return "L" + invoke.getBootstrap().getCP().getCPHandleClass(cpIndex);
|
||||
}
|
||||
|
||||
private String getLambdaCalleeName() throws IllegalArgumentException, InvalidClassFileException {
|
||||
int cpIndex = invoke.getBootstrap().callArgumentIndex(1);
|
||||
return invoke.getBootstrap().getCP().getCPHandleName(cpIndex);
|
||||
}
|
||||
|
||||
private String getLambdaCalleeSignature() throws IllegalArgumentException, InvalidClassFileException {
|
||||
int cpIndex = invoke.getBootstrap().callArgumentIndex(1);
|
||||
return invoke.getBootstrap().getCP().getCPHandleType(cpIndex);
|
||||
}
|
||||
|
||||
private String getLambdaDeclaredSignature() throws IllegalArgumentException, InvalidClassFileException {
|
||||
int cpIndex = invoke.getBootstrap().callArgumentIndex(0);
|
||||
return invoke.getBootstrap().getCP().getCPMethodType(cpIndex);
|
||||
}
|
||||
|
||||
private int getLambdaCalleeKind() throws IllegalArgumentException, InvalidClassFileException {
|
||||
int cpIndex = invoke.getBootstrap().callArgumentIndex(1);
|
||||
return invoke.getBootstrap().getCP().getCPHandleKind(cpIndex);
|
||||
}
|
||||
|
||||
private IMethod makeTrampoline() {
|
||||
SSAInstructionFactory insts = getClassLoader().getInstructionFactory();
|
||||
|
||||
MethodReference ref = trampoline();
|
||||
MethodSummary summary = new MethodSummary(ref);
|
||||
|
||||
int inst = 0;
|
||||
int args = invoke.getNumberOfParameters(), v = args + 1;
|
||||
for(int i = 0; i < invoke.getNumberOfParameters(); i++) {
|
||||
Atom f = Atom.findOrCreateUnicodeAtom("c" + i);
|
||||
summary.addStatement(insts.GetInstruction(inst++, v++, 1, getField(f).getReference()));
|
||||
}
|
||||
|
||||
try {
|
||||
MethodReference callee = MethodReference.findOrCreate(ClassLoaderReference.Application, getLambdaCalleeClass(), getLambdaCalleeName(), getLambdaCalleeSignature());
|
||||
|
||||
Dispatch code;
|
||||
int kind = getLambdaCalleeKind();
|
||||
switch (kind) {
|
||||
case 5: code = Dispatch.VIRTUAL; break;
|
||||
case 6: code = Dispatch.STATIC; break;
|
||||
case 7: code = Dispatch.SPECIAL; break;
|
||||
case 9: code = Dispatch.INTERFACE; break;
|
||||
default:
|
||||
throw new Error("unexpected dynamic invoke type " + kind);
|
||||
}
|
||||
|
||||
int numParams = getClassHierarchy().resolveMethod(callee).getNumberOfParameters();
|
||||
int params[] = new int[ numParams ];
|
||||
for(int i = 0; i < invoke.getNumberOfParameters(); i++) {
|
||||
params[i] = args + i + 1;
|
||||
}
|
||||
for(int n = 2, i = invoke.getNumberOfParameters(); i < numParams; i++) {
|
||||
params[i] = n++;
|
||||
}
|
||||
|
||||
if (callee.getReturnType().equals(TypeReference.Void)) {
|
||||
summary.addStatement(insts.InvokeInstruction(inst++, params, v++, CallSiteReference.make(inst, callee, code), null));
|
||||
} else {
|
||||
int ret = v++;
|
||||
summary.addStatement(insts.InvokeInstruction(inst++, ret, params, v++, CallSiteReference.make(inst, callee, code), null));
|
||||
summary.addStatement(insts.ReturnInstruction(inst++, ret, callee.getReturnType().isPrimitiveType()));
|
||||
}
|
||||
} catch (IllegalArgumentException | InvalidClassFileException e) {
|
||||
assert false : e.toString();
|
||||
}
|
||||
|
||||
SummarizedMethod method = new SummarizedMethod(ref, summary, LambdaSummaryClass.this);
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReferenceType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@ -485,10 +485,10 @@ public class XMLMethodSummaryReader implements BytecodeConstants {
|
||||
int defNum = nextLocal;
|
||||
symbolTable.put(defVar, new Integer(nextLocal++));
|
||||
|
||||
governingMethod.addStatement(insts.InvokeInstruction(governingMethod.getNumberOfStatements(), defNum, params, exceptionValue, site));
|
||||
governingMethod.addStatement(insts.InvokeInstruction(governingMethod.getNumberOfStatements(), defNum, params, exceptionValue, site, null));
|
||||
} else {
|
||||
// ignore return value, if any
|
||||
governingMethod.addStatement(insts.InvokeInstruction(governingMethod.getNumberOfStatements(), params, exceptionValue, site));
|
||||
governingMethod.addStatement(insts.InvokeInstruction(governingMethod.getNumberOfStatements(), params, exceptionValue, site, null));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,11 +41,13 @@ import com.ibm.wala.shrikeBT.IStoreInstruction;
|
||||
import com.ibm.wala.shrikeBT.ITypeTestInstruction;
|
||||
import com.ibm.wala.shrikeBT.IUnaryOpInstruction;
|
||||
import com.ibm.wala.shrikeBT.IndirectionData;
|
||||
import com.ibm.wala.shrikeBT.InvokeDynamicInstruction;
|
||||
import com.ibm.wala.shrikeBT.MonitorInstruction;
|
||||
import com.ibm.wala.shrikeBT.NewInstruction;
|
||||
import com.ibm.wala.shrikeBT.ReturnInstruction;
|
||||
import com.ibm.wala.shrikeBT.SwitchInstruction;
|
||||
import com.ibm.wala.shrikeBT.ThrowInstruction;
|
||||
import com.ibm.wala.shrikeCT.BootstrapMethodsReader.BootstrapMethod;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.ssa.ShrikeIndirectionData.ShrikeLocalName;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
@ -588,12 +590,18 @@ public class SSABuilder extends AbstractIntStackMachine {
|
||||
IInvokeInstruction.IDispatch code = instruction.getInvocationCode();
|
||||
CallSiteReference site = CallSiteReference.make(getCurrentProgramCounter(), m, code);
|
||||
int exc = reuseOrCreateException();
|
||||
|
||||
BootstrapMethod bootstrap = null;
|
||||
if (instruction instanceof InvokeDynamicInstruction) {
|
||||
bootstrap = ((InvokeDynamicInstruction)instruction).getBootstrap();
|
||||
}
|
||||
|
||||
if (instruction.getPushedWordSize() > 0) {
|
||||
int result = reuseOrCreateDef();
|
||||
workingState.push(result);
|
||||
emitInstruction(insts.InvokeInstruction(getCurrentInstructionIndex(), result, params, exc, site));
|
||||
emitInstruction(insts.InvokeInstruction(getCurrentInstructionIndex(), result, params, exc, site, bootstrap));
|
||||
} else {
|
||||
emitInstruction(insts.InvokeInstruction(getCurrentInstructionIndex(), params, exc, site));
|
||||
emitInstruction(insts.InvokeInstruction(getCurrentInstructionIndex(), params, exc, site, bootstrap));
|
||||
}
|
||||
doIndirectWrites(bytecodeIndirections.indirectlyWrittenLocals(getCurrentInstructionIndex()), -1);
|
||||
}
|
||||
|
||||
@ -66,9 +66,9 @@ public interface SSAInstructionFactory {
|
||||
|
||||
SSAInstanceofInstruction InstanceofInstruction(int iindex, int result, int ref, TypeReference checkedType);
|
||||
|
||||
SSAInvokeInstruction InvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site);
|
||||
SSAInvokeInstruction InvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site, BootstrapMethod bootstrap);
|
||||
|
||||
SSAInvokeInstruction InvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site);
|
||||
SSAInvokeInstruction InvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site, BootstrapMethod bootstrap);
|
||||
|
||||
SSALoadIndirectInstruction LoadIndirectInstruction(int iindex, int lval, TypeReference t, int addressVal);
|
||||
|
||||
@ -100,6 +100,4 @@ public interface SSAInstructionFactory {
|
||||
|
||||
SSAUnaryOpInstruction UnaryOpInstruction(int iindex, IUnaryOpInstruction.IOperator operator, int result, int val);
|
||||
|
||||
SSAInstruction InvokeInstruction(int i, int[] js, int j, CallSiteReference site, BootstrapMethod bootstrap);
|
||||
|
||||
}
|
||||
|
||||
@ -32,5 +32,8 @@ public class SSAInvokeDynamicInstruction extends SSAInvokeInstruction {
|
||||
defs == null ? exception : defs[result == -1 ? 0 : 1], site, bootstrap);
|
||||
}
|
||||
|
||||
|
||||
public BootstrapMethod getBootstrap() {
|
||||
return bootstrap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ public abstract class SSAInvokeInstruction extends SSAAbstractInvokeInstruction
|
||||
// result == -1 for void-returning methods, which are the only calls
|
||||
// that have a single value def.
|
||||
return insts.InvokeInstruction(iindex, defs == null || result == -1 ? result : defs[0], uses == null ? params : uses,
|
||||
defs == null ? exception : defs[result == -1 ? 0 : 1], site);
|
||||
defs == null ? exception : defs[result == -1 ? 0 : 1], site, null);
|
||||
}
|
||||
|
||||
public static void assertParamsKosher(int result, int[] params, CallSiteReference site) throws IllegalArgumentException {
|
||||
|
||||
@ -72,6 +72,12 @@ public final class MethodReference extends MemberReference {
|
||||
|
||||
public final static Selector equalsSelector = new Selector(equalsAtom, equalsDesc);
|
||||
|
||||
public final static MethodReference lambdaMetafactory =
|
||||
findOrCreate(
|
||||
TypeReference.LambdaMetaFactory,
|
||||
Atom.findOrCreateUnicodeAtom("metafactory"),
|
||||
Descriptor.findOrCreateUTF8("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"));
|
||||
|
||||
/**
|
||||
* types of parameters to this method.
|
||||
*/
|
||||
|
||||
@ -344,6 +344,8 @@ public final class TypeReference implements Serializable {
|
||||
|
||||
public final static TypeReference Unknown = findOrCreate(ClassLoaderReference.Primordial, UnknownName);
|
||||
|
||||
public final static TypeReference LambdaMetaFactory = findOrCreate(ClassLoaderReference.Primordial, "Ljava/lang/invoke/LambdaMetafactory");
|
||||
|
||||
private static TypeReference makePrimitive(TypeName n) {
|
||||
return makePrimitive(ClassLoaderReference.Primordial, n);
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ public class TypeSafeInstructionFactory {
|
||||
// TODO somehow check exception?
|
||||
|
||||
result.setAssigned();
|
||||
return insts.InvokeInstruction(iindex, result.getNumber(), aParams, exception.getNumber(), site);
|
||||
return insts.InvokeInstruction(iindex, result.getNumber(), aParams, exception.getNumber(), site, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -300,7 +300,7 @@ public class TypeSafeInstructionFactory {
|
||||
|
||||
// TODO somehow check exception?
|
||||
|
||||
return insts.InvokeInstruction(iindex, aParams, exception.getNumber(), site);
|
||||
return insts.InvokeInstruction(iindex, aParams, exception.getNumber(), site, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -855,7 +855,7 @@ public class DexSSABuilder extends AbstractIntRegisterMachine {
|
||||
|
||||
if(m.getReturnType().equals(TypeReference.Void))
|
||||
{
|
||||
SSAInstruction inst = insts.InvokeInstruction(getCurrentInstructionIndex(), params, exc, site);
|
||||
SSAInstruction inst = insts.InvokeInstruction(getCurrentInstructionIndex(), params, exc, site, null);
|
||||
//System.out.println("Emitting(1) InvokeInstruction: "+inst);
|
||||
emitInstruction(inst);
|
||||
} else {
|
||||
@ -867,7 +867,7 @@ public class DexSSABuilder extends AbstractIntRegisterMachine {
|
||||
int dest = dexCFG.getDexMethod().getReturnReg();
|
||||
|
||||
setLocal(dest, result);
|
||||
SSAInstruction inst = insts.InvokeInstruction(getCurrentInstructionIndex(), result, params, exc, site);
|
||||
SSAInstruction inst = insts.InvokeInstruction(getCurrentInstructionIndex(), result, params, exc, site, null);
|
||||
//System.out.println("Emitting(2) InvokeInstruction: "+inst);
|
||||
emitInstruction(inst);
|
||||
}
|
||||
|
||||
@ -431,9 +431,9 @@ public class AppModelMethod {
|
||||
CallSiteReference newSite = CallSiteReference.make(methodSummary.getNumberOfStatements(), site.getDeclaredTarget(), site.getInvocationCode());
|
||||
SSAInvokeInstruction s = null;
|
||||
if (newSite.getDeclaredTarget().getReturnType().equals(TypeReference.Void)) {
|
||||
s = insts.InvokeInstruction(methodSummary.getNumberOfStatements(), params, nextLocal++, newSite);
|
||||
s = insts.InvokeInstruction(methodSummary.getNumberOfStatements(), params, nextLocal++, newSite, null);
|
||||
} else {
|
||||
s = insts.InvokeInstruction(methodSummary.getNumberOfStatements(), nextLocal++, params, nextLocal++, newSite);
|
||||
s = insts.InvokeInstruction(methodSummary.getNumberOfStatements(), nextLocal++, params, nextLocal++, newSite, null);
|
||||
}
|
||||
methodSummary.addStatement(s);
|
||||
// cache.invalidate(this, Everywhere.EVERYWHERE);
|
||||
|
||||
@ -37,8 +37,9 @@ public class CodeScraper implements ClassFileTransformer {
|
||||
sourceFile = reader.getCP().getCPUtf8(index);
|
||||
}
|
||||
}
|
||||
if (className == null || sourceFile == null || !sourceFile.endsWith("java")) try {
|
||||
if (className == null || sourceFile == null || !sourceFile.endsWith("java") || true) try {
|
||||
String log = prefix + File.separator + reader.getName() + ".class";
|
||||
(new File(log)).getParentFile().mkdirs();
|
||||
FileOutputStream f = new FileOutputStream(log);
|
||||
f.write(classfileBuffer);
|
||||
f.close();
|
||||
@ -54,7 +55,6 @@ public class CodeScraper implements ClassFileTransformer {
|
||||
}
|
||||
|
||||
public static void premain(String agentArgs, Instrumentation inst) {
|
||||
System.err.println("adding CodeScraper");
|
||||
inst.addTransformer(new CodeScraper());
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ public class InvokeDynamicInstruction extends Instruction implements IInvokeInst
|
||||
protected String methodName;
|
||||
protected String methodType;
|
||||
|
||||
public InvokeDynamicInstruction(short opcode, BootstrapMethod bootstrap, String methodName, String methodType) {
|
||||
private InvokeDynamicInstruction(short opcode, BootstrapMethod bootstrap, String methodName, String methodType) {
|
||||
super(opcode);
|
||||
this.bootstrap = bootstrap;
|
||||
this.methodName = methodName;
|
||||
@ -93,7 +93,7 @@ public class InvokeDynamicInstruction extends Instruction implements IInvokeInst
|
||||
|
||||
@Override
|
||||
public String getClassType() {
|
||||
return getBootstrap().methodClass();
|
||||
return "L" + getBootstrap().methodClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -19,6 +19,7 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction.Dispatch;
|
||||
import com.ibm.wala.shrikeCT.BootstrapMethodsReader.BootstrapMethod;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
/**
|
||||
|
||||
@ -29,6 +29,8 @@ public class BootstrapMethodsReader extends AttributeReader {
|
||||
Object callArgument(ClassLoader cl, int i);
|
||||
int callArgumentIndex(int i);
|
||||
int callArgumentKind(int i);
|
||||
ConstantPoolParser getCP();
|
||||
int getIndexInClassFile();
|
||||
}
|
||||
|
||||
private BootstrapMethod entries[];
|
||||
@ -46,6 +48,7 @@ public class BootstrapMethodsReader extends AttributeReader {
|
||||
for(int i = 0; i < entries.length; i++) {
|
||||
final int methodHandleOffset = cr.getUShort(attr + base);
|
||||
final int argsBase = attr + base + 4;
|
||||
final int index = i;
|
||||
|
||||
final int argumentCount = cr.getUShort(attr + base + 2);
|
||||
entries[i] = new BootstrapMethod() {
|
||||
@ -119,10 +122,10 @@ public class BootstrapMethodsReader extends AttributeReader {
|
||||
return cp.getCPLong(index);
|
||||
case ClassConstants.CONSTANT_MethodHandle:
|
||||
String className = cp.getCPHandleClass(index);
|
||||
Class<?> cls = Class.forName(className.replace('/', '.'), false, cl);
|
||||
String eltName = cp.getCPHandleName(index);
|
||||
String eltDesc = cp.getCPHandleType(index);
|
||||
MethodType type = MethodType.fromMethodDescriptorString(eltDesc, cl);
|
||||
Class<?> cls = Class.forName(className.replace('/', '.'), false, cl);
|
||||
Method m = cls.getDeclaredMethod(eltName, type.parameterList().toArray(new Class[type.parameterCount()]));
|
||||
Lookup lk = MethodHandles.lookup().in(cls);
|
||||
m.setAccessible(true);
|
||||
@ -147,6 +150,16 @@ public class BootstrapMethodsReader extends AttributeReader {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantPoolParser getCP() {
|
||||
return cp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexInClassFile() {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
base += (argumentCount*2) + 4;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user