First attempt to refactor dependency checker

This commit is contained in:
Alexey Andreev 2014-03-24 13:26:32 +04:00
parent 8286ad9289
commit 00d160e92b
19 changed files with 475 additions and 312 deletions

View File

@ -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("<clinit>", 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) {
}
}

View File

@ -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) {
}
}

View File

@ -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("<init>", ValueType.VOID));
checker.linkMethod(ref, newInstanceStack).use();
}
@Override
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
public void fieldAchieved(DependencyAgent dependencyAgent, FieldDependency field) {
}
}

View File

@ -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<URL> 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("<init>", 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) {
}
}

View File

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

View File

@ -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<MethodReference, MethodReader> methodReaderCache;
@ -47,12 +49,12 @@ public class DependencyChecker implements DependencyInfo {
ConcurrentMap<String, DependencyStack> missingClasses = 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());
}
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<MethodReference, MethodReader>() {
@ -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("<clinit>", 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<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;
}
}

View File

@ -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();
}
}

View File

@ -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 <konsoletyper@gmail.com>
*/
public interface DependencyInfo {
boolean isMethodAchievable(MethodReference methodRef);
Collection<MethodReference> getAchievableMethods();
Collection<FieldReference> getAchievableFields();
@ -33,4 +36,6 @@ public interface DependencyInfo {
FieldDependencyInfo getField(FieldReference fieldRef);
MethodDependencyInfo getMethod(MethodReference methodRef);
Collection<ClassHolder> getGeneratedClasses();
}

View File

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

View File

@ -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()) {

View File

@ -15,7 +15,6 @@
*/
package org.teavm.model;
/**
*
* @author Alexey Andreev

View File

@ -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<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;
}
return ModelUtils.copyClass(original);
}
}

View File

@ -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;
}
}
}

View File

@ -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<? extends SwitchTableEntryReader> 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<? extends VariableReader> 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<? extends VariableReader> 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;
}
}
}

View File

@ -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;

View File

@ -93,7 +93,6 @@ public class TeaVM implements TeaVMHost {
classSource.addTransformer(transformer);
}
@Override
public void add(MethodReference methodRef, Generator generator) {
methodGenerators.put(methodRef, generator);

View File

@ -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) {
}
}

View File

@ -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;
}

View File

@ -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) {
}
}