public MethodDependency linkMethod(String className, MethodDescriptor descriptor) { return analyzer.linkMethod(className, descriptor); }
public MethodDependency linkMethod(MethodReference methodRef) { return analyzer.linkMethod(methodRef); }
public MethodDependency linkMethod(MethodReference method) { return linkMethod(method.getClassName(), method.getDescriptor()); }
@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(); } }
void initClass(ClassDependency cls, CallLocation location) { ClassReader reader = cls.getClassReader(); MethodReader method = reader.getMethod(CLINIT_METHOD); if (method != null) { deferredTasks.add(() -> { MethodDependency initMethod = linkMethod(method.getReference()); if (location != null) { initMethod.addLocation(location); } initMethod.use(); }); } }
@Override public void cloneArray(VariableReader receiver, VariableReader array) { DependencyNode arrayNode = getNode(array); MethodDependency cloneDep = getAnalyzer().linkMethod(CLONE_METHOD); cloneDep.addLocation(impreciseLocation); cloneDep.use(); }
for (Class<?> type : Arrays.asList(int.class, long.class, float.class, double.class)) { MethodReference method = new MethodReference(WasmRuntime.class, "compare", type, type, int.class); dependencyAnalyzer.linkMethod(method).use(); dependencyAnalyzer.linkMethod(method).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "align", Address.class, int.class, Address.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "fillZero", Address.class, int.class, void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "moveMemoryBlock", Address.class, Address.class, int.class, void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "allocStack", int.class, Address.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "getStackTop", Address.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "getNextStackFrame", Address.class, Address.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "getStackRootCount", Address.class, int.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "getStackRootPointer", Address.class, Address.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "setExceptionHandlerId", Address.class, int.class, void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "getCallSiteId", Address.class, int.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "resourceMapKeys", Address.class, String[].class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(WasmRuntime.class, "lookupResource", Address.class, String.class, Address.class)).use();
@Override public void contributeDependencies(DependencyAnalyzer dependencyAnalyzer) { dependencyAnalyzer.linkMethod(new MethodReference(Allocator.class, "allocate", RuntimeClass.class, Address.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(Allocator.class, "allocateArray", RuntimeClass.class, int.class, Address.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(Allocator.class, "allocateMultiArray", RuntimeClass.class, Address.class, int.class, RuntimeArray.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(Allocator.class, "<clinit>", void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(ExceptionHandling.class, "throwException", Throwable.class, void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(ExceptionHandling.class, "throwClassCastException", void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(ExceptionHandling.class, "throwNullPointerException", void.class)).use(); dependencyAnalyzer.linkMethod(new MethodReference(ExceptionHandling.class, "catchException", Throwable.class)).use(); dependencyAnalyzer.linkClass("java.lang.String"); dependencyAnalyzer.linkClass("java.lang.Class"); dependencyAnalyzer.linkField(new FieldReference("java.lang.String", "hashCode")); ClassDependency runtimeClassDep = dependencyAnalyzer.linkClass(RuntimeClass.class.getName()); ClassDependency runtimeObjectDep = dependencyAnalyzer.linkClass(RuntimeObject.class.getName()); ClassDependency runtimeArrayDep = dependencyAnalyzer.linkClass(RuntimeArray.class.getName()); for (ClassDependency classDep : Arrays.asList(runtimeClassDep, runtimeObjectDep, runtimeArrayDep)) { for (FieldReader field : classDep.getClassReader().getFields()) { dependencyAnalyzer.linkField(field.getReference()); } } }
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])); } }
@Override protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, List<? extends VariableReader> arguments) { DependencyNode[] actualArgs = new DependencyNode[arguments.size() + 1]; for (int i = 0; i < arguments.size(); ++i) { actualArgs[i + 1] = nodes[arguments.get(i).getIndex()]; } actualArgs[0] = getNode(instance); DependencyConsumer listener = new VirtualCallConsumer(getNode(instance), method.getClassName(), method.getDescriptor(), dependencyAnalyzer, actualArgs, receiver != null ? getNode(receiver) : null, getCallLocation(), currentExceptionConsumer); getNode(instance).addConsumer(listener); dependencyAnalyzer.getClassSource().overriddenMethods(method).forEach(methodImpl -> { dependencyAnalyzer.linkMethod(methodImpl.getReference()).addLocation(getCallLocation()); }); }
@Override public void nullCheck(VariableReader receiver, VariableReader value) { DependencyNode valueNode = getNode(value); DependencyNode receiverNode = getNode(receiver); if (valueNode != null) { valueNode.connect(receiverNode); } MethodDependency npeMethod = getAnalyzer().linkMethod(NPE_INIT_METHOD); npeMethod.addLocation(getCallLocation()); npeMethod.use(); }
@Override public void monitorEnter(VariableReader objectRef) { if (getAnalyzer().asyncSupported) { MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_ENTER_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); } MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_ENTER_SYNC_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); }
@Override public void monitorExit(VariableReader objectRef) { if (getAnalyzer().asyncSupported) { MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_EXIT_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); } MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_EXIT_SYNC_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); }
@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 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(); }
dep = dependencyAnalyzer.linkMethod(new MethodReference(Class.class.getName(), "getClass", ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class))); dep.getVariable(0).propagate(dependencyAnalyzer.getType("org.teavm.platform.PlatformClass")); dep = dependencyAnalyzer.linkMethod(new MethodReference(String.class, "<init>", char[].class, void.class)); dep.getVariable(0).propagate(stringType); dep.getVariable(1).propagate(dependencyAnalyzer.getType("[C")); dependencyAnalyzer.linkMethod(new MethodReference(Object.class, "clone", Object.class)); MethodDependency exceptionCons = dependencyAnalyzer.linkMethod(new MethodReference( NoClassDefFoundError.class, "<init>", String.class, void.class)); dep = dependencyAnalyzer.linkMethod(new MethodReference(Object.class, "toString", String.class)); dep.getVariable(0).propagate(dependencyAnalyzer.getType("java.lang.Object")); dep.use(); exceptionCons = dependencyAnalyzer.linkMethod(new MethodReference(NoSuchFieldError.class, "<init>", String.class, void.class)); exceptionCons.use(); exceptionCons.getVariable(0).propagate(dependencyAnalyzer.getType(NoSuchFieldError.class.getName())); exceptionCons.getVariable(1).propagate(stringType); exceptionCons = dependencyAnalyzer.linkMethod(new MethodReference(NoSuchMethodError.class, "<init>", String.class, void.class)); exceptionCons.use(); exceptionCons = dependencyAnalyzer.linkMethod(new MethodReference( RuntimeException.class, "<init>", String.class, void.class)); exceptionCons.getVariable(0).propagate(dependencyAnalyzer.getType(RuntimeException.class.getName()));
MethodDependency methodDep = analyzer.linkMethod(className, methodDesc); methodDep.addLocation(location); if (!methodDep.isMissing()) {
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); }
@Override public void cloneArray(VariableReader receiver, VariableReader array) { DependencyNode arrayNode = getNode(array); DependencyNode receiverNode = getNode(receiver); if (arrayNode != null && receiverNode != null) { arrayNode.addConsumer(receiverNode::propagate); arrayNode.getArrayItem().connect(receiverNode.getArrayItem()); } MethodDependency cloneDep = getAnalyzer().linkMethod(CLONE_METHOD); cloneDep.addLocation(getCallLocation()); arrayNode.connect(cloneDep.getVariable(0)); cloneDep.use(); }
dependencyAnalyzer.linkClass(method.getClassName()); MethodDependency methodDep = dependencyAnalyzer.linkMethod(method); methodDep.addLocation(callLocation); methodDep.use();