@Override public CallGraph getCallGraph() { return vm.getDependencyInfo().getCallGraph(); }
public MissingItemsProcessor(DependencyInfo dependencyInfo, ClassHierarchy hierarchy, Diagnostics diagnostics) { this.dependencyInfo = dependencyInfo; this.diagnostics = diagnostics; this.hierarchy = hierarchy; reachableClasses = dependencyInfo.getReachableClasses(); reachableMethods = dependencyInfo.getReachableMethods(); reachableFields = dependencyInfo.getReachableFields(); }
private boolean checkClass(TextLocation location, String className) { if (!reachableClasses.contains(className) || !dependencyInfo.getClass(className).isMissing()) { return true; } diagnostics.error(new CallLocation(methodRef, location), "Class {{c0}} was not found", className); emitExceptionThrow(location, NoClassDefFoundError.class.getName(), "Class not found: " + className); return false; }
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); } } }
@SuppressWarnings("WeakerAccess") public ListableClassHolderSource link(DependencyInfo dependency) { reportPhase(TeaVMPhase.LINKING, dependency.getReachableClasses().size()); Linker linker = new Linker(); MutableClassHolderSource cutClasses = new MutableClassHolderSource(); MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency, diagnostics); if (wasCancelled()) { return cutClasses; } int index = 0; for (String className : dependency.getReachableClasses()) { ClassReader clsReader = dependency.getClassSource().get(className); if (clsReader == null) { continue; } ClassHolder cls = ModelUtils.copyClass(clsReader); cutClasses.putClassHolder(cls); missingItemsProcessor.processClass(cls); linker.link(dependency, cls); progressListener.progressReached(++index); } return cutClasses; }
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; }
private void propagateAlongVirtualCalls(Program program) { ClassReaderSource classSource = dependencyInfo.getClassSource(); MethodDependencyInfo methodDep = dependencyInfo.getMethod(resolvedMethodRef); if (methodDep == null) { continue;
InvokeInstruction invoke = (InvokeInstruction) insn; if (invoke.getType() == InvocationType.SPECIAL) { MethodDependencyInfo linkedMethod = dependency.getMethodImplementation(invoke.getMethod()); if (linkedMethod != null) { invoke.setMethod(linkedMethod.getReference()); FieldDependencyInfo linkedField = dependency.getField(getField.getField()); if (linkedField != null) { getField.setField(linkedField.getReference()); FieldDependencyInfo linkedField = dependency.getField(putField.getField()); if (linkedField != null) { putField.setField(linkedField.getReference());
private void postBuild(TeaVM vm, long startTime) { if (!vm.wasCancelled()) { log.info("Recompiled stale methods: " + programCache.getPendingItemsCount()); fireBuildComplete(vm); if (vm.getProblemProvider().getSevereProblems().isEmpty()) { log.info("Build complete successfully"); saveNewResult(); lastReachedClasses = vm.getDependencyInfo().getReachableClasses().size(); classSource.commit(); programCache.commit(); astCache.commit(); reportCompilationComplete(true); } else { log.info("Build complete with errors"); reportCompilationComplete(false); } printStats(vm, startTime); TeaVMProblemRenderer.describeProblems(vm, log); } else { log.info("Build cancelled"); fireBuildCancelled(); } astCache.discard(); programCache.discard(); buildTarget.clear(); cancelRequested = false; }
private boolean checkField(TextLocation location, FieldReference field) { if (!checkClass(location, field.getClassName())) { return false; } if (!reachableFields.contains(field) || !dependencyInfo.getField(field).isMissing()) { return true; } diagnostics.error(new CallLocation(methodRef, location), "Field {{f0}} was not found", field); emitExceptionThrow(location, NoSuchFieldError.class.getName(), "Field not found: " + field); return true; }
private void insertClinit(DependencyInfo dependency, String className, MethodReference method, Instruction insn) { if (className.equals(method.getClassName())) { return; } ClassReader cls = dependency.getClassSource().get(className); if (cls == null || cls.getMethod(clinitDescriptor) != null) { InitClassInstruction initInsn = new InitClassInstruction(); initInsn.setClassName(className); initInsn.setLocation(insn.getLocation()); insn.insertPrevious(initInsn); } } }
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; }
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; }
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); } } }
private void propagate(Program program) { ClassReaderSource classSource = dependencyInfo.getClassSource(); MethodDependencyInfo methodDep = dependencyInfo.getMethod(resolvedMethodRef); if (methodDep != null) { if (callSite.receiver >= 0) {
if (insn instanceof InvokeInstruction) { InvokeInstruction invoke = (InvokeInstruction) insn; MethodDependencyInfo linkedMethod = dependency.getMethodImplementation(invoke.getMethod()); if (linkedMethod != null) { invoke.setMethod(linkedMethod.getReference()); FieldDependencyInfo linkedField = dependency.getField(getField.getField()); if (linkedField != null) { getField.setField(linkedField.getReference()); FieldDependencyInfo linkedField = dependency.getField(getField.getField()); if (linkedField != null) { getField.setField(linkedField.getReference());
@Override public void visit(GetFieldInstruction insn) { FieldDependencyInfo fieldDep = dependencyInfo.getField(insn.getField()); ValueDependencyInfo valueDep = fieldDep.getValue(); readValue(valueDep, insn.getReceiver()); }
private void devirtualize(Program program, MethodReference method, DependencyInfo dependencyInfo) { ClassInference inference = new ClassInference(dependencyInfo, hierarchy); inference.infer(program, method); for (BasicBlock block : program.getBasicBlocks()) { for (Instruction instruction : block) { if (!(instruction instanceof InvokeInstruction)) { continue; } InvokeInstruction invoke = (InvokeInstruction) instruction; if (invoke.getType() != InvocationType.VIRTUAL) { continue; } Set<MethodReference> implementations = new HashSet<>(); for (String className : inference.classesOf(invoke.getInstance().getIndex())) { MethodReference rawMethod = new MethodReference(className, invoke.getMethod().getDescriptor()); MethodReader resolvedMethod = dependencyInfo.getClassSource().resolveImplementation(rawMethod); if (resolvedMethod != null) { implementations.add(resolvedMethod.getReference()); } } if (implementations.size() == 1) { invoke.setType(InvocationType.SPECIAL); invoke.setMethod(implementations.iterator().next()); } } } }
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 static void describeProblems(TeaVM vm, TeaVMToolLog log) { describeProblems(vm.getDependencyInfo().getCallGraph(), vm.getProblemProvider(), log); }