Fix html4j tests

This commit is contained in:
Alexey Andreev 2019-01-31 19:20:14 +03:00
parent 7d2c76f711
commit 95a3a30a6e
7 changed files with 59 additions and 90 deletions

View File

@ -39,10 +39,15 @@ import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.model.emit.ProgramEmitter; import org.teavm.model.emit.ProgramEmitter;
import org.teavm.model.emit.ValueEmitter; import org.teavm.model.emit.ValueEmitter;
import org.teavm.platform.Platform;
import org.teavm.platform.PlatformAnnotationProvider; import org.teavm.platform.PlatformAnnotationProvider;
import org.teavm.platform.PlatformClass;
public class AnnotationDependencyListener extends AbstractDependencyListener { public class AnnotationDependencyListener extends AbstractDependencyListener {
private Set<MethodReference> reachedMethods = new HashSet<>(); private Set<MethodReference> 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) { private String getAnnotationImplementor(DependencyAgent agent, String annotationType) {
String implementorName = annotationType + "$$_impl"; String implementorName = annotationType + "$$_impl";
@ -150,6 +155,9 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
private void reachGetAnnotations(DependencyAgent agent, DependencyNode node) { private void reachGetAnnotations(DependencyAgent agent, DependencyNode node) {
node.getClassValueNode().addConsumer(type -> { node.getClassValueNode().addConsumer(type -> {
String className = type.getName(); String className = type.getName();
if (className.endsWith(ANNOTATIONS_READER_SUFFIX)) {
return;
}
ClassReader cls = agent.getClassSource().get(className); ClassReader cls = agent.getClassSource().get(className);
if (cls == null) { if (cls == null) {
@ -165,12 +173,12 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
} }
private void createAnnotationClass(DependencyAgent agent, String className) { private void createAnnotationClass(DependencyAgent agent, String className) {
String readerClassName = className + "$$__annotations__$$"; String readerClassName = className + ANNOTATIONS_READER_SUFFIX;
if (agent.getClassSource().get(readerClassName) != null) { if (agent.getClassSource().get(readerClassName) != null) {
return; return;
} }
ClassHolder cls = new ClassHolder(className + "$$__annotations__$$"); ClassHolder cls = new ClassHolder(readerClassName);
cls.setLevel(AccessLevel.PUBLIC); cls.setLevel(AccessLevel.PUBLIC);
cls.setOwnerName("java.lang.Object"); cls.setOwnerName("java.lang.Object");
cls.getInterfaces().add(PlatformAnnotationProvider.class.getName()); cls.getInterfaces().add(PlatformAnnotationProvider.class.getName());
@ -183,9 +191,20 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
ClassReader annotatedClass = agent.getClassSource().get(className); ClassReader annotatedClass = agent.getClassSource().get(className);
cls.addMethod(ctor); cls.addMethod(ctor);
cls.addMethod(addReader(agent, annotatedClass)); MethodHolder reader = addReader(agent, annotatedClass);
cls.addMethod(reader);
agent.submitClass(cls); 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) { private MethodHolder addReader(DependencyAgent agent, ClassReader cls) {

View File

@ -191,10 +191,6 @@ abstract class AbstractInstructionAnalyzer extends AbstractInstructionReader {
invokeVirtual(receiver, instance, method, arguments); invokeVirtual(receiver, instance, method, arguments);
break; break;
} }
if (method.getName().equals("getClass") && method.parameterCount() == 0
&& method.getReturnType().isObject(Class.class) && receiver != null) {
getNode(instance).connect(getNode(receiver).getClassValueNode());
}
} }
} }

View File

@ -30,6 +30,7 @@ import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource; import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementModifier; import org.teavm.model.ElementModifier;
import org.teavm.model.IncomingReader; import org.teavm.model.IncomingReader;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodHolder; import org.teavm.model.MethodHolder;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.PhiReader; import org.teavm.model.PhiReader;
@ -41,6 +42,7 @@ import org.teavm.model.instructions.ArrayElementType;
import org.teavm.model.text.ListingBuilder; import org.teavm.model.text.ListingBuilder;
class DependencyGraphBuilder { class DependencyGraphBuilder {
private static final MethodDescriptor GET_CLASS = new MethodDescriptor("getClass", Class.class);
private DependencyAnalyzer dependencyAnalyzer; private DependencyAnalyzer dependencyAnalyzer;
private DependencyNode[] nodes; private DependencyNode[] nodes;
private DependencyNode resultNode; private DependencyNode resultNode;
@ -323,6 +325,10 @@ class DependencyGraphBuilder {
@Override @Override
protected void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method, protected void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments) { List<? extends VariableReader> arguments) {
if (method.getDescriptor().equals(GET_CLASS)) {
invokeGetClass(receiver, instance);
return;
}
CallLocation callLocation = getCallLocation(); CallLocation callLocation = getCallLocation();
if (instance == null) { if (instance == null) {
dependencyAnalyzer.linkClass(method.getClassName()).initClass(callLocation); dependencyAnalyzer.linkClass(method.getClassName()).initClass(callLocation);
@ -359,6 +365,11 @@ class DependencyGraphBuilder {
@Override @Override
protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments) { List<? extends VariableReader> arguments) {
if (method.getDescriptor().equals(GET_CLASS)) {
invokeGetClass(receiver, instance);
return;
}
DependencyNode[] actualArgs = new DependencyNode[arguments.size() + 1]; DependencyNode[] actualArgs = new DependencyNode[arguments.size() + 1];
for (int i = 0; i < arguments.size(); ++i) { for (int i = 0; i < arguments.size(); ++i) {
actualArgs[i + 1] = nodes[arguments.get(i).getIndex()]; 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 @Override
public void nullCheck(VariableReader receiver, VariableReader value) { public void nullCheck(VariableReader receiver, VariableReader value) {
super.nullCheck(receiver, value); super.nullCheck(receiver, value);

View File

@ -32,7 +32,6 @@ import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
public class DependencyNode implements ValueDependencyInfo { public class DependencyNode implements ValueDependencyInfo {
private static final int SMALL_TYPES_THRESHOLD = 3;
private static final int DEGREE_THRESHOLD = 2; private static final int DEGREE_THRESHOLD = 2;
DependencyAnalyzer dependencyAnalyzer; DependencyAnalyzer dependencyAnalyzer;
List<DependencyConsumer> followers; List<DependencyConsumer> 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) { public void connect(DependencyNode node) {
connect(node, null); connect(node, null);
} }

View File

@ -31,6 +31,9 @@ class FastInstructionAnalyzer extends AbstractInstructionAnalyzer {
@Override @Override
protected void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method, protected void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments) { List<? extends VariableReader> arguments) {
if (instance != null) {
invokeGetClass(method);
}
CallLocation callLocation = impreciseLocation; CallLocation callLocation = impreciseLocation;
if (instance == null) { if (instance == null) {
dependencyAnalyzer.linkClass(method.getClassName()).initClass(callLocation); dependencyAnalyzer.linkClass(method.getClassName()).initClass(callLocation);
@ -43,12 +46,19 @@ class FastInstructionAnalyzer extends AbstractInstructionAnalyzer {
@Override @Override
protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments) { List<? extends VariableReader> arguments) {
invokeGetClass(method);
dependencyAnalyzer.getVirtualCallConsumer(method).addLocation(impreciseLocation); 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 @Override
public void cloneArray(VariableReader receiver, VariableReader array) { public void cloneArray(VariableReader receiver, VariableReader array) {
DependencyNode arrayNode = getNode(array);
MethodDependency cloneDep = getAnalyzer().linkMethod(CLONE_METHOD); MethodDependency cloneDep = getAnalyzer().linkMethod(CLONE_METHOD);
cloneDep.addLocation(impreciseLocation); cloneDep.addLocation(impreciseLocation);
cloneDep.use(); cloneDep.use();

View File

@ -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, "<init>",
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);
});
});
}
}
}

View File

@ -105,7 +105,6 @@ public class PlatformPlugin implements TeaVMPlugin {
host.add(new NewInstanceDependencySupport()); host.add(new NewInstanceDependencySupport());
host.add(new ClassLookupDependencySupport()); host.add(new ClassLookupDependencySupport());
host.add(new EnumDependencySupport()); host.add(new EnumDependencySupport());
host.add(new AnnotationDependencySupport());
host.add(new PlatformDependencyListener()); host.add(new PlatformDependencyListener());
host.add(new AsyncDependencyListener()); host.add(new AsyncDependencyListener());