001/* 002 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.truffle; 024 025import static com.oracle.graal.compiler.GraalCompiler.*; 026import static jdk.internal.jvmci.code.CodeUtil.*; 027 028import java.util.*; 029 030import jdk.internal.jvmci.code.*; 031import jdk.internal.jvmci.code.CallingConvention.*; 032import com.oracle.graal.debug.*; 033import com.oracle.graal.debug.Debug.*; 034import jdk.internal.jvmci.meta.*; 035import jdk.internal.jvmci.meta.Assumptions.Assumption; 036 037import com.oracle.graal.compiler.target.*; 038import com.oracle.graal.graphbuilderconf.*; 039import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; 040import com.oracle.graal.lir.asm.*; 041import com.oracle.graal.lir.phases.*; 042import com.oracle.graal.nodes.*; 043import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; 044import com.oracle.graal.phases.*; 045import com.oracle.graal.phases.tiers.*; 046import com.oracle.graal.phases.util.*; 047import com.oracle.graal.truffle.nodes.*; 048import com.oracle.truffle.api.*; 049import com.oracle.truffle.api.nodes.*; 050 051/** 052 * Implementation of the Truffle compiler using Graal. 053 */ 054public abstract class TruffleCompiler { 055 056 protected final Providers providers; 057 protected final Suites suites; 058 protected final GraphBuilderConfiguration config; 059 protected final LIRSuites lirSuites; 060 protected final PartialEvaluator partialEvaluator; 061 protected final Backend backend; 062 protected final GraalTruffleCompilationListener compilationNotify; 063 064 // @formatter:off 065 private static final Class<?>[] SKIPPED_EXCEPTION_CLASSES = new Class[]{ 066 UnexpectedResultException.class, 067 SlowPathException.class, 068 ArithmeticException.class, 069 IllegalArgumentException.class, 070 VirtualMachineError.class, 071 StringIndexOutOfBoundsException.class, 072 ClassCastException.class 073 }; 074 // @formatter:on 075 076 public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability, 077 OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints); 078 079 public TruffleCompiler(Plugins plugins, Suites suites, LIRSuites lirSuites, Backend backend) { 080 GraalTruffleRuntime graalTruffleRuntime = ((GraalTruffleRuntime) Truffle.getRuntime()); 081 this.compilationNotify = graalTruffleRuntime.getCompilationNotify(); 082 this.backend = backend; 083 Providers backendProviders = backend.getProviders(); 084 ConstantReflectionProvider constantReflection = new TruffleConstantReflectionProvider(backendProviders.getConstantReflection(), backendProviders.getMetaAccess()); 085 this.providers = backendProviders.copyWith(constantReflection); 086 this.suites = suites; 087 this.lirSuites = lirSuites; 088 089 ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); 090 091 GraphBuilderConfiguration baseConfig = graalTruffleRuntime.enableInfopoints() ? GraphBuilderConfiguration.getInfopointDefault(new Plugins(plugins)) 092 : GraphBuilderConfiguration.getDefault(new Plugins(plugins)); 093 this.config = baseConfig.withSkippedExceptionTypes(skippedExceptionTypes).withOmitAssertions(TruffleCompilerOptions.TruffleExcludeAssertions.getValue()); 094 095 this.partialEvaluator = createPartialEvaluator(); 096 097 if (Debug.isEnabled()) { 098 DebugEnvironment.initialize(System.out); 099 } 100 } 101 102 public GraphBuilderConfiguration getGraphBuilderConfiguration() { 103 return config; 104 } 105 106 protected abstract PartialEvaluator createPartialEvaluator(); 107 108 public static ResolvedJavaType[] getSkippedExceptionTypes(MetaAccessProvider metaAccess) { 109 ResolvedJavaType[] skippedExceptionTypes = new ResolvedJavaType[SKIPPED_EXCEPTION_CLASSES.length]; 110 for (int i = 0; i < SKIPPED_EXCEPTION_CLASSES.length; i++) { 111 skippedExceptionTypes[i] = metaAccess.lookupJavaType(SKIPPED_EXCEPTION_CLASSES[i]); 112 } 113 return skippedExceptionTypes; 114 } 115 116 public static final DebugTimer PartialEvaluationTime = Debug.timer("PartialEvaluationTime"); 117 public static final DebugTimer CompilationTime = Debug.timer("CompilationTime"); 118 public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation"); 119 120 public static final DebugMemUseTracker PartialEvaluationMemUse = Debug.memUseTracker("TrufflePartialEvaluationMemUse"); 121 public static final DebugMemUseTracker CompilationMemUse = Debug.memUseTracker("TruffleCompilationMemUse"); 122 public static final DebugMemUseTracker CodeInstallationMemUse = Debug.memUseTracker("TruffleCodeInstallationMemUse"); 123 124 public void compileMethod(final OptimizedCallTarget compilable) { 125 StructuredGraph graph = null; 126 127 compilationNotify.notifyCompilationStarted(compilable); 128 129 try { 130 PhaseSuite<HighTierContext> graphBuilderSuite = createGraphBuilderSuite(); 131 132 try (DebugCloseable a = PartialEvaluationTime.start(); DebugCloseable c = PartialEvaluationMemUse.start()) { 133 graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES); 134 } 135 136 if (Thread.currentThread().isInterrupted()) { 137 return; 138 } 139 140 compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph); 141 CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), graphBuilderSuite, compilable); 142 compilationNotify.notifyCompilationSuccess(compilable, graph, compilationResult); 143 } catch (Throwable t) { 144 System.out.println("compilation failed!?"); 145 compilationNotify.notifyCompilationFailed(compilable, graph, t); 146 throw t; 147 } 148 } 149 150 public CompilationResult compileMethodHelper(StructuredGraph graph, String name, PhaseSuite<HighTierContext> graphBuilderSuite, InstalledCode predefinedInstalledCode) { 151 try (Scope s = Debug.scope("TruffleFinal")) { 152 Debug.dump(1, graph, "After TruffleTier"); 153 } catch (Throwable e) { 154 throw Debug.handle(e); 155 } 156 157 CompilationResult result = null; 158 try (DebugCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache()); DebugCloseable c = CompilationMemUse.start()) { 159 SpeculationLog speculationLog = graph.getSpeculationLog(); 160 if (speculationLog != null) { 161 speculationLog.collectFailedSpeculations(); 162 } 163 164 CodeCacheProvider codeCache = providers.getCodeCache(); 165 CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); 166 CompilationResult compilationResult = new CompilationResult(name); 167 result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), graphBuilderSuite, Optimizations, getProfilingInfo(graph), suites, lirSuites, 168 compilationResult, CompilationResultBuilderFactory.Default); 169 } catch (Throwable e) { 170 throw Debug.handle(e); 171 } 172 173 compilationNotify.notifyCompilationGraalTierFinished((OptimizedCallTarget) predefinedInstalledCode, graph); 174 175 if (graph.isInlinedMethodRecordingEnabled()) { 176 result.setMethods(graph.method(), graph.getInlinedMethods()); 177 result.setBytecodeSize(graph.getBytecodeSize()); 178 } else { 179 assert result.getMethods() == null; 180 } 181 182 List<AssumptionValidAssumption> validAssumptions = new ArrayList<>(); 183 Set<Assumption> newAssumptions = new HashSet<>(); 184 for (Assumption assumption : graph.getAssumptions()) { 185 processAssumption(newAssumptions, assumption, validAssumptions); 186 } 187 188 if (result.getAssumptions() != null) { 189 for (Assumption assumption : result.getAssumptions()) { 190 processAssumption(newAssumptions, assumption, validAssumptions); 191 } 192 } 193 194 result.setAssumptions(newAssumptions.toArray(new Assumption[newAssumptions.size()])); 195 196 InstalledCode installedCode; 197 try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); DebugCloseable a = CodeInstallationTime.start(); DebugCloseable c = CodeInstallationMemUse.start()) { 198 installedCode = providers.getCodeCache().addMethod(graph.method(), result, graph.getSpeculationLog(), predefinedInstalledCode); 199 } catch (Throwable e) { 200 throw Debug.handle(e); 201 } 202 203 for (AssumptionValidAssumption a : validAssumptions) { 204 a.getAssumption().registerInstalledCode(installedCode); 205 } 206 207 return result; 208 } 209 210 protected abstract PhaseSuite<HighTierContext> createGraphBuilderSuite(); 211 212 public void processAssumption(Set<Assumption> newAssumptions, Assumption assumption, List<AssumptionValidAssumption> manual) { 213 if (assumption != null) { 214 if (assumption instanceof AssumptionValidAssumption) { 215 AssumptionValidAssumption assumptionValidAssumption = (AssumptionValidAssumption) assumption; 216 manual.add(assumptionValidAssumption); 217 } else { 218 newAssumptions.add(assumption); 219 } 220 } 221 } 222 223 public PartialEvaluator getPartialEvaluator() { 224 return partialEvaluator; 225 } 226}