Fixes small bugs. Introduces a new class source that does a slight

optimization before providing classes.
This commit is contained in:
konsoletyper 2014-09-04 17:18:22 +04:00
parent 89d6a453ec
commit f740782881
3 changed files with 63 additions and 35 deletions

View File

@ -16,9 +16,9 @@
package org.teavm.dependency; package org.teavm.dependency;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.*; import org.teavm.model.instructions.*;
import org.teavm.model.util.ListingBuilder; import org.teavm.model.util.ListingBuilder;
@ -124,7 +124,7 @@ class DependencyGraphBuilder {
private final DependencyNode[] parameters; private final DependencyNode[] parameters;
private final DependencyNode result; private final DependencyNode result;
private final DependencyStack stack; private final DependencyStack stack;
private final ConcurrentMap<MethodReference, MethodReference> knownMethods = new ConcurrentHashMap<>(); private final Set<MethodReference> knownMethods = new HashSet<>();
private ExceptionConsumer exceptionConsumer; private ExceptionConsumer exceptionConsumer;
public VirtualCallConsumer(DependencyNode node, ClassReader filterClass, public VirtualCallConsumer(DependencyNode node, ClassReader filterClass,
@ -155,13 +155,13 @@ class DependencyGraphBuilder {
} }
MethodReference methodRef = new MethodReference(className, methodDesc); MethodReference methodRef = new MethodReference(className, methodDesc);
MethodDependency methodDep = checker.linkMethod(methodRef, stack); MethodDependency methodDep = checker.linkMethod(methodRef, stack);
if (!methodDep.isMissing() && knownMethods.putIfAbsent(methodRef, methodRef) == null) { if (!methodDep.isMissing() && knownMethods.add(methodRef)) {
methodDep.use(); methodDep.use();
DependencyNode[] targetParams = methodDep.getVariables(); DependencyNode[] targetParams = methodDep.getVariables();
for (int i = 0; i < parameters.length; ++i) { for (int i = 0; i < parameters.length; ++i) {
parameters[i].connect(targetParams[i]); parameters[i].connect(targetParams[i]);
} }
if (methodDep.getResult() != null) { if (result != null && methodDep.getResult() != null) {
methodDep.getResult().connect(result); methodDep.getResult().connect(result);
} }
methodDep.getThrown().addConsumer(exceptionConsumer); methodDep.getThrown().addConsumer(exceptionConsumer);

View File

@ -16,10 +16,6 @@
package org.teavm.dependency; package org.teavm.dependency;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
/** /**
* *
@ -29,10 +25,9 @@ public class DependencyNode implements ValueDependencyInfo {
private DependencyChecker dependencyChecker; private DependencyChecker dependencyChecker;
private Set<DependencyConsumer> followers = new HashSet<>(); private Set<DependencyConsumer> followers = new HashSet<>();
private BitSet types = new BitSet(); private BitSet types = new BitSet();
private ConcurrentMap<DependencyNode, DependencyNodeToNodeTransition> transitions = new ConcurrentHashMap<>(); private Map<DependencyNode, DependencyNodeToNodeTransition> transitions = new HashMap<>();
private volatile String tag; private volatile String tag;
private final AtomicReference<DependencyNode> arrayItemNode = new AtomicReference<>(); private DependencyNode arrayItemNode;
private volatile CountDownLatch arrayItemNodeLatch = new CountDownLatch(1);
private int degree; private int degree;
DependencyNode(DependencyChecker dependencyChecker) { DependencyNode(DependencyChecker dependencyChecker) {
@ -105,7 +100,8 @@ public class DependencyNode implements ValueDependencyInfo {
public void connect(DependencyNode node, DependencyTypeFilter filter) { public void connect(DependencyNode node, DependencyTypeFilter filter) {
DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter); DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter);
if (transitions.putIfAbsent(node, transition) == null) { if (!transitions.containsKey(node)) {
transitions.put(node, transition);
if (DependencyChecker.shouldLog) { if (DependencyChecker.shouldLog) {
System.out.println("Connecting " + tag + " to " + node.tag); System.out.println("Connecting " + tag + " to " + node.tag);
} }
@ -119,34 +115,18 @@ public class DependencyNode implements ValueDependencyInfo {
@Override @Override
public DependencyNode getArrayItem() { public DependencyNode getArrayItem() {
DependencyNode result = arrayItemNode.get(); if (arrayItemNode == null) {
if (result == null) { arrayItemNode = new DependencyNode(dependencyChecker, degree + 1);
result = new DependencyNode(dependencyChecker, degree + 1);
if (arrayItemNode.compareAndSet(null, result)) {
if (DependencyChecker.shouldLog) { if (DependencyChecker.shouldLog) {
arrayItemNode.get().tag = tag + "["; arrayItemNode.tag = tag + "[";
}
arrayItemNodeLatch.countDown();
arrayItemNodeLatch = null;
} else {
result = arrayItemNode.get();
} }
} }
CountDownLatch latch = arrayItemNodeLatch; return arrayItemNode;
if (latch != null) {
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return result;
}
}
return result;
} }
@Override @Override
public boolean hasArrayType() { public boolean hasArrayType() {
return arrayItemNode.get() != null && !arrayItemNode.get().types.isEmpty(); return arrayItemNode != null && arrayItemNode.types.isEmpty();
} }
public boolean hasType(DependencyAgentType type) { public boolean hasType(DependencyAgentType type) {

View File

@ -0,0 +1,48 @@
/*
* 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.model;
import java.util.HashMap;
import java.util.Map;
import org.teavm.optimization.GlobalValueNumbering;
import org.teavm.optimization.UnusedVariableElimination;
/**
*
* @author Alexey Andreev
*/
public class PreOptimizingClassHolderSource implements ClassHolderSource {
private ClassHolderSource innerClassSource;
private Map<String, ClassHolder> cache = new HashMap<>();
public PreOptimizingClassHolderSource(ClassHolderSource innerClassSource) {
this.innerClassSource = innerClassSource;
}
@Override
public ClassHolder get(String name) {
ClassHolder cls = cache.get(name);
if (cls == null) {
cls = innerClassSource.get(name);
for (MethodHolder method : cls.getMethods()) {
new GlobalValueNumbering().optimize(method, method.getProgram());
new UnusedVariableElimination().optimize(method, method.getProgram());
}
cache.put(name, cls);
}
return cls;
}
}