001/* 002 * Copyright (c) 2011, 2013, 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.phases; 024 025import java.util.regex.*; 026 027import com.oracle.graal.debug.*; 028import com.oracle.graal.debug.Debug.*; 029 030import com.oracle.graal.graph.*; 031import com.oracle.graal.nodes.*; 032 033/** 034 * Base class for all compiler phases. Subclasses should be stateless. There will be one global 035 * instance for each compiler phase that is shared for all compilations. VM-, target- and 036 * compilation-specific data can be passed with a context object. 037 */ 038public abstract class BasePhase<C> { 039 040 public static final int PHASE_DUMP_LEVEL = 1; 041 public static final int BEFORE_PHASE_DUMP_LEVEL = 3; 042 043 private CharSequence name; 044 045 /** 046 * Records time spent in {@link #apply(StructuredGraph, Object, boolean)}. 047 */ 048 private final DebugTimer timer; 049 050 /** 051 * Counts calls to {@link #apply(StructuredGraph, Object, boolean)}. 052 */ 053 private final DebugMetric executionCount; 054 055 /** 056 * Accumulates the {@linkplain Graph#getNodeCount() live node count} of all graphs sent to 057 * {@link #apply(StructuredGraph, Object, boolean)}. 058 */ 059 private final DebugMetric inputNodesCount; 060 061 /** 062 * Records memory usage within {@link #apply(StructuredGraph, Object, boolean)}. 063 */ 064 private final DebugMemUseTracker memUseTracker; 065 066 @SuppressWarnings("all") 067 private static boolean assertionsEnabled() { 068 boolean enabled = false; 069 assert enabled = true; 070 return enabled; 071 } 072 073 private static final Pattern NAME_PATTERN = assertionsEnabled() ? Pattern.compile("[A-Z][A-Za-z0-9]+") : null; 074 075 private static boolean checkName(String name) { 076 assert NAME_PATTERN.matcher(name).matches() : "illegal phase name: " + name; 077 return true; 078 } 079 080 private static class BasePhaseStatistics { 081 /** 082 * Records time spent in {@link #apply(StructuredGraph, Object, boolean)}. 083 */ 084 private final DebugTimer timer; 085 086 /** 087 * Counts calls to {@link #apply(StructuredGraph, Object, boolean)}. 088 */ 089 private final DebugMetric executionCount; 090 091 /** 092 * Accumulates the {@linkplain Graph#getNodeCount() live node count} of all graphs sent to 093 * {@link #apply(StructuredGraph, Object, boolean)}. 094 */ 095 private final DebugMetric inputNodesCount; 096 097 /** 098 * Records memory usage within {@link #apply(StructuredGraph, Object, boolean)}. 099 */ 100 private final DebugMemUseTracker memUseTracker; 101 102 BasePhaseStatistics(Class<?> clazz) { 103 timer = Debug.timer("PhaseTime_%s", clazz); 104 executionCount = Debug.metric("PhaseCount_%s", clazz); 105 memUseTracker = Debug.memUseTracker("PhaseMemUse_%s", clazz); 106 inputNodesCount = Debug.metric("PhaseNodes_%s", clazz); 107 } 108 } 109 110 private static final ClassValue<BasePhaseStatistics> statisticsClassValue = new ClassValue<BasePhaseStatistics>() { 111 @Override 112 protected BasePhaseStatistics computeValue(Class<?> c) { 113 return new BasePhaseStatistics(c); 114 } 115 }; 116 117 protected BasePhase() { 118 BasePhaseStatistics statistics = statisticsClassValue.get(getClass()); 119 timer = statistics.timer; 120 executionCount = statistics.executionCount; 121 memUseTracker = statistics.memUseTracker; 122 inputNodesCount = statistics.inputNodesCount; 123 } 124 125 protected BasePhase(String name) { 126 assert checkName(name); 127 this.name = name; 128 BasePhaseStatistics statistics = statisticsClassValue.get(getClass()); 129 timer = statistics.timer; 130 executionCount = statistics.executionCount; 131 memUseTracker = statistics.memUseTracker; 132 inputNodesCount = statistics.inputNodesCount; 133 } 134 135 public final void apply(final StructuredGraph graph, final C context) { 136 apply(graph, context, true); 137 } 138 139 protected final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { 140 try (DebugCloseable a = timer.start(); Scope s = Debug.scope(getClass(), this); DebugCloseable c = memUseTracker.start()) { 141 if (dumpGraph && Debug.isDumpEnabled(BEFORE_PHASE_DUMP_LEVEL)) { 142 Debug.dump(BEFORE_PHASE_DUMP_LEVEL, graph, "Before phase %s", getName()); 143 } 144 this.run(graph, context); 145 executionCount.increment(); 146 inputNodesCount.add(graph.getNodeCount()); 147 if (dumpGraph && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) { 148 Debug.dump(PHASE_DUMP_LEVEL, graph, "%s", getName()); 149 } 150 if (Fingerprint.ENABLED) { 151 String graphDesc = graph.method() == null ? graph.name : graph.method().format("%H.%n(%p)"); 152 Fingerprint.submit("After phase %s nodes in %s are %s", getName(), graphDesc, graph.getNodes().snapshot()); 153 } 154 if (Debug.isVerifyEnabled()) { 155 Debug.verify(graph, "%s", getName()); 156 } 157 assert graph.verify(); 158 } catch (Throwable t) { 159 throw Debug.handle(t); 160 } 161 } 162 163 protected CharSequence createName() { 164 String className = BasePhase.this.getClass().getName(); 165 String s = className.substring(className.lastIndexOf(".") + 1); // strip the package name 166 if (s.endsWith("Phase")) { 167 s = s.substring(0, s.length() - "Phase".length()); 168 } 169 return s; 170 } 171 172 public final CharSequence getName() { 173 if (name == null) { 174 name = createName(); 175 } 176 return name; 177 } 178 179 protected abstract void run(StructuredGraph graph, C context); 180}