mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix serialization of call graph. Fix minor bugs in build daemon
This commit is contained in:
parent
1ae4a95128
commit
891b906a8c
|
@ -15,98 +15,251 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.callgraph;
|
package org.teavm.callgraph;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
|
import com.carrotsearch.hppc.ObjectIntOpenHashMap;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
public class DefaultCallGraph implements CallGraph, Serializable {
|
public class DefaultCallGraph implements CallGraph, Serializable {
|
||||||
private transient Map<MethodReference, DefaultCallGraphNode> nodes = new HashMap<>();
|
Map<MethodReference, DefaultCallGraphNode> nodes = new LinkedHashMap<>();
|
||||||
private List<Map.Entry<MethodReference, DefaultCallGraphNode>> nodeList;
|
Map<FieldReference, Set<DefaultFieldAccessSite>> fieldAccessSites = new LinkedHashMap<>();
|
||||||
private transient Map<FieldReference, Set<DefaultFieldAccessSite>> fieldAccessSites = new HashMap<>();
|
Map<String, Set<DefaultClassAccessSite>> classAccessSites = new LinkedHashMap<>();
|
||||||
private List<Map.Entry<FieldReference, DefaultFieldAccessSite>> fieldAccessSiteList;
|
|
||||||
private transient Map<String, Set<DefaultClassAccessSite>> classAccessSites = new HashMap<>();
|
|
||||||
private List<Map.Entry<String, DefaultClassAccessSite>> classAccessSiteList;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DefaultCallGraphNode getNode(MethodReference method) {
|
public DefaultCallGraphNode getNode(MethodReference method) {
|
||||||
ensureDeserialized();
|
|
||||||
return nodes.computeIfAbsent(method, k -> new DefaultCallGraphNode(this, method));
|
return nodes.computeIfAbsent(method, k -> new DefaultCallGraphNode(this, method));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DefaultFieldAccessSite> getFieldAccess(FieldReference reference) {
|
public Collection<DefaultFieldAccessSite> getFieldAccess(FieldReference reference) {
|
||||||
ensureDeserialized();
|
|
||||||
Set<DefaultFieldAccessSite> resultSet = fieldAccessSites.get(reference);
|
Set<DefaultFieldAccessSite> resultSet = fieldAccessSites.get(reference);
|
||||||
return resultSet != null ? Collections.unmodifiableSet(resultSet) : Collections.emptySet();
|
return resultSet != null ? Collections.unmodifiableSet(resultSet) : Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFieldAccess(DefaultFieldAccessSite accessSite) {
|
void addFieldAccess(DefaultFieldAccessSite accessSite) {
|
||||||
ensureDeserialized();
|
|
||||||
fieldAccessSites.computeIfAbsent(accessSite.getField(), k -> new HashSet<>()).add(accessSite);
|
fieldAccessSites.computeIfAbsent(accessSite.getField(), k -> new HashSet<>()).add(accessSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DefaultClassAccessSite> getClassAccess(String className) {
|
public Collection<DefaultClassAccessSite> getClassAccess(String className) {
|
||||||
ensureDeserialized();
|
|
||||||
Set<DefaultClassAccessSite> resultSet = classAccessSites.get(className);
|
Set<DefaultClassAccessSite> resultSet = classAccessSites.get(className);
|
||||||
return resultSet != null ? Collections.unmodifiableSet(resultSet) : Collections.emptySet();
|
return resultSet != null ? Collections.unmodifiableSet(resultSet) : Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addClassAccess(DefaultClassAccessSite accessSite) {
|
void addClassAccess(DefaultClassAccessSite accessSite) {
|
||||||
ensureDeserialized();
|
|
||||||
classAccessSites.computeIfAbsent(accessSite.getClassName(), k -> new HashSet<>()).add(accessSite);
|
classAccessSites.computeIfAbsent(accessSite.getClassName(), k -> new HashSet<>()).add(accessSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureDeserialized() {
|
|
||||||
if (nodes != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes = new HashMap<>();
|
|
||||||
for (Map.Entry<MethodReference, DefaultCallGraphNode> entry : nodeList) {
|
|
||||||
nodes.put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
nodeList = null;
|
|
||||||
|
|
||||||
fieldAccessSites = new HashMap<>();
|
|
||||||
for (Map.Entry<FieldReference, DefaultFieldAccessSite> entry : fieldAccessSiteList) {
|
|
||||||
fieldAccessSites.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).add(entry.getValue());
|
|
||||||
}
|
|
||||||
fieldAccessSiteList = null;
|
|
||||||
|
|
||||||
classAccessSites = new HashMap<>();
|
|
||||||
for (Map.Entry<String, DefaultClassAccessSite> entry : classAccessSiteList) {
|
|
||||||
classAccessSites.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).add(entry.getValue());
|
|
||||||
}
|
|
||||||
classAccessSiteList = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||||
ensureDeserialized();
|
SerializableCallGraphBuilder builder = new SerializableCallGraphBuilder();
|
||||||
nodeList = new ArrayList<>(nodes.entrySet());
|
out.writeObject(builder.build(this));
|
||||||
|
|
||||||
fieldAccessSiteList = new ArrayList<>();
|
|
||||||
for (Map.Entry<FieldReference, Set<DefaultFieldAccessSite>> entry : fieldAccessSites.entrySet()) {
|
|
||||||
for (DefaultFieldAccessSite site : entry.getValue()) {
|
|
||||||
fieldAccessSiteList.add(new AbstractMap.SimpleEntry<>(entry.getKey(), site));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
classAccessSiteList = new ArrayList<>();
|
|
||||||
for (Map.Entry<String, Set<DefaultClassAccessSite>> 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 {
|
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||||
in.defaultReadObject();
|
SerializableCallGraph scg = (SerializableCallGraph) in.readObject();
|
||||||
|
nodes = new LinkedHashMap<>();
|
||||||
|
fieldAccessSites = new LinkedHashMap<>();
|
||||||
|
classAccessSites = new LinkedHashMap<>();
|
||||||
|
new CallGraphBuilder().build(scg, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SerializableCallGraphBuilder {
|
||||||
|
List<SerializableCallGraph.Node> nodes = new ArrayList<>();
|
||||||
|
ObjectIntMap<DefaultCallGraphNode> nodeToIndex = new ObjectIntOpenHashMap<>();
|
||||||
|
List<SerializableCallGraph.CallSite> callSites = new ArrayList<>();
|
||||||
|
List<DefaultCallSite> originalCallSites = new ArrayList<>();
|
||||||
|
ObjectIntMap<DefaultCallSite> callSiteToIndex = new ObjectIntOpenHashMap<>();
|
||||||
|
List<SerializableCallGraph.FieldAccess> fieldAccessList = new ArrayList<>();
|
||||||
|
ObjectIntMap<DefaultFieldAccessSite> fieldAccessToIndex = new ObjectIntOpenHashMap<>();
|
||||||
|
List<SerializableCallGraph.ClassAccess> classAccessList = new ArrayList<>();
|
||||||
|
ObjectIntMap<DefaultClassAccessSite> classAccessToIndex = new ObjectIntOpenHashMap<>();
|
||||||
|
List<DefaultCallGraphNode> nodesToProcess = new ArrayList<>();
|
||||||
|
List<DefaultCallSite> callSitesToProcess = new ArrayList<>();
|
||||||
|
List<DefaultFieldAccessSite> fieldAccessToProcess = new ArrayList<>();
|
||||||
|
List<DefaultClassAccessSite> classAccessToProcess = new ArrayList<>();
|
||||||
|
|
||||||
|
SerializableCallGraph build(DefaultCallGraph cg) {
|
||||||
|
SerializableCallGraph scg = new SerializableCallGraph();
|
||||||
|
|
||||||
|
scg.nodeIndexes = cg.nodes.values().stream()
|
||||||
|
.mapToInt(this::getNode)
|
||||||
|
.toArray();
|
||||||
|
scg.fieldAccessIndexes = cg.fieldAccessSites.values().stream()
|
||||||
|
.flatMapToInt(accessSites -> accessSites.stream().mapToInt(this::getFieldAccess))
|
||||||
|
.toArray();
|
||||||
|
scg.classAccessIndexes = cg.classAccessSites.values().stream()
|
||||||
|
.flatMapToInt(accessSites -> accessSites.stream().mapToInt(this::getClassAccess))
|
||||||
|
.toArray();
|
||||||
|
|
||||||
|
while (step()) {
|
||||||
|
// just repeat
|
||||||
|
}
|
||||||
|
|
||||||
|
scg.nodes = nodes.toArray(new SerializableCallGraph.Node[0]);
|
||||||
|
scg.callSites = callSites.toArray(new SerializableCallGraph.CallSite[0]);
|
||||||
|
scg.fieldAccessList = fieldAccessList.toArray(new SerializableCallGraph.FieldAccess[0]);
|
||||||
|
scg.classAccessList = classAccessList.toArray(new SerializableCallGraph.ClassAccess[0]);
|
||||||
|
|
||||||
|
return scg;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean step() {
|
||||||
|
return processNodes() | processCallSites() | processFieldAccess() | processClassAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean processNodes() {
|
||||||
|
boolean hasAny = false;
|
||||||
|
for (DefaultCallGraphNode node : nodesToProcess.toArray(new DefaultCallGraphNode[0])) {
|
||||||
|
int index = nodeToIndex.get(node);
|
||||||
|
SerializableCallGraph.Node serializableNode = nodes.get(index);
|
||||||
|
serializableNode.method = node.getMethod();
|
||||||
|
serializableNode.callSites = node.getCallSites().stream()
|
||||||
|
.mapToInt(this::getCallSite)
|
||||||
|
.toArray();
|
||||||
|
serializableNode.callerCallSites = node.getCallerCallSites().stream()
|
||||||
|
.mapToInt(this::getCallSite)
|
||||||
|
.toArray();
|
||||||
|
serializableNode.fieldAccessSites = node.getFieldAccessSites().stream()
|
||||||
|
.mapToInt(this::getFieldAccess)
|
||||||
|
.toArray();
|
||||||
|
serializableNode.classAccessSites = node.getClassAccessSites().stream()
|
||||||
|
.mapToInt(this::getClassAccess)
|
||||||
|
.toArray();
|
||||||
|
hasAny = true;
|
||||||
|
}
|
||||||
|
nodesToProcess.clear();
|
||||||
|
return hasAny;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean processCallSites() {
|
||||||
|
boolean hasAny = false;
|
||||||
|
for (DefaultCallSite callSite : callSitesToProcess.toArray(new DefaultCallSite[0])) {
|
||||||
|
int index = callSiteToIndex.get(callSite);
|
||||||
|
SerializableCallGraph.CallSite scs = callSites.get(index);
|
||||||
|
scs.location = callSite.getLocation();
|
||||||
|
scs.caller = getNode(callSite.getCaller());
|
||||||
|
scs.callee = getNode(callSite.getCallee());
|
||||||
|
hasAny = true;
|
||||||
|
}
|
||||||
|
callSitesToProcess.clear();
|
||||||
|
return hasAny;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean processFieldAccess() {
|
||||||
|
boolean hasAny = false;
|
||||||
|
for (DefaultFieldAccessSite accessSite : fieldAccessToProcess.toArray(new DefaultFieldAccessSite[0])) {
|
||||||
|
int index = fieldAccessToIndex.get(accessSite);
|
||||||
|
SerializableCallGraph.FieldAccess sfa = fieldAccessList.get(index);
|
||||||
|
sfa.location = accessSite.getLocation();
|
||||||
|
sfa.field = accessSite.getField();
|
||||||
|
sfa.callee = getNode(accessSite.getCallee());
|
||||||
|
hasAny = true;
|
||||||
|
}
|
||||||
|
fieldAccessToProcess.clear();
|
||||||
|
return hasAny;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean processClassAccess() {
|
||||||
|
boolean hasAny = false;
|
||||||
|
for (DefaultClassAccessSite accessSite : classAccessToProcess.toArray(new DefaultClassAccessSite[0])) {
|
||||||
|
int index = classAccessToIndex.get(accessSite);
|
||||||
|
SerializableCallGraph.ClassAccess sca = classAccessList.get(index);
|
||||||
|
sca.location = accessSite.getLocation();
|
||||||
|
sca.className = accessSite.getClassName();
|
||||||
|
sca.callee = getNode(accessSite.getCallee());
|
||||||
|
hasAny = true;
|
||||||
|
}
|
||||||
|
classAccessToProcess.clear();
|
||||||
|
return hasAny;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getNode(DefaultCallGraphNode node) {
|
||||||
|
int index = nodeToIndex.getOrDefault(node, -1);
|
||||||
|
if (index < 0) {
|
||||||
|
index = nodeToIndex.size();
|
||||||
|
nodeToIndex.put(node, index);
|
||||||
|
nodes.add(new SerializableCallGraph.Node());
|
||||||
|
nodesToProcess.add(node);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getCallSite(DefaultCallSite callSite) {
|
||||||
|
int index = callSiteToIndex.getOrDefault(callSite, -1);
|
||||||
|
if (index < 0) {
|
||||||
|
index = callSiteToIndex.size();
|
||||||
|
callSiteToIndex.put(callSite, index);
|
||||||
|
callSites.add(new SerializableCallGraph.CallSite());
|
||||||
|
callSitesToProcess.add(callSite);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getFieldAccess(DefaultFieldAccessSite fieldAccessSite) {
|
||||||
|
int index = fieldAccessToIndex.getOrDefault(fieldAccessSite, -1);
|
||||||
|
if (index < 0) {
|
||||||
|
index = fieldAccessToIndex.size();
|
||||||
|
fieldAccessToIndex.put(fieldAccessSite, index);
|
||||||
|
fieldAccessList.add(new SerializableCallGraph.FieldAccess());
|
||||||
|
fieldAccessToProcess.add(fieldAccessSite);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getClassAccess(DefaultClassAccessSite classAccessSite) {
|
||||||
|
int index = classAccessToIndex.getOrDefault(classAccessSite, -1);
|
||||||
|
if (index < 0) {
|
||||||
|
index = classAccessToIndex.size();
|
||||||
|
classAccessToIndex.put(classAccessSite, index);
|
||||||
|
classAccessList.add(new SerializableCallGraph.ClassAccess());
|
||||||
|
classAccessToProcess.add(classAccessSite);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CallGraphBuilder {
|
||||||
|
List<DefaultCallGraphNode> nodes = new ArrayList<>();
|
||||||
|
List<DefaultCallSite> callSites = new ArrayList<>();
|
||||||
|
List<DefaultFieldAccessSite> fieldAccessList = new ArrayList<>();
|
||||||
|
List<DefaultClassAccessSite> classAccessList = new ArrayList<>();
|
||||||
|
|
||||||
|
void build(SerializableCallGraph scg, DefaultCallGraph cg) {
|
||||||
|
for (SerializableCallGraph.Node serializableNode : scg.nodes) {
|
||||||
|
nodes.add(new DefaultCallGraphNode(cg, serializableNode.method));
|
||||||
|
}
|
||||||
|
for (SerializableCallGraph.CallSite scs : scg.callSites) {
|
||||||
|
callSites.add(new DefaultCallSite(scs.location, nodes.get(scs.callee), nodes.get(scs.caller)));
|
||||||
|
}
|
||||||
|
for (SerializableCallGraph.FieldAccess sfa : scg.fieldAccessList) {
|
||||||
|
fieldAccessList.add(new DefaultFieldAccessSite(sfa.location, nodes.get(sfa.callee), sfa.field));
|
||||||
|
}
|
||||||
|
for (SerializableCallGraph.ClassAccess sca : scg.classAccessList) {
|
||||||
|
classAccessList.add(new DefaultClassAccessSite(sca.location, nodes.get(sca.callee), sca.className));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index : scg.nodeIndexes) {
|
||||||
|
DefaultCallGraphNode node = nodes.get(index);
|
||||||
|
cg.nodes.put(node.getMethod(), node);
|
||||||
|
}
|
||||||
|
for (int index : scg.fieldAccessIndexes) {
|
||||||
|
cg.addFieldAccess(fieldAccessList.get(index));
|
||||||
|
}
|
||||||
|
for (int index : scg.classAccessIndexes) {
|
||||||
|
cg.addClassAccess(classAccessList.get(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.callgraph;
|
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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -29,20 +25,17 @@ import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
|
|
||||||
public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
public class DefaultCallGraphNode implements CallGraphNode {
|
||||||
private DefaultCallGraph graph;
|
private DefaultCallGraph graph;
|
||||||
private MethodReference method;
|
private MethodReference method;
|
||||||
private transient Set<DefaultCallSite> callSites = new HashSet<>();
|
Set<DefaultCallSite> callSites = new HashSet<>();
|
||||||
private List<DefaultCallSite> callSiteList;
|
private Set<DefaultCallSite> safeCallSites;
|
||||||
private transient Set<DefaultCallSite> safeCallSites;
|
List<DefaultCallSite> callerCallSites = new ArrayList<>();
|
||||||
private List<DefaultCallSite> callerCallSites = new ArrayList<>();
|
private List<DefaultCallSite> safeCallersCallSites;
|
||||||
private transient List<DefaultCallSite> safeCallersCallSites;
|
Set<DefaultFieldAccessSite> fieldAccessSites = new HashSet<>();
|
||||||
private transient Set<DefaultFieldAccessSite> fieldAccessSites = new HashSet<>();
|
private Set<DefaultFieldAccessSite> safeFieldAccessSites;
|
||||||
private List<DefaultFieldAccessSite> fieldAccessSiteList;
|
Set<DefaultClassAccessSite> classAccessSites = new HashSet<>();
|
||||||
private transient Set<DefaultFieldAccessSite> safeFieldAccessSites;
|
private Set<DefaultClassAccessSite> safeClassAccessSites;
|
||||||
private transient Set<DefaultClassAccessSite> classAccessSites = new HashSet<>();
|
|
||||||
private List<DefaultClassAccessSite> classAccessSiteList;
|
|
||||||
private transient Set<DefaultClassAccessSite> safeClassAccessSites;
|
|
||||||
|
|
||||||
DefaultCallGraphNode(DefaultCallGraph graph, MethodReference method) {
|
DefaultCallGraphNode(DefaultCallGraph graph, MethodReference method) {
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
|
@ -61,7 +54,6 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DefaultCallSite> getCallSites() {
|
public Collection<DefaultCallSite> getCallSites() {
|
||||||
ensureDeserialized();
|
|
||||||
if (safeCallSites == null) {
|
if (safeCallSites == null) {
|
||||||
safeCallSites = Collections.unmodifiableSet(callSites);
|
safeCallSites = Collections.unmodifiableSet(callSites);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +62,6 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DefaultCallSite> getCallerCallSites() {
|
public Collection<DefaultCallSite> getCallerCallSites() {
|
||||||
ensureDeserialized();
|
|
||||||
if (safeCallersCallSites == null) {
|
if (safeCallersCallSites == null) {
|
||||||
safeCallersCallSites = Collections.unmodifiableList(callerCallSites);
|
safeCallersCallSites = Collections.unmodifiableList(callerCallSites);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +69,6 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addCallSite(MethodReference method, TextLocation location) {
|
public boolean addCallSite(MethodReference method, TextLocation location) {
|
||||||
ensureDeserialized();
|
|
||||||
DefaultCallGraphNode callee = graph.getNode(method);
|
DefaultCallGraphNode callee = graph.getNode(method);
|
||||||
DefaultCallSite callSite = new DefaultCallSite(location, callee, this);
|
DefaultCallSite callSite = new DefaultCallSite(location, callee, this);
|
||||||
if (callSites.add(callSite)) {
|
if (callSites.add(callSite)) {
|
||||||
|
@ -95,7 +85,6 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DefaultFieldAccessSite> getFieldAccessSites() {
|
public Collection<DefaultFieldAccessSite> getFieldAccessSites() {
|
||||||
ensureDeserialized();
|
|
||||||
if (safeFieldAccessSites == null) {
|
if (safeFieldAccessSites == null) {
|
||||||
safeFieldAccessSites = Collections.unmodifiableSet(fieldAccessSites);
|
safeFieldAccessSites = Collections.unmodifiableSet(fieldAccessSites);
|
||||||
}
|
}
|
||||||
|
@ -103,7 +92,6 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addFieldAccess(FieldReference field, TextLocation location) {
|
public boolean addFieldAccess(FieldReference field, TextLocation location) {
|
||||||
ensureDeserialized();
|
|
||||||
DefaultFieldAccessSite site = new DefaultFieldAccessSite(location, this, field);
|
DefaultFieldAccessSite site = new DefaultFieldAccessSite(location, this, field);
|
||||||
if (fieldAccessSites.add(site)) {
|
if (fieldAccessSites.add(site)) {
|
||||||
graph.addFieldAccess(site);
|
graph.addFieldAccess(site);
|
||||||
|
@ -114,8 +102,7 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends ClassAccessSite> getClassAccessSites() {
|
public Collection<DefaultClassAccessSite> getClassAccessSites() {
|
||||||
ensureDeserialized();
|
|
||||||
if (safeClassAccessSites == null) {
|
if (safeClassAccessSites == null) {
|
||||||
safeClassAccessSites = Collections.unmodifiableSet(classAccessSites);
|
safeClassAccessSites = Collections.unmodifiableSet(classAccessSites);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +110,6 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addClassAccess(String className, TextLocation location) {
|
public boolean addClassAccess(String className, TextLocation location) {
|
||||||
ensureDeserialized();
|
|
||||||
DefaultClassAccessSite site = new DefaultClassAccessSite(location, this, className);
|
DefaultClassAccessSite site = new DefaultClassAccessSite(location, this, className);
|
||||||
if (classAccessSites.add(site)) {
|
if (classAccessSites.add(site)) {
|
||||||
graph.addClassAccess(site);
|
graph.addClassAccess(site);
|
||||||
|
@ -132,31 +118,4 @@ public class DefaultCallGraphNode implements CallGraphNode, Serializable {
|
||||||
return false;
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,10 @@ import org.teavm.model.TextLocation;
|
||||||
|
|
||||||
public class DefaultClassAccessSite implements ClassAccessSite, Serializable {
|
public class DefaultClassAccessSite implements ClassAccessSite, Serializable {
|
||||||
private TextLocation location;
|
private TextLocation location;
|
||||||
private CallGraphNode callee;
|
private DefaultCallGraphNode callee;
|
||||||
private String className;
|
private String className;
|
||||||
|
|
||||||
DefaultClassAccessSite(TextLocation location, CallGraphNode callee, String className) {
|
DefaultClassAccessSite(TextLocation location, DefaultCallGraphNode callee, String className) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.callee = callee;
|
this.callee = callee;
|
||||||
this.className = className;
|
this.className = className;
|
||||||
|
@ -36,7 +36,7 @@ public class DefaultClassAccessSite implements ClassAccessSite, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CallGraphNode getCallee() {
|
public DefaultCallGraphNode getCallee() {
|
||||||
return callee;
|
return callee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,10 @@ import org.teavm.model.TextLocation;
|
||||||
|
|
||||||
public class DefaultFieldAccessSite implements FieldAccessSite, Serializable {
|
public class DefaultFieldAccessSite implements FieldAccessSite, Serializable {
|
||||||
private TextLocation location;
|
private TextLocation location;
|
||||||
private CallGraphNode callee;
|
private DefaultCallGraphNode callee;
|
||||||
private FieldReference field;
|
private FieldReference field;
|
||||||
|
|
||||||
DefaultFieldAccessSite(TextLocation location, CallGraphNode callee, FieldReference field) {
|
DefaultFieldAccessSite(TextLocation location, DefaultCallGraphNode callee, FieldReference field) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.callee = callee;
|
this.callee = callee;
|
||||||
this.field = field;
|
this.field = field;
|
||||||
|
@ -37,8 +37,8 @@ public class DefaultFieldAccessSite implements FieldAccessSite, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CallGraphNode getCallee() {
|
public DefaultCallGraphNode getCallee() {
|
||||||
return null;
|
return callee;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 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.callgraph;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.TextLocation;
|
||||||
|
|
||||||
|
class SerializableCallGraph implements Serializable {
|
||||||
|
int[] nodeIndexes;
|
||||||
|
int[] fieldAccessIndexes;
|
||||||
|
int[] classAccessIndexes;
|
||||||
|
Node[] nodes;
|
||||||
|
CallSite[] callSites;
|
||||||
|
FieldAccess[] fieldAccessList;
|
||||||
|
ClassAccess[] classAccessList;
|
||||||
|
|
||||||
|
static class Node implements Serializable {
|
||||||
|
MethodReference method;
|
||||||
|
int[] callSites;
|
||||||
|
int[] callerCallSites;
|
||||||
|
int[] fieldAccessSites;
|
||||||
|
int[] classAccessSites;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CallSite implements Serializable {
|
||||||
|
TextLocation location;
|
||||||
|
int callee;
|
||||||
|
int caller;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FieldAccess implements Serializable {
|
||||||
|
TextLocation location;
|
||||||
|
int callee;
|
||||||
|
FieldReference field;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ClassAccess implements Serializable {
|
||||||
|
TextLocation location;
|
||||||
|
int callee;
|
||||||
|
String className;
|
||||||
|
}
|
||||||
|
}
|
|
@ -119,6 +119,8 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
||||||
tool.setDebugInformationGenerated(debugInformationGenerated);
|
tool.setDebugInformationGenerated(debugInformationGenerated);
|
||||||
tool.setSourceFilesCopied(sourceFilesCopied);
|
tool.setSourceFilesCopied(sourceFilesCopied);
|
||||||
|
|
||||||
|
tool.setMinifying(false);
|
||||||
|
|
||||||
for (SourceFileProvider fileProvider : sourceFileProviders) {
|
for (SourceFileProvider fileProvider : sourceFileProviders) {
|
||||||
tool.addSourceFileProvider(fileProvider);
|
tool.addSourceFileProvider(fileProvider);
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,8 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
||||||
tool.setDebugInformationGenerated(request.debugInformationGenerated);
|
tool.setDebugInformationGenerated(request.debugInformationGenerated);
|
||||||
tool.setSourceFilesCopied(request.sourceFilesCopied);
|
tool.setSourceFilesCopied(request.sourceFilesCopied);
|
||||||
|
|
||||||
|
tool.setMinifying(false);
|
||||||
|
|
||||||
for (String sourceDirectory : request.sourceDirectories) {
|
for (String sourceDirectory : request.sourceDirectories) {
|
||||||
tool.addSourceFileProvider(new DirectorySourceFileProvider(new File(sourceDirectory)));
|
tool.addSourceFileProvider(new DirectorySourceFileProvider(new File(sourceDirectory)));
|
||||||
}
|
}
|
||||||
|
@ -162,15 +164,10 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
|
public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
|
||||||
if ((System.currentTimeMillis() - lastReportedTime) > 100) {
|
|
||||||
lastReportedTime = System.currentTimeMillis();
|
|
||||||
try {
|
try {
|
||||||
return callback.phaseStarted(phase, count);
|
return callback.phaseStarted(phase, count);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
return TeaVMProgressFeedback.CANCEL;
|
throw new RuntimeException(e);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return TeaVMProgressFeedback.CONTINUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +178,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
||||||
try {
|
try {
|
||||||
return callback.progressReached(progress);
|
return callback.progressReached(progress);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
return TeaVMProgressFeedback.CANCEL;
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return TeaVMProgressFeedback.CONTINUE;
|
return TeaVMProgressFeedback.CONTINUE;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user