Speed-up dependency checker

=
This commit is contained in:
konsoletyper 2014-09-04 13:24:39 +04:00
parent ec9e927701
commit 89d6a453ec
7 changed files with 51 additions and 150 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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