Mercurial > hg > graal-jvmci-8
view graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java @ 10611:1546866ebb8d
First draft of Truffle graph caching.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 06 Jul 2013 00:29:59 +0200 |
parents | |
children | 549a7568ce14 |
line wrap: on
line source
/* * Copyright (c) 2013, 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. * * 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.graal.truffle; import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.truffle.phases.*; /** * Implementation of a cache for Truffle graphs for improving partial evaluation time. */ public final class TruffleCache { private final MetaAccessProvider metaAccessProvider; private final GraphBuilderConfiguration config; private final OptimisticOptimizations optimisticOptimizations; private final Replacements replacements; private final HashMap<ResolvedJavaMethod, StructuredGraph> cache = new HashMap<>(); public TruffleCache(MetaAccessProvider metaAccessProvider, GraphBuilderConfiguration config, OptimisticOptimizations optimisticOptimizations, Replacements replacements) { this.metaAccessProvider = metaAccessProvider; this.config = config; this.optimisticOptimizations = optimisticOptimizations; this.replacements = replacements; } public StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList<ValueNode> arguments) { if (cache.containsKey(method)) { StructuredGraph graph = cache.get(method); if (checkArgumentStamps(graph, arguments)) { return graph; } } StructuredGraph resultGraph = Debug.sandbox("TruffleCache", new Object[]{metaAccessProvider, method}, DebugScope.getConfig(), new Callable<StructuredGraph>() { public StructuredGraph call() { StructuredGraph newGraph = parseGraph(method); // Get stamps from actual arguments. List<Stamp> stamps = new ArrayList<>(); for (ValueNode arg : arguments) { stamps.add(arg.stamp()); } if (cache.containsKey(method)) { // Make sure stamps are generalized based on previous stamps. StructuredGraph graph = cache.get(method); for (LocalNode localNode : graph.getNodes(LocalNode.class)) { int index = localNode.index(); Stamp stamp = stamps.get(index); stamps.set(index, stamp.meet(localNode.stamp())); } } // Set stamps into graph before optimizing. for (LocalNode localNode : newGraph.getNodes(LocalNode.class)) { int index = localNode.index(); Stamp stamp = stamps.get(index); localNode.setStamp(stamp); } optimizeGraph(newGraph); cache.put(method, newGraph); if (TruffleCompilerOptions.TraceTruffleCompilationDetails.getValue()) { TTY.println(String.format("[truffle] added to graph cache method %s with %d nodes.", method, newGraph.getNodeCount())); } return newGraph; } }); return resultGraph; } private void optimizeGraph(StructuredGraph newGraph) { // Canonicalize / constant propagate. Assumptions assumptions = new Assumptions(false); CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), null, null); canonicalizerPhase.apply(newGraph); // Intrinsify methods. new ReplaceIntrinsicsPhase(replacements).apply(newGraph); // Convert deopt to guards. new ConvertDeoptimizeToGuardPhase().apply(newGraph); } private StructuredGraph parseGraph(ResolvedJavaMethod method) { StructuredGraph graph = new StructuredGraph(method); new GraphBuilderPhase(metaAccessProvider, config, optimisticOptimizations).apply(graph); return graph; } private static boolean checkArgumentStamps(StructuredGraph graph, NodeInputList<ValueNode> arguments) { assert graph.getNodes(LocalNode.class).count() == arguments.count(); for (LocalNode localNode : graph.getNodes(LocalNode.class)) { Stamp newStamp = localNode.stamp().meet(arguments.get(localNode.index()).stamp()); if (!newStamp.equals(localNode.stamp())) { if (TruffleCompilerOptions.TraceTruffleCompilationDetails.getValue()) { TTY.println(String.format("[truffle] graph cache entry too specific for method %s argument %s previous stamp %s new stamp %s.", graph.method(), localNode, localNode.stamp(), newStamp)); } return false; } } return true; } }