private Set<MethodReference> getImplementations(String[] classNames, MethodReference ref) { OptionalPredicate<String> isSuperclass = hierarchy.getSuperclassPredicate(ref.getClassName()); Set<MethodReference> methods = new HashSet<>(); for (String className : classNames) { if (className.startsWith("[")) { className = "java.lang.Object"; } ClassReader cls = hierarchy.getClassSource().get(className); if (cls == null || !isSuperclass.test(cls.getName(), false)) { continue; } MethodDependencyInfo methodDep = dependency.getMethodImplementation(new MethodReference( className, ref.getDescriptor())); if (methodDep != null) { methods.add(methodDep.getReference()); } } return methods; }
readValue(methodDep.getResult(), program.variableAt(callSite.receiver)); writeValue(methodDep.getVariable(i + 1), program.variableAt(callSite.arguments[i])); for (String thrownTypeName : methodDep.getThrown().getTypes()) { propagateException(thrownTypeName, program.basicBlockAt(callSite.block));
private boolean checkMethod(TextLocation location, MethodReference method) { if (!checkClass(location, method.getClassName())) { return false; } if (!reachableMethods.contains(method)) { return true; } MethodDependencyInfo methodDep = dependencyInfo.getMethod(method); if (!methodDep.isMissing() || !methodDep.isUsed()) { return true; } diagnostics.error(new CallLocation(methodRef, location), "Method {{m0}} was not found", method); emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method); return true; }
private Set<String> findClassesRequiringName() { Set<String> classesRequiringName = new HashSet<>(); MethodDependencyInfo getNameMethod = context.getDependencyInfo().getMethod( new MethodReference(Class.class, "getName", String.class)); if (getNameMethod != null) { classesRequiringName.addAll(Arrays.asList(getNameMethod.getVariable(0).getClassValueNode().getTypes())); } MethodDependencyInfo getSimpleNameMethod = context.getDependencyInfo().getMethod( new MethodReference(Class.class, "getSimpleName", String.class)); if (getSimpleNameMethod != null) { classesRequiringName.addAll(Arrays.asList( getSimpleNameMethod.getVariable(0).getClassValueNode().getTypes())); } return classesRequiringName; }
public void link(ClassHolder cls) { for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { MethodReference methodRef = method.getReference(); MethodDependencyInfo methodDep = dependency.getMethod(methodRef); if (methodDep == null) { cls.removeMethod(method); } else if (!methodDep.isUsed()) { method.getModifiers().add(ElementModifier.ABSTRACT); method.setProgram(null); } else if (method.getProgram() != null) { link(method.getReference(), method.getProgram()); } } for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) { FieldReference fieldRef = new FieldReference(cls.getName(), field.getName()); if (dependency.getField(fieldRef) == null) { cls.removeField(field); } } }
@Override public void visit(ExitInstruction insn) { if (insn.getValueToReturn() != null) { ValueDependencyInfo resultDependency = thisMethodDep.getResult(); int resultDegree = 0; while (resultDependency.hasArrayType() && resultDegree <= MAX_DEGREE) { resultDependency = resultDependency.getArrayItem(); for (String paramType : resultDependency.getTypes()) { addType(insn.getValueToReturn().getIndex(), resultDegree, paramType); } ++resultDegree; } } }
private boolean checkMethod(TextLocation location, MethodReference method) { if (!checkClass(location, method.getClassName())) { return false; } if (!achievableMethods.contains(method) || !dependencyInfo.getMethod(method).isMissing()) { return true; } diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Method {{m0}} was not found", method); emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method); return true; }
public void apply(MethodHolder method) { MethodDependencyInfo methodDep = dependency.getMethod(method.getReference()); if (methodDep == null) { return; } Program program = method.getProgram(); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); for (Instruction insn : block) { if (!(insn instanceof InvokeInstruction)) { continue; } InvokeInstruction invoke = (InvokeInstruction) insn; if (invoke.getType() != InvocationType.VIRTUAL) { continue; } ValueDependencyInfo var = methodDep.getVariable(invoke.getInstance().getIndex()); Set<MethodReference> implementations = getImplementations(var.getTypes(), invoke.getMethod()); if (implementations.size() == 1) { invoke.setType(InvocationType.SPECIAL); invoke.setMethod(implementations.iterator().next()); } else { virtualMethods.addAll(implementations); } } } }
if (methodDep == null) { cls.removeMethod(method); } else if (!methodDep.isUsed()) { method.getModifiers().add(ElementModifier.ABSTRACT); } else {
@Override public void visit(ExitInstruction insn) { if (insn.getValueToReturn() != null) { ValueDependencyInfo resultDependency = thisMethodDep.getResult(); int resultDegree = 0; while (resultDependency.hasArrayType()) { resultDependency = resultDependency.getArrayItem(); for (String paramType : resultDependency.getTypes()) { tasks.add(new Task(insn.getValueToReturn().getIndex(), ++resultDegree, paramType)); } } } }
if (methodDep != null) { if (insn.getReceiver() != null) { readValue(methodDep.getResult(), insn.getReceiver()); writeValue(methodDep.getVariable(i + 1), insn.getArguments().get(i)); for (String type : methodDep.getThrown().getTypes()) { propagateException(type, currentBlock);
if (methodDep.getReference().getReturnType() == ValueType.VOID) { pe.exit(); } else {
ValueDependencyInfo paramDep = thisMethodDep.getVariable(i); if (paramDep != null) { int degree = 0;
public void link(DependencyInfo dependency, ClassHolder cls) { for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { MethodReference methodRef = new MethodReference(cls.getName(), method.getDescriptor()); MethodDependencyInfo methodDep = dependency.getMethod(methodRef); if (methodDep == null) { cls.removeMethod(method); } else if (!methodDep.isUsed()) { method.getModifiers().add(ElementModifier.ABSTRACT); method.setProgram(null); } else if (method.getProgram() != null) { link(dependency, method); } } for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) { FieldReference fieldRef = new FieldReference(cls.getName(), field.getName()); if (dependency.getField(fieldRef) == null) { cls.removeField(field); } } }
if (methodDep != null) { if (insn.getReceiver() != null) { readValue(methodDep.getResult(), insn.getReceiver(), tasks); writeValue(methodDep.getVariable(i + 1), insn.getArguments().get(i), tasks); for (String type : methodDep.getThrown().getTypes()) { tasks.add(new Task(currentBlock.getIndex(), -1, type));
MethodDependencyInfo linkedMethod = dependency.getMethodImplementation(invoke.getMethod()); if (linkedMethod != null) { invoke.setMethod(linkedMethod.getReference());
ValueDependencyInfo paramDep = thisMethodDep.getVariable(i); if (paramDep != null) { int degree = 0;
if (methodDep != null) { if (callSite.receiver >= 0) { readValue(methodDep.getResult(), program.variableAt(callSite.receiver), queue); writeValue(methodDep.getVariable(i + 1), program.variableAt(callSite.arguments[i]), queue); for (String type : methodDep.getThrown().getTypes()) { queue.add(new Task(callSite.block, -1, type));
private Set<MethodReference> getImplementations(String[] classNames, MethodReference ref) { Set<MethodReference> methods = new HashSet<>(); for (String className : classNames) { if (className.startsWith("[")) { className = "java.lang.Object"; } ClassReader cls = classSource.get(className); if (cls == null || !classSource.isSuperType(ref.getClassName(), cls.getName()).orElse(false)) { continue; } MethodDependencyInfo methodDep = dependency.getMethodImplementation(new MethodReference( className, ref.getDescriptor())); if (methodDep != null) { methods.add(methodDep.getReference()); } } return methods; } }
public void apply(MethodHolder method) { MethodDependencyInfo methodDep = dependency.getMethod(method.getReference()); if (methodDep == null) { return; } Program program = method.getProgram(); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); for (Instruction insn : block) { if (!(insn instanceof InvokeInstruction)) { continue; } InvokeInstruction invoke = (InvokeInstruction) insn; if (invoke.getType() != InvocationType.VIRTUAL) { continue; } ValueDependencyInfo var = methodDep.getVariable(invoke.getInstance().getIndex()); Set<MethodReference> implementations = getImplementations(var.getTypes(), invoke.getMethod()); if (implementations.size() == 1) { invoke.setType(InvocationType.SPECIAL); invoke.setMethod(implementations.iterator().next()); } } } }