mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
First attempt to refactor dependency checker
This commit is contained in:
parent
8286ad9289
commit
00d160e92b
|
@ -26,29 +26,29 @@ public class ClassLookupDependencySupport implements DependencyListener {
|
||||||
private DependencyNode allClasses;
|
private DependencyNode allClasses;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyAgent agent) {
|
||||||
allClasses = dependencyChecker.createNode();
|
allClasses = agent.createNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
allClasses.propagate(className);
|
allClasses.propagate(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
if (ref.getClassName().equals("java.lang.Class") && ref.getName().equals("forNameImpl")) {
|
if (ref.getClassName().equals("java.lang.Class") && ref.getName().equals("forNameImpl")) {
|
||||||
final DependencyStack stack = method.getStack();
|
final DependencyStack stack = method.getStack();
|
||||||
allClasses.addConsumer(new DependencyConsumer() {
|
allClasses.addConsumer(new DependencyConsumer() {
|
||||||
@Override public void consume(String type) {
|
@Override public void consume(String type) {
|
||||||
ClassReader cls = dependencyChecker.getClassSource().get(type);
|
ClassReader cls = agent.getClassSource().get(type);
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MethodReader initMethod = cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID));
|
MethodReader initMethod = cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID));
|
||||||
if (initMethod != null) {
|
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
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
public void fieldAchieved(DependencyAgent dependencyChecker, FieldDependency field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,13 @@ public class EnumDependencySupport implements DependencyListener {
|
||||||
private volatile DependencyStack enumConstantsStack;
|
private volatile DependencyStack enumConstantsStack;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyAgent agent) {
|
||||||
allEnums = dependencyChecker.createNode();
|
allEnums = agent.createNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
ClassReader cls = dependencyChecker.getClassSource().get(className);
|
ClassReader cls = agent.getClassSource().get(className);
|
||||||
if (cls == null || cls.getParent() == null || !cls.getParent().equals("java.lang.Enum")) {
|
if (cls == null || cls.getParent() == null || !cls.getParent().equals("java.lang.Enum")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -45,25 +45,25 @@ public class EnumDependencySupport implements DependencyListener {
|
||||||
MethodReader method = cls.getMethod(new MethodDescriptor("values",
|
MethodReader method = cls.getMethod(new MethodDescriptor("values",
|
||||||
ValueType.arrayOf(ValueType.object(cls.getName()))));
|
ValueType.arrayOf(ValueType.object(cls.getName()))));
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
dependencyChecker.linkMethod(method.getReference(), enumConstantsStack).use();
|
agent.linkMethod(method.getReference(), enumConstantsStack).use();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||||
if (method.getReference().getClassName().equals("java.lang.Class") &&
|
if (method.getReference().getClassName().equals("java.lang.Class") &&
|
||||||
method.getReference().getName().equals("getEnumConstantsImpl")) {
|
method.getReference().getName().equals("getEnumConstantsImpl")) {
|
||||||
allEnums.connect(method.getResult().getArrayItem());
|
allEnums.connect(method.getResult().getArrayItem());
|
||||||
method.getResult().propagate("[java.lang.Enum");
|
method.getResult().propagate("[java.lang.Enum");
|
||||||
enumConstantsStack = method.getStack();
|
enumConstantsStack = method.getStack();
|
||||||
for (String cls : dependencyChecker.getAchievableClasses()) {
|
for (String cls : agent.getAchievableClasses()) {
|
||||||
classAchieved(dependencyChecker, cls);
|
classAchieved(agent, cls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,13 @@ public class NewInstanceDependencySupport implements DependencyListener {
|
||||||
private DependencyStack newInstanceStack;
|
private DependencyStack newInstanceStack;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyAgent agent) {
|
||||||
allClassesNode = dependencyChecker.createNode();
|
allClassesNode = agent.createNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
ClassReader cls = dependencyChecker.getClassSource().get(className);
|
ClassReader cls = agent.getClassSource().get(className);
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -47,25 +47,25 @@ public class NewInstanceDependencySupport implements DependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
|
||||||
MethodReader reader = method.getMethod();
|
MethodReader reader = method.getMethod();
|
||||||
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
|
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
|
||||||
newInstanceStack = method.getStack();
|
newInstanceStack = method.getStack();
|
||||||
allClassesNode.connect(method.getResult());
|
allClassesNode.connect(method.getResult());
|
||||||
method.getResult().addConsumer(new DependencyConsumer() {
|
method.getResult().addConsumer(new DependencyConsumer() {
|
||||||
@Override public void consume(String type) {
|
@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("<init>", ValueType.VOID));
|
MethodReference ref = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
|
||||||
checker.linkMethod(ref, newInstanceStack).use();
|
checker.linkMethod(ref, newInstanceStack).use();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
public void fieldAchieved(DependencyAgent dependencyAgent, FieldDependency field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,12 +78,12 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyAgent agent) {
|
||||||
allClassesNode = dependencyChecker.createNode();
|
allClassesNode = agent.createNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
try {
|
try {
|
||||||
Enumeration<URL> resources = classLoader.getResources("META-INF/services/" + className);
|
Enumeration<URL> resources = classLoader.getResources("META-INF/services/" + className);
|
||||||
while (resources.hasMoreElements()) {
|
while (resources.hasMoreElements()) {
|
||||||
|
@ -119,7 +119,7 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) {
|
if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) {
|
||||||
method.getResult().propagate("[java.lang.Object");
|
method.getResult().propagate("[java.lang.Object");
|
||||||
|
@ -127,18 +127,18 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
|
||||||
allClassesNode.connect(method.getResult().getArrayItem());
|
allClassesNode.connect(method.getResult().getArrayItem());
|
||||||
method.getResult().getArrayItem().addConsumer(new DependencyConsumer() {
|
method.getResult().getArrayItem().addConsumer(new DependencyConsumer() {
|
||||||
@Override public void consume(String type) {
|
@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("<init>", ValueType.VOID));
|
MethodReference ctor = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
|
||||||
dependencyChecker.linkMethod(ctor, stack).use();
|
agent.linkMethod(ctor, stack).use();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -22,15 +22,17 @@ import java.util.concurrent.ConcurrentMap;
|
||||||
import org.teavm.common.*;
|
import org.teavm.common.*;
|
||||||
import org.teavm.common.ConcurrentCachedMapper.KeyListener;
|
import org.teavm.common.ConcurrentCachedMapper.KeyListener;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.model.util.ModelUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class DependencyChecker implements DependencyInfo {
|
public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
||||||
private static Object dummyValue = new Object();
|
private static Object dummyValue = new Object();
|
||||||
static final boolean shouldLog = System.getProperty("org.teavm.logDependencies", "false").equals("true");
|
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 ClassLoader classLoader;
|
||||||
private FiniteExecutor executor;
|
private FiniteExecutor executor;
|
||||||
private Mapper<MethodReference, MethodReader> methodReaderCache;
|
private Mapper<MethodReference, MethodReader> methodReaderCache;
|
||||||
|
@ -47,12 +49,12 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>();
|
ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>();
|
||||||
ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>();
|
ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader) {
|
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
|
||||||
this(classSource, classLoader, new SimpleFiniteExecutor());
|
this(classSource, classLoader, new SimpleFiniteExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||||
this.classSource = classSource;
|
this.classSource = new DependencyClassSource(classSource);
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
methodReaderCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodReader>() {
|
methodReaderCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodReader>() {
|
||||||
|
@ -108,14 +110,26 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DependencyNode createNode() {
|
public DependencyNode createNode() {
|
||||||
return new DependencyNode(this);
|
return new DependencyNode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
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) {
|
public void addDependencyListener(DependencyListener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
listener.started(this);
|
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() {
|
executor.executeFast(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
consumer.consume(type);
|
consumer.consume(type);
|
||||||
|
@ -158,6 +172,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack) {
|
public MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack) {
|
||||||
if (methodRef == null) {
|
if (methodRef == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
@ -166,6 +181,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
return methodCache.map(methodRef);
|
return methodCache.map(methodRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void initClass(String className, final DependencyStack stack) {
|
public void initClass(String className, final DependencyStack stack) {
|
||||||
classStacks.putIfAbsent(className, stack);
|
classStacks.putIfAbsent(className, stack);
|
||||||
MethodDescriptor clinitDesc = new MethodDescriptor("<clinit>", ValueType.VOID);
|
MethodDescriptor clinitDesc = new MethodDescriptor("<clinit>", ValueType.VOID);
|
||||||
|
@ -302,6 +318,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
return dep;
|
return dep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isMethodAchievable(MethodReference methodRef) {
|
public boolean isMethodAchievable(MethodReference methodRef) {
|
||||||
return methodCache.caches(methodRef);
|
return methodCache.caches(methodRef);
|
||||||
}
|
}
|
||||||
|
@ -321,6 +338,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
return new HashSet<>(achievableClasses.keySet());
|
return new HashSet<>(achievableClasses.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public FieldDependency linkField(FieldReference fieldRef, DependencyStack stack) {
|
public FieldDependency linkField(FieldReference fieldRef, DependencyStack stack) {
|
||||||
fieldStacks.putIfAbsent(fieldRef, stack);
|
fieldStacks.putIfAbsent(fieldRef, stack);
|
||||||
return fieldCache.map(fieldRef);
|
return fieldCache.map(fieldRef);
|
||||||
|
@ -420,4 +438,14 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<ClassHolder> getGeneratedClasses() {
|
||||||
|
Collection<ClassHolder> classes = classSource.getGeneratedClasses();
|
||||||
|
List<ClassHolder> copies = new ArrayList<>(classes.size());
|
||||||
|
for (ClassHolder cls : classes) {
|
||||||
|
copies.add(ModelUtils.copyClass(cls));
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<String, ClassHolder> generatedClasses = new ConcurrentHashMap<>();
|
||||||
|
private ConcurrentCachedMapper<String, ClassReader> cache = new ConcurrentCachedMapper<>(
|
||||||
|
new Mapper<String, ClassReader>() {
|
||||||
|
@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<ClassHolder> getGeneratedClasses() {
|
||||||
|
return generatedClasses.values();
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
@ -24,6 +25,8 @@ import org.teavm.model.MethodReference;
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public interface DependencyInfo {
|
public interface DependencyInfo {
|
||||||
|
boolean isMethodAchievable(MethodReference methodRef);
|
||||||
|
|
||||||
Collection<MethodReference> getAchievableMethods();
|
Collection<MethodReference> getAchievableMethods();
|
||||||
|
|
||||||
Collection<FieldReference> getAchievableFields();
|
Collection<FieldReference> getAchievableFields();
|
||||||
|
@ -33,4 +36,6 @@ public interface DependencyInfo {
|
||||||
FieldDependencyInfo getField(FieldReference fieldRef);
|
FieldDependencyInfo getField(FieldReference fieldRef);
|
||||||
|
|
||||||
MethodDependencyInfo getMethod(MethodReference methodRef);
|
MethodDependencyInfo getMethod(MethodReference methodRef);
|
||||||
|
|
||||||
|
Collection<ClassHolder> getGeneratedClasses();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@ package org.teavm.dependency;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface DependencyListener {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,30 +36,38 @@ public class Linker {
|
||||||
for (String className : dependency.getAchievableClasses()) {
|
for (String className : dependency.getAchievableClasses()) {
|
||||||
ClassHolder classHolder = classes.get(className);
|
ClassHolder classHolder = classes.get(className);
|
||||||
cutClasses.putClassHolder(classHolder);
|
cutClasses.putClassHolder(classHolder);
|
||||||
for (MethodHolder method : classHolder.getMethods().toArray(new MethodHolder[0])) {
|
link(classHolder);
|
||||||
MethodReference methodRef = new MethodReference(className, method.getDescriptor());
|
}
|
||||||
MethodDependencyInfo methodDep = dependency.getMethod(methodRef);
|
for (ClassHolder generatedClass : dependency.getGeneratedClasses()) {
|
||||||
if (methodDep == null) {
|
cutClasses.putClassHolder(generatedClass);
|
||||||
classHolder.removeMethod(method);
|
link(generatedClass);
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cutClasses;
|
return cutClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void link(MethodHolder cls) {
|
public void link(ClassHolder cls) {
|
||||||
Program program = cls.getProgram();
|
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) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
for (Instruction insn : block.getInstructions()) {
|
for (Instruction insn : block.getInstructions()) {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model;
|
package org.teavm.model;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
|
|
|
@ -15,11 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model;
|
package org.teavm.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.teavm.common.Mapper;
|
import org.teavm.common.Mapper;
|
||||||
import org.teavm.model.util.ProgramUtils;
|
import org.teavm.model.util.ModelUtils;
|
||||||
import org.teavm.resource.MapperClassHolderSource;
|
import org.teavm.resource.MapperClassHolderSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,68 +45,6 @@ public class CopyClassHolderSource implements ClassHolderSource {
|
||||||
if (original == null) {
|
if (original == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ClassHolder copy = new ClassHolder(className);
|
return ModelUtils.copyClass(original);
|
||||||
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<String, AnnotationValue> 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<AnnotationValue> 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<String, AnnotationValue> 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<AnnotationValue> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.util;
|
package org.teavm.model.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphBuilder;
|
import org.teavm.common.GraphBuilder;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
@ -67,9 +68,9 @@ public final class ProgramUtils {
|
||||||
return graphBuilder.build();
|
return graphBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Program copy(Program program) {
|
public static Program copy(ProgramReader program) {
|
||||||
Program copy = new Program();
|
Program copy = new Program();
|
||||||
CopyVisitor insnCopier = new CopyVisitor();
|
InstructionCopyReader insnCopier = new InstructionCopyReader();
|
||||||
insnCopier.programCopy = copy;
|
insnCopier.programCopy = copy;
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
copy.createVariable();
|
copy.createVariable();
|
||||||
|
@ -78,16 +79,16 @@ public final class ProgramUtils {
|
||||||
copy.createBasicBlock();
|
copy.createBasicBlock();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlockReader block = program.basicBlockAt(i);
|
||||||
BasicBlock blockCopy = copy.basicBlockAt(i);
|
BasicBlock blockCopy = copy.basicBlockAt(i);
|
||||||
for (Instruction insn : block.getInstructions()) {
|
for (int j = 0; j < block.instructionCount(); ++j) {
|
||||||
insn.acceptVisitor(insnCopier);
|
block.readInstruction(j, insnCopier);
|
||||||
blockCopy.getInstructions().add(insnCopier.copy);
|
blockCopy.getInstructions().add(insnCopier.copy);
|
||||||
}
|
}
|
||||||
for (Phi phi : block.getPhis()) {
|
for (PhiReader phi : block.readPhis()) {
|
||||||
Phi phiCopy = new Phi();
|
Phi phiCopy = new Phi();
|
||||||
phiCopy.setReceiver(copy.variableAt(phi.getReceiver().getIndex()));
|
phiCopy.setReceiver(copy.variableAt(phi.getReceiver().getIndex()));
|
||||||
for (Incoming incoming : phi.getIncomings()) {
|
for (IncomingReader incoming : phi.readIncomings()) {
|
||||||
Incoming incomingCopy = new Incoming();
|
Incoming incomingCopy = new Incoming();
|
||||||
incomingCopy.setSource(copy.basicBlockAt(incoming.getSource().getIndex()));
|
incomingCopy.setSource(copy.basicBlockAt(incoming.getSource().getIndex()));
|
||||||
incomingCopy.setValue(copy.variableAt(incoming.getValue().getIndex()));
|
incomingCopy.setValue(copy.variableAt(incoming.getValue().getIndex()));
|
||||||
|
@ -95,7 +96,7 @@ public final class ProgramUtils {
|
||||||
}
|
}
|
||||||
blockCopy.getPhis().add(phiCopy);
|
blockCopy.getPhis().add(phiCopy);
|
||||||
}
|
}
|
||||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
||||||
TryCatchBlock tryCatchCopy = new TryCatchBlock();
|
TryCatchBlock tryCatchCopy = new TryCatchBlock();
|
||||||
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
||||||
tryCatchCopy.setExceptionVariable(copy.variableAt(tryCatch.getExceptionVariable().getIndex()));
|
tryCatchCopy.setExceptionVariable(copy.variableAt(tryCatch.getExceptionVariable().getIndex()));
|
||||||
|
@ -106,160 +107,166 @@ public final class ProgramUtils {
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CopyVisitor implements InstructionVisitor {
|
private static class InstructionCopyReader implements InstructionReader {
|
||||||
Instruction copy;
|
Instruction copy;
|
||||||
Program programCopy;
|
Program programCopy;
|
||||||
|
|
||||||
@Override
|
private Variable copyVar(VariableReader var) {
|
||||||
public void visit(EmptyInstruction insn) {
|
|
||||||
copy = new EmptyInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Variable copyVar(Variable var) {
|
|
||||||
return programCopy.variableAt(var.getIndex());
|
return programCopy.variableAt(var.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
private BasicBlock copyBlock(BasicBlock block) {
|
private BasicBlock copyBlock(BasicBlockReader block) {
|
||||||
return programCopy.basicBlockAt(block.getIndex());
|
return programCopy.basicBlockAt(block.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ClassConstantInstruction insn) {
|
public void nop() {
|
||||||
|
copy = new EmptyInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void classConstant(VariableReader receiver, ValueType cst) {
|
||||||
ClassConstantInstruction insnCopy = new ClassConstantInstruction();
|
ClassConstantInstruction insnCopy = new ClassConstantInstruction();
|
||||||
insnCopy.setConstant(insn.getConstant());
|
insnCopy.setConstant(cst);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullConstantInstruction insn) {
|
public void nullConstant(VariableReader receiver) {
|
||||||
NullConstantInstruction insnCopy = new NullConstantInstruction();
|
NullConstantInstruction insnCopy = new NullConstantInstruction();
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IntegerConstantInstruction insn) {
|
public void integerConstant(VariableReader receiver, int cst) {
|
||||||
IntegerConstantInstruction insnCopy = new IntegerConstantInstruction();
|
IntegerConstantInstruction insnCopy = new IntegerConstantInstruction();
|
||||||
insnCopy.setConstant(insn.getConstant());
|
insnCopy.setConstant(cst);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(LongConstantInstruction insn) {
|
public void longConstant(VariableReader receiver, long cst) {
|
||||||
LongConstantInstruction insnCopy = new LongConstantInstruction();
|
LongConstantInstruction insnCopy = new LongConstantInstruction();
|
||||||
insnCopy.setConstant(insn.getConstant());
|
insnCopy.setConstant(cst);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(FloatConstantInstruction insn) {
|
public void floatConstant(VariableReader receiver, float cst) {
|
||||||
FloatConstantInstruction insnCopy = new FloatConstantInstruction();
|
FloatConstantInstruction insnCopy = new FloatConstantInstruction();
|
||||||
insnCopy.setConstant(insn.getConstant());
|
insnCopy.setConstant(cst);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(DoubleConstantInstruction insn) {
|
public void doubleConstant(VariableReader receiver, double cst) {
|
||||||
DoubleConstantInstruction insnCopy = new DoubleConstantInstruction();
|
DoubleConstantInstruction insnCopy = new DoubleConstantInstruction();
|
||||||
insnCopy.setConstant(insn.getConstant());
|
insnCopy.setConstant(cst);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StringConstantInstruction insn) {
|
public void stringConstant(VariableReader receiver, String cst) {
|
||||||
StringConstantInstruction insnCopy = new StringConstantInstruction();
|
StringConstantInstruction insnCopy = new StringConstantInstruction();
|
||||||
insnCopy.setConstant(insn.getConstant());
|
insnCopy.setConstant(cst);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BinaryInstruction insn) {
|
public void binary(BinaryOperation op, VariableReader receiver, VariableReader first, VariableReader second,
|
||||||
BinaryInstruction insnCopy = new BinaryInstruction(insn.getOperation(), insn.getOperandType());
|
NumericOperandType type) {
|
||||||
insnCopy.setFirstOperand(copyVar(insn.getFirstOperand()));
|
BinaryInstruction insnCopy = new BinaryInstruction(op, type);
|
||||||
insnCopy.setSecondOperand(copyVar(insn.getSecondOperand()));
|
insnCopy.setFirstOperand(copyVar(first));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setSecondOperand(copyVar(second));
|
||||||
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NegateInstruction insn) {
|
public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) {
|
||||||
NegateInstruction insnCopy = new NegateInstruction(insn.getOperandType());
|
NegateInstruction insnCopy = new NegateInstruction(type);
|
||||||
insnCopy.setOperand(copyVar(insn.getOperand()));
|
insnCopy.setOperand(copyVar(operand));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignInstruction insn) {
|
public void assign(VariableReader receiver, VariableReader assignee) {
|
||||||
AssignInstruction insnCopy = new AssignInstruction();
|
AssignInstruction insnCopy = new AssignInstruction();
|
||||||
insnCopy.setAssignee(copyVar(insn.getAssignee()));
|
insnCopy.setAssignee(copyVar(assignee));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastInstruction insn) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
||||||
CastInstruction insnCopy = new CastInstruction();
|
CastInstruction insnCopy = new CastInstruction();
|
||||||
insnCopy.setValue(copyVar(insn.getValue()));
|
insnCopy.setValue(copyVar(value));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
insnCopy.setTargetType(insn.getTargetType());
|
insnCopy.setTargetType(targetType);
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastNumberInstruction insn) {
|
public void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType,
|
||||||
CastNumberInstruction insnCopy = new CastNumberInstruction(insn.getSourceType(), insn.getTargetType());
|
NumericOperandType targetType) {
|
||||||
insnCopy.setValue(copyVar(insn.getValue()));
|
CastNumberInstruction insnCopy = new CastNumberInstruction(sourceType, targetType);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setValue(copyVar(value));
|
||||||
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastIntegerInstruction insn) {
|
public void cast(VariableReader receiver, VariableReader value, IntegerSubtype type,
|
||||||
CastIntegerInstruction insnCopy = new CastIntegerInstruction(insn.getTargetType(), insn.getDirection());
|
CastIntegerDirection dir) {
|
||||||
insnCopy.setValue(copyVar(insn.getValue()));
|
CastIntegerInstruction insnCopy = new CastIntegerInstruction(type, dir);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setValue(copyVar(value));
|
||||||
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BranchingInstruction insn) {
|
public void jumpIf(BranchingCondition cond, VariableReader operand, BasicBlockReader consequent,
|
||||||
BranchingInstruction insnCopy = new BranchingInstruction(insn.getCondition());
|
BasicBlockReader alternative) {
|
||||||
insnCopy.setOperand(copyVar(insn.getOperand()));
|
BranchingInstruction insnCopy = new BranchingInstruction(cond);
|
||||||
insnCopy.setConsequent(copyBlock(insn.getConsequent()));
|
insnCopy.setOperand(copyVar(operand));
|
||||||
insnCopy.setAlternative(copyBlock(insn.getAlternative()));
|
insnCopy.setConsequent(copyBlock(consequent));
|
||||||
|
insnCopy.setAlternative(copyBlock(alternative));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BinaryBranchingInstruction insn) {
|
public void jumpIf(BinaryBranchingCondition cond, VariableReader first, VariableReader second,
|
||||||
BinaryBranchingInstruction insnCopy = new BinaryBranchingInstruction(insn.getCondition());
|
BasicBlockReader consequent, BasicBlockReader alternative) {
|
||||||
insnCopy.setFirstOperand(copyVar(insn.getFirstOperand()));
|
BinaryBranchingInstruction insnCopy = new BinaryBranchingInstruction(cond);
|
||||||
insnCopy.setSecondOperand(copyVar(insn.getSecondOperand()));
|
insnCopy.setFirstOperand(copyVar(first));
|
||||||
insnCopy.setConsequent(copyBlock(insn.getConsequent()));
|
insnCopy.setSecondOperand(copyVar(second));
|
||||||
insnCopy.setAlternative(copyBlock(insn.getAlternative()));
|
insnCopy.setConsequent(copyBlock(consequent));
|
||||||
|
insnCopy.setAlternative(copyBlock(alternative));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(JumpInstruction insn) {
|
public void jump(BasicBlockReader target) {
|
||||||
JumpInstruction insnCopy = new JumpInstruction();
|
JumpInstruction insnCopy = new JumpInstruction();
|
||||||
insnCopy.setTarget(copyBlock(insn.getTarget()));
|
insnCopy.setTarget(copyBlock(target));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchInstruction insn) {
|
public void choose(VariableReader condition, List<? extends SwitchTableEntryReader> table,
|
||||||
|
BasicBlockReader defaultTarget) {
|
||||||
SwitchInstruction insnCopy = new SwitchInstruction();
|
SwitchInstruction insnCopy = new SwitchInstruction();
|
||||||
insnCopy.setCondition(copyVar(insn.getCondition()));
|
insnCopy.setCondition(copyVar(condition));
|
||||||
insnCopy.setDefaultTarget(copyBlock(insn.getDefaultTarget()));
|
insnCopy.setDefaultTarget(copyBlock(defaultTarget));
|
||||||
for (SwitchTableEntry entry : insn.getEntries()) {
|
for (SwitchTableEntryReader entry : table) {
|
||||||
SwitchTableEntry entryCopy = new SwitchTableEntry();
|
SwitchTableEntry entryCopy = new SwitchTableEntry();
|
||||||
entryCopy.setCondition(entry.getCondition());
|
entryCopy.setCondition(entry.getCondition());
|
||||||
entryCopy.setTarget(copyBlock(entry.getTarget()));
|
entryCopy.setTarget(copyBlock(entry.getTarget()));
|
||||||
|
@ -269,143 +276,147 @@ public final class ProgramUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ExitInstruction insn) {
|
public void exit(VariableReader valueToReturn) {
|
||||||
ExitInstruction insnCopy = new ExitInstruction();
|
ExitInstruction insnCopy = new ExitInstruction();
|
||||||
insnCopy.setValueToReturn(insn.getValueToReturn() != null ? copyVar(insn.getValueToReturn()) : null);
|
insnCopy.setValueToReturn(valueToReturn != null ? copyVar(valueToReturn) : null);
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(RaiseInstruction insn) {
|
public void raise(VariableReader exception) {
|
||||||
RaiseInstruction insnCopy = new RaiseInstruction();
|
RaiseInstruction insnCopy = new RaiseInstruction();
|
||||||
insnCopy.setException(copyVar(insn.getException()));
|
insnCopy.setException(copyVar(exception));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructArrayInstruction insn) {
|
public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) {
|
||||||
ConstructArrayInstruction insnCopy = new ConstructArrayInstruction();
|
ConstructArrayInstruction insnCopy = new ConstructArrayInstruction();
|
||||||
insnCopy.setItemType(insn.getItemType());
|
insnCopy.setItemType(itemType);
|
||||||
insnCopy.setSize(copyVar(insn.getSize()));
|
insnCopy.setSize(copyVar(size));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructInstruction insn) {
|
public void createArray(VariableReader receiver, ValueType itemType,
|
||||||
ConstructInstruction insnCopy = new ConstructInstruction();
|
List<? extends VariableReader> dimensions) {
|
||||||
insnCopy.setType(insn.getType());
|
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
|
||||||
copy = insnCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(ConstructMultiArrayInstruction insn) {
|
|
||||||
ConstructMultiArrayInstruction insnCopy = new ConstructMultiArrayInstruction();
|
ConstructMultiArrayInstruction insnCopy = new ConstructMultiArrayInstruction();
|
||||||
insnCopy.setItemType(insn.getItemType());
|
insnCopy.setItemType(itemType);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
for (Variable dim : insn.getDimensions()) {
|
for (VariableReader dim : dimensions) {
|
||||||
insnCopy.getDimensions().add(copyVar(dim));
|
insnCopy.getDimensions().add(copyVar(dim));
|
||||||
}
|
}
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
GetFieldInstruction insnCopy = new GetFieldInstruction();
|
||||||
insnCopy.setField(insn.getField());
|
insnCopy.setField(field);
|
||||||
insnCopy.setFieldType(insn.getFieldType());
|
insnCopy.setFieldType(fieldType);
|
||||||
insnCopy.setInstance(insn.getInstance() != null ? copyVar(insn.getInstance()) : null);
|
insnCopy.setInstance(instance != null ? copyVar(instance) : null);
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PutFieldInstruction insn) {
|
public void putField(VariableReader instance, FieldReference field, VariableReader value) {
|
||||||
PutFieldInstruction insnCopy = new PutFieldInstruction();
|
PutFieldInstruction insnCopy = new PutFieldInstruction();
|
||||||
insnCopy.setField(insn.getField());
|
insnCopy.setField(field);
|
||||||
insnCopy.setInstance(insn.getInstance() != null ? copyVar(insn.getInstance()) : null);
|
insnCopy.setInstance(instance != null ? copyVar(instance) : null);
|
||||||
insnCopy.setValue(copyVar(insn.getValue()));
|
insnCopy.setValue(copyVar(value));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ArrayLengthInstruction insn) {
|
public void arrayLength(VariableReader receiver, VariableReader array) {
|
||||||
ArrayLengthInstruction insnCopy = new ArrayLengthInstruction();
|
ArrayLengthInstruction insnCopy = new ArrayLengthInstruction();
|
||||||
insnCopy.setArray(copyVar(insn.getArray()));
|
insnCopy.setArray(copyVar(array));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CloneArrayInstruction insn) {
|
public void cloneArray(VariableReader receiver, VariableReader array) {
|
||||||
CloneArrayInstruction insnCopy = new CloneArrayInstruction();
|
CloneArrayInstruction insnCopy = new CloneArrayInstruction();
|
||||||
insnCopy.setArray(copyVar(insn.getArray()));
|
insnCopy.setArray(copyVar(array));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnwrapArrayInstruction insn) {
|
public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) {
|
||||||
UnwrapArrayInstruction insnCopy = new UnwrapArrayInstruction(insn.getElementType());
|
UnwrapArrayInstruction insnCopy = new UnwrapArrayInstruction(elementType);
|
||||||
insnCopy.setArray(copyVar(insn.getArray()));
|
insnCopy.setArray(copyVar(array));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GetElementInstruction insn) {
|
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
|
||||||
GetElementInstruction insnCopy = new GetElementInstruction();
|
GetElementInstruction insnCopy = new GetElementInstruction();
|
||||||
insnCopy.setArray(copyVar(insn.getArray()));
|
insnCopy.setArray(copyVar(array));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
insnCopy.setIndex(copyVar(insn.getIndex()));
|
insnCopy.setIndex(copyVar(index));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PutElementInstruction insn) {
|
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
|
||||||
PutElementInstruction insnCopy = new PutElementInstruction();
|
PutElementInstruction insnCopy = new PutElementInstruction();
|
||||||
insnCopy.setArray(copyVar(insn.getArray()));
|
insnCopy.setArray(copyVar(array));
|
||||||
insnCopy.setValue(copyVar(insn.getValue()));
|
insnCopy.setValue(copyVar(value));
|
||||||
insnCopy.setIndex(copyVar(insn.getIndex()));
|
insnCopy.setIndex(copyVar(index));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InvokeInstruction insn) {
|
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||||
|
List<? extends VariableReader> arguments, InvocationType type) {
|
||||||
InvokeInstruction insnCopy = new InvokeInstruction();
|
InvokeInstruction insnCopy = new InvokeInstruction();
|
||||||
insnCopy.setMethod(insn.getMethod());
|
insnCopy.setMethod(method);
|
||||||
insnCopy.setType(insn.getType());
|
insnCopy.setType(type);
|
||||||
insnCopy.setInstance(insn.getInstance() != null ? copyVar(insn.getInstance()) : null);
|
insnCopy.setInstance(instance != null ? copyVar(instance) : null);
|
||||||
insnCopy.setReceiver(insn.getReceiver() != null ? copyVar(insn.getReceiver()) : null);
|
insnCopy.setReceiver(receiver != null ? copyVar(receiver) : null);
|
||||||
for (Variable arg : insn.getArguments()) {
|
for (VariableReader arg : arguments) {
|
||||||
insnCopy.getArguments().add(copyVar(arg));
|
insnCopy.getArguments().add(copyVar(arg));
|
||||||
}
|
}
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IsInstanceInstruction insn) {
|
public void isInstance(VariableReader receiver, VariableReader value, ValueType type) {
|
||||||
IsInstanceInstruction insnCopy = new IsInstanceInstruction();
|
IsInstanceInstruction insnCopy = new IsInstanceInstruction();
|
||||||
insnCopy.setValue(copyVar(insn.getValue()));
|
insnCopy.setValue(copyVar(value));
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
insnCopy.setType(insn.getType());
|
insnCopy.setType(type);
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassInstruction insn) {
|
public void initClass(String className) {
|
||||||
InitClassInstruction insnCopy = new InitClassInstruction();
|
InitClassInstruction insnCopy = new InitClassInstruction();
|
||||||
insnCopy.setClassName(insn.getClassName());
|
insnCopy.setClassName(className);
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullCheckInstruction insn) {
|
public void nullCheck(VariableReader receiver, VariableReader value) {
|
||||||
NullCheckInstruction insnCopy = new NullCheckInstruction();
|
NullCheckInstruction insnCopy = new NullCheckInstruction();
|
||||||
insnCopy.setReceiver(copyVar(insn.getReceiver()));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
insnCopy.setValue(copyVar(insn.getValue()));
|
insnCopy.setValue(copyVar(value));
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.vm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.teavm.common.ConcurrentCachedMapper;
|
import org.teavm.common.ConcurrentCachedMapper;
|
||||||
import org.teavm.common.Mapper;
|
import org.teavm.common.Mapper;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
|
|
|
@ -93,7 +93,6 @@ public class TeaVM implements TeaVMHost {
|
||||||
classSource.addTransformer(transformer);
|
classSource.addTransformer(transformer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(MethodReference methodRef, Generator generator) {
|
public void add(MethodReference methodRef, Generator generator) {
|
||||||
methodGenerators.put(methodRef, generator);
|
methodGenerators.put(methodRef, generator);
|
||||||
|
|
|
@ -67,21 +67,21 @@ public class EntryPointGenerator extends AbstractRendererListener implements Dep
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyAgent agent) {
|
||||||
for (String className : classesToLoad) {
|
for (String className : classesToLoad) {
|
||||||
dependencyChecker.initClass(className, DependencyStack.ROOT);
|
agent.initClass(className, DependencyStack.ROOT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
private DependencyNode allClassesNode;
|
private DependencyNode allClassesNode;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyAgent agent) {
|
||||||
allClassesNode = dependencyChecker.createNode();
|
allClassesNode = agent.createNode();
|
||||||
allClassesNode.setTag("JavaScriptBody:global");
|
allClassesNode.setTag("JavaScriptBody:global");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
ClassReader cls = dependencyChecker.getClassSource().get(className);
|
ClassReader cls = agent.getClassSource().get(className);
|
||||||
if (cls != null && !cls.hasModifier(ElementModifier.ABSTRACT) &&
|
if (cls != null && !cls.hasModifier(ElementModifier.ABSTRACT) &&
|
||||||
!cls.hasModifier(ElementModifier.INTERFACE)) {
|
!cls.hasModifier(ElementModifier.INTERFACE)) {
|
||||||
allClassesNode.propagate(className);
|
allClassesNode.propagate(className);
|
||||||
|
@ -52,13 +52,13 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||||
if (method.isMissing()) {
|
if (method.isMissing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AnnotationReader annot = method.getMethod().getAnnotations().get(JavaScriptBody.class.getName());
|
AnnotationReader annot = method.getMethod().getAnnotations().get(JavaScriptBody.class.getName());
|
||||||
if (annot != null) {
|
if (annot != null) {
|
||||||
includeDefaultDependencies(dependencyChecker);
|
includeDefaultDependencies(agent);
|
||||||
AnnotationValue javacall = annot.getValue("javacall");
|
AnnotationValue javacall = annot.getValue("javacall");
|
||||||
if (method.getResult() != null) {
|
if (method.getResult() != null) {
|
||||||
allClassesNode.connect(method.getResult());
|
allClassesNode.connect(method.getResult());
|
||||||
|
@ -74,26 +74,26 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
}
|
}
|
||||||
if (javacall != null && javacall.getBoolean()) {
|
if (javacall != null && javacall.getBoolean()) {
|
||||||
String body = annot.getValue("body").getString();
|
String body = annot.getValue("body").getString();
|
||||||
new GeneratorJsCallback(dependencyChecker, method).parse(body);
|
new GeneratorJsCallback(agent, method).parse(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void includeDefaultDependencies(DependencyChecker dependencyChecker) {
|
private void includeDefaultDependencies(DependencyAgent agent) {
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.fromJsMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.fromJsMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.toJsMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.toJsMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.intValueMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.intValueMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.booleanValueMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.doubleValueMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.charValueMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.charValueMethod, DependencyStack.ROOT).use();
|
||||||
dependencyChecker.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, DependencyStack.ROOT).use();
|
agent.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, DependencyStack.ROOT).use();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
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 class GeneratorJsCallback extends JsCallback {
|
||||||
private DependencyChecker dependencyChecker;
|
private DependencyAgent agent;
|
||||||
private MethodDependency caller;
|
private MethodDependency caller;
|
||||||
public GeneratorJsCallback(DependencyChecker dependencyChecker, MethodDependency caller) {
|
public GeneratorJsCallback(DependencyAgent agent, MethodDependency caller) {
|
||||||
this.dependencyChecker = dependencyChecker;
|
this.agent = agent;
|
||||||
this.caller = caller;
|
this.caller = caller;
|
||||||
}
|
}
|
||||||
@Override protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
@Override protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
||||||
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
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);
|
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 (!methodDep.isMissing()) {
|
||||||
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
|
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
|
||||||
methodDep.use();
|
methodDep.use();
|
||||||
|
@ -142,7 +142,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
allClassesNode.connect(methodDep.getVariable(i));
|
allClassesNode.connect(methodDep.getVariable(i));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
allClassesNode.addConsumer(new VirtualCallbackConsumer(dependencyChecker, reader, caller));
|
allClassesNode.addConsumer(new VirtualCallbackConsumer(agent, reader, caller));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
@ -150,30 +150,30 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VirtualCallbackConsumer implements DependencyConsumer {
|
private class VirtualCallbackConsumer implements DependencyConsumer {
|
||||||
private DependencyChecker dependencyChecker;
|
private DependencyAgent agent;
|
||||||
private MethodReader superMethod;
|
private MethodReader superMethod;
|
||||||
private ClassReader superClass;
|
private ClassReader superClass;
|
||||||
private MethodDependency caller;
|
private MethodDependency caller;
|
||||||
public VirtualCallbackConsumer(DependencyChecker dependencyChecker, MethodReader superMethod,
|
public VirtualCallbackConsumer(DependencyAgent agent, MethodReader superMethod,
|
||||||
MethodDependency caller) {
|
MethodDependency caller) {
|
||||||
this.dependencyChecker = dependencyChecker;
|
this.agent = agent;
|
||||||
this.superMethod = superMethod;
|
this.superMethod = superMethod;
|
||||||
this.caller = caller;
|
this.caller = caller;
|
||||||
this.superClass = dependencyChecker.getClassSource().get(superMethod.getOwnerName());
|
this.superClass = agent.getClassSource().get(superMethod.getOwnerName());
|
||||||
}
|
}
|
||||||
@Override public void consume(String type) {
|
@Override public void consume(String type) {
|
||||||
if (!isAssignableFrom(superClass, type)) {
|
if (!isAssignableFrom(superClass, type)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MethodReference methodRef = new MethodReference(type, superMethod.getDescriptor());
|
MethodReference methodRef = new MethodReference(type, superMethod.getDescriptor());
|
||||||
MethodDependency method = dependencyChecker.linkMethod(methodRef, caller.getStack());
|
MethodDependency method = agent.linkMethod(methodRef, caller.getStack());
|
||||||
method.use();
|
method.use();
|
||||||
for (int i = 0; i < method.getParameterCount(); ++i) {
|
for (int i = 0; i < method.getParameterCount(); ++i) {
|
||||||
allClassesNode.connect(method.getVariable(i));
|
allClassesNode.connect(method.getVariable(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private boolean isAssignableFrom(ClassReader supertype, String subtypeName) {
|
private boolean isAssignableFrom(ClassReader supertype, String subtypeName) {
|
||||||
ClassReaderSource classSource = dependencyChecker.getClassSource();
|
ClassReaderSource classSource = agent.getClassSource();
|
||||||
if (supertype.getName().equals(subtypeName)) {
|
if (supertype.getName().equals(subtypeName)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,13 +31,13 @@ class TestExceptionDependency implements DependencyListener {
|
||||||
private DependencyNode allClasses;
|
private DependencyNode allClasses;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyAgent agent) {
|
||||||
allClasses = dependencyChecker.createNode();
|
allClasses = agent.createNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
public void classAchieved(DependencyAgent agent, String className) {
|
||||||
if (isException(dependencyChecker.getClassSource(), className)) {
|
if (isException(agent.getClassSource(), className)) {
|
||||||
allClasses.propagate(className);
|
allClasses.propagate(className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,13 +57,13 @@ class TestExceptionDependency implements DependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||||
if (method.getReference().equals(getMessageRef)) {
|
if (method.getReference().equals(getMessageRef)) {
|
||||||
allClasses.connect(method.getVariable(0));
|
allClasses.connect(method.getVariable(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user