Mercurial > hg > truffle
view graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java @ 15090:07e7aae05983
Truffle: context sensitive inlining cleanup
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 14 Apr 2014 18:25:23 +0200 |
parents | 448338c9ce96 |
children | 2ed720ce9273 |
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.hotspot; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; import static com.oracle.graal.truffle.OptimizedCallTargetLog.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.truffle.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; /** * Call target for running truffle on a standard VM (and not in SubstrateVM). */ public final class HotSpotOptimizedCallTarget extends OptimizedCallTarget { protected final TruffleCompiler compiler; private Future<InstalledCode> installedCodeTask; private SpeculationLog speculationLog = new HotSpotSpeculationLog(); HotSpotOptimizedCallTarget(RootNode rootNode, TruffleCompiler compiler, int invokeCounter, int compilationThreshold, boolean compilationEnabled) { super(rootNode, invokeCounter, compilationThreshold, compilationEnabled, TruffleUseTimeForCompilationDecision.getValue() ? new TimedCompilationPolicy() : new DefaultCompilationPolicy()); this.compiler = compiler; } @Override public SpeculationLog getSpeculationLog() { return speculationLog; } public boolean isOptimized() { return installedCode != null || installedCodeTask != null; } @CompilerDirectives.SlowPath @Override public Object call(Object[] args) { return CompilerDirectives.inInterpreter() ? callHelper(args) : executeHelper(args); } private Object callHelper(Object[] args) { if (installedCode != null && installedCode.isValid()) { reinstallCallMethodShortcut(); } if (TruffleCallTargetProfiling.getValue()) { callCount++; } if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, installedCode != null)) { try { return installedCode.executeVarargs(new Object[]{this, args}); } catch (InvalidInstalledCodeException ex) { return compiledCodeInvalidated(args); } } else { return interpreterCall(args); } } private static void reinstallCallMethodShortcut() { if (TraceTruffleCompilation.getValue()) { OUT.println("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut."); } HotSpotTruffleRuntime.installOptimizedCallTargetCallMethod(); } private Object compiledCodeInvalidated(Object[] args) { invalidate(null, null, "Compiled code invalidated"); return call(args); } @Override protected void invalidate(Node oldNode, Node newNode, CharSequence reason) { InstalledCode m = this.installedCode; if (m != null) { CompilerAsserts.neverPartOfCompilation(); installedCode = null; compilationProfile.reportInvalidated(); logOptimizedInvalidated(this, oldNode, newNode, reason); } cancelInstalledTask(oldNode, newNode, reason); } private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { Future<InstalledCode> task = this.installedCodeTask; if (task != null) { task.cancel(true); this.installedCodeTask = null; logOptimizingUnqueued(this, oldNode, newNode, reason); compilationProfile.reportInvalidated(); } } private Object interpreterCall(Object[] args) { CompilerAsserts.neverPartOfCompilation(); compilationProfile.reportInterpreterCall(); if (compilationEnabled && compilationPolicy.shouldCompile(compilationProfile)) { InstalledCode code = compile(); if (code != null && code.isValid()) { this.installedCode = code; try { return code.executeVarargs(new Object[]{this, args}); } catch (InvalidInstalledCodeException ex) { return compiledCodeInvalidated(args); } } } return executeHelper(args); } private boolean isCompiling() { Future<InstalledCode> codeTask = this.installedCodeTask; if (codeTask != null) { if (codeTask.isCancelled()) { installedCodeTask = null; return false; } return true; } return false; } @Override public InstalledCode compile() { if (isCompiling()) { if (installedCodeTask.isDone()) { return receiveInstalledCode(); } return null; } else { performInlining(); logOptimizingQueued(this); this.installedCodeTask = compiler.compile(this); if (!TruffleBackgroundCompilation.getValue()) { return receiveInstalledCode(); } return null; } } private InstalledCode receiveInstalledCode() { try { return installedCodeTask.get(); } catch (InterruptedException | ExecutionException e) { compilationEnabled = false; logOptimizingFailed(this, e.getMessage()); if (e.getCause() instanceof BailoutException) { // Bailout => move on. } else { if (TraceTruffleCompilationExceptions.getValue()) { e.printStackTrace(OUT); } if (TruffleCompilationExceptionsAreFatal.getValue()) { System.exit(-1); } } return null; } } }