Reduce memory consumption

This commit is contained in:
Alexey Andreev 2024-03-18 17:02:42 +01:00
parent 6e416c11d7
commit 622006de0e
4 changed files with 90 additions and 38 deletions

View File

@ -42,7 +42,7 @@ public class DependencyNode implements ValueDependencyInfo {
private DependencyNode arrayItemNode;
DependencyNode classValueNode;
DependencyNode classNodeParent;
boolean classNodeComplete;
private boolean classNodeComplete;
int degree;
boolean locked;
MethodReference method;
@ -65,13 +65,13 @@ public class DependencyNode implements ValueDependencyInfo {
propagateCount++;
moveToSeparateDomain();
typeSet.addType(type);
scheduleSingleType(type, null);
scheduleSingleType(type);
}
}
private void scheduleSingleType(DependencyType type, Runnable action) {
private void scheduleSingleType(DependencyType type) {
if (DependencyAnalyzer.shouldLog) {
for (DependencyNode node : typeSet.domain) {
for (DependencyNode node : typeSet.domain()) {
if (node.filter(type)) {
System.out.println(node.tag + " -> " + type.getName());
}
@ -81,10 +81,6 @@ public class DependencyNode implements ValueDependencyInfo {
Transition[] transitions = typeSet.getTransitions().toArray(Transition.class);
List<ConsumerWithNode> consumerEntries = typeSet.getConsumers();
if (action != null) {
action.run();
}
for (Transition transition : transitions) {
if (transition.source.filter(type) && transition.filterType(type)) {
dependencyAnalyzer.schedulePropagation(transition, type);
@ -146,7 +142,7 @@ public class DependencyNode implements ValueDependencyInfo {
void scheduleMultipleTypes(DependencyType[] newTypes, Runnable action) {
if (DependencyAnalyzer.shouldLog) {
for (DependencyNode node : typeSet.domain) {
for (var node : typeSet.domain()) {
for (DependencyType type : newTypes) {
if (node.filter(type)) {
System.out.println(node.tag + " -> " + type.getName());
@ -217,16 +213,6 @@ public class DependencyNode implements ValueDependencyInfo {
}
}
static class DeferredConsumerTypes {
final DependencyConsumer consumer;
final DependencyType[] types;
DeferredConsumerTypes(DependencyConsumer consumer, DependencyType[] types) {
this.consumer = consumer;
this.types = types;
}
}
boolean filter(DependencyType type) {
if (typeFilter == null) {
return true;
@ -282,7 +268,7 @@ public class DependencyNode implements ValueDependencyInfo {
}
}
boolean connectWithoutChildNodes(DependencyNode node, DependencyTypeFilter filter) {
private boolean connectWithoutChildNodes(DependencyNode node, DependencyTypeFilter filter) {
if (this == node) {
return false;
}
@ -467,7 +453,7 @@ public class DependencyNode implements ValueDependencyInfo {
return i == result.length ? result : Arrays.copyOf(result, i);
}
DependencyType[] getTypesInternal(DependencyTypeFilter filter, DependencyNode sourceNode,
private DependencyType[] getTypesInternal(DependencyTypeFilter filter, DependencyNode sourceNode,
DependencyNode targetNode) {
if (typeSet == null) {
return TypeSet.EMPTY_TYPES;
@ -487,7 +473,7 @@ public class DependencyNode implements ValueDependencyInfo {
if (typeSet == null) {
Collection<DependencyNode> domain = findDomain();
typeSet = new TypeSet(dependencyAnalyzer, this);
typeSet.domain.addAll(domain);
typeSet.addDomain(domain);
for (DependencyNode node : domain) {
node.typeSet = typeSet;
}
@ -503,11 +489,11 @@ public class DependencyNode implements ValueDependencyInfo {
return;
}
typeSet.domain.removeAll(domain);
typeSet.removeDomain(domain);
typeSet.invalidate();
typeSet = typeSet.copy(this);
typeSet.domain.addAll(domain);
typeSet.addDomain(domain);
for (DependencyNode node : domain) {
node.typeSet = typeSet;
@ -515,7 +501,7 @@ public class DependencyNode implements ValueDependencyInfo {
}
}
Collection<DependencyNode> findDomain() {
private Collection<DependencyNode> findDomain() {
if (!dependencyAnalyzer.domainOptimizationEnabled()) {
return Collections.singleton(this);
}

View File

@ -17,7 +17,6 @@ package org.teavm.dependency;
import com.carrotsearch.hppc.IntHashSet;
import java.util.Arrays;
import java.util.Collection;
import org.teavm.model.ClassHierarchy;
import org.teavm.model.ValueType;
@ -26,7 +25,7 @@ class Transition {
DependencyNode destination;
DependencyTypeFilter filter;
IntHashSet pendingTypes;
byte destSubsetOfSrc;
private byte destSubsetOfSrc;
Transition(DependencyNode source, DependencyNode destination, DependencyTypeFilter filter) {
this.source = source;
@ -64,19 +63,19 @@ class Transition {
}
}
void mergeDomains(DependencyType[] types) {
private void mergeDomains(DependencyType[] types) {
destination.moveToSeparateDomain();
destination.scheduleMultipleTypes(types, () -> {
Collection<DependencyNode> domainToMerge = destination.typeSet.domain;
var domainToMerge = destination.typeSet.domain();
for (DependencyNode node : domainToMerge) {
node.typeSet = source.typeSet;
source.typeSet.domain.add(node);
source.typeSet.addDomain(node);
}
source.typeSet.invalidate();
});
}
boolean shouldMergeDomains() {
private boolean shouldMergeDomains() {
if (!source.dependencyAnalyzer.domainOptimizationEnabled() || filter != null || !isDestSubsetOfSrc()) {
return false;
}

View File

@ -20,7 +20,8 @@ import com.carrotsearch.hppc.cursors.ObjectCursor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.LinkedHashSet;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
@ -34,14 +35,14 @@ class TypeSet {
private BitSet types;
private int typesCount;
Set<DependencyNode> domain = new LinkedHashSet<>();
private Object domain;
ObjectArrayList<Transition> transitions;
ArrayList<ConsumerWithNode> consumers;
TypeSet(DependencyAnalyzer dependencyAnalyzer, DependencyNode origin) {
this.dependencyAnalyzer = dependencyAnalyzer;
this.origin = origin;
domain.add(origin);
domain = origin;
}
void addType(DependencyType type) {
@ -210,10 +211,76 @@ class TypeSet {
consumers = null;
}
Set<? extends DependencyNode> domain() {
if (domain == null) {
return Set.of();
} else if (domain instanceof DependencyNode) {
return Set.of((DependencyNode) domain);
} else {
//noinspection unchecked
return (Set<? extends DependencyNode>) domain;
}
}
void addDomain(DependencyNode node) {
if (domain == null) {
domain = node;
} else if (domain instanceof DependencyNode) {
if (domain == node) {
return;
}
domain = new HashSet<>(Set.of((DependencyNode) domain));
}
@SuppressWarnings("unchecked")
var set = (Set<DependencyNode>) domain;
set.add(node);
}
void addDomain(Collection<? extends DependencyNode> nodes) {
if (nodes.isEmpty()) {
return;
}
if (domain == null) {
if (nodes.size() == 1) {
domain = nodes.iterator().next();
}
return;
} else if (domain instanceof DependencyNode) {
if (nodes.contains(domain) && nodes.size() == 1) {
return;
}
domain = new HashSet<>(Set.of((DependencyNode) domain));
}
@SuppressWarnings("unchecked")
var set = (Set<DependencyNode>) domain;
set.addAll(nodes);
}
void removeDomain(Collection<? extends DependencyNode> nodes) {
if (domain == null || nodes.isEmpty()) {
return;
}
if (domain instanceof DependencyNode) {
if (nodes.contains(domain)) {
domain = null;
}
return;
}
@SuppressWarnings("unchecked")
var set = (Set<DependencyNode>) domain;
set.removeAll(nodes);
if (set.isEmpty()) {
domain = null;
} else if (set.size() == 1) {
domain = set.iterator().next();
}
}
ObjectArrayList<Transition> getTransitions() {
if (transitions == null) {
transitions = new ObjectArrayList<>(domain.size() * 2);
for (DependencyNode node : domain) {
transitions = new ObjectArrayList<>();
for (DependencyNode node : domain()) {
if (node.transitions != null) {
for (ObjectCursor<Transition> cursor : node.transitionList) {
Transition transition = cursor.value;
@ -230,7 +297,7 @@ class TypeSet {
List<ConsumerWithNode> getConsumers() {
if (consumers == null) {
consumers = new ArrayList<>();
for (DependencyNode node : domain) {
for (var node : domain()) {
if (node.followers != null) {
consumers.add(new ConsumerWithNode(node.followers.toArray(new DependencyConsumer[0]), node));
}

View File

@ -22,7 +22,7 @@ import org.teavm.model.CallLocation;
import org.teavm.model.MethodDescriptor;
class VirtualCallConsumer implements DependencyConsumer {
private static int SMALL_TYPES_THRESHOLD = 16;
private static final int SMALL_TYPES_THRESHOLD = 16;
private final MethodDescriptor methodDesc;
private final DependencyAnalyzer analyzer;
private final DependencyNode[] parameters;