Skip to content

Commit 54db64f

Browse files
author
Christian Wimmer
committed
[GR-37247] Reduce memory footprint.
PullRequest: graal/11378
2 parents 039edd0 + 8360033 commit 54db64f

File tree

18 files changed

+138
-33
lines changed

18 files changed

+138
-33
lines changed

compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,15 @@ public void copy(Node fromNode, Node toNode) {
204204
}
205205
}
206206

207+
void minimizeSize(Node node) {
208+
for (int i = getDirectCount(); i < getCount(); i++) {
209+
NodeList<Node> list = getNodeList(node, offsets, i);
210+
if (list != null) {
211+
list.minimizeSize();
212+
}
213+
}
214+
}
215+
207216
/**
208217
* Sets the value of a given edge without notifying the new and old nodes on the other end of
209218
* the edge of the change.

compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -948,15 +948,31 @@ protected void afterNodeIdChange(Node node, Object value) {
948948
* of nodes is compressed such that all non-null entries precede all null entries while
949949
* preserving the ordering between the nodes within the list.
950950
*/
951-
public boolean maybeCompress() {
952-
if (debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()) {
951+
public final boolean maybeCompress() {
952+
return compress(false);
953+
}
954+
955+
/**
956+
* Minimize the memory occupied by the graph by trimming all node arrays to the minimum size.
957+
* Note that this can make subsequent optimization phases run slower, because additions to the
958+
* graph must re-allocate larger arrays again. So invoking this method is only beneficial if a
959+
* graph is alive for a long time.
960+
*/
961+
public final void minimizeSize() {
962+
compress(true);
963+
}
964+
965+
protected boolean compress(boolean minimizeSize) {
966+
if (!minimizeSize && (debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod())) {
953967
return false;
954968
}
955969
int liveNodeCount = getNodeCount();
956-
int liveNodePercent = liveNodeCount * 100 / nodesSize;
957-
int compressionThreshold = Options.GraphCompressionThreshold.getValue(options);
958-
if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) {
959-
return false;
970+
if (!minimizeSize) {
971+
int liveNodePercent = liveNodeCount * 100 / nodesSize;
972+
int compressionThreshold = Options.GraphCompressionThreshold.getValue(options);
973+
if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) {
974+
return false;
975+
}
960976
}
961977
GraphCompressions.increment(debug);
962978
int nextId = 0;
@@ -984,9 +1000,38 @@ public boolean maybeCompress() {
9841000
compressions++;
9851001
nodesDeletedBeforeLastCompression += nodesDeletedSinceLastCompression;
9861002
nodesDeletedSinceLastCompression = 0;
1003+
1004+
if (minimizeSize) {
1005+
/* Trim the array of all alive nodes itself. */
1006+
nodes = trimArrayToNewSize(nodes, nextId, NodeList.EMPTY_NODE_ARRAY);
1007+
/* Remove deleted nodes from the linked list of Node.typeCacheNext. */
1008+
recomputeIterableNodeLists();
1009+
/* Trim node arrays used within each node. */
1010+
for (Node node : nodes) {
1011+
node.extraUsages = trimArrayToNewSize(node.extraUsages, node.extraUsagesCount, NodeList.EMPTY_NODE_ARRAY);
1012+
node.getNodeClass().getInputEdges().minimizeSize(node);
1013+
node.getNodeClass().getSuccessorEdges().minimizeSize(node);
1014+
}
1015+
}
9871016
return true;
9881017
}
9891018

1019+
static <T> T[] trimArrayToNewSize(T[] input, int newSize, T[] emptyArray) {
1020+
assert emptyArray.length == 0;
1021+
if (input.length == newSize) {
1022+
return input;
1023+
}
1024+
for (int i = newSize; i < input.length; i++) {
1025+
GraalError.guarantee(input[i] == null, "removing non-null element");
1026+
}
1027+
1028+
if (newSize == 0) {
1029+
return emptyArray;
1030+
} else {
1031+
return Arrays.copyOf(input, newSize);
1032+
}
1033+
}
1034+
9901035
/**
9911036
* Returns an {@link Iterable} providing all the live nodes whose type is compatible with
9921037
* {@code type}.

compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ protected NodeList(Node self, int initialSize) {
7676
checkMaxSize(initialSize);
7777
this.size = initialSize;
7878
this.initialSize = initialSize;
79-
this.nodes = new Node[initialSize];
79+
if (initialSize == 0) {
80+
this.nodes = EMPTY_NODE_ARRAY;
81+
} else {
82+
this.nodes = new Node[initialSize];
83+
}
8084
}
8185

8286
protected NodeList(Node self, T[] elements) {
@@ -232,8 +236,13 @@ public void initialize(int index, Node node) {
232236
void copy(NodeList<? extends Node> other) {
233237
self.incModCount();
234238
incModCount();
235-
Node[] newNodes = new Node[other.size];
236-
System.arraycopy(other.nodes, 0, newNodes, 0, newNodes.length);
239+
Node[] newNodes;
240+
if (other.size == 0) {
241+
newNodes = EMPTY_NODE_ARRAY;
242+
} else {
243+
newNodes = new Node[other.size];
244+
System.arraycopy(other.nodes, 0, newNodes, 0, newNodes.length);
245+
}
237246
nodes = newNodes;
238247
size = other.size;
239248
}
@@ -279,6 +288,10 @@ void clearWithoutUpdate() {
279288
size = 0;
280289
}
281290

291+
void minimizeSize() {
292+
nodes = Graph.trimArrayToNewSize(nodes, size, EMPTY_NODE_ARRAY);
293+
}
294+
282295
@Override
283296
@SuppressWarnings("unchecked")
284297
public boolean remove(Object node) {

compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/AbstractForeignCallStub.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ protected final StructuredGraph getGraph(DebugContext debug, CompilationIdentifi
221221
ResolvedJavaMethod getAndClearObjectResult = foreignCallSnippets.getAndClearObjectResult.getMethod();
222222
ResolvedJavaMethod verifyObject = foreignCallSnippets.verifyObject.getMethod();
223223
ResolvedJavaMethod thisMethod = getGraphMethod();
224-
GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString(), false);
224+
GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString(), false, true);
225225
StructuredGraph graph = kit.getGraph();
226226
graph.disableFrameStateVerification();
227227
ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));

compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,8 +560,8 @@ protected void afterNodeIdChange(Node node, Object value) {
560560
}
561561

562562
@Override
563-
public boolean maybeCompress() {
564-
if (super.maybeCompress()) {
563+
protected boolean compress(boolean minimizeSize) {
564+
if (super.compress(minimizeSize)) {
565565
/*
566566
* The schedule contains a NodeMap which is unusable after compression.
567567
*/

compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ protected abstract static class Structure {
106106
}
107107

108108
public GraphKit(DebugContext debug, ResolvedJavaMethod stubMethod, Providers providers, WordTypes wordTypes, Plugins graphBuilderPlugins, CompilationIdentifier compilationId, String name,
109-
boolean trackNodeSourcePosition) {
109+
boolean trackNodeSourcePosition, boolean recordInlinedMethods) {
110110
super(providers);
111-
StructuredGraph.Builder builder = new StructuredGraph.Builder(debug.getOptions(), debug).compilationId(compilationId).profileProvider(null);
111+
StructuredGraph.Builder builder = new StructuredGraph.Builder(debug.getOptions(), debug).recordInlinedMethods(recordInlinedMethods).compilationId(compilationId).profileProvider(null);
112112
if (name != null) {
113113
builder.name(name);
114114
} else {

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnalysisParsedGraph.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ public static AnalysisParsedGraph parseBytecode(BigBang bb, AnalysisMethod metho
114114
return EMPTY;
115115
}
116116

117-
graph = new StructuredGraph.Builder(options, debug).method(method).build();
117+
graph = new StructuredGraph.Builder(options, debug)
118+
.method(method)
119+
.recordInlinedMethods(false)
120+
.build();
118121
try (DebugContext.Scope s = debug.scope("ClosedWorldAnalysis", graph, method)) {
119122

120123
// enable this logging to get log output in compilation passes

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ private boolean parse() {
205205
* needed after static analysis.
206206
*/
207207
if (bb.strengthenGraalGraphs()) {
208+
graph.minimizeSize();
208209
method.setAnalyzedGraph(graph);
209210
}
210211

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private enum State {
6060
private final AtomicReference<State> state;
6161
private final LongAdder postedOperations;
6262
private final LongAdder completedOperations;
63-
private final List<DebugContextRunnable> postedBeforeStart;
63+
private List<DebugContextRunnable> postedBeforeStart;
6464
private final CopyOnWriteArrayList<Throwable> exceptions = new CopyOnWriteArrayList<>();
6565

6666
private ExecutorService executorService;
@@ -90,7 +90,6 @@ public CompletionExecutor(BigBang bb, ForkJoinPool forkJoin, Runnable heartbeatC
9090
state = new AtomicReference<>(State.UNUSED);
9191
postedOperations = new LongAdder();
9292
completedOperations = new LongAdder();
93-
postedBeforeStart = new ArrayList<>();
9493
startingThread = Thread.currentThread();
9594
}
9695

@@ -103,7 +102,7 @@ public void init(Timing newTiming) {
103102
setState(State.BEFORE_START);
104103
postedOperations.reset();
105104
completedOperations.reset();
106-
postedBeforeStart.clear();
105+
postedBeforeStart = new ArrayList<>();
107106
vmConfig = bb.getHostVM().getConfiguration();
108107
}
109108

@@ -213,7 +212,7 @@ public void start() {
213212

214213
setState(State.STARTED);
215214
postedBeforeStart.forEach(this::execute);
216-
postedBeforeStart.clear();
215+
postedBeforeStart = null;
217216
}
218217

219218
private void setState(State newState) {
@@ -271,7 +270,7 @@ public long complete() throws InterruptedException {
271270
}
272271

273272
public long getPostedOperations() {
274-
return postedOperations.sum() + postedBeforeStart.size();
273+
return postedOperations.sum() + (postedBeforeStart == null ? 0 : postedBeforeStart.size());
275274
}
276275

277276
public boolean isSequential() {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,12 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod
220220

221221
EncodedGraph encodedGraph = new EncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, null, null, false, trackNodeSourcePosition);
222222
try (DebugContext debug = openSnippetDebugContext("SVMSnippet_", method, options)) {
223-
StructuredGraph result = new StructuredGraph.Builder(options, debug).method(method).trackNodeSourcePosition(trackNodeSourcePosition).setIsSubstitution(true).build();
223+
StructuredGraph result = new StructuredGraph.Builder(options, debug)
224+
.method(method)
225+
.trackNodeSourcePosition(trackNodeSourcePosition)
226+
.recordInlinedMethods(false)
227+
.setIsSubstitution(true)
228+
.build();
224229
PEGraphDecoder graphDecoder = new PEGraphDecoder(ConfigurationValues.getTarget().arch, result, providers, null, snippetInvocationPlugins, new InlineInvokePlugin[0], parameterPlugin, null,
225230
null, null, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), true) {
226231

0 commit comments

Comments
 (0)