LIRPhase.java revision 12651:6ef01bd40ce2
1/*
2 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.lir.phases;
24
25import java.util.regex.Pattern;
26
27import org.graalvm.compiler.debug.Debug;
28import org.graalvm.compiler.debug.Debug.Scope;
29import org.graalvm.compiler.debug.DebugCloseable;
30import org.graalvm.compiler.debug.DebugMemUseTracker;
31import org.graalvm.compiler.debug.DebugTimer;
32import org.graalvm.compiler.lir.LIR;
33import org.graalvm.compiler.lir.gen.LIRGenerationResult;
34import org.graalvm.compiler.options.Option;
35import org.graalvm.compiler.options.OptionType;
36import org.graalvm.compiler.options.OptionValue;
37
38import jdk.vm.ci.code.TargetDescription;
39
40/**
41 * Base class for all {@link LIR low-level} phases. Subclasses should be stateless. There will be
42 * one global instance for each phase that is shared for all compilations.
43 */
44public abstract class LIRPhase<C> {
45
46    public static class Options {
47        // @formatter:off
48        @Option(help = "Enable LIR level optimiztations.", type = OptionType.Debug)
49        public static final OptionValue<Boolean> LIROptimization = new OptionValue<>(true);
50        // @formatter:on
51    }
52
53    /**
54     * Records time spent within {@link #apply}.
55     */
56    private final DebugTimer timer;
57
58    /**
59     * Records memory usage within {@link #apply}.
60     */
61    private final DebugMemUseTracker memUseTracker;
62
63    public static final class LIRPhaseStatistics {
64        /**
65         * Records time spent within {@link #apply}.
66         */
67        public final DebugTimer timer;
68
69        /**
70         * Records memory usage within {@link #apply}.
71         */
72        public final DebugMemUseTracker memUseTracker;
73
74        private LIRPhaseStatistics(Class<?> clazz) {
75            timer = Debug.timer("LIRPhaseTime_%s", clazz);
76            memUseTracker = Debug.memUseTracker("LIRPhaseMemUse_%s", clazz);
77        }
78    }
79
80    public static final ClassValue<LIRPhaseStatistics> statisticsClassValue = new ClassValue<LIRPhaseStatistics>() {
81        @Override
82        protected LIRPhaseStatistics computeValue(Class<?> c) {
83            return new LIRPhaseStatistics(c);
84        }
85    };
86
87    /** Lazy initialization to create pattern only when assertions are enabled. */
88    static class NamePatternHolder {
89        static final Pattern NAME_PATTERN = Pattern.compile("[A-Z][A-Za-z0-9]+");
90    }
91
92    private static boolean checkName(CharSequence name) {
93        assert name == null || NamePatternHolder.NAME_PATTERN.matcher(name).matches() : "illegal phase name: " + name;
94        return true;
95    }
96
97    public LIRPhase() {
98        LIRPhaseStatistics statistics = statisticsClassValue.get(getClass());
99        timer = statistics.timer;
100        memUseTracker = statistics.memUseTracker;
101    }
102
103    public final void apply(TargetDescription target, LIRGenerationResult lirGenRes, C context) {
104        apply(target, lirGenRes, context, true);
105    }
106
107    @SuppressWarnings("try")
108    public final void apply(TargetDescription target, LIRGenerationResult lirGenRes, C context, boolean dumpLIR) {
109        try (Scope s = Debug.scope(getName(), this)) {
110            try (DebugCloseable a = timer.start(); DebugCloseable c = memUseTracker.start()) {
111                run(target, lirGenRes, context);
112                if (dumpLIR && Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
113                    Debug.dump(Debug.BASIC_LOG_LEVEL, lirGenRes.getLIR(), "%s", getName());
114                }
115            }
116        } catch (Throwable e) {
117            throw Debug.handle(e);
118        }
119    }
120
121    protected abstract void run(TargetDescription target, LIRGenerationResult lirGenRes, C context);
122
123    public static CharSequence createName(Class<?> clazz) {
124        String className = clazz.getName();
125        String s = className.substring(className.lastIndexOf(".") + 1); // strip the package name
126        int innerClassPos = s.indexOf('$');
127        if (innerClassPos > 0) {
128            /* Remove inner class name. */
129            s = s.substring(0, innerClassPos);
130        }
131        if (s.endsWith("Phase")) {
132            s = s.substring(0, s.length() - "Phase".length());
133        }
134        return s;
135    }
136
137    protected CharSequence createName() {
138        return createName(getClass());
139    }
140
141    public final CharSequence getName() {
142        CharSequence name = createName();
143        assert checkName(name);
144        return name;
145    }
146}
147