diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ClassLookupDependencySupport.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/ClassLookupDependencySupport.java index 765e4171d..80ea34007 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ClassLookupDependencySupport.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/ClassLookupDependencySupport.java @@ -26,29 +26,29 @@ public class ClassLookupDependencySupport implements DependencyListener { private DependencyNode allClasses; @Override - public void started(DependencyChecker dependencyChecker) { - allClasses = dependencyChecker.createNode(); + public void started(DependencyAgent agent) { + allClasses = agent.createNode(); } @Override - public void classAchieved(DependencyChecker dependencyChecker, String className) { + public void classAchieved(DependencyAgent agent, String className) { allClasses.propagate(className); } @Override - public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) { + public void methodAchieved(final DependencyAgent agent, MethodDependency method) { MethodReference ref = method.getReference(); if (ref.getClassName().equals("java.lang.Class") && ref.getName().equals("forNameImpl")) { final DependencyStack stack = method.getStack(); allClasses.addConsumer(new DependencyConsumer() { @Override public void consume(String type) { - ClassReader cls = dependencyChecker.getClassSource().get(type); + ClassReader cls = agent.getClassSource().get(type); if (cls == null) { return; } MethodReader initMethod = cls.getMethod(new MethodDescriptor("", ValueType.VOID)); if (initMethod != null) { - dependencyChecker.linkMethod(initMethod.getReference(), stack).use(); + agent.linkMethod(initMethod.getReference(), stack).use(); } } }); @@ -56,6 +56,6 @@ public class ClassLookupDependencySupport implements DependencyListener { } @Override - public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) { + public void fieldAchieved(DependencyAgent dependencyChecker, FieldDependency field) { } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumDependencySupport.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumDependencySupport.java index 21cf3283c..649d37370 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumDependencySupport.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumDependencySupport.java @@ -30,13 +30,13 @@ public class EnumDependencySupport implements DependencyListener { private volatile DependencyStack enumConstantsStack; @Override - public void started(DependencyChecker dependencyChecker) { - allEnums = dependencyChecker.createNode(); + public void started(DependencyAgent agent) { + allEnums = agent.createNode(); } @Override - public void classAchieved(DependencyChecker dependencyChecker, String className) { - ClassReader cls = dependencyChecker.getClassSource().get(className); + public void classAchieved(DependencyAgent agent, String className) { + ClassReader cls = agent.getClassSource().get(className); if (cls == null || cls.getParent() == null || !cls.getParent().equals("java.lang.Enum")) { return; } @@ -45,25 +45,25 @@ public class EnumDependencySupport implements DependencyListener { MethodReader method = cls.getMethod(new MethodDescriptor("values", ValueType.arrayOf(ValueType.object(cls.getName())))); if (method != null) { - dependencyChecker.linkMethod(method.getReference(), enumConstantsStack).use(); + agent.linkMethod(method.getReference(), enumConstantsStack).use(); } } } @Override - public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) { + public void methodAchieved(DependencyAgent agent, MethodDependency method) { if (method.getReference().getClassName().equals("java.lang.Class") && method.getReference().getName().equals("getEnumConstantsImpl")) { allEnums.connect(method.getResult().getArrayItem()); method.getResult().propagate("[java.lang.Enum"); enumConstantsStack = method.getStack(); - for (String cls : dependencyChecker.getAchievableClasses()) { - classAchieved(dependencyChecker, cls); + for (String cls : agent.getAchievableClasses()) { + classAchieved(agent, cls); } } } @Override - public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) { + public void fieldAchieved(DependencyAgent agent, FieldDependency field) { } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java index 09dd74958..cbf9016a0 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java @@ -27,13 +27,13 @@ public class NewInstanceDependencySupport implements DependencyListener { private DependencyStack newInstanceStack; @Override - public void started(DependencyChecker dependencyChecker) { - allClassesNode = dependencyChecker.createNode(); + public void started(DependencyAgent agent) { + allClassesNode = agent.createNode(); } @Override - public void classAchieved(DependencyChecker dependencyChecker, String className) { - ClassReader cls = dependencyChecker.getClassSource().get(className); + public void classAchieved(DependencyAgent agent, String className) { + ClassReader cls = agent.getClassSource().get(className); if (cls == null) { return; } @@ -47,25 +47,25 @@ public class NewInstanceDependencySupport implements DependencyListener { } @Override - public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) { + public void methodAchieved(final DependencyAgent agent, MethodDependency method) { MethodReader reader = method.getMethod(); if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) { newInstanceStack = method.getStack(); allClassesNode.connect(method.getResult()); method.getResult().addConsumer(new DependencyConsumer() { @Override public void consume(String type) { - attachConstructor(dependencyChecker, type); + attachConstructor(agent, type); } }); } } - private void attachConstructor(DependencyChecker checker, String type) { + private void attachConstructor(DependencyAgent checker, String type) { MethodReference ref = new MethodReference(type, new MethodDescriptor("", ValueType.VOID)); checker.linkMethod(ref, newInstanceStack).use(); } @Override - public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) { + public void fieldAchieved(DependencyAgent dependencyAgent, FieldDependency field) { } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java index 852148ed5..16c06c192 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java @@ -78,12 +78,12 @@ public class ServiceLoaderSupport implements Generator, DependencyListener { } @Override - public void started(DependencyChecker dependencyChecker) { - allClassesNode = dependencyChecker.createNode(); + public void started(DependencyAgent agent) { + allClassesNode = agent.createNode(); } @Override - public void classAchieved(DependencyChecker dependencyChecker, String className) { + public void classAchieved(DependencyAgent agent, String className) { try { Enumeration resources = classLoader.getResources("META-INF/services/" + className); while (resources.hasMoreElements()) { @@ -119,7 +119,7 @@ public class ServiceLoaderSupport implements Generator, DependencyListener { } @Override - public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) { + public void methodAchieved(final DependencyAgent agent, MethodDependency method) { MethodReference ref = method.getReference(); if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) { method.getResult().propagate("[java.lang.Object"); @@ -127,18 +127,18 @@ public class ServiceLoaderSupport implements Generator, DependencyListener { allClassesNode.connect(method.getResult().getArrayItem()); method.getResult().getArrayItem().addConsumer(new DependencyConsumer() { @Override public void consume(String type) { - initConstructor(dependencyChecker, type); + initConstructor(agent, type); } }); } } - private void initConstructor(DependencyChecker dependencyChecker, String type) { + private void initConstructor(DependencyAgent agent, String type) { MethodReference ctor = new MethodReference(type, new MethodDescriptor("", ValueType.VOID)); - dependencyChecker.linkMethod(ctor, stack).use(); + agent.linkMethod(ctor, stack).use(); } @Override - public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) { + public void fieldAchieved(DependencyAgent agent, FieldDependency field) { } } diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java new file mode 100644 index 000000000..d1011fb2e --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java @@ -0,0 +1,26 @@ +package org.teavm.dependency; + +import org.teavm.model.ClassHolder; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.FieldReference; +import org.teavm.model.MethodReference; + +/** + * + * @author Alexey Andreev + */ +public interface DependencyAgent extends DependencyInfo { + DependencyNode createNode(); + + ClassReaderSource getClassSource(); + + String generateClassName(); + + void submitClass(ClassHolder cls); + + MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack); + + void initClass(String className, final DependencyStack stack); + + FieldDependency linkField(FieldReference fieldRef, DependencyStack stack); +} diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java index c57e63fe1..fd06f3b4f 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java @@ -22,15 +22,17 @@ import java.util.concurrent.ConcurrentMap; import org.teavm.common.*; import org.teavm.common.ConcurrentCachedMapper.KeyListener; import org.teavm.model.*; +import org.teavm.model.util.ModelUtils; /** * * @author Alexey Andreev */ -public class DependencyChecker implements DependencyInfo { +public class DependencyChecker implements DependencyInfo, DependencyAgent { private static Object dummyValue = new Object(); static final boolean shouldLog = System.getProperty("org.teavm.logDependencies", "false").equals("true"); - private ClassReaderSource classSource; + private int classNameSuffix; + private DependencyClassSource classSource; private ClassLoader classLoader; private FiniteExecutor executor; private Mapper methodReaderCache; @@ -47,12 +49,12 @@ public class DependencyChecker implements DependencyInfo { ConcurrentMap missingClasses = new ConcurrentHashMap<>(); ConcurrentMap missingFields = new ConcurrentHashMap<>(); - public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader) { + public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) { this(classSource, classLoader, new SimpleFiniteExecutor()); } - public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) { - this.classSource = classSource; + public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) { + this.classSource = new DependencyClassSource(classSource); this.classLoader = classLoader; this.executor = executor; methodReaderCache = new ConcurrentCachedMapper<>(new Mapper() { @@ -108,14 +110,26 @@ public class DependencyChecker implements DependencyInfo { }); } + @Override public DependencyNode createNode() { return new DependencyNode(this); } + @Override public ClassReaderSource getClassSource() { return classSource; } + @Override + public String generateClassName() { + return "$$tmp$$.TempClass" + classNameSuffix++; + } + + @Override + public void submitClass(ClassHolder cls) { + classSource.submit(ModelUtils.copyClass(cls)); + } + public void addDependencyListener(DependencyListener listener) { listeners.add(listener); listener.started(this); @@ -135,7 +149,7 @@ public class DependencyChecker implements DependencyInfo { } } - public void schedulePropagation(final DependencyConsumer consumer, final String type) { + void schedulePropagation(final DependencyConsumer consumer, final String type) { executor.executeFast(new Runnable() { @Override public void run() { consumer.consume(type); @@ -158,6 +172,7 @@ public class DependencyChecker implements DependencyInfo { return result; } + @Override public MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack) { if (methodRef == null) { throw new IllegalArgumentException(); @@ -166,6 +181,7 @@ public class DependencyChecker implements DependencyInfo { return methodCache.map(methodRef); } + @Override public void initClass(String className, final DependencyStack stack) { classStacks.putIfAbsent(className, stack); MethodDescriptor clinitDesc = new MethodDescriptor("", ValueType.VOID); @@ -302,6 +318,7 @@ public class DependencyChecker implements DependencyInfo { return dep; } + @Override public boolean isMethodAchievable(MethodReference methodRef) { return methodCache.caches(methodRef); } @@ -321,6 +338,7 @@ public class DependencyChecker implements DependencyInfo { return new HashSet<>(achievableClasses.keySet()); } + @Override public FieldDependency linkField(FieldReference fieldRef, DependencyStack stack) { fieldStacks.putIfAbsent(fieldRef, stack); return fieldCache.map(fieldRef); @@ -420,4 +438,14 @@ public class DependencyChecker implements DependencyInfo { sb.append('\n'); } } + + @Override + public Collection getGeneratedClasses() { + Collection classes = classSource.getGeneratedClasses(); + List copies = new ArrayList<>(classes.size()); + for (ClassHolder cls : classes) { + copies.add(ModelUtils.copyClass(cls)); + } + return classes; + } } diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java new file mode 100644 index 000000000..b2394600d --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java @@ -0,0 +1,70 @@ +/* + * Copyright 2014 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.dependency; + +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.teavm.common.ConcurrentCachedMapper; +import org.teavm.common.Mapper; +import org.teavm.model.ClassHolder; +import org.teavm.model.ClassReader; +import org.teavm.model.ClassReaderSource; + +/** + * + * @author Alexey Andreev + */ +class DependencyClassSource implements ClassReaderSource { + private ClassReaderSource innerSource; + private ConcurrentMap generatedClasses = new ConcurrentHashMap<>(); + private ConcurrentCachedMapper cache = new ConcurrentCachedMapper<>( + new Mapper() { + @Override public ClassReader map(String preimage) { + return findClass(preimage); + } + }); + + public DependencyClassSource(ClassReaderSource innerSource) { + this.innerSource = innerSource; + } + + @Override + public ClassReader get(String name) { + return cache.map(name); + } + + public void submit(ClassHolder cls) { + if (innerSource.get(cls.getName()) != null) { + throw new IllegalArgumentException("Class " + cls.getName() + " is already defined"); + } + if (generatedClasses.putIfAbsent(cls.getName(), cls) != null) { + throw new IllegalArgumentException("Class " + cls.getName() + " is already defined"); + } + } + + private ClassReader findClass(String name) { + ClassReader cls = innerSource.get(name); + if (cls == null) { + cls = generatedClasses.get(name); + } + return cls; + } + + public Collection getGeneratedClasses() { + return generatedClasses.values(); + } +} diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyInfo.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyInfo.java index f941bf4ad..bfed04ecd 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyInfo.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyInfo.java @@ -16,6 +16,7 @@ package org.teavm.dependency; import java.util.Collection; +import org.teavm.model.ClassHolder; import org.teavm.model.FieldReference; import org.teavm.model.MethodReference; @@ -24,6 +25,8 @@ import org.teavm.model.MethodReference; * @author Alexey Andreev */ public interface DependencyInfo { + boolean isMethodAchievable(MethodReference methodRef); + Collection getAchievableMethods(); Collection getAchievableFields(); @@ -33,4 +36,6 @@ public interface DependencyInfo { FieldDependencyInfo getField(FieldReference fieldRef); MethodDependencyInfo getMethod(MethodReference methodRef); + + Collection getGeneratedClasses(); } diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyListener.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyListener.java index 1ad57dee1..a662d129d 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyListener.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyListener.java @@ -20,11 +20,11 @@ package org.teavm.dependency; * @author Alexey Andreev */ public interface DependencyListener { - void started(DependencyChecker dependencyChecker); + void started(DependencyAgent agent); - void classAchieved(DependencyChecker dependencyChecker, String className); + void classAchieved(DependencyAgent agent, String className); - void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method); + void methodAchieved(DependencyAgent agent, MethodDependency method); - void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field); + void fieldAchieved(DependencyAgent agent, FieldDependency field); } diff --git a/teavm-core/src/main/java/org/teavm/dependency/Linker.java b/teavm-core/src/main/java/org/teavm/dependency/Linker.java index 583eb29f2..75815b4ad 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/Linker.java +++ b/teavm-core/src/main/java/org/teavm/dependency/Linker.java @@ -36,30 +36,38 @@ public class Linker { for (String className : dependency.getAchievableClasses()) { ClassHolder classHolder = classes.get(className); cutClasses.putClassHolder(classHolder); - for (MethodHolder method : classHolder.getMethods().toArray(new MethodHolder[0])) { - MethodReference methodRef = new MethodReference(className, method.getDescriptor()); - MethodDependencyInfo methodDep = dependency.getMethod(methodRef); - if (methodDep == null) { - classHolder.removeMethod(method); - } else if (!methodDep.isUsed()) { - method.getModifiers().add(ElementModifier.ABSTRACT); - method.setProgram(null); - } else if (method.getProgram() != null) { - link(method); - } - } - for (FieldHolder field : classHolder.getFields().toArray(new FieldHolder[0])) { - FieldReference fieldRef = new FieldReference(className, field.getName()); - if (dependency.getField(fieldRef) == null) { - classHolder.removeField(field); - } - } + link(classHolder); + } + for (ClassHolder generatedClass : dependency.getGeneratedClasses()) { + cutClasses.putClassHolder(generatedClass); + link(generatedClass); } return cutClasses; } - public void link(MethodHolder cls) { - Program program = cls.getProgram(); + public void link(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(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); + } + } + } + + public void link(MethodHolder method) { + Program program = method.getProgram(); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); for (Instruction insn : block.getInstructions()) { diff --git a/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java b/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java index e55785a95..593360e11 100644 --- a/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java +++ b/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java @@ -15,7 +15,6 @@ */ package org.teavm.model; - /** * * @author Alexey Andreev diff --git a/teavm-core/src/main/java/org/teavm/model/CopyClassHolderSource.java b/teavm-core/src/main/java/org/teavm/model/CopyClassHolderSource.java index 0fb83fda2..d7091392b 100644 --- a/teavm-core/src/main/java/org/teavm/model/CopyClassHolderSource.java +++ b/teavm-core/src/main/java/org/teavm/model/CopyClassHolderSource.java @@ -15,11 +15,8 @@ */ package org.teavm.model; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; import org.teavm.common.Mapper; -import org.teavm.model.util.ProgramUtils; +import org.teavm.model.util.ModelUtils; import org.teavm.resource.MapperClassHolderSource; /** @@ -48,68 +45,6 @@ public class CopyClassHolderSource implements ClassHolderSource { if (original == null) { return null; } - ClassHolder copy = new ClassHolder(className); - copy.setLevel(original.getLevel()); - copy.getModifiers().addAll(original.getModifiers()); - copy.setParent(original.getParent()); - copy.getInterfaces().addAll(original.getInterfaces()); - for (MethodHolder method : original.getMethods()) { - copy.addMethod(copyMethod(method)); - } - for (FieldHolder field : original.getFields()) { - copy.addField(copyField(field)); - } - copy.setOwnerName(original.getOwnerName()); - copyAnnotations(original.getAnnotations(), copy.getAnnotations()); - return copy; - } - - private MethodHolder copyMethod(MethodHolder method) { - MethodHolder copy = new MethodHolder(method.getDescriptor()); - copy.setLevel(method.getLevel()); - copy.getModifiers().addAll(method.getModifiers()); - copy.setProgram(ProgramUtils.copy(method.getProgram())); - copyAnnotations(method.getAnnotations(), copy.getAnnotations()); - return copy; - } - - private FieldHolder copyField(FieldHolder field) { - FieldHolder copy = new FieldHolder(field.getName()); - copy.setLevel(field.getLevel()); - copy.getModifiers().addAll(field.getModifiers()); - copy.setType(field.getType()); - copy.setInitialValue(field.getInitialValue()); - copyAnnotations(field.getAnnotations(), copy.getAnnotations()); - return copy; - } - - private void copyAnnotations(AnnotationContainer src, AnnotationContainer dst) { - for (AnnotationHolder annot : src.all()) { - dst.add(copyAnnotation(annot)); - } - } - - private AnnotationHolder copyAnnotation(AnnotationHolder annot) { - AnnotationHolder copy = new AnnotationHolder(annot.getType()); - for (Map.Entry entry : annot.getValues().entrySet()) { - copy.getValues().put(entry.getKey(), copyAnnotationValue(entry.getValue())); - } - return copy; - } - - private AnnotationValue copyAnnotationValue(AnnotationValue value) { - switch (value.getType()) { - case AnnotationValue.LIST: { - List listCopy = new ArrayList<>(); - for (AnnotationValue item : value.getList()) { - listCopy.add(copyAnnotationValue(item)); - } - return new AnnotationValue(listCopy); - } - case AnnotationValue.ANNOTATION: - return new AnnotationValue(copyAnnotation(value.getAnnotation())); - default: - return value; - } + return ModelUtils.copyClass(original); } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/ModelUtils.java b/teavm-core/src/main/java/org/teavm/model/util/ModelUtils.java new file mode 100644 index 000000000..3b0cc8017 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/util/ModelUtils.java @@ -0,0 +1,81 @@ +package org.teavm.model.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.teavm.model.*; + +/** + * + * @author Alexey Andreev + */ +public final class ModelUtils { + private ModelUtils() { + } + + public static ClassHolder copyClass(ClassHolder original) { + ClassHolder copy = new ClassHolder(original.getName()); + copy.setLevel(original.getLevel()); + copy.getModifiers().addAll(original.getModifiers()); + copy.setParent(original.getParent()); + copy.getInterfaces().addAll(original.getInterfaces()); + for (MethodHolder method : original.getMethods()) { + copy.addMethod(copyMethod(method)); + } + for (FieldHolder field : original.getFields()) { + copy.addField(copyField(field)); + } + copy.setOwnerName(original.getOwnerName()); + copyAnnotations(original.getAnnotations(), copy.getAnnotations()); + return copy; + } + + public static MethodHolder copyMethod(MethodHolder method) { + MethodHolder copy = new MethodHolder(method.getDescriptor()); + copy.setLevel(method.getLevel()); + copy.getModifiers().addAll(method.getModifiers()); + copy.setProgram(ProgramUtils.copy(method.getProgram())); + copyAnnotations(method.getAnnotations(), copy.getAnnotations()); + return copy; + } + + public static FieldHolder copyField(FieldHolder field) { + FieldHolder copy = new FieldHolder(field.getName()); + copy.setLevel(field.getLevel()); + copy.getModifiers().addAll(field.getModifiers()); + copy.setType(field.getType()); + copy.setInitialValue(field.getInitialValue()); + copyAnnotations(field.getAnnotations(), copy.getAnnotations()); + return copy; + } + + private static void copyAnnotations(AnnotationContainer src, AnnotationContainer dst) { + for (AnnotationHolder annot : src.all()) { + dst.add(copyAnnotation(annot)); + } + } + + private static AnnotationHolder copyAnnotation(AnnotationHolder annot) { + AnnotationHolder copy = new AnnotationHolder(annot.getType()); + for (Map.Entry entry : annot.getValues().entrySet()) { + copy.getValues().put(entry.getKey(), copyAnnotationValue(entry.getValue())); + } + return copy; + } + + private static AnnotationValue copyAnnotationValue(AnnotationValue value) { + switch (value.getType()) { + case AnnotationValue.LIST: { + List listCopy = new ArrayList<>(); + for (AnnotationValue item : value.getList()) { + listCopy.add(copyAnnotationValue(item)); + } + return new AnnotationValue(listCopy); + } + case AnnotationValue.ANNOTATION: + return new AnnotationValue(copyAnnotation(value.getAnnotation())); + default: + return value; + } + } +} diff --git a/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java b/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java index c49f852de..9058d08c6 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java +++ b/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java @@ -15,6 +15,7 @@ */ package org.teavm.model.util; +import java.util.List; import org.teavm.common.Graph; import org.teavm.common.GraphBuilder; import org.teavm.model.*; @@ -67,9 +68,9 @@ public final class ProgramUtils { return graphBuilder.build(); } - public static Program copy(Program program) { + public static Program copy(ProgramReader program) { Program copy = new Program(); - CopyVisitor insnCopier = new CopyVisitor(); + InstructionCopyReader insnCopier = new InstructionCopyReader(); insnCopier.programCopy = copy; for (int i = 0; i < program.variableCount(); ++i) { copy.createVariable(); @@ -78,16 +79,16 @@ public final class ProgramUtils { copy.createBasicBlock(); } for (int i = 0; i < program.basicBlockCount(); ++i) { - BasicBlock block = program.basicBlockAt(i); + BasicBlockReader block = program.basicBlockAt(i); BasicBlock blockCopy = copy.basicBlockAt(i); - for (Instruction insn : block.getInstructions()) { - insn.acceptVisitor(insnCopier); + for (int j = 0; j < block.instructionCount(); ++j) { + block.readInstruction(j, insnCopier); blockCopy.getInstructions().add(insnCopier.copy); } - for (Phi phi : block.getPhis()) { + for (PhiReader phi : block.readPhis()) { Phi phiCopy = new Phi(); phiCopy.setReceiver(copy.variableAt(phi.getReceiver().getIndex())); - for (Incoming incoming : phi.getIncomings()) { + for (IncomingReader incoming : phi.readIncomings()) { Incoming incomingCopy = new Incoming(); incomingCopy.setSource(copy.basicBlockAt(incoming.getSource().getIndex())); incomingCopy.setValue(copy.variableAt(incoming.getValue().getIndex())); @@ -95,7 +96,7 @@ public final class ProgramUtils { } blockCopy.getPhis().add(phiCopy); } - for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { TryCatchBlock tryCatchCopy = new TryCatchBlock(); tryCatchCopy.setExceptionType(tryCatch.getExceptionType()); tryCatchCopy.setExceptionVariable(copy.variableAt(tryCatch.getExceptionVariable().getIndex())); @@ -106,160 +107,166 @@ public final class ProgramUtils { return copy; } - private static class CopyVisitor implements InstructionVisitor { + private static class InstructionCopyReader implements InstructionReader { Instruction copy; Program programCopy; - @Override - public void visit(EmptyInstruction insn) { - copy = new EmptyInstruction(); - } - - private Variable copyVar(Variable var) { + private Variable copyVar(VariableReader var) { return programCopy.variableAt(var.getIndex()); } - private BasicBlock copyBlock(BasicBlock block) { + private BasicBlock copyBlock(BasicBlockReader block) { return programCopy.basicBlockAt(block.getIndex()); } @Override - public void visit(ClassConstantInstruction insn) { + public void nop() { + copy = new EmptyInstruction(); + } + + @Override + public void classConstant(VariableReader receiver, ValueType cst) { ClassConstantInstruction insnCopy = new ClassConstantInstruction(); - insnCopy.setConstant(insn.getConstant()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setConstant(cst); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(NullConstantInstruction insn) { + public void nullConstant(VariableReader receiver) { NullConstantInstruction insnCopy = new NullConstantInstruction(); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(IntegerConstantInstruction insn) { + public void integerConstant(VariableReader receiver, int cst) { IntegerConstantInstruction insnCopy = new IntegerConstantInstruction(); - insnCopy.setConstant(insn.getConstant()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setConstant(cst); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(LongConstantInstruction insn) { + public void longConstant(VariableReader receiver, long cst) { LongConstantInstruction insnCopy = new LongConstantInstruction(); - insnCopy.setConstant(insn.getConstant()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setConstant(cst); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(FloatConstantInstruction insn) { + public void floatConstant(VariableReader receiver, float cst) { FloatConstantInstruction insnCopy = new FloatConstantInstruction(); - insnCopy.setConstant(insn.getConstant()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setConstant(cst); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(DoubleConstantInstruction insn) { + public void doubleConstant(VariableReader receiver, double cst) { DoubleConstantInstruction insnCopy = new DoubleConstantInstruction(); - insnCopy.setConstant(insn.getConstant()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setConstant(cst); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(StringConstantInstruction insn) { + public void stringConstant(VariableReader receiver, String cst) { StringConstantInstruction insnCopy = new StringConstantInstruction(); - insnCopy.setConstant(insn.getConstant()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setConstant(cst); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(BinaryInstruction insn) { - BinaryInstruction insnCopy = new BinaryInstruction(insn.getOperation(), insn.getOperandType()); - insnCopy.setFirstOperand(copyVar(insn.getFirstOperand())); - insnCopy.setSecondOperand(copyVar(insn.getSecondOperand())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + public void binary(BinaryOperation op, VariableReader receiver, VariableReader first, VariableReader second, + NumericOperandType type) { + BinaryInstruction insnCopy = new BinaryInstruction(op, type); + insnCopy.setFirstOperand(copyVar(first)); + insnCopy.setSecondOperand(copyVar(second)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(NegateInstruction insn) { - NegateInstruction insnCopy = new NegateInstruction(insn.getOperandType()); - insnCopy.setOperand(copyVar(insn.getOperand())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) { + NegateInstruction insnCopy = new NegateInstruction(type); + insnCopy.setOperand(copyVar(operand)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(AssignInstruction insn) { + public void assign(VariableReader receiver, VariableReader assignee) { AssignInstruction insnCopy = new AssignInstruction(); - insnCopy.setAssignee(copyVar(insn.getAssignee())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setAssignee(copyVar(assignee)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(CastInstruction insn) { + public void cast(VariableReader receiver, VariableReader value, ValueType targetType) { CastInstruction insnCopy = new CastInstruction(); - insnCopy.setValue(copyVar(insn.getValue())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); - insnCopy.setTargetType(insn.getTargetType()); + insnCopy.setValue(copyVar(value)); + insnCopy.setReceiver(copyVar(receiver)); + insnCopy.setTargetType(targetType); copy = insnCopy; } @Override - public void visit(CastNumberInstruction insn) { - CastNumberInstruction insnCopy = new CastNumberInstruction(insn.getSourceType(), insn.getTargetType()); - insnCopy.setValue(copyVar(insn.getValue())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + public void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType, + NumericOperandType targetType) { + CastNumberInstruction insnCopy = new CastNumberInstruction(sourceType, targetType); + insnCopy.setValue(copyVar(value)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(CastIntegerInstruction insn) { - CastIntegerInstruction insnCopy = new CastIntegerInstruction(insn.getTargetType(), insn.getDirection()); - insnCopy.setValue(copyVar(insn.getValue())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + public void cast(VariableReader receiver, VariableReader value, IntegerSubtype type, + CastIntegerDirection dir) { + CastIntegerInstruction insnCopy = new CastIntegerInstruction(type, dir); + insnCopy.setValue(copyVar(value)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(BranchingInstruction insn) { - BranchingInstruction insnCopy = new BranchingInstruction(insn.getCondition()); - insnCopy.setOperand(copyVar(insn.getOperand())); - insnCopy.setConsequent(copyBlock(insn.getConsequent())); - insnCopy.setAlternative(copyBlock(insn.getAlternative())); + public void jumpIf(BranchingCondition cond, VariableReader operand, BasicBlockReader consequent, + BasicBlockReader alternative) { + BranchingInstruction insnCopy = new BranchingInstruction(cond); + insnCopy.setOperand(copyVar(operand)); + insnCopy.setConsequent(copyBlock(consequent)); + insnCopy.setAlternative(copyBlock(alternative)); copy = insnCopy; } @Override - public void visit(BinaryBranchingInstruction insn) { - BinaryBranchingInstruction insnCopy = new BinaryBranchingInstruction(insn.getCondition()); - insnCopy.setFirstOperand(copyVar(insn.getFirstOperand())); - insnCopy.setSecondOperand(copyVar(insn.getSecondOperand())); - insnCopy.setConsequent(copyBlock(insn.getConsequent())); - insnCopy.setAlternative(copyBlock(insn.getAlternative())); + public void jumpIf(BinaryBranchingCondition cond, VariableReader first, VariableReader second, + BasicBlockReader consequent, BasicBlockReader alternative) { + BinaryBranchingInstruction insnCopy = new BinaryBranchingInstruction(cond); + insnCopy.setFirstOperand(copyVar(first)); + insnCopy.setSecondOperand(copyVar(second)); + insnCopy.setConsequent(copyBlock(consequent)); + insnCopy.setAlternative(copyBlock(alternative)); copy = insnCopy; } @Override - public void visit(JumpInstruction insn) { + public void jump(BasicBlockReader target) { JumpInstruction insnCopy = new JumpInstruction(); - insnCopy.setTarget(copyBlock(insn.getTarget())); + insnCopy.setTarget(copyBlock(target)); copy = insnCopy; } @Override - public void visit(SwitchInstruction insn) { + public void choose(VariableReader condition, List table, + BasicBlockReader defaultTarget) { SwitchInstruction insnCopy = new SwitchInstruction(); - insnCopy.setCondition(copyVar(insn.getCondition())); - insnCopy.setDefaultTarget(copyBlock(insn.getDefaultTarget())); - for (SwitchTableEntry entry : insn.getEntries()) { + insnCopy.setCondition(copyVar(condition)); + insnCopy.setDefaultTarget(copyBlock(defaultTarget)); + for (SwitchTableEntryReader entry : table) { SwitchTableEntry entryCopy = new SwitchTableEntry(); entryCopy.setCondition(entry.getCondition()); entryCopy.setTarget(copyBlock(entry.getTarget())); @@ -269,143 +276,147 @@ public final class ProgramUtils { } @Override - public void visit(ExitInstruction insn) { + public void exit(VariableReader valueToReturn) { ExitInstruction insnCopy = new ExitInstruction(); - insnCopy.setValueToReturn(insn.getValueToReturn() != null ? copyVar(insn.getValueToReturn()) : null); + insnCopy.setValueToReturn(valueToReturn != null ? copyVar(valueToReturn) : null); copy = insnCopy; } @Override - public void visit(RaiseInstruction insn) { + public void raise(VariableReader exception) { RaiseInstruction insnCopy = new RaiseInstruction(); - insnCopy.setException(copyVar(insn.getException())); + insnCopy.setException(copyVar(exception)); copy = insnCopy; } @Override - public void visit(ConstructArrayInstruction insn) { + public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) { ConstructArrayInstruction insnCopy = new ConstructArrayInstruction(); - insnCopy.setItemType(insn.getItemType()); - insnCopy.setSize(copyVar(insn.getSize())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setItemType(itemType); + insnCopy.setSize(copyVar(size)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(ConstructInstruction insn) { - ConstructInstruction insnCopy = new ConstructInstruction(); - insnCopy.setType(insn.getType()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); - copy = insnCopy; - } - - @Override - public void visit(ConstructMultiArrayInstruction insn) { + public void createArray(VariableReader receiver, ValueType itemType, + List dimensions) { ConstructMultiArrayInstruction insnCopy = new ConstructMultiArrayInstruction(); - insnCopy.setItemType(insn.getItemType()); - insnCopy.setReceiver(copyVar(insn.getReceiver())); - for (Variable dim : insn.getDimensions()) { + insnCopy.setItemType(itemType); + insnCopy.setReceiver(copyVar(receiver)); + for (VariableReader dim : dimensions) { insnCopy.getDimensions().add(copyVar(dim)); } copy = insnCopy; } @Override - public void visit(GetFieldInstruction insn) { + public void create(VariableReader receiver, String type) { + ConstructInstruction insnCopy = new ConstructInstruction(); + insnCopy.setType(type); + insnCopy.setReceiver(copyVar(receiver)); + copy = insnCopy; + } + + @Override + public void getField(VariableReader receiver, VariableReader instance, FieldReference field, + ValueType fieldType) { GetFieldInstruction insnCopy = new GetFieldInstruction(); - insnCopy.setField(insn.getField()); - insnCopy.setFieldType(insn.getFieldType()); - insnCopy.setInstance(insn.getInstance() != null ? copyVar(insn.getInstance()) : null); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setField(field); + insnCopy.setFieldType(fieldType); + insnCopy.setInstance(instance != null ? copyVar(instance) : null); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(PutFieldInstruction insn) { + public void putField(VariableReader instance, FieldReference field, VariableReader value) { PutFieldInstruction insnCopy = new PutFieldInstruction(); - insnCopy.setField(insn.getField()); - insnCopy.setInstance(insn.getInstance() != null ? copyVar(insn.getInstance()) : null); - insnCopy.setValue(copyVar(insn.getValue())); + insnCopy.setField(field); + insnCopy.setInstance(instance != null ? copyVar(instance) : null); + insnCopy.setValue(copyVar(value)); copy = insnCopy; } @Override - public void visit(ArrayLengthInstruction insn) { + public void arrayLength(VariableReader receiver, VariableReader array) { ArrayLengthInstruction insnCopy = new ArrayLengthInstruction(); - insnCopy.setArray(copyVar(insn.getArray())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setArray(copyVar(array)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(CloneArrayInstruction insn) { + public void cloneArray(VariableReader receiver, VariableReader array) { CloneArrayInstruction insnCopy = new CloneArrayInstruction(); - insnCopy.setArray(copyVar(insn.getArray())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + insnCopy.setArray(copyVar(array)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(UnwrapArrayInstruction insn) { - UnwrapArrayInstruction insnCopy = new UnwrapArrayInstruction(insn.getElementType()); - insnCopy.setArray(copyVar(insn.getArray())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); + public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) { + UnwrapArrayInstruction insnCopy = new UnwrapArrayInstruction(elementType); + insnCopy.setArray(copyVar(array)); + insnCopy.setReceiver(copyVar(receiver)); copy = insnCopy; } @Override - public void visit(GetElementInstruction insn) { + public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { GetElementInstruction insnCopy = new GetElementInstruction(); - insnCopy.setArray(copyVar(insn.getArray())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); - insnCopy.setIndex(copyVar(insn.getIndex())); + insnCopy.setArray(copyVar(array)); + insnCopy.setReceiver(copyVar(receiver)); + insnCopy.setIndex(copyVar(index)); copy = insnCopy; } @Override - public void visit(PutElementInstruction insn) { + public void putElement(VariableReader array, VariableReader index, VariableReader value) { PutElementInstruction insnCopy = new PutElementInstruction(); - insnCopy.setArray(copyVar(insn.getArray())); - insnCopy.setValue(copyVar(insn.getValue())); - insnCopy.setIndex(copyVar(insn.getIndex())); + insnCopy.setArray(copyVar(array)); + insnCopy.setValue(copyVar(value)); + insnCopy.setIndex(copyVar(index)); copy = insnCopy; } @Override - public void visit(InvokeInstruction insn) { + public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, + List arguments, InvocationType type) { InvokeInstruction insnCopy = new InvokeInstruction(); - insnCopy.setMethod(insn.getMethod()); - insnCopy.setType(insn.getType()); - insnCopy.setInstance(insn.getInstance() != null ? copyVar(insn.getInstance()) : null); - insnCopy.setReceiver(insn.getReceiver() != null ? copyVar(insn.getReceiver()) : null); - for (Variable arg : insn.getArguments()) { + insnCopy.setMethod(method); + insnCopy.setType(type); + insnCopy.setInstance(instance != null ? copyVar(instance) : null); + insnCopy.setReceiver(receiver != null ? copyVar(receiver) : null); + for (VariableReader arg : arguments) { insnCopy.getArguments().add(copyVar(arg)); } copy = insnCopy; } @Override - public void visit(IsInstanceInstruction insn) { + public void isInstance(VariableReader receiver, VariableReader value, ValueType type) { IsInstanceInstruction insnCopy = new IsInstanceInstruction(); - insnCopy.setValue(copyVar(insn.getValue())); - insnCopy.setReceiver(copyVar(insn.getReceiver())); - insnCopy.setType(insn.getType()); + insnCopy.setValue(copyVar(value)); + insnCopy.setReceiver(copyVar(receiver)); + insnCopy.setType(type); copy = insnCopy; } @Override - public void visit(InitClassInstruction insn) { + public void initClass(String className) { InitClassInstruction insnCopy = new InitClassInstruction(); - insnCopy.setClassName(insn.getClassName()); + insnCopy.setClassName(className); copy = insnCopy; } @Override - public void visit(NullCheckInstruction insn) { + public void nullCheck(VariableReader receiver, VariableReader value) { NullCheckInstruction insnCopy = new NullCheckInstruction(); - insnCopy.setReceiver(copyVar(insn.getReceiver())); - insnCopy.setValue(copyVar(insn.getValue())); + insnCopy.setReceiver(copyVar(receiver)); + insnCopy.setValue(copyVar(value)); copy = insnCopy; } + } } diff --git a/teavm-core/src/main/java/org/teavm/vm/JavascriptProcessedClassSource.java b/teavm-core/src/main/java/org/teavm/vm/JavascriptProcessedClassSource.java index b54e56ed3..a775e28a3 100644 --- a/teavm-core/src/main/java/org/teavm/vm/JavascriptProcessedClassSource.java +++ b/teavm-core/src/main/java/org/teavm/vm/JavascriptProcessedClassSource.java @@ -17,6 +17,7 @@ package org.teavm.vm; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; import org.teavm.common.ConcurrentCachedMapper; import org.teavm.common.Mapper; import org.teavm.model.ClassHolder; diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index 5db617e44..03d908c6c 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -93,7 +93,6 @@ public class TeaVM implements TeaVMHost { classSource.addTransformer(transformer); } - @Override public void add(MethodReference methodRef, Generator generator) { methodGenerators.put(methodRef, generator); diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/EntryPointGenerator.java b/teavm-html4j/src/main/java/org/teavm/html4j/EntryPointGenerator.java index 123fb9d4f..b6cfc9256 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/EntryPointGenerator.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/EntryPointGenerator.java @@ -67,21 +67,21 @@ public class EntryPointGenerator extends AbstractRendererListener implements Dep } @Override - public void started(DependencyChecker dependencyChecker) { + public void started(DependencyAgent agent) { for (String className : classesToLoad) { - dependencyChecker.initClass(className, DependencyStack.ROOT); + agent.initClass(className, DependencyStack.ROOT); } } @Override - public void classAchieved(DependencyChecker dependencyChecker, String className) { + public void classAchieved(DependencyAgent agent, String className) { } @Override - public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) { + public void methodAchieved(DependencyAgent agent, MethodDependency method) { } @Override - public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) { + public void fieldAchieved(DependencyAgent agent, FieldDependency field) { } } diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java index 4ca4f5bb3..a64d8b4d7 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java @@ -27,8 +27,8 @@ public class JavaScriptBodyDependency implements DependencyListener { private DependencyNode allClassesNode; @Override - public void started(DependencyChecker dependencyChecker) { - allClassesNode = dependencyChecker.createNode(); + public void started(DependencyAgent agent) { + allClassesNode = agent.createNode(); allClassesNode.setTag("JavaScriptBody:global"); } @@ -43,8 +43,8 @@ public class JavaScriptBodyDependency implements DependencyListener { } @Override - public void classAchieved(DependencyChecker dependencyChecker, String className) { - ClassReader cls = dependencyChecker.getClassSource().get(className); + public void classAchieved(DependencyAgent agent, String className) { + ClassReader cls = agent.getClassSource().get(className); if (cls != null && !cls.hasModifier(ElementModifier.ABSTRACT) && !cls.hasModifier(ElementModifier.INTERFACE)) { allClassesNode.propagate(className); @@ -52,13 +52,13 @@ public class JavaScriptBodyDependency implements DependencyListener { } @Override - public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) { + public void methodAchieved(DependencyAgent agent, MethodDependency method) { if (method.isMissing()) { return; } AnnotationReader annot = method.getMethod().getAnnotations().get(JavaScriptBody.class.getName()); if (annot != null) { - includeDefaultDependencies(dependencyChecker); + includeDefaultDependencies(agent); AnnotationValue javacall = annot.getValue("javacall"); if (method.getResult() != null) { allClassesNode.connect(method.getResult()); @@ -74,26 +74,26 @@ public class JavaScriptBodyDependency implements DependencyListener { } if (javacall != null && javacall.getBoolean()) { String body = annot.getValue("body").getString(); - new GeneratorJsCallback(dependencyChecker, method).parse(body); + new GeneratorJsCallback(agent, method).parse(body); } } } - private void includeDefaultDependencies(DependencyChecker dependencyChecker) { - dependencyChecker.linkMethod(JavaScriptConvGenerator.fromJsMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.toJsMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.intValueMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.booleanValueMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.doubleValueMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.charValueMethod, DependencyStack.ROOT).use(); - dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, DependencyStack.ROOT).use(); + private void includeDefaultDependencies(DependencyAgent agent) { + agent.linkMethod(JavaScriptConvGenerator.fromJsMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.toJsMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.intValueMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.charValueMethod, DependencyStack.ROOT).use(); + agent.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, DependencyStack.ROOT).use(); } @Override - public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency fieldDep) { + public void fieldAchieved(DependencyAgent agent, FieldDependency fieldDep) { } private static MethodReader findMethod(ClassReaderSource classSource, String clsName, MethodDescriptor desc) { @@ -124,17 +124,17 @@ public class JavaScriptBodyDependency implements DependencyListener { } private class GeneratorJsCallback extends JsCallback { - private DependencyChecker dependencyChecker; + private DependencyAgent agent; private MethodDependency caller; - public GeneratorJsCallback(DependencyChecker dependencyChecker, MethodDependency caller) { - this.dependencyChecker = dependencyChecker; + public GeneratorJsCallback(DependencyAgent agent, MethodDependency caller) { + this.agent = agent; this.caller = caller; } @Override protected CharSequence callMethod(String ident, String fqn, String method, String params) { MethodDescriptor desc = MethodDescriptor.parse(method + params + "V"); - MethodReader reader = findMethod(dependencyChecker.getClassSource(), fqn, desc); + MethodReader reader = findMethod(agent.getClassSource(), fqn, desc); MethodReference ref = reader != null ? reader.getReference() : new MethodReference(fqn, desc); - MethodDependency methodDep = dependencyChecker.linkMethod(ref, caller.getStack()); + MethodDependency methodDep = agent.linkMethod(ref, caller.getStack()); if (!methodDep.isMissing()) { if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) { methodDep.use(); @@ -142,7 +142,7 @@ public class JavaScriptBodyDependency implements DependencyListener { allClassesNode.connect(methodDep.getVariable(i)); } } else { - allClassesNode.addConsumer(new VirtualCallbackConsumer(dependencyChecker, reader, caller)); + allClassesNode.addConsumer(new VirtualCallbackConsumer(agent, reader, caller)); } } return ""; @@ -150,30 +150,30 @@ public class JavaScriptBodyDependency implements DependencyListener { } private class VirtualCallbackConsumer implements DependencyConsumer { - private DependencyChecker dependencyChecker; + private DependencyAgent agent; private MethodReader superMethod; private ClassReader superClass; private MethodDependency caller; - public VirtualCallbackConsumer(DependencyChecker dependencyChecker, MethodReader superMethod, + public VirtualCallbackConsumer(DependencyAgent agent, MethodReader superMethod, MethodDependency caller) { - this.dependencyChecker = dependencyChecker; + this.agent = agent; this.superMethod = superMethod; this.caller = caller; - this.superClass = dependencyChecker.getClassSource().get(superMethod.getOwnerName()); + this.superClass = agent.getClassSource().get(superMethod.getOwnerName()); } @Override public void consume(String type) { if (!isAssignableFrom(superClass, type)) { return; } MethodReference methodRef = new MethodReference(type, superMethod.getDescriptor()); - MethodDependency method = dependencyChecker.linkMethod(methodRef, caller.getStack()); + MethodDependency method = agent.linkMethod(methodRef, caller.getStack()); method.use(); for (int i = 0; i < method.getParameterCount(); ++i) { allClassesNode.connect(method.getVariable(i)); } } private boolean isAssignableFrom(ClassReader supertype, String subtypeName) { - ClassReaderSource classSource = dependencyChecker.getClassSource(); + ClassReaderSource classSource = agent.getClassSource(); if (supertype.getName().equals(subtypeName)) { return true; } diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/TestExceptionDependency.java b/teavm-maven-plugin/src/main/java/org/teavm/maven/TestExceptionDependency.java index 46a60158d..7fad5ec08 100644 --- a/teavm-maven-plugin/src/main/java/org/teavm/maven/TestExceptionDependency.java +++ b/teavm-maven-plugin/src/main/java/org/teavm/maven/TestExceptionDependency.java @@ -31,13 +31,13 @@ class TestExceptionDependency implements DependencyListener { private DependencyNode allClasses; @Override - public void started(DependencyChecker dependencyChecker) { - allClasses = dependencyChecker.createNode(); + public void started(DependencyAgent agent) { + allClasses = agent.createNode(); } @Override - public void classAchieved(DependencyChecker dependencyChecker, String className) { - if (isException(dependencyChecker.getClassSource(), className)) { + public void classAchieved(DependencyAgent agent, String className) { + if (isException(agent.getClassSource(), className)) { allClasses.propagate(className); } } @@ -57,13 +57,13 @@ class TestExceptionDependency implements DependencyListener { } @Override - public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) { + public void methodAchieved(DependencyAgent agent, MethodDependency method) { if (method.getReference().equals(getMessageRef)) { allClasses.connect(method.getVariable(0)); } } @Override - public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) { + public void fieldAchieved(DependencyAgent agent, FieldDependency field) { } }