diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/reflect/AnnotationDependencyListener.java b/classlib/src/main/java/org/teavm/classlib/java/lang/reflect/AnnotationDependencyListener.java index 2568e7890..6a31cc4b9 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/reflect/AnnotationDependencyListener.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/reflect/AnnotationDependencyListener.java @@ -39,10 +39,15 @@ import org.teavm.model.MethodReference; import org.teavm.model.ValueType; import org.teavm.model.emit.ProgramEmitter; import org.teavm.model.emit.ValueEmitter; +import org.teavm.platform.Platform; import org.teavm.platform.PlatformAnnotationProvider; +import org.teavm.platform.PlatformClass; public class AnnotationDependencyListener extends AbstractDependencyListener { private Set reachedMethods = new HashSet<>(); + private static final MethodReference GET_ANNOTATIONS_METHOD = new MethodReference( + Platform.class, "getAnnotations", PlatformClass.class, Annotation[].class); + private static final String ANNOTATIONS_READER_SUFFIX = "$$__annotations__$$"; private String getAnnotationImplementor(DependencyAgent agent, String annotationType) { String implementorName = annotationType + "$$_impl"; @@ -150,6 +155,9 @@ public class AnnotationDependencyListener extends AbstractDependencyListener { private void reachGetAnnotations(DependencyAgent agent, DependencyNode node) { node.getClassValueNode().addConsumer(type -> { String className = type.getName(); + if (className.endsWith(ANNOTATIONS_READER_SUFFIX)) { + return; + } ClassReader cls = agent.getClassSource().get(className); if (cls == null) { @@ -165,12 +173,12 @@ public class AnnotationDependencyListener extends AbstractDependencyListener { } private void createAnnotationClass(DependencyAgent agent, String className) { - String readerClassName = className + "$$__annotations__$$"; + String readerClassName = className + ANNOTATIONS_READER_SUFFIX; if (agent.getClassSource().get(readerClassName) != null) { return; } - ClassHolder cls = new ClassHolder(className + "$$__annotations__$$"); + ClassHolder cls = new ClassHolder(readerClassName); cls.setLevel(AccessLevel.PUBLIC); cls.setOwnerName("java.lang.Object"); cls.getInterfaces().add(PlatformAnnotationProvider.class.getName()); @@ -183,9 +191,20 @@ public class AnnotationDependencyListener extends AbstractDependencyListener { ClassReader annotatedClass = agent.getClassSource().get(className); cls.addMethod(ctor); - cls.addMethod(addReader(agent, annotatedClass)); + MethodHolder reader = addReader(agent, annotatedClass); + cls.addMethod(reader); agent.submitClass(cls); + + MethodDependency ctorDep = agent.linkMethod(ctor.getReference()); + ctorDep.getVariable(0).propagate(agent.getType(readerClassName)); + ctorDep.use(); + + MethodDependency annotationsDep = agent.linkMethod(GET_ANNOTATIONS_METHOD); + MethodDependency readerDep = agent.linkMethod(reader.getReference()); + readerDep.getVariable(0).propagate(agent.getType(readerClassName)); + readerDep.getResult().getArrayItem().connect(annotationsDep.getResult().getArrayItem()); + readerDep.use(); } private MethodHolder addReader(DependencyAgent agent, ClassReader cls) { diff --git a/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java b/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java index 8d7dfc024..51153b943 100644 --- a/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java +++ b/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java @@ -191,10 +191,6 @@ abstract class AbstractInstructionAnalyzer extends AbstractInstructionReader { invokeVirtual(receiver, instance, method, arguments); break; } - if (method.getName().equals("getClass") && method.parameterCount() == 0 - && method.getReturnType().isObject(Class.class) && receiver != null) { - getNode(instance).connect(getNode(receiver).getClassValueNode()); - } } } diff --git a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index b2487b93c..c613ccf7b 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -30,6 +30,7 @@ import org.teavm.model.ClassReader; import org.teavm.model.ClassReaderSource; import org.teavm.model.ElementModifier; import org.teavm.model.IncomingReader; +import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodHolder; import org.teavm.model.MethodReference; import org.teavm.model.PhiReader; @@ -41,6 +42,7 @@ import org.teavm.model.instructions.ArrayElementType; import org.teavm.model.text.ListingBuilder; class DependencyGraphBuilder { + private static final MethodDescriptor GET_CLASS = new MethodDescriptor("getClass", Class.class); private DependencyAnalyzer dependencyAnalyzer; private DependencyNode[] nodes; private DependencyNode resultNode; @@ -323,6 +325,10 @@ class DependencyGraphBuilder { @Override protected void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method, List arguments) { + if (method.getDescriptor().equals(GET_CLASS)) { + invokeGetClass(receiver, instance); + return; + } CallLocation callLocation = getCallLocation(); if (instance == null) { dependencyAnalyzer.linkClass(method.getClassName()).initClass(callLocation); @@ -359,6 +365,11 @@ class DependencyGraphBuilder { @Override protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, List arguments) { + if (method.getDescriptor().equals(GET_CLASS)) { + invokeGetClass(receiver, instance); + return; + } + DependencyNode[] actualArgs = new DependencyNode[arguments.size() + 1]; for (int i = 0; i < arguments.size(); ++i) { actualArgs[i + 1] = nodes[arguments.get(i).getIndex()]; @@ -375,6 +386,21 @@ class DependencyGraphBuilder { }); } + private void invokeGetClass(VariableReader receiver, VariableReader instance) { + MethodDependency getClassDep = dependencyAnalyzer.linkMethod("java.lang.Object", GET_CLASS); + getClassDep.addLocation(getCallLocation()); + getNode(instance).addConsumer(t -> { + getClassDep.getVariable(0).propagate(t); + if (receiver != null) { + getNode(receiver).getClassValueNode().propagate(t); + } + }); + if (receiver != null) { + getNode(receiver).propagate(dependencyAnalyzer.getType("java.lang.Class")); + } + getClassDep.use(); + } + @Override public void nullCheck(VariableReader receiver, VariableReader value) { super.nullCheck(receiver, value); diff --git a/core/src/main/java/org/teavm/dependency/DependencyNode.java b/core/src/main/java/org/teavm/dependency/DependencyNode.java index 066ffc7db..30683cc3f 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyNode.java +++ b/core/src/main/java/org/teavm/dependency/DependencyNode.java @@ -32,7 +32,6 @@ import org.teavm.model.MethodReference; import org.teavm.model.ValueType; public class DependencyNode implements ValueDependencyInfo { - private static final int SMALL_TYPES_THRESHOLD = 3; private static final int DEGREE_THRESHOLD = 2; DependencyAnalyzer dependencyAnalyzer; List followers; @@ -385,12 +384,6 @@ public class DependencyNode implements ValueDependencyInfo { } } - private void propagateTypes(Transition transition) { - if (typeSet != null) { - dependencyAnalyzer.schedulePropagation(transition, getTypesInternal()); - } - } - public void connect(DependencyNode node) { connect(node, null); } diff --git a/core/src/main/java/org/teavm/dependency/FastInstructionAnalyzer.java b/core/src/main/java/org/teavm/dependency/FastInstructionAnalyzer.java index 6ae2fc6dd..9c7f2d261 100644 --- a/core/src/main/java/org/teavm/dependency/FastInstructionAnalyzer.java +++ b/core/src/main/java/org/teavm/dependency/FastInstructionAnalyzer.java @@ -31,6 +31,9 @@ class FastInstructionAnalyzer extends AbstractInstructionAnalyzer { @Override protected void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method, List arguments) { + if (instance != null) { + invokeGetClass(method); + } CallLocation callLocation = impreciseLocation; if (instance == null) { dependencyAnalyzer.linkClass(method.getClassName()).initClass(callLocation); @@ -43,12 +46,19 @@ class FastInstructionAnalyzer extends AbstractInstructionAnalyzer { @Override protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, List arguments) { + invokeGetClass(method); dependencyAnalyzer.getVirtualCallConsumer(method).addLocation(impreciseLocation); } + private void invokeGetClass(MethodReference method) { + if (method.getName().equals("getClass") && method.parameterCount() == 0 + && method.getReturnType().isObject(Class.class)) { + dependencyAnalyzer.instancesNode.connect(dependencyAnalyzer.classesNode); + } + } + @Override public void cloneArray(VariableReader receiver, VariableReader array) { - DependencyNode arrayNode = getNode(array); MethodDependency cloneDep = getAnalyzer().linkMethod(CLONE_METHOD); cloneDep.addLocation(impreciseLocation); cloneDep.use(); diff --git a/platform/src/main/java/org/teavm/platform/plugin/AnnotationDependencySupport.java b/platform/src/main/java/org/teavm/platform/plugin/AnnotationDependencySupport.java deleted file mode 100644 index 119a289f2..000000000 --- a/platform/src/main/java/org/teavm/platform/plugin/AnnotationDependencySupport.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2015 Alexey Andreev. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.teavm.platform.plugin; - -import java.lang.annotation.Annotation; -import org.teavm.dependency.AbstractDependencyListener; -import org.teavm.dependency.DependencyAgent; -import org.teavm.dependency.DependencyNode; -import org.teavm.dependency.MethodDependency; -import org.teavm.model.MethodReference; -import org.teavm.model.ValueType; -import org.teavm.platform.Platform; -import org.teavm.platform.PlatformAnnotationProvider; - -public class AnnotationDependencySupport extends AbstractDependencyListener { - private DependencyNode allClasses; - private MethodDependency getAnnotationsDep; - - @Override - public void started(DependencyAgent agent) { - allClasses = agent.createNode(); - } - - @Override - public void classReached(DependencyAgent agent, String className) { - allClasses.propagate(agent.getType(className)); - } - - @Override - public void methodReached(DependencyAgent agent, MethodDependency method) { - if (method.getReference().getClassName().equals(Platform.class.getName()) - && method.getReference().getName().equals("getAnnotations")) { - method.getResult().propagate(agent.getType("[" + ValueType.parse(Annotation.class).toString())); - if (getAnnotationsDep == null) { - getAnnotationsDep = agent.linkMethod(new MethodReference(PlatformAnnotationProvider.class, - "getAnnotations", Annotation[].class)); - } - method.addLocationListener(getAnnotationsDep::addLocation); - - allClasses.addConsumer(type -> { - if (type.getName().endsWith("$$__annotations__$$")) { - return; - } - String className = type.getName() + "$$__annotations__$$"; - MethodDependency initMethod = agent.linkMethod(new MethodReference(className, "", - ValueType.VOID)); - initMethod.propagate(0, className); - initMethod.use(); - MethodDependency readMethod = agent.linkMethod(new MethodReference(className, - "getAnnotations", ValueType.parse(Annotation[].class))); - readMethod.getResult().getArrayItem().connect(method.getResult().getArrayItem()); - readMethod.use(); - - method.addLocationListener(location -> { - initMethod.addLocation(location); - readMethod.addLocation(location); - }); - }); - } - } -} diff --git a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java index 022f1bdca..b79fc1d65 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java +++ b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java @@ -105,7 +105,6 @@ public class PlatformPlugin implements TeaVMPlugin { host.add(new NewInstanceDependencySupport()); host.add(new ClassLookupDependencySupport()); host.add(new EnumDependencySupport()); - host.add(new AnnotationDependencySupport()); host.add(new PlatformDependencyListener()); host.add(new AsyncDependencyListener());