1 /*
  2  * Copyright (c) 2012, 2023, 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  *
 23  */
 24 
 25 #ifndef SHARE_OPTO_PHASETYPE_HPP
 26 #define SHARE_OPTO_PHASETYPE_HPP
 27 
 28 #include "utilities/bitMap.inline.hpp"
 29 
 30 #define COMPILER_PHASES(flags) \
 31   flags(BEFORE_STRINGOPTS,            "Before StringOpts") \
 32   flags(AFTER_STRINGOPTS,             "After StringOpts") \
 33   flags(BEFORE_REMOVEUSELESS,         "Before RemoveUseless") \
 34   flags(AFTER_PARSING,                "After Parsing") \
 35   flags(BEFORE_ITER_GVN,              "Before Iter GVN") \
 36   flags(ITER_GVN1,                    "Iter GVN 1") \
 37   flags(AFTER_ITER_GVN_STEP,          "After Iter GVN Step") \
 38   flags(AFTER_ITER_GVN,               "After Iter GVN") \
 39   flags(INCREMENTAL_INLINE_STEP,      "Incremental Inline Step") \
 40   flags(INCREMENTAL_INLINE_CLEANUP,   "Incremental Inline Cleanup") \
 41   flags(INCREMENTAL_INLINE,           "Incremental Inline") \
 42   flags(INCREMENTAL_BOXING_INLINE,    "Incremental Boxing Inline") \
 43   flags(EXPAND_VUNBOX,                "Expand VectorUnbox") \
 44   flags(SCALARIZE_VBOX,               "Scalarize VectorBox") \
 45   flags(INLINE_VECTOR_REBOX,          "Inline Vector Rebox Calls") \
 46   flags(EXPAND_VBOX,                  "Expand VectorBox") \
 47   flags(ELIMINATE_VBOX_ALLOC,         "Eliminate VectorBoxAllocate") \
 48   flags(ITER_GVN_BEFORE_EA,           "Iter GVN before EA") \
 49   flags(ITER_GVN_AFTER_VECTOR,        "Iter GVN after vector box elimination") \
 50   flags(BEFORE_BEAUTIFY_LOOPS,        "Before beautify loops") \
 51   flags(AFTER_BEAUTIFY_LOOPS,         "After beautify loops") \
 52   flags(BEFORE_CLOOPS,                "Before CountedLoop") \
 53   flags(AFTER_CLOOPS,                 "After CountedLoop") \
 54   flags(PHASEIDEAL_BEFORE_EA,         "PhaseIdealLoop before EA") \
 55   flags(AFTER_EA,                     "After Escape Analysis") \
 56   flags(ITER_GVN_AFTER_EA,            "Iter GVN after EA") \
 57   flags(ITER_GVN_AFTER_ELIMINATION,   "Iter GVN after eliminating allocations and locks") \
 58   flags(PHASEIDEALLOOP1,              "PhaseIdealLoop 1") \
 59   flags(PHASEIDEALLOOP2,              "PhaseIdealLoop 2") \
 60   flags(PHASEIDEALLOOP3,              "PhaseIdealLoop 3") \
 61   flags(CCP1,                         "PhaseCCP 1") \
 62   flags(ITER_GVN2,                    "Iter GVN 2") \
 63   flags(PHASEIDEALLOOP_ITERATIONS,    "PhaseIdealLoop iterations") \
 64   flags(MACRO_EXPANSION,              "Macro expand") \
 65   flags(BARRIER_EXPANSION,            "Barrier expand") \
 66   flags(OPTIMIZE_FINISHED,            "Optimize finished") \
 67   flags(BEFORE_MATCHING,              "Before matching") \
 68   flags(MATCHING,                     "After matching") \
 69   flags(GLOBAL_CODE_MOTION,           "Global code motion") \
 70   flags(MACH_ANALYSIS,                "After mach analysis") \
 71   flags(FINAL_CODE,                   "Final Code") \
 72   flags(END,                          "End") \
 73   flags(FAILURE,                      "Failure") \
 74   flags(SPLIT_INLINES_ARRAY,          "Split inlines array") \
 75   flags(SPLIT_INLINES_ARRAY_IGVN,     "IGVN after split inlines array") \
 76   flags(ALL,                          "All") \
 77   flags(DEBUG,                        "Debug")
 78 
 79 #define table_entry(name, description) PHASE_##name,
 80 enum CompilerPhaseType {
 81   COMPILER_PHASES(table_entry)
 82   PHASE_NUM_TYPES,
 83   PHASE_NONE
 84 };
 85 #undef table_entry
 86 
 87 static const char* phase_descriptions[] = {
 88 #define array_of_labels(name, description) description,
 89        COMPILER_PHASES(array_of_labels)
 90 #undef array_of_labels
 91 };
 92 
 93 static const char* phase_names[] = {
 94 #define array_of_labels(name, description) #name,
 95        COMPILER_PHASES(array_of_labels)
 96 #undef array_of_labels
 97 };
 98 
 99 class CompilerPhaseTypeHelper {
100   public:
101   static const char* to_name(CompilerPhaseType cpt) {
102     return phase_names[cpt];
103   }
104   static const char* to_description(CompilerPhaseType cpt) {
105     return phase_descriptions[cpt];
106   }
107 };
108 
109 static CompilerPhaseType find_phase(const char* str) {
110   for (int i = 0; i < PHASE_NUM_TYPES; i++) {
111     if (strcmp(phase_names[i], str) == 0) {
112       return (CompilerPhaseType)i;
113     }
114   }
115   return PHASE_NONE;
116 }
117 
118 class PhaseNameIter {
119  private:
120   char* _token;
121   char* _saved_ptr;
122   char* _list;
123 
124  public:
125   PhaseNameIter(ccstrlist option) {
126     _list = (char*) canonicalize(option);
127     _saved_ptr = _list;
128     _token = strtok_r(_saved_ptr, ",", &_saved_ptr);
129   }
130 
131   ~PhaseNameIter() {
132     FREE_C_HEAP_ARRAY(char, _list);
133   }
134 
135   const char* operator*() const { return _token; }
136 
137   PhaseNameIter& operator++() {
138     _token = strtok_r(nullptr, ",", &_saved_ptr);
139     return *this;
140   }
141 
142   ccstrlist canonicalize(ccstrlist option_value) {
143     char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
144     int i = 0;
145     char current;
146     while ((current = option_value[i]) != '\0') {
147       if (current == '\n' || current == ' ') {
148         canonicalized_list[i] = ',';
149       } else {
150         canonicalized_list[i] = current;
151       }
152       i++;
153     }
154     canonicalized_list[i] = '\0';
155     return canonicalized_list;
156   }
157 };
158 
159 class PhaseNameValidator {
160  private:
161   CHeapBitMap _phase_name_set;
162   bool _valid;
163   char* _bad;
164 
165  public:
166   PhaseNameValidator(ccstrlist option) :
167     _phase_name_set(PHASE_NUM_TYPES, mtCompiler),
168     _valid(true),
169     _bad(nullptr)
170   {
171     for (PhaseNameIter iter(option); *iter != nullptr && _valid; ++iter) {
172 
173       CompilerPhaseType cpt = find_phase(*iter);
174       if (PHASE_NONE == cpt) {
175         const size_t len = MIN2<size_t>(strlen(*iter), 63) + 1;  // cap len to a value we know is enough for all phase descriptions
176         _bad = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
177         // strncpy always writes len characters. If the source string is shorter, the function fills the remaining bytes with nulls.
178         strncpy(_bad, *iter, len);
179         _valid = false;
180       } else if (PHASE_ALL == cpt) {
181         _phase_name_set.set_range(0, PHASE_NUM_TYPES);
182       } else {
183         assert(cpt < PHASE_NUM_TYPES, "out of bounds");
184         _phase_name_set.set_bit(cpt);
185       }
186     }
187   }
188 
189   ~PhaseNameValidator() {
190     if (_bad != nullptr) {
191       FREE_C_HEAP_ARRAY(char, _bad);
192     }
193   }
194 
195   const BitMap& phase_name_set() const {
196     assert(is_valid(), "Use of invalid phase name set");
197     return _phase_name_set;
198   }
199 
200   bool is_valid() const {
201     return _valid;
202   }
203 
204   const char* what() const {
205     return _bad;
206   }
207 };
208 
209 #endif // SHARE_OPTO_PHASETYPE_HPP