mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Speed-up dependency checker
=
This commit is contained in:
parent
ec9e927701
commit
89d6a453ec
|
@ -48,6 +48,9 @@ public class CachedMapper<T, R> implements Mapper<T, R> {
|
||||||
cache.put(preimage, wrapper);
|
cache.put(preimage, wrapper);
|
||||||
wrapper.value = innerMapper.map(preimage);
|
wrapper.value = innerMapper.map(preimage);
|
||||||
wrapper.computed = true;
|
wrapper.computed = true;
|
||||||
|
for (KeyListener<T> listener : keyListeners) {
|
||||||
|
listener.keyAdded(preimage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!wrapper.computed) {
|
if (!wrapper.computed) {
|
||||||
throw new IllegalStateException("Recursive calls are not allowed");
|
throw new IllegalStateException("Recursive calls are not allowed");
|
||||||
|
|
|
@ -153,7 +153,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
||||||
|
|
||||||
public void addEntryPoint(MethodReference methodRef, String... argumentTypes) {
|
public void addEntryPoint(MethodReference methodRef, String... argumentTypes) {
|
||||||
ValueType[] parameters = methodRef.getDescriptor().getParameterTypes();
|
ValueType[] parameters = methodRef.getDescriptor().getParameterTypes();
|
||||||
if (parameters.length != argumentTypes.length) {
|
if (parameters.length + 1 != argumentTypes.length) {
|
||||||
throw new IllegalArgumentException("argumentTypes length does not match the number of method's arguments");
|
throw new IllegalArgumentException("argumentTypes length does not match the number of method's arguments");
|
||||||
}
|
}
|
||||||
MethodDependency method = linkMethod(methodRef, DependencyStack.ROOT);
|
MethodDependency method = linkMethod(methodRef, DependencyStack.ROOT);
|
||||||
|
@ -173,6 +173,16 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void schedulePropagation(final DependencyConsumer consumer, final DependencyType[] types) {
|
||||||
|
tasks.add(new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
for (DependencyType type : types) {
|
||||||
|
consumer.consume(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
boolean achieveClass(String className, DependencyStack stack) {
|
boolean achieveClass(String className, DependencyStack stack) {
|
||||||
classStacks.put(className, stack);
|
classStacks.put(className, stack);
|
||||||
if (!achievableClasses.add(className)) {
|
if (!achievableClasses.add(className)) {
|
||||||
|
|
|
@ -20,5 +20,5 @@ package org.teavm.dependency;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface DependencyGraphCreator {
|
public interface DependencyGraphCreator {
|
||||||
DependencyGraphCreatorProduct createDependency(DependencyChecker checker, DependencyStack stack);
|
void createDependency(MethodDependency method);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import org.teavm.common.IntegerArray;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -67,15 +66,40 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void propagate(DependencyAgentType[] agentTypes) {
|
||||||
|
DependencyType[] types = new DependencyType[agentTypes.length];
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < agentTypes.length; ++i) {
|
||||||
|
DependencyAgentType agentType = agentTypes[i];
|
||||||
|
if (!(agentType instanceof DependencyType)) {
|
||||||
|
throw new IllegalArgumentException("The given type does not belong to the same dependency checker");
|
||||||
|
}
|
||||||
|
DependencyType type = (DependencyType)agentType;
|
||||||
|
if (type.getDependencyChecker() != dependencyChecker) {
|
||||||
|
throw new IllegalArgumentException("The given type does not belong to the same dependency checker");
|
||||||
|
}
|
||||||
|
if (!this.types.get(type.index)) {
|
||||||
|
types[j++] = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < j; ++i) {
|
||||||
|
this.types.set(types[i].index);
|
||||||
|
if (DependencyChecker.shouldLog) {
|
||||||
|
System.out.println(tag + " -> " + types[i].getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) {
|
||||||
|
dependencyChecker.schedulePropagation(consumer, Arrays.copyOf(types, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void addConsumer(DependencyConsumer consumer) {
|
public void addConsumer(DependencyConsumer consumer) {
|
||||||
if (followers.add(consumer)) {
|
if (followers.add(consumer)) {
|
||||||
IntegerArray indexes = new IntegerArray(8);
|
List<DependencyType> types = new ArrayList<>();
|
||||||
for (int index = types.nextSetBit(0); index >= 0; index = types.nextSetBit(index + 1)) {
|
for (int index = this.types.nextSetBit(0); index >= 0; index = this.types.nextSetBit(index + 1)) {
|
||||||
indexes.add(index);
|
types.add(dependencyChecker.types.get(index));
|
||||||
}
|
|
||||||
for (int index : indexes.getAll()) {
|
|
||||||
dependencyChecker.schedulePropagation(consumer, dependencyChecker.types.get(index));
|
|
||||||
}
|
}
|
||||||
|
dependencyChecker.schedulePropagation(consumer, types.toArray(new DependencyType[types.size()]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
@ -33,8 +32,8 @@ public class MethodDependency implements MethodDependencyInfo {
|
||||||
private DependencyStack stack;
|
private DependencyStack stack;
|
||||||
private MethodReader method;
|
private MethodReader method;
|
||||||
private MethodReference reference;
|
private MethodReference reference;
|
||||||
private AtomicBoolean used = new AtomicBoolean();
|
private boolean used;
|
||||||
private volatile Runnable useRunner;
|
private Runnable useRunner;
|
||||||
|
|
||||||
MethodDependency(DependencyChecker dependencyChecker, DependencyNode[] variableNodes, int parameterCount,
|
MethodDependency(DependencyChecker dependencyChecker, DependencyNode[] variableNodes, int parameterCount,
|
||||||
DependencyNode resultNode, DependencyNode thrown, DependencyStack stack, MethodReader method,
|
DependencyNode resultNode, DependencyNode thrown, DependencyStack stack, MethodReader method,
|
||||||
|
@ -102,11 +101,12 @@ public class MethodDependency implements MethodDependencyInfo {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUsed() {
|
public boolean isUsed() {
|
||||||
return used.get();
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void use() {
|
public void use() {
|
||||||
if (used.compareAndSet(false, true)) {
|
if (!used) {
|
||||||
|
used = true;
|
||||||
if (useRunner != null) {
|
if (useRunner != null) {
|
||||||
useRunner.run();
|
useRunner.run();
|
||||||
useRunner = null;
|
useRunner = null;
|
||||||
|
@ -119,9 +119,6 @@ public class MethodDependency implements MethodDependencyInfo {
|
||||||
runner.run();
|
runner.run();
|
||||||
} else {
|
} else {
|
||||||
useRunner = runner;
|
useRunner = runner;
|
||||||
if (isUsed()) {
|
|
||||||
runner.run();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 org.teavm.model.ClassReader;
|
|
||||||
import org.teavm.model.ClassReaderSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
class ProgrammableDependencyGraphCreator implements DependencyGraphCreator {
|
|
||||||
int nodeCount;
|
|
||||||
Connection[] connections;
|
|
||||||
TypeRestrictedConnection[] typeRestrictedConnections;
|
|
||||||
TypePropagation[] typePropagations;
|
|
||||||
String[] initializedClasses;
|
|
||||||
int[] variableMap;
|
|
||||||
int resultIndex;
|
|
||||||
|
|
||||||
ProgrammableDependencyGraphCreator() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DependencyGraphCreatorProduct createDependency(DependencyChecker checker, DependencyStack stack) {
|
|
||||||
DependencyNode[] nodes = new DependencyNode[nodeCount];
|
|
||||||
for (int i = 0; i < nodes.length; ++i) {
|
|
||||||
nodes[i] = checker.createNode();
|
|
||||||
}
|
|
||||||
for (Connection conn : connections) {
|
|
||||||
nodes[conn.from].connect(nodes[conn.to]);
|
|
||||||
}
|
|
||||||
for (TypeRestrictedConnection conn : typeRestrictedConnections) {
|
|
||||||
nodes[conn.from].connect(nodes[conn.to], new DependencySupertypeFilter(checker.getClassSource(),
|
|
||||||
checker.getClassSource().get(conn.superclass)));
|
|
||||||
}
|
|
||||||
for (TypePropagation propagation : typePropagations) {
|
|
||||||
nodes[propagation.var].propagate(checker.getType(propagation.type));
|
|
||||||
}
|
|
||||||
for (String className : initializedClasses) {
|
|
||||||
checker.initClass(className, stack);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Connection {
|
|
||||||
int from;
|
|
||||||
int to;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TypeRestrictedConnection {
|
|
||||||
int from;
|
|
||||||
int to;
|
|
||||||
String superclass;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TypePropagation {
|
|
||||||
int var;
|
|
||||||
String type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DependencySupertypeFilter implements DependencyTypeFilter {
|
|
||||||
private ClassReaderSource classSource;
|
|
||||||
private ClassReader superClass;
|
|
||||||
public DependencySupertypeFilter(ClassReaderSource classSource, ClassReader superClass) {
|
|
||||||
this.classSource = classSource;
|
|
||||||
this.superClass = superClass;
|
|
||||||
}
|
|
||||||
@Override public boolean match(DependencyAgentType type) {
|
|
||||||
if (superClass.getName().equals("java.lang.Object")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return isAssignableFrom(classSource, superClass, type.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isAssignableFrom(ClassReaderSource classSource, ClassReader supertype,
|
|
||||||
String subtypeName) {
|
|
||||||
if (supertype.getName().equals(subtypeName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ClassReader subtype = classSource.get(subtypeName);
|
|
||||||
if (subtype == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (subtype.getParent() != null && isAssignableFrom(classSource, supertype, subtype.getParent())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (String iface : subtype.getInterfaces()) {
|
|
||||||
if (isAssignableFrom(classSource, supertype, iface)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class ProgrammableDependencyGraphCreatorBuilder {
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user