public DependencyType getType(String name) { return analyzer.getType(name); }
public MethodDependency propagate(int parameterIndex, String type) { return propagate(parameterIndex, dependencyAnalyzer.getType(type)); }
@Override public boolean hasType(String type) { return hasType(dependencyAnalyzer.getType(type)); }
public MethodDependency propagate(int parameterIndex, Class<?> type) { return propagate(parameterIndex, dependencyAnalyzer.getType(type.getName())); }
@Override public int[] tryExtract(BitSet types) { int[] result = itemTypeFilter.tryExtract(types); if (result == null) { return null; } for (int i = 0; i < result.length; ++i) { String name = analyzer.types.get(i).getName(); int mapped; if (name.startsWith("[")) { mapped = analyzer.getType("[" + name).index; } else if (name.startsWith("~")) { mapped = analyzer.getType("[" + name.substring(1)).index; } else { mapped = analyzer.getType(ValueType.arrayOf(ValueType.object(name)).toString()).index; } result[i] = mapped; } return result; } }
@Override public void nullCheck(VariableReader receiver, VariableReader value) { super.nullCheck(receiver, value); currentExceptionConsumer.consume(dependencyAnalyzer.getType("java.lang.NullPointerException")); }
private void markSupertypesAsHavingSubtypes(String name) { ClassReader cls = unprocessedClassSource.get(name); if (cls == null) { cls = classSource.get(name); if (cls == null) { return; } } if (cls.getParent() != null) { getType(cls.getParent()).subtypeExists = true; } for (String itf : cls.getInterfaces()) { getType(itf).subtypeExists = true; } }
private boolean matchCacheMiss(DependencyType type) { if (!type.getName().startsWith("[")) { return false; } String typeName = type.getName().substring(1); ValueType valueType = ValueType.parseIfPossible(typeName); if (valueType == null || valueType instanceof ValueType.Primitive) { return false; } if (valueType instanceof ValueType.Object) { typeName = ((ValueType.Object) valueType).getClassName(); } return itemTypeFilter.match(analyzer.getType(typeName)); }
public void addEntryPoint(MethodReference methodRef, String... argumentTypes) { ValueType[] parameters = methodRef.getDescriptor().getParameterTypes(); if (parameters.length + 1 != argumentTypes.length) { throw new IllegalArgumentException("argumentTypes length does not match the number of method's arguments"); } MethodDependency method = linkMethod(methodRef); method.use(); DependencyNode[] varNodes = method.getVariables(); varNodes[0].propagate(getType(methodRef.getClassName())); for (int i = 0; i < argumentTypes.length; ++i) { varNodes[i + 1].propagate(getType(argumentTypes[i])); } }
DependencyTypeFilter getSuperClassFilter(String superClass) { DependencyTypeFilter result = superClassFilters.get(superClass); if (result == null) { if (superClass.startsWith("[")) { char second = superClass.charAt(1); if (second == '[') { result = new SuperArrayFilter(this, getSuperClassFilter(superClass.substring(1))); } else if (second == 'L') { ValueType.Object itemType = (ValueType.Object) ValueType.parse(superClass.substring(1)); result = new SuperArrayFilter(this, getSuperClassFilter(itemType.getClassName())); } else { result = new ExactTypeFilter(superClass); } } else { if (superClass.equals("java.lang.Object")) { result = t -> true; } else { result = new SuperClassFilter(this, getType(superClass)); } } superClassFilters.put(superClass, result); } return result; }
@Override public void consume(DependencyType type) { String className = type.getName(); if (DependencyAnalyzer.shouldLog) { System.out.println("Virtual call of " + methodDesc + " detected on " + node.getTag() + ". " + "Target class is " + className); } if (className.startsWith("[")) { className = "java.lang.Object"; type = analyzer.getType(className); } MethodDependency methodDep = analyzer.linkMethod(className, methodDesc); if (!methods.add(methodDep)) { return; } for (CallLocation location : callLocations.values()) { methodDep.addLocation(location); } if (!methodDep.isMissing()) { methodDep.use(); } }
@Override public void classConstant(VariableReader receiver, ValueType cst) { DependencyNode node = getNode(receiver); if (node != null) { node.propagate(getAnalyzer().getType("java.lang.Class")); if (!(cst instanceof ValueType.Primitive)) { StringBuilder sb = new StringBuilder(); if (cst instanceof ValueType.Object) { sb.append(((ValueType.Object) cst).getClassName()); } else { sb.append(cst.toString()); } node.getClassValueNode().propagate(getAnalyzer().getType(sb.toString())); } else { node.getClassValueNode().propagate(getAnalyzer().getType("~" + cst.toString())); } } while (cst instanceof ValueType.Array) { cst = ((ValueType.Array) cst).getItemType(); } if (cst instanceof ValueType.Object) { String className = ((ValueType.Object) cst).getClassName(); getAnalyzer().linkClass(className); } }
public static void includeStackTraceMethods(DependencyAnalyzer dependencyAnalyzer) { MethodDependency dep; DependencyType stringType = dependencyAnalyzer.getType("java.lang.String"); dep = dependencyAnalyzer.linkMethod(new MethodReference( StackTraceElement.class, "<init>", String.class, String.class, String.class, int.class, void.class)); dep.getVariable(0).propagate(dependencyAnalyzer.getType(StackTraceElement.class.getName())); dep.getVariable(1).propagate(stringType); dep.getVariable(2).propagate(stringType); dep.getVariable(3).propagate(stringType); dep.use(); dep = dependencyAnalyzer.linkMethod(new MethodReference( Throwable.class, "setStackTrace", StackTraceElement[].class, void.class)); dep.getVariable(0).propagate(dependencyAnalyzer.getType(Throwable.class.getName())); dep.getVariable(1).propagate(dependencyAnalyzer.getType("[Ljava/lang/StackTraceElement;")); dep.getVariable(1).getArrayItem().propagate(dependencyAnalyzer.getType(StackTraceElement.class.getName())); dep.use(); }
@Override public void create(VariableReader receiver, String type) { getAnalyzer().linkClass(type); DependencyNode node = getNode(receiver); if (node != null) { node.propagate(getAnalyzer().getType(type)); } }
@Override public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) { DependencyNode node = getNode(receiver); if (node != null) { node.propagate(getAnalyzer().getType("[" + itemType)); } String className = extractClassName(itemType); if (className != null) { getAnalyzer().linkClass(className); } }
@Override public void createArray(VariableReader receiver, ValueType itemType, List<? extends VariableReader> dimensions) { DependencyNode node = getNode(receiver); for (int i = 0; i < dimensions.size(); ++i) { if (node == null) { break; } String itemTypeStr; if (itemType instanceof ValueType.Object) { itemTypeStr = ((ValueType.Object) itemType).getClassName(); } else { itemTypeStr = itemType.toString(); } node.propagate(getAnalyzer().getType(itemTypeStr)); node = node.getArrayItem(); itemType = ((ValueType.Array) itemType).getItemType(); } String className = extractClassName(itemType); if (className != null) { getAnalyzer().linkClass(className); } }
@Override public void stringConstant(VariableReader receiver, String cst) { DependencyNode node = getNode(receiver); if (node != null) { node.propagate(getAnalyzer().getType("java.lang.String")); } MethodDependency method = getAnalyzer().linkMethod(STRING_INIT_FROM_CHARS_METHOD); method.addLocation(getCallLocation()); method.use(); }
public void entryPoint(String className, String name) { if (entryPoints.containsKey(name)) { throw new IllegalArgumentException("Entry point with public name `" + name + "' already defined " + "for class " + className); } ClassReader cls = dependencyAnalyzer.getClassSource().get(className); if (cls == null) { diagnostics.error(null, "There's no main class: '{{c0}}'", className); return; } if (cls.getMethod(MAIN_METHOD_DESC) == null) { diagnostics.error(null, "Specified main class '{{c0}}' does not have method '" + MAIN_METHOD_DESC + "'", cls.getName()); return; } MethodDependency mainMethod = dependencyAnalyzer.linkMethod(new MethodReference(className, "main", ValueType.parse(String[].class), ValueType.VOID)); TeaVMEntryPoint entryPoint = new TeaVMEntryPoint(name, mainMethod); dependencyAnalyzer.defer(() -> { dependencyAnalyzer.linkClass(className).initClass(null); mainMethod.getVariable(1).propagate(dependencyAnalyzer.getType("[Ljava/lang/String;")); mainMethod.getVariable(1).getArrayItem().propagate(dependencyAnalyzer.getType("java.lang.String")); mainMethod.use(); }); entryPoints.put(name, entryPoint); }
type = analyzer.getType(className);
DependencyAnalyzer(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services, Diagnostics diagnostics) { unprocessedClassSource = classSource; this.diagnostics = diagnostics; this.classSource = new DependencyClassSource(classSource, diagnostics, incrementalCache); classHierarchy = new ClassHierarchy(this.classSource); this.classLoader = classLoader; this.services = services; fieldReaderCache = new CachedMapper<>(preimage -> this.classSource.resolveMutable(preimage)); fieldCache = new CachedMapper<>(preimage -> { FieldReader field = fieldReaderCache.map(preimage); if (field != null && !field.getReference().equals(preimage)) { return fieldCache.map(field.getReference()); } FieldDependency node = createFieldNode(preimage, field); if (field != null && field.getInitialValue() instanceof String) { node.getValue().propagate(getType("java.lang.String")); } return node; }); classCache = new CachedMapper<>(this::createClassDependency); agent = new DependencyAgent(this); }