mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
f39bfdf028
|
@ -52,7 +52,7 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
switch (method.getReference().getName()) {
|
switch (method.getReference().getName()) {
|
||||||
case "doArrayCopy":
|
case "doArrayCopy":
|
||||||
achieveArrayCopy(method);
|
achieveArrayCopy(method);
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
||||||
ValueType.INTEGER, ValueType.LONG, ValueType.FLOAT, ValueType.DOUBLE, ValueType.BOOLEAN };
|
ValueType.INTEGER, ValueType.LONG, ValueType.FLOAT, ValueType.DOUBLE, ValueType.BOOLEAN };
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
switch (method.getReference().getName()) {
|
switch (method.getReference().getName()) {
|
||||||
case "getLength":
|
case "getLength":
|
||||||
achieveGetLength(agent, method);
|
achieveGetLength(agent, method);
|
||||||
|
|
|
@ -61,6 +61,10 @@ public class CachedMapper<T, R> implements Mapper<T, R> {
|
||||||
return wrapper.value;
|
return wrapper.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void replace(T preimage, R value) {
|
||||||
|
cache.get(preimage).value = value;
|
||||||
|
}
|
||||||
|
|
||||||
public void invalidate(T preimage) {
|
public void invalidate(T preimage) {
|
||||||
cache.remove(preimage);
|
cache.remove(preimage);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,4 +37,8 @@ public abstract class AbstractDependencyListener implements DependencyListener {
|
||||||
@Override
|
@Override
|
||||||
public void fieldReached(DependencyAgent agent, FieldDependency field, CallLocation location) {
|
public void fieldReached(DependencyAgent agent, FieldDependency field, CallLocation location) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void completing(DependencyAgent agent) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,10 @@ public class DependencyAgent implements DependencyInfo, ServiceRepository {
|
||||||
checker.submitClass(cls);
|
checker.submitClass(cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void submitMethod(MethodReference method, Program program) {
|
||||||
|
checker.submitMethod(method, program);
|
||||||
|
}
|
||||||
|
|
||||||
public MethodDependency linkMethod(MethodReference methodRef, CallLocation callLocation) {
|
public MethodDependency linkMethod(MethodReference methodRef, CallLocation callLocation) {
|
||||||
return checker.linkMethod(methodRef, callLocation);
|
return checker.linkMethod(methodRef, callLocation);
|
||||||
}
|
}
|
||||||
|
@ -80,18 +84,18 @@ public class DependencyAgent implements DependencyInfo, ServiceRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<MethodReference> getAchievableMethods() {
|
public Collection<MethodReference> getReachableMethods() {
|
||||||
return checker.getAchievableMethods();
|
return checker.getReachableMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FieldReference> getAchievableFields() {
|
public Collection<FieldReference> getReachableFields() {
|
||||||
return checker.getAchievableFields();
|
return checker.getReachableFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getAchievableClasses() {
|
public Collection<String> getReachableClasses() {
|
||||||
return checker.getAchievableClasses();
|
return checker.getReachableClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldHolder;
|
import org.teavm.model.FieldHolder;
|
||||||
import org.teavm.model.FieldReader;
|
import org.teavm.model.FieldReader;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
|
@ -46,8 +47,10 @@ import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.util.ModelUtils;
|
import org.teavm.model.util.ModelUtils;
|
||||||
|
import org.teavm.model.util.ProgramUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -76,6 +79,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
List<DependencyNode> nodes = new ArrayList<>();
|
List<DependencyNode> nodes = new ArrayList<>();
|
||||||
List<BitSet> typeBitSets = new ArrayList<>();
|
List<BitSet> typeBitSets = new ArrayList<>();
|
||||||
Map<MethodReference, BootstrapMethodSubstitutor> bootstrapMethodSubstitutors = new HashMap<>();
|
Map<MethodReference, BootstrapMethodSubstitutor> bootstrapMethodSubstitutors = new HashMap<>();
|
||||||
|
private boolean completing;
|
||||||
|
|
||||||
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
|
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
|
||||||
Diagnostics diagnostics) {
|
Diagnostics diagnostics) {
|
||||||
|
@ -153,9 +157,36 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void submitClass(ClassHolder cls) {
|
public void submitClass(ClassHolder cls) {
|
||||||
|
if (completing) {
|
||||||
|
throw new IllegalStateException("Can't submit class during completion phase");
|
||||||
|
}
|
||||||
classSource.submit(ModelUtils.copyClass(cls));
|
classSource.submit(ModelUtils.copyClass(cls));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void submitMethod(MethodReference methodRef, Program program) {
|
||||||
|
if (!completing) {
|
||||||
|
throw new IllegalStateException("Can't submit class during check phase");
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodDependency dep = getMethod(methodRef);
|
||||||
|
if (dep == null) {
|
||||||
|
throw new IllegalArgumentException("Method was not reached: " + methodRef);
|
||||||
|
}
|
||||||
|
MethodHolder method = dep.method;
|
||||||
|
|
||||||
|
if (!method.hasModifier(ElementModifier.NATIVE)) {
|
||||||
|
throw new IllegalArgumentException("Method is not native: " + methodRef);
|
||||||
|
}
|
||||||
|
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||||
|
method.setProgram(ProgramUtils.copy(program));
|
||||||
|
|
||||||
|
dep.used = false;
|
||||||
|
lock(dep, false);
|
||||||
|
scheduleMethodAnalysis(dep);
|
||||||
|
|
||||||
|
processQueue();
|
||||||
|
}
|
||||||
|
|
||||||
public void addDependencyListener(DependencyListener listener) {
|
public void addDependencyListener(DependencyListener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
listener.started(agent);
|
listener.started(agent);
|
||||||
|
@ -193,7 +224,10 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
|
|
||||||
private Set<String> classesAddedByRoot = new HashSet<>();
|
private Set<String> classesAddedByRoot = new HashSet<>();
|
||||||
|
|
||||||
public ClassDependency linkClass(final String className, final CallLocation callLocation) {
|
public ClassDependency linkClass(String className, CallLocation callLocation) {
|
||||||
|
if (completing && getClass(className) == null) {
|
||||||
|
throw new IllegalStateException("Can't link class during completion phase");
|
||||||
|
}
|
||||||
ClassDependency dep = classCache.map(className);
|
ClassDependency dep = classCache.map(className);
|
||||||
boolean added = true;
|
boolean added = true;
|
||||||
if (callLocation != null && callLocation.getMethod() != null) {
|
if (callLocation != null && callLocation.getMethod() != null) {
|
||||||
|
@ -247,6 +281,9 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
private Set<MethodReference> methodsAddedByRoot = new HashSet<>();
|
private Set<MethodReference> methodsAddedByRoot = new HashSet<>();
|
||||||
|
|
||||||
public MethodDependency linkMethod(MethodReference methodRef, CallLocation callLocation) {
|
public MethodDependency linkMethod(MethodReference methodRef, CallLocation callLocation) {
|
||||||
|
if (completing && getMethod(methodRef) == null) {
|
||||||
|
throw new IllegalStateException("Can't submit class during completion phase");
|
||||||
|
}
|
||||||
if (methodRef == null) {
|
if (methodRef == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
@ -272,9 +309,9 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initClass(ClassDependency cls, final CallLocation callLocation) {
|
void initClass(ClassDependency cls, CallLocation callLocation) {
|
||||||
ClassReader reader = cls.getClassReader();
|
ClassReader reader = cls.getClassReader();
|
||||||
final MethodReader method = reader.getMethod(new MethodDescriptor("<clinit>", void.class));
|
MethodReader method = reader.getMethod(new MethodDescriptor("<clinit>", void.class));
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
tasks.add(() -> linkMethod(method.getReference(), callLocation).use());
|
tasks.add(() -> linkMethod(method.getReference(), callLocation).use());
|
||||||
}
|
}
|
||||||
|
@ -286,6 +323,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
DependencyNode[] parameterNodes = new DependencyNode[arguments.length + 1];
|
DependencyNode[] parameterNodes = new DependencyNode[arguments.length + 1];
|
||||||
for (int i = 0; i < parameterNodes.length; ++i) {
|
for (int i = 0; i < parameterNodes.length; ++i) {
|
||||||
parameterNodes[i] = createNode();
|
parameterNodes[i] = createNode();
|
||||||
|
parameterNodes[i].method = methodRef;
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
parameterNodes[i].setTag(methodRef + ":" + i);
|
parameterNodes[i].setTag(methodRef + ":" + i);
|
||||||
}
|
}
|
||||||
|
@ -295,15 +333,17 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
resultNode = null;
|
resultNode = null;
|
||||||
} else {
|
} else {
|
||||||
resultNode = createNode();
|
resultNode = createNode();
|
||||||
|
resultNode.method = methodRef;
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
resultNode.setTag(methodRef + ":RESULT");
|
resultNode.setTag(methodRef + ":RESULT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DependencyNode thrown = createNode();
|
DependencyNode thrown = createNode();
|
||||||
|
thrown.method = methodRef;
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
thrown.setTag(methodRef + ":THROWN");
|
thrown.setTag(methodRef + ":THROWN");
|
||||||
}
|
}
|
||||||
final MethodDependency dep = new MethodDependency(this, parameterNodes, paramCount, resultNode, thrown,
|
MethodDependency dep = new MethodDependency(this, parameterNodes, paramCount, resultNode, thrown,
|
||||||
method, methodRef);
|
method, methodRef);
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
tasks.add(() -> {
|
tasks.add(() -> {
|
||||||
|
@ -314,7 +354,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
return dep;
|
return dep;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduleMethodAnalysis(final MethodDependency dep) {
|
void scheduleMethodAnalysis(MethodDependency dep) {
|
||||||
tasks.add(() -> {
|
tasks.add(() -> {
|
||||||
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
|
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
|
||||||
graphBuilder.buildGraph(dep);
|
graphBuilder.buildGraph(dep);
|
||||||
|
@ -322,23 +362,26 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<MethodReference> getAchievableMethods() {
|
public Collection<MethodReference> getReachableMethods() {
|
||||||
return methodCache.getCachedPreimages();
|
return methodCache.getCachedPreimages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FieldReference> getAchievableFields() {
|
public Collection<FieldReference> getReachableFields() {
|
||||||
return fieldCache.getCachedPreimages();
|
return fieldCache.getCachedPreimages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getAchievableClasses() {
|
public Collection<String> getReachableClasses() {
|
||||||
return classCache.getCachedPreimages();
|
return classCache.getCachedPreimages();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<FieldReference> fieldsAddedByRoot = new HashSet<>();
|
private Set<FieldReference> fieldsAddedByRoot = new HashSet<>();
|
||||||
|
|
||||||
public FieldDependency linkField(final FieldReference fieldRef, final CallLocation location) {
|
public FieldDependency linkField(FieldReference fieldRef, CallLocation location) {
|
||||||
|
if (completing) {
|
||||||
|
throw new IllegalStateException("Can't submit class during completion phase");
|
||||||
|
}
|
||||||
boolean added = true;
|
boolean added = true;
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
added = callGraph.getNode(location.getMethod()).addFieldAccess(fieldRef, location.getSourceLocation());
|
added = callGraph.getNode(location.getMethod()).addFieldAccess(fieldRef, location.getSourceLocation());
|
||||||
|
@ -382,7 +425,7 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
private void activateDependencyPlugin(MethodDependency methodDep, CallLocation location) {
|
private void activateDependencyPlugin(MethodDependency methodDep, CallLocation location) {
|
||||||
attachDependencyPlugin(methodDep);
|
attachDependencyPlugin(methodDep);
|
||||||
if (methodDep.dependencyPlugin != null) {
|
if (methodDep.dependencyPlugin != null) {
|
||||||
methodDep.dependencyPlugin.methodAchieved(agent, methodDep, location);
|
methodDep.dependencyPlugin.methodReached(agent, methodDep, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,8 +464,10 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
return method != null ? methodCache.getKnown(method.getReference()) : null;
|
return method != null ? methodCache.getKnown(method.getReference()) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processDependencies() {
|
private void processQueue() {
|
||||||
interrupted = false;
|
if (interrupted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (!tasks.isEmpty()) {
|
while (!tasks.isEmpty()) {
|
||||||
tasks.poll().run();
|
tasks.poll().run();
|
||||||
|
@ -436,6 +481,45 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void processDependencies() {
|
||||||
|
interrupted = false;
|
||||||
|
processQueue();
|
||||||
|
if (!interrupted) {
|
||||||
|
completing = true;
|
||||||
|
lock();
|
||||||
|
for (DependencyListener listener : listeners) {
|
||||||
|
listener.completing(agent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lock() {
|
||||||
|
for (MethodReference method : getReachableMethods()) {
|
||||||
|
lock(getMethod(method), true);
|
||||||
|
}
|
||||||
|
for (FieldReference field : getReachableFields()) {
|
||||||
|
lock(getField(field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lock(MethodDependency dep, boolean lock) {
|
||||||
|
for (DependencyNode node : dep.variableNodes) {
|
||||||
|
if (node != null) {
|
||||||
|
node.locked = lock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dep.resultNode != null) {
|
||||||
|
dep.resultNode.locked = lock;
|
||||||
|
}
|
||||||
|
if (dep.thrown != null) {
|
||||||
|
dep.thrown.locked = lock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lock(FieldDependency dep) {
|
||||||
|
dep.value.locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
public <T> T getService(Class<T> type) {
|
public <T> T getService(Class<T> type) {
|
||||||
return services.getService(type);
|
return services.getService(type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,10 @@ class DependencyGraphBuilder {
|
||||||
nodeClassCount = Math.max(nodeClassCount, nodeMapping[i] + 1);
|
nodeClassCount = Math.max(nodeClassCount, nodeMapping[i] + 1);
|
||||||
}
|
}
|
||||||
DependencyNode[] nodeClasses = Arrays.copyOf(dep.getVariables(), nodeClassCount);
|
DependencyNode[] nodeClasses = Arrays.copyOf(dep.getVariables(), nodeClassCount);
|
||||||
|
MethodReference ref = method.getReference();
|
||||||
for (int i = dep.getVariableCount(); i < nodeClasses.length; ++i) {
|
for (int i = dep.getVariableCount(); i < nodeClasses.length; ++i) {
|
||||||
nodeClasses[i] = dependencyChecker.createNode();
|
nodeClasses[i] = dependencyChecker.createNode();
|
||||||
|
nodeClasses[i].method = ref;
|
||||||
if (DependencyChecker.shouldLog) {
|
if (DependencyChecker.shouldLog) {
|
||||||
nodeClasses[i].setTag(dep.getMethod().getReference() + ":" + i);
|
nodeClasses[i].setTag(dep.getMethod().getReference() + ":" + i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,11 @@ public interface DependencyInfo {
|
||||||
|
|
||||||
ClassLoader getClassLoader();
|
ClassLoader getClassLoader();
|
||||||
|
|
||||||
Collection<MethodReference> getAchievableMethods();
|
Collection<MethodReference> getReachableMethods();
|
||||||
|
|
||||||
Collection<FieldReference> getAchievableFields();
|
Collection<FieldReference> getReachableFields();
|
||||||
|
|
||||||
Collection<String> getAchievableClasses();
|
Collection<String> getReachableClasses();
|
||||||
|
|
||||||
FieldDependencyInfo getField(FieldReference fieldRef);
|
FieldDependencyInfo getField(FieldReference fieldRef);
|
||||||
|
|
||||||
|
|
|
@ -29,4 +29,6 @@ public interface DependencyListener {
|
||||||
void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location);
|
void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location);
|
||||||
|
|
||||||
void fieldReached(DependencyAgent agent, FieldDependency field, CallLocation location);
|
void fieldReached(DependencyAgent agent, FieldDependency field, CallLocation location);
|
||||||
|
|
||||||
|
void completing(DependencyAgent agent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -31,6 +32,8 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
private DependencyNode arrayItemNode;
|
private DependencyNode arrayItemNode;
|
||||||
private int degree;
|
private int degree;
|
||||||
int index;
|
int index;
|
||||||
|
boolean locked;
|
||||||
|
MethodReference method;
|
||||||
|
|
||||||
DependencyNode(DependencyChecker dependencyChecker, int index) {
|
DependencyNode(DependencyChecker dependencyChecker, int index) {
|
||||||
this(dependencyChecker, index, 0);
|
this(dependencyChecker, index, 0);
|
||||||
|
@ -45,6 +48,10 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
private boolean addType(DependencyType type) {
|
private boolean addType(DependencyType type) {
|
||||||
if (types == null) {
|
if (types == null) {
|
||||||
if (smallTypes == null) {
|
if (smallTypes == null) {
|
||||||
|
if (locked) {
|
||||||
|
throw new IllegalStateException("Error propagating type " + type.getName()
|
||||||
|
+ " to node in " + method);
|
||||||
|
}
|
||||||
smallTypes = new int[] { type.index };
|
smallTypes = new int[] { type.index };
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -62,12 +69,19 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
}
|
}
|
||||||
smallTypes = null;
|
smallTypes = null;
|
||||||
} else {
|
} else {
|
||||||
|
if (locked) {
|
||||||
|
throw new IllegalStateException("Error propagating type " + type.getName() + " to node in method "
|
||||||
|
+ method);
|
||||||
|
}
|
||||||
smallTypes = Arrays.copyOf(smallTypes, smallTypes.length + 1);
|
smallTypes = Arrays.copyOf(smallTypes, smallTypes.length + 1);
|
||||||
smallTypes[smallTypes.length - 1] = type.index;
|
smallTypes[smallTypes.length - 1] = type.index;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!types.get(type.index)) {
|
if (!types.get(type.index)) {
|
||||||
|
if (locked) {
|
||||||
|
throw new IllegalStateException("Error propagating type " + type.getName() + " to node " + tag);
|
||||||
|
}
|
||||||
types.set(type.index);
|
types.set(type.index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,5 +22,5 @@ import org.teavm.model.CallLocation;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface DependencyPlugin {
|
public interface DependencyPlugin {
|
||||||
void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location);
|
void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.teavm.model.FieldReference;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class FieldDependency implements FieldDependencyInfo {
|
public class FieldDependency implements FieldDependencyInfo {
|
||||||
private DependencyNode value;
|
DependencyNode value;
|
||||||
private FieldReader field;
|
private FieldReader field;
|
||||||
private FieldReference reference;
|
private FieldReference reference;
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,13 @@ import org.teavm.model.MethodReference;
|
||||||
*/
|
*/
|
||||||
public class MethodDependency implements MethodDependencyInfo {
|
public class MethodDependency implements MethodDependencyInfo {
|
||||||
private DependencyChecker dependencyChecker;
|
private DependencyChecker dependencyChecker;
|
||||||
private DependencyNode[] variableNodes;
|
DependencyNode[] variableNodes;
|
||||||
private int parameterCount;
|
private int parameterCount;
|
||||||
private DependencyNode resultNode;
|
DependencyNode resultNode;
|
||||||
private DependencyNode thrown;
|
DependencyNode thrown;
|
||||||
MethodHolder method;
|
MethodHolder method;
|
||||||
private MethodReference reference;
|
private MethodReference reference;
|
||||||
private boolean used;
|
boolean used;
|
||||||
DependencyPlugin dependencyPlugin;
|
DependencyPlugin dependencyPlugin;
|
||||||
boolean dependencyPluginAttached;
|
boolean dependencyPluginAttached;
|
||||||
|
|
||||||
|
|
|
@ -1525,10 +1525,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
case NEGATE:
|
case NEGATE:
|
||||||
if (outerPrecedence.ordinal() > Precedence.UNARY.ordinal()) {
|
if (outerPrecedence.ordinal() > Precedence.UNARY.ordinal()) {
|
||||||
writer.append('(');
|
writer.append('(');
|
||||||
} else if (outerPrecedence.ordinal() >= Precedence.ADDITION.ordinal()) {
|
|
||||||
writer.append(' ');
|
|
||||||
}
|
}
|
||||||
writer.append("-");
|
writer.append(" -");
|
||||||
precedence = Precedence.UNARY;
|
precedence = Precedence.UNARY;
|
||||||
expr.getOperand().acceptVisitor(this);
|
expr.getOperand().acceptVisitor(this);
|
||||||
if (outerPrecedence.ordinal() > Precedence.UNARY.ordinal()) {
|
if (outerPrecedence.ordinal() > Precedence.UNARY.ordinal()) {
|
||||||
|
@ -1664,16 +1662,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
}
|
}
|
||||||
String str = constantToString(expr.getValue());
|
String str = constantToString(expr.getValue());
|
||||||
if (str.startsWith("-")) {
|
if (str.startsWith("-")) {
|
||||||
if (precedence.ordinal() >= Precedence.UNARY.ordinal()) {
|
|
||||||
writer.append('(');
|
|
||||||
} else {
|
|
||||||
writer.append(' ');
|
writer.append(' ');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
writer.append(str);
|
writer.append(str);
|
||||||
if (str.startsWith("-") && precedence.ordinal() >= Precedence.UNARY.ordinal()) {
|
|
||||||
writer.append(')');
|
|
||||||
}
|
|
||||||
if (expr.getLocation() != null) {
|
if (expr.getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.teavm.model.FieldReader;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.InstructionLocation;
|
import org.teavm.model.InstructionLocation;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
|
@ -146,6 +147,10 @@ public final class ProgramEmitter {
|
||||||
return var(var, type);
|
return var(var, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValueEmitter constantNull(Class<?> type) {
|
||||||
|
return constantNull(ValueType.parse(type));
|
||||||
|
}
|
||||||
|
|
||||||
public ValueEmitter defaultValue(ValueType type) {
|
public ValueEmitter defaultValue(ValueType type) {
|
||||||
if (type instanceof ValueType.Primitive) {
|
if (type instanceof ValueType.Primitive) {
|
||||||
switch (((ValueType.Primitive) type).getKind()) {
|
switch (((ValueType.Primitive) type).getKind()) {
|
||||||
|
@ -387,8 +392,13 @@ public final class ProgramEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ProgramEmitter create(MethodHolder method, ClassReaderSource classSource) {
|
public static ProgramEmitter create(MethodHolder method, ClassReaderSource classSource) {
|
||||||
|
ProgramEmitter pe = create(method.getDescriptor(), classSource);
|
||||||
|
method.setProgram(pe.getProgram());
|
||||||
|
return pe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProgramEmitter create(MethodDescriptor method, ClassReaderSource classSource) {
|
||||||
Program program = new Program();
|
Program program = new Program();
|
||||||
method.setProgram(program);
|
|
||||||
BasicBlock zeroBlock = program.createBasicBlock();
|
BasicBlock zeroBlock = program.createBasicBlock();
|
||||||
BasicBlock block = program.createBasicBlock();
|
BasicBlock block = program.createBasicBlock();
|
||||||
|
|
||||||
|
@ -440,13 +450,13 @@ public final class ProgramEmitter {
|
||||||
return phi(ValueType.object(cls.getName()));
|
return phi(ValueType.object(cls.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChooseEmitter choise(ValueEmitter value) {
|
public ChooseEmitter choice(ValueEmitter value) {
|
||||||
SwitchInstruction insn = new SwitchInstruction();
|
SwitchInstruction insn = new SwitchInstruction();
|
||||||
insn.setCondition(value.getVariable());
|
insn.setCondition(value.getVariable());
|
||||||
return new ChooseEmitter(this, insn, prepareBlock());
|
return new ChooseEmitter(this, insn, prepareBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringChooseEmitter stringChoise(ValueEmitter value) {
|
public StringChooseEmitter stringChoice(ValueEmitter value) {
|
||||||
SwitchInstruction insn = new SwitchInstruction();
|
SwitchInstruction insn = new SwitchInstruction();
|
||||||
return new StringChooseEmitter(this, value, insn, prepareBlock());
|
return new StringChooseEmitter(this, value, insn, prepareBlock());
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,9 +41,9 @@ public class MissingItemsProcessor {
|
||||||
public MissingItemsProcessor(DependencyInfo dependencyInfo, Diagnostics diagnostics) {
|
public MissingItemsProcessor(DependencyInfo dependencyInfo, Diagnostics diagnostics) {
|
||||||
this.dependencyInfo = dependencyInfo;
|
this.dependencyInfo = dependencyInfo;
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
achievableClasses = dependencyInfo.getAchievableClasses();
|
achievableClasses = dependencyInfo.getReachableClasses();
|
||||||
achievableMethods = dependencyInfo.getAchievableMethods();
|
achievableMethods = dependencyInfo.getReachableMethods();
|
||||||
achievableFields = dependencyInfo.getAchievableFields();
|
achievableFields = dependencyInfo.getReachableFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processClass(ClassHolder cls) {
|
public void processClass(ClassHolder cls) {
|
||||||
|
|
|
@ -312,11 +312,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<String> getClasses() {
|
public Collection<String> getClasses() {
|
||||||
return dependencyChecker.getAchievableClasses();
|
return dependencyChecker.getReachableClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<MethodReference> getMethods() {
|
public Collection<MethodReference> getMethods() {
|
||||||
return dependencyChecker.getAchievableMethods();
|
return dependencyChecker.getReachableMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DependencyInfo getDependencyInfo() {
|
public DependencyInfo getDependencyInfo() {
|
||||||
|
@ -474,7 +474,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListableClassHolderSource link(DependencyInfo dependency) {
|
public ListableClassHolderSource link(DependencyInfo dependency) {
|
||||||
reportPhase(TeaVMPhase.LINKING, dependency.getAchievableClasses().size());
|
reportPhase(TeaVMPhase.LINKING, dependency.getReachableClasses().size());
|
||||||
Linker linker = new Linker();
|
Linker linker = new Linker();
|
||||||
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
||||||
MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency, diagnostics);
|
MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency, diagnostics);
|
||||||
|
@ -482,7 +482,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
return cutClasses;
|
return cutClasses;
|
||||||
}
|
}
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (String className : dependency.getAchievableClasses()) {
|
for (String className : dependency.getReachableClasses()) {
|
||||||
ClassReader clsReader = dependency.getClassSource().get(className);
|
ClassReader clsReader = dependency.getClassSource().get(className);
|
||||||
if (clsReader == null) {
|
if (clsReader == null) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -717,13 +717,16 @@ public class AstWriter {
|
||||||
private void printUnary(UnaryExpression node, int precedence) throws IOException {
|
private void printUnary(UnaryExpression node, int precedence) throws IOException {
|
||||||
int innerPrecedence = node.isPostfix() ? PRECEDENCE_POSTFIX : PRECEDENCE_PREFIX;
|
int innerPrecedence = node.isPostfix() ? PRECEDENCE_POSTFIX : PRECEDENCE_PREFIX;
|
||||||
|
|
||||||
|
|
||||||
if (innerPrecedence > precedence) {
|
if (innerPrecedence > precedence) {
|
||||||
writer.append('(');
|
writer.append('(');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node.isPostfix()) {
|
if (!node.isPostfix()) {
|
||||||
writer.append(AstNode.operatorToString(node.getType()));
|
String op = AstNode.operatorToString(node.getType());
|
||||||
|
if (op.startsWith("-")) {
|
||||||
|
writer.append(' ');
|
||||||
|
}
|
||||||
|
writer.append(op);
|
||||||
if (requiresWhitespaces(node.getType())) {
|
if (requiresWhitespaces(node.getType())) {
|
||||||
writer.append(' ');
|
writer.append(' ');
|
||||||
}
|
}
|
||||||
|
@ -768,13 +771,14 @@ public class AstWriter {
|
||||||
}
|
}
|
||||||
print(node.getLeft(), leftPrecedence);
|
print(node.getLeft(), leftPrecedence);
|
||||||
|
|
||||||
|
String op = AstNode.operatorToString(node.getType());
|
||||||
boolean ws = requiresWhitespaces(node.getType());
|
boolean ws = requiresWhitespaces(node.getType());
|
||||||
if (ws) {
|
if (ws || op.startsWith("-")) {
|
||||||
writer.append(' ');
|
writer.append(' ');
|
||||||
} else {
|
} else {
|
||||||
writer.ws();
|
writer.ws();
|
||||||
}
|
}
|
||||||
writer.append(AstNode.operatorToString(node.getType()));
|
writer.append(op);
|
||||||
if (ws) {
|
if (ws) {
|
||||||
writer.append(' ');
|
writer.append(' ');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -169,7 +169,7 @@ public class JSNativeGenerator implements Injector, DependencyPlugin, Generator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(final DependencyAgent agent, final MethodDependency method,
|
public void methodReached(final DependencyAgent agent, final MethodDependency method,
|
||||||
final CallLocation location) {
|
final CallLocation location) {
|
||||||
switch (method.getReference().getName()) {
|
switch (method.getReference().getName()) {
|
||||||
case "invoke":
|
case "invoke":
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class AsyncMethodGenerator implements Generator, DependencyPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyAgent checker, MethodDependency method, CallLocation location) {
|
public void methodReached(DependencyAgent checker, MethodDependency method, CallLocation location) {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
MethodReference asyncRef = getAsyncReference(ref);
|
MethodReference asyncRef = getAsyncReference(ref);
|
||||||
MethodDependency asyncMethod = checker.linkMethod(asyncRef, location);
|
MethodDependency asyncMethod = checker.linkMethod(asyncRef, location);
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class EnumDependencySupport extends AbstractDependencyListener {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
method.getResult().propagate(agent.getType("[java.lang.Enum"));
|
method.getResult().propagate(agent.getType("[java.lang.Enum"));
|
||||||
for (String cls : agent.getAchievableClasses()) {
|
for (String cls : agent.getReachableClasses()) {
|
||||||
classReached(agent, cls, location);
|
classReached(agent, cls, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ import org.teavm.platform.PlatformRunnable;
|
||||||
*/
|
*/
|
||||||
public class PlatformGenerator implements Generator, Injector, DependencyPlugin {
|
public class PlatformGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
switch (method.getReference().getName()) {
|
switch (method.getReference().getName()) {
|
||||||
case "asJavaClass":
|
case "asJavaClass":
|
||||||
method.getResult().propagate(agent.getType("java.lang.Class"));
|
method.getResult().propagate(agent.getType("java.lang.Class"));
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.teavm.platform.PlatformQueue;
|
||||||
*/
|
*/
|
||||||
public class PlatformQueueGenerator implements Injector, DependencyPlugin {
|
public class PlatformQueueGenerator implements Injector, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
MethodDependency addMethod = agent.linkMethod(new MethodReference(PlatformQueue.class, "wrap",
|
MethodDependency addMethod = agent.linkMethod(new MethodReference(PlatformQueue.class, "wrap",
|
||||||
Object.class, PlatformObject.class), null);
|
Object.class, PlatformObject.class), null);
|
||||||
addMethod.getVariable(1).connect(method.getResult());
|
addMethod.getVariable(1).connect(method.getResult());
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- Configure Java compiler to use Java 7 syntax -->
|
<!-- Configure Java compiler to use Java 8 syntax -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.1</version>
|
<version>3.1</version>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user