001/* 002 * Copyright (c) 2015, 2015, 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.lir.phases; 024 025import java.util.*; 026import java.util.regex.*; 027 028import jdk.internal.jvmci.code.*; 029import com.oracle.graal.debug.*; 030import com.oracle.graal.debug.Debug.*; 031import jdk.internal.jvmci.options.*; 032 033import com.oracle.graal.compiler.common.cfg.*; 034import com.oracle.graal.lir.*; 035import com.oracle.graal.lir.gen.*; 036 037/** 038 * Base class for all {@link LIR low-level} phases. Subclasses should be stateless. There will be 039 * one global instance for each phase that is shared for all compilations. 040 */ 041public abstract class LIRPhase<C> { 042 043 public static class Options { 044 // @formatter:off 045 @Option(help = "Enable LIR level optimiztations.", type = OptionType.Debug) 046 public static final OptionValue<Boolean> LIROptimization = new OptionValue<>(true); 047 // @formatter:on 048 } 049 050 private static final int PHASE_DUMP_LEVEL = 2; 051 052 private CharSequence name; 053 054 /** 055 * Records time spent within {@link #apply}. 056 */ 057 private final DebugTimer timer; 058 059 /** 060 * Records memory usage within {@link #apply}. 061 */ 062 private final DebugMemUseTracker memUseTracker; 063 064 private static class LIRPhaseStatistics { 065 /** 066 * Records time spent within {@link #apply}. 067 */ 068 private final DebugTimer timer; 069 070 /** 071 * Records memory usage within {@link #apply}. 072 */ 073 private final DebugMemUseTracker memUseTracker; 074 075 LIRPhaseStatistics(Class<?> clazz) { 076 timer = Debug.timer("LIRPhaseTime_%s", clazz); 077 memUseTracker = Debug.memUseTracker("LIRPhaseMemUse_%s", clazz); 078 } 079 } 080 081 private static final ClassValue<LIRPhaseStatistics> statisticsClassValue = new ClassValue<LIRPhaseStatistics>() { 082 @Override 083 protected LIRPhaseStatistics computeValue(Class<?> c) { 084 return new LIRPhaseStatistics(c); 085 } 086 }; 087 088 @SuppressWarnings("all") 089 private static boolean assertionsEnabled() { 090 boolean enabled = false; 091 assert enabled = true; 092 return enabled; 093 } 094 095 private static final Pattern NAME_PATTERN = assertionsEnabled() ? Pattern.compile("[A-Z][A-Za-z0-9]+") : null; 096 097 private static boolean checkName(String name) { 098 assert name == null || NAME_PATTERN.matcher(name).matches() : "illegal phase name: " + name; 099 return true; 100 } 101 102 public LIRPhase() { 103 LIRPhaseStatistics statistics = statisticsClassValue.get(getClass()); 104 timer = statistics.timer; 105 memUseTracker = statistics.memUseTracker; 106 } 107 108 protected LIRPhase(String name) { 109 assert checkName(name); 110 this.name = name; 111 LIRPhaseStatistics statistics = statisticsClassValue.get(getClass()); 112 timer = statistics.timer; 113 memUseTracker = statistics.memUseTracker; 114 } 115 116 public final <B extends AbstractBlockBase<B>> void apply(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, C context) { 117 apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, true); 118 } 119 120 public final <B extends AbstractBlockBase<B>> void apply(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, C context, boolean dumpLIR) { 121 try (Scope s = Debug.scope(getName(), this)) { 122 try (DebugCloseable a = timer.start(); DebugCloseable c = memUseTracker.start()) { 123 run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context); 124 if (dumpLIR && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) { 125 Debug.dump(PHASE_DUMP_LEVEL, lirGenRes.getLIR(), "%s", getName()); 126 } 127 } 128 } catch (Throwable e) { 129 throw Debug.handle(e); 130 } 131 } 132 133 protected abstract <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, C context); 134 135 protected CharSequence createName() { 136 String className = LIRPhase.this.getClass().getName(); 137 String s = className.substring(className.lastIndexOf(".") + 1); // strip the package name 138 if (s.endsWith("Phase")) { 139 s = s.substring(0, s.length() - "Phase".length()); 140 } 141 return s; 142 } 143 144 public final CharSequence getName() { 145 if (name == null) { 146 name = createName(); 147 } 148 return name; 149 } 150 151}