Skip to content

Commit

Permalink
Encode compilation graphs to reduce memory footprint of the image gen…
Browse files Browse the repository at this point in the history
…erator
  • Loading branch information
Christian Wimmer committed Apr 30, 2022
1 parent f8c21ae commit 3041baf
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 165 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.hosted.code;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.EncodedGraph;
import org.graalvm.compiler.nodes.GraphEncoder;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;

import com.oracle.graal.pointsto.flow.AnalysisParsedGraph;
import com.oracle.svm.hosted.meta.HostedMethod;

public final class CompilationGraph {

public static class InvokeInfo {
public final InvokeKind invokeKind;
public final HostedMethod targetMethod;
public final HostedMethod directCaller;
public final NodeSourcePosition nodeSourcePosition;

InvokeInfo(InvokeKind invokeKind, HostedMethod targetMethod, HostedMethod directCaller, NodeSourcePosition nodeSourcePosition) {
this.invokeKind = invokeKind;
this.targetMethod = targetMethod;
this.directCaller = directCaller;
this.nodeSourcePosition = nodeSourcePosition;
}
}

public static class AllocationInfo {
public final NodeSourcePosition nodeSourcePosition;

AllocationInfo(NodeSourcePosition nodeSourcePosition) {
this.nodeSourcePosition = nodeSourcePosition;
}
}

private final EncodedGraph encodedGraph;
private final int nodeCount;
private final Set<InvokeInfo> invokeInfos;
private final Set<AllocationInfo> allocationInfos;

private CompilationGraph(EncodedGraph encodedGraph, int nodeCount, Set<InvokeInfo> invokeInfos, Set<AllocationInfo> allocationInfos) {
this.encodedGraph = encodedGraph;
this.nodeCount = nodeCount;
this.invokeInfos = invokeInfos;
this.allocationInfos = allocationInfos;
}

static CompilationGraph encode(StructuredGraph graph) {
Set<InvokeInfo> invokeInfos = new HashSet<>();
Set<AllocationInfo> allocationInfos = new HashSet<>();
for (var n : graph.getNodes()) {
if (n instanceof MethodCallTargetNode) {
MethodCallTargetNode node = (MethodCallTargetNode) n;
invokeInfos.add(new InvokeInfo(
node.invokeKind(),
(HostedMethod) node.targetMethod(),
(HostedMethod) node.invoke().stateAfter().getMethod(),
node.getNodeSourcePosition()));
}
if (UninterruptibleAnnotationChecker.isAllocationNode(n)) {
allocationInfos.add(new AllocationInfo(n.getNodeSourcePosition()));
}
}

return new CompilationGraph(
GraphEncoder.encodeSingleGraph(graph, AnalysisParsedGraph.HOST_ARCHITECTURE),
graph.getNodeCount(),
invokeInfos.isEmpty() ? Collections.emptySet() : invokeInfos,
allocationInfos.isEmpty() ? Collections.emptySet() : allocationInfos);
}

public EncodedGraph getEncodedGraph() {
return encodedGraph;
}

public int getNodeCount() {
return nodeCount;
}

public Set<InvokeInfo> getInvokeInfos() {
return invokeInfos;
}

public Set<AllocationInfo> getAllocationInfos() {
return allocationInfos;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.GraphDecoder;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.options.OptionValues;

import com.oracle.svm.core.SubstrateOptions;
import com.oracle.graal.pointsto.flow.AnalysisParsedGraph;
import com.oracle.svm.core.annotate.DeoptTest;
import com.oracle.svm.core.annotate.Specialize;
import com.oracle.svm.hosted.code.CompileQueue.CompileFunction;
Expand All @@ -48,14 +52,13 @@ public class CompilationInfo {
*/
protected boolean inCompileQueue;

protected volatile StructuredGraph graph;
private volatile CompilationGraph compilationGraph;
private OptionValues compileOptions;

protected boolean isTrivialMethod;

protected boolean canDeoptForTesting;

protected boolean modifiesSpecialRegisters;

/**
* The constant arguments for a {@link DeoptTest} method called by a {@link Specialize} method.
* Note: this is only used for testing.
Expand Down Expand Up @@ -126,22 +129,41 @@ public HostedMethod getDeoptTargetMethod() {
return deoptTarget;
}

public void setGraph(StructuredGraph graph) {
this.graph = graph;
public CompilationGraph getCompilationGraph() {
return compilationGraph;
}

public void clear() {
graph = null;
specializedArguments = null;
}
@SuppressWarnings("try")
public StructuredGraph createGraph(DebugContext debug, CompilationIdentifier compilationId, boolean decode) {
var graph = new StructuredGraph.Builder(compileOptions, debug)
.method(method)
.recordInlinedMethods(false)
.trackNodeSourcePosition(getCompilationGraph().getEncodedGraph().trackNodeSourcePosition())
.compilationId(compilationId)
.build();

public StructuredGraph getGraph() {
if (decode) {
try (var s = debug.scope("CreateGraph", graph, method)) {
var decoder = new GraphDecoder(AnalysisParsedGraph.HOST_ARCHITECTURE, graph);
decoder.decode(getCompilationGraph().getEncodedGraph());
} catch (Throwable ex) {
throw debug.handle(ex);
}
}
return graph;
}

public boolean modifiesSpecialRegisters() {
assert SubstrateOptions.useLLVMBackend();
return modifiesSpecialRegisters;
void encodeGraph(StructuredGraph graph) {
compilationGraph = CompilationGraph.encode(graph);
}

public void setCompileOptions(OptionValues compileOptions) {
this.compileOptions = compileOptions;
}

public void clear() {
compilationGraph = null;
specializedArguments = null;
}

public boolean isTrivialMethod() {
Expand Down
Loading

0 comments on commit 3041baf

Please sign in to comment.