diff --git a/core/src/main/java/org/teavm/callgraph/DefaultCallGraph.java b/core/src/main/java/org/teavm/callgraph/DefaultCallGraph.java index 1819c6192..865f37110 100644 --- a/core/src/main/java/org/teavm/callgraph/DefaultCallGraph.java +++ b/core/src/main/java/org/teavm/callgraph/DefaultCallGraph.java @@ -15,58 +15,98 @@ */ package org.teavm.callgraph; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.util.*; import org.teavm.model.FieldReference; import org.teavm.model.MethodReference; -/** - * - * @author Alexey Andreev - */ -public class DefaultCallGraph implements CallGraph { - private Map nodes = new HashMap<>(); - private Map> fieldAccessSites = new HashMap<>(); - private Map> classAccessSites = new HashMap<>(); +public class DefaultCallGraph implements CallGraph, Serializable { + private transient Map nodes = new HashMap<>(); + private List> nodeList; + private transient Map> fieldAccessSites = new HashMap<>(); + private List> fieldAccessSiteList; + private transient Map> classAccessSites = new HashMap<>(); + private List> classAccessSiteList; @Override public DefaultCallGraphNode getNode(MethodReference method) { - DefaultCallGraphNode node = nodes.get(method); - if (node == null) { - node = new DefaultCallGraphNode(this, method); - nodes.put(method, node); - } - return nodes.get(method); + ensureDeserialized(); + return nodes.computeIfAbsent(method, k -> new DefaultCallGraphNode(this, method)); } @Override public Collection getFieldAccess(FieldReference reference) { + ensureDeserialized(); Set resultSet = fieldAccessSites.get(reference); - return resultSet != null ? Collections.unmodifiableSet(resultSet) - : Collections.emptySet(); + return resultSet != null ? Collections.unmodifiableSet(resultSet) : Collections.emptySet(); } void addFieldAccess(DefaultFieldAccessSite accessSite) { - Set sites = fieldAccessSites.get(accessSite.getField()); - if (sites == null) { - sites = new HashSet<>(); - fieldAccessSites.put(accessSite.getField(), sites); - } - sites.add(accessSite); + ensureDeserialized(); + fieldAccessSites.computeIfAbsent(accessSite.getField(), k -> new HashSet<>()).add(accessSite); } @Override public Collection getClassAccess(String className) { + ensureDeserialized(); Set resultSet = classAccessSites.get(className); - return resultSet != null ? Collections.unmodifiableSet(resultSet) - : Collections.emptySet(); + return resultSet != null ? Collections.unmodifiableSet(resultSet) : Collections.emptySet(); } void addClassAccess(DefaultClassAccessSite accessSite) { - Set sites = classAccessSites.get(accessSite.getClassName()); - if (sites == null) { - sites = new HashSet<>(); - classAccessSites.put(accessSite.getClassName(), sites); + ensureDeserialized(); + classAccessSites.computeIfAbsent(accessSite.getClassName(), k -> new HashSet<>()).add(accessSite); + } + + private void ensureDeserialized() { + if (nodes != null) { + return; } - sites.add(accessSite); + + nodes = new HashMap<>(); + for (Map.Entry entry : nodeList) { + nodes.put(entry.getKey(), entry.getValue()); + } + nodeList = null; + + fieldAccessSites = new HashMap<>(); + for (Map.Entry entry : fieldAccessSiteList) { + fieldAccessSites.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).add(entry.getValue()); + } + fieldAccessSiteList = null; + + classAccessSites = new HashMap<>(); + for (Map.Entry entry : classAccessSiteList) { + classAccessSites.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).add(entry.getValue()); + } + classAccessSiteList = null; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + ensureDeserialized(); + nodeList = new ArrayList<>(nodes.entrySet()); + + fieldAccessSiteList = new ArrayList<>(); + for (Map.Entry> entry : fieldAccessSites.entrySet()) { + for (DefaultFieldAccessSite site : entry.getValue()) { + fieldAccessSiteList.add(new AbstractMap.SimpleEntry<>(entry.getKey(), site)); + } + } + + classAccessSiteList = new ArrayList<>(); + for (Map.Entry> entry : classAccessSites.entrySet()) { + for (DefaultClassAccessSite site : entry.getValue()) { + classAccessSiteList.add(new AbstractMap.SimpleEntry<>(entry.getKey(), site)); + } + } + + out.defaultWriteObject(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); } } diff --git a/core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java b/core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java index f1563c57d..33e153a30 100644 --- a/core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java +++ b/core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java @@ -15,6 +15,10 @@ */ package org.teavm.callgraph; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -25,20 +29,19 @@ import org.teavm.model.FieldReference; import org.teavm.model.MethodReference; import org.teavm.model.TextLocation; -/** - * - * @author Alexey Andreev - */ -public class DefaultCallGraphNode implements CallGraphNode { +public class DefaultCallGraphNode implements CallGraphNode, Serializable { private DefaultCallGraph graph; private MethodReference method; - private Set callSites = new HashSet<>(); + private transient Set callSites = new HashSet<>(); + private List callSiteList; private transient Set safeCallSites; private List callerCallSites = new ArrayList<>(); private transient List safeCallersCallSites; - private Set fieldAccessSites = new HashSet<>(); + private transient Set fieldAccessSites = new HashSet<>(); + private List fieldAccessSiteList; private transient Set safeFieldAccessSites; - private Set classAccessSites = new HashSet<>(); + private transient Set classAccessSites = new HashSet<>(); + private List classAccessSiteList; private transient Set safeClassAccessSites; DefaultCallGraphNode(DefaultCallGraph graph, MethodReference method) { @@ -58,6 +61,7 @@ public class DefaultCallGraphNode implements CallGraphNode { @Override public Collection getCallSites() { + ensureDeserialized(); if (safeCallSites == null) { safeCallSites = Collections.unmodifiableSet(callSites); } @@ -66,6 +70,7 @@ public class DefaultCallGraphNode implements CallGraphNode { @Override public Collection getCallerCallSites() { + ensureDeserialized(); if (safeCallersCallSites == null) { safeCallersCallSites = Collections.unmodifiableList(callerCallSites); } @@ -73,6 +78,7 @@ public class DefaultCallGraphNode implements CallGraphNode { } public boolean addCallSite(MethodReference method, TextLocation location) { + ensureDeserialized(); DefaultCallGraphNode callee = graph.getNode(method); DefaultCallSite callSite = new DefaultCallSite(location, callee, this); if (callSites.add(callSite)) { @@ -89,6 +95,7 @@ public class DefaultCallGraphNode implements CallGraphNode { @Override public Collection getFieldAccessSites() { + ensureDeserialized(); if (safeFieldAccessSites == null) { safeFieldAccessSites = Collections.unmodifiableSet(fieldAccessSites); } @@ -96,6 +103,7 @@ public class DefaultCallGraphNode implements CallGraphNode { } public boolean addFieldAccess(FieldReference field, TextLocation location) { + ensureDeserialized(); DefaultFieldAccessSite site = new DefaultFieldAccessSite(location, this, field); if (fieldAccessSites.add(site)) { graph.addFieldAccess(site); @@ -107,6 +115,7 @@ public class DefaultCallGraphNode implements CallGraphNode { @Override public Collection getClassAccessSites() { + ensureDeserialized(); if (safeClassAccessSites == null) { safeClassAccessSites = Collections.unmodifiableSet(classAccessSites); } @@ -114,6 +123,7 @@ public class DefaultCallGraphNode implements CallGraphNode { } public boolean addClassAccess(String className, TextLocation location) { + ensureDeserialized(); DefaultClassAccessSite site = new DefaultClassAccessSite(location, this, className); if (classAccessSites.add(site)) { graph.addClassAccess(site); @@ -122,4 +132,31 @@ public class DefaultCallGraphNode implements CallGraphNode { return false; } } + + private void ensureDeserialized() { + if (callSites != null) { + return; + } + + callSites = new HashSet<>(callSiteList); + callSiteList = null; + + fieldAccessSites = new HashSet<>(fieldAccessSiteList); + fieldAccessSiteList = null; + + classAccessSites = new HashSet<>(classAccessSiteList); + classAccessSiteList = null; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + ensureDeserialized(); + callSiteList = new ArrayList<>(callSites); + fieldAccessSiteList = new ArrayList<>(fieldAccessSites); + classAccessSiteList = new ArrayList<>(classAccessSites); + out.defaultWriteObject(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + } } diff --git a/core/src/main/java/org/teavm/callgraph/DefaultCallSite.java b/core/src/main/java/org/teavm/callgraph/DefaultCallSite.java index 6cb40f152..1e22993c7 100644 --- a/core/src/main/java/org/teavm/callgraph/DefaultCallSite.java +++ b/core/src/main/java/org/teavm/callgraph/DefaultCallSite.java @@ -15,14 +15,11 @@ */ package org.teavm.callgraph; +import java.io.Serializable; import java.util.Objects; import org.teavm.model.TextLocation; -/** - * - * @author Alexey Andreev - */ -public class DefaultCallSite implements CallSite { +public class DefaultCallSite implements CallSite, Serializable { private TextLocation location; private DefaultCallGraphNode callee; private DefaultCallGraphNode caller; diff --git a/core/src/main/java/org/teavm/callgraph/DefaultClassAccessSite.java b/core/src/main/java/org/teavm/callgraph/DefaultClassAccessSite.java index 85da4fdfa..afa679a44 100644 --- a/core/src/main/java/org/teavm/callgraph/DefaultClassAccessSite.java +++ b/core/src/main/java/org/teavm/callgraph/DefaultClassAccessSite.java @@ -15,14 +15,11 @@ */ package org.teavm.callgraph; +import java.io.Serializable; import java.util.Objects; import org.teavm.model.TextLocation; -/** - * - * @author Alexey Andreev - */ -public class DefaultClassAccessSite implements ClassAccessSite { +public class DefaultClassAccessSite implements ClassAccessSite, Serializable { private TextLocation location; private CallGraphNode callee; private String className; diff --git a/core/src/main/java/org/teavm/callgraph/DefaultFieldAccessSite.java b/core/src/main/java/org/teavm/callgraph/DefaultFieldAccessSite.java index 21cb13f18..b086e9d94 100644 --- a/core/src/main/java/org/teavm/callgraph/DefaultFieldAccessSite.java +++ b/core/src/main/java/org/teavm/callgraph/DefaultFieldAccessSite.java @@ -15,15 +15,12 @@ */ package org.teavm.callgraph; +import java.io.Serializable; import java.util.Objects; import org.teavm.model.FieldReference; import org.teavm.model.TextLocation; -/** - * - * @author Alexey Andreev - */ -public class DefaultFieldAccessSite implements FieldAccessSite { +public class DefaultFieldAccessSite implements FieldAccessSite, Serializable { private TextLocation location; private CallGraphNode callee; private FieldReference field; diff --git a/core/src/main/java/org/teavm/diagnostics/Problem.java b/core/src/main/java/org/teavm/diagnostics/Problem.java index ee35b6996..b310e154d 100644 --- a/core/src/main/java/org/teavm/diagnostics/Problem.java +++ b/core/src/main/java/org/teavm/diagnostics/Problem.java @@ -15,14 +15,11 @@ */ package org.teavm.diagnostics; +import java.io.Serializable; import java.util.Arrays; import org.teavm.model.*; -/** - * - * @author Alexey Andreev - */ -public class Problem { +public class Problem implements Serializable { private ProblemSeverity severity; private CallLocation location; private String text; diff --git a/core/src/main/java/org/teavm/diagnostics/ProblemProvider.java b/core/src/main/java/org/teavm/diagnostics/ProblemProvider.java index 8faa4e069..5aa38bcde 100644 --- a/core/src/main/java/org/teavm/diagnostics/ProblemProvider.java +++ b/core/src/main/java/org/teavm/diagnostics/ProblemProvider.java @@ -17,10 +17,6 @@ package org.teavm.diagnostics; import java.util.List; -/** - * - * @author Alexey Andreev - */ public interface ProblemProvider { List getProblems(); diff --git a/core/src/main/java/org/teavm/diagnostics/ProblemSeverity.java b/core/src/main/java/org/teavm/diagnostics/ProblemSeverity.java index 6e270b944..b26acca95 100644 --- a/core/src/main/java/org/teavm/diagnostics/ProblemSeverity.java +++ b/core/src/main/java/org/teavm/diagnostics/ProblemSeverity.java @@ -15,11 +15,9 @@ */ package org.teavm.diagnostics; -/** - * - * @author Alexey Andreev - */ -public enum ProblemSeverity { +import java.io.Serializable; + +public enum ProblemSeverity implements Serializable { ERROR, WARNING } diff --git a/core/src/main/java/org/teavm/model/CallLocation.java b/core/src/main/java/org/teavm/model/CallLocation.java index 5c753cd9a..0b00f3f8a 100644 --- a/core/src/main/java/org/teavm/model/CallLocation.java +++ b/core/src/main/java/org/teavm/model/CallLocation.java @@ -15,9 +15,10 @@ */ package org.teavm.model; +import java.io.Serializable; import java.util.Objects; -public class CallLocation { +public class CallLocation implements Serializable { private MethodReference method; private TextLocation sourceLocation; diff --git a/core/src/main/java/org/teavm/model/FieldReference.java b/core/src/main/java/org/teavm/model/FieldReference.java index 5dc6ae891..a16cf6cb9 100644 --- a/core/src/main/java/org/teavm/model/FieldReference.java +++ b/core/src/main/java/org/teavm/model/FieldReference.java @@ -15,11 +15,9 @@ */ package org.teavm.model; -/** - * - * @author Alexey Andreev - */ -public class FieldReference { +import java.io.Serializable; + +public class FieldReference implements Serializable { private String className; private String fieldName; diff --git a/core/src/main/java/org/teavm/model/MethodReference.java b/core/src/main/java/org/teavm/model/MethodReference.java index 104e70fd1..76abd8300 100644 --- a/core/src/main/java/org/teavm/model/MethodReference.java +++ b/core/src/main/java/org/teavm/model/MethodReference.java @@ -17,6 +17,7 @@ package org.teavm.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import java.io.Serializable; import java.util.Arrays; /** @@ -30,7 +31,7 @@ import java.util.Arrays; * * @author Alexey Andreev */ -public class MethodReference { +public class MethodReference implements Serializable { private String className; private String name; private ValueType[] signature; diff --git a/core/src/main/java/org/teavm/model/PrimitiveType.java b/core/src/main/java/org/teavm/model/PrimitiveType.java index 1c3ba2fce..83edda24c 100644 --- a/core/src/main/java/org/teavm/model/PrimitiveType.java +++ b/core/src/main/java/org/teavm/model/PrimitiveType.java @@ -15,11 +15,9 @@ */ package org.teavm.model; -/** - * - * @author Alexey Andreev - */ -public enum PrimitiveType { +import java.io.Serializable; + +public enum PrimitiveType implements Serializable { BOOLEAN, CHARACTER, BYTE, diff --git a/core/src/main/java/org/teavm/model/TextLocation.java b/core/src/main/java/org/teavm/model/TextLocation.java index 9995d41ce..73675ef98 100644 --- a/core/src/main/java/org/teavm/model/TextLocation.java +++ b/core/src/main/java/org/teavm/model/TextLocation.java @@ -15,9 +15,10 @@ */ package org.teavm.model; +import java.io.Serializable; import java.util.Objects; -public class TextLocation { +public class TextLocation implements Serializable { private String fileName; private int line = -1; diff --git a/core/src/main/java/org/teavm/model/ValueType.java b/core/src/main/java/org/teavm/model/ValueType.java index bf7fc948d..d554f643d 100644 --- a/core/src/main/java/org/teavm/model/ValueType.java +++ b/core/src/main/java/org/teavm/model/ValueType.java @@ -15,15 +15,11 @@ */ package org.teavm.model; +import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; - -/** - * - * @author Alexey Andreev - */ -public abstract class ValueType { +public abstract class ValueType implements Serializable { volatile String reprCache; private static final Map, ValueType> primitiveMap = new HashMap<>(); diff --git a/core/src/main/java/org/teavm/vm/TeaVMProgressFeedback.java b/core/src/main/java/org/teavm/vm/TeaVMProgressFeedback.java index 54d7470ea..7fd870c11 100644 --- a/core/src/main/java/org/teavm/vm/TeaVMProgressFeedback.java +++ b/core/src/main/java/org/teavm/vm/TeaVMProgressFeedback.java @@ -15,11 +15,9 @@ */ package org.teavm.vm; -/** - * - * @author Alexey Andreev - */ -public enum TeaVMProgressFeedback { +import java.io.Serializable; + +public enum TeaVMProgressFeedback implements Serializable { CONTINUE, CANCEL }