1 /* 2 * Copyright (c) 1998, 2014, 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 #include "precompiled.hpp" 26 #include "ci/ciMethod.hpp" 27 #include "ci/ciUtilities.hpp" 28 #include "compiler/compilerDirectives.hpp" 29 #include "compiler/compilerOracle.hpp" 30 31 CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) { 32 _c1_store = new DirectiveSet(this); 33 _c2_store = new DirectiveSet(this); 34 }; 35 36 CompilerDirectives::~CompilerDirectives() { 37 if (_c1_store != NULL) { 38 delete _c1_store; 39 } 40 if (_c2_store != NULL) { 41 delete _c2_store; 42 } 43 44 // remove all linked method matchers 45 BasicMatcher* tmp = _match; 46 while (tmp != NULL) { 47 BasicMatcher* next = tmp->next(); 48 delete tmp; 49 tmp = next; 50 } 51 } 52 53 void CompilerDirectives::print(outputStream* st) { 54 st->cr(); 55 if (_match != NULL) { 56 st->print_cr("Directive:"); 57 st->print(" matching: "); 58 _match->print(st); 59 BasicMatcher* tmp = _match->next(); 60 while (tmp != NULL) { 61 st->print(", "); 62 tmp->print(st); 63 tmp = tmp->next(); 64 } 65 st->cr(); 66 } else { 67 assert(0, "There should always be a match"); 68 } 69 70 if (_c1_store != NULL) { 71 st->print_cr(" c1 directives:"); 72 _c1_store->print(st); 73 } 74 if (_c2_store != NULL) { 75 st->print_cr(" c2 directives:"); 76 _c2_store->print(st); 77 } 78 //--- 79 } 80 81 CompilerDirectives* CompilerDirectives::next() { 82 return _next; 83 } 84 85 bool CompilerDirectives::match(methodHandle method, int comp_level) { 86 if (method == NULL) { 87 return false; 88 } 89 if (_match->match(method)) { 90 return true; 91 } 92 return false; 93 } 94 95 bool CompilerDirectives::add_match(char* str, const char*& error_msg) { 96 int bytes_read; 97 98 BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg); 99 if (bm == NULL) { 100 assert(error_msg != NULL, "Must have error message"); 101 return false; 102 } else { 103 bm->set_next(_match); 104 _match = bm; 105 return true; 106 } 107 } 108 109 void CompilerDirectives::inc_refcount() { 110 assert(DirectivesStack_lock->owned_by_self(), ""); 111 _ref_count++; 112 } 113 114 void CompilerDirectives::dec_refcount() { 115 assert(DirectivesStack_lock->owned_by_self(), ""); 116 _ref_count--; 117 if (_ref_count == 0) { 118 delete this; 119 } 120 } 121 122 DirectiveSet* CompilerDirectives::get_for(int comp_level) { 123 assert(DirectivesStack_lock->owned_by_self(), ""); 124 inc_refcount(); // The compiling thread is responsible to decrement this when finished. 125 assert((comp_level >= CompLevel_simple) && (comp_level <= CompLevel_full_optimization), "Outside bounds"); 126 if (comp_level == CompLevel_full_optimization) { 127 return _c2_store; 128 } else { 129 return _c1_store; 130 } 131 } 132 133 DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) { 134 #define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue; 135 compilerdirectives_common_flags(init_defaults_definition) 136 compilerdirectives_c2_flags(init_defaults_definition) 137 compilerdirectives_c1_flags(init_defaults_definition) 138 memset(_modified, 0, sizeof _modified); 139 } 140 141 void DirectiveSet::release() { 142 MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); 143 directive()->dec_refcount(); 144 } 145 146 DirectiveSet::~DirectiveSet() { 147 // remove all linked methodmatchers 148 InlineMatcher* tmp = _inlinematchers; 149 while (tmp != NULL) { 150 InlineMatcher* next = tmp->next(); 151 delete tmp; 152 tmp = next; 153 } 154 155 #ifdef COMPILER2 156 // Free if modified, otherwise it just points to the global vm flag value 157 if (_modified[DisableIntrinsicsIndex]) { 158 FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicsOption); 159 } 160 #endif 161 } 162 163 // Backward compatibility for CompileCommands 164 // Breaks the abstraction and causes lots of extra complexity 165 // - if some option is changed we need to copy dirset since it no longer can be shared 166 // - Need to free copy after use 167 // - Requires a modified bit so we don't overwrite options that is set by directives 168 169 DirectiveSet* DirectiveSet::late_cc_init(methodHandle method) { 170 // Early bail out - checking all options is expensive - we rely on them not being used 171 // Only set a flag if it has not been modified and value changes. 172 // Only copy set if a flag needs to be set 173 if (CompileCommandCompatibilityOption && CompilerOracle::has_any_option()) { 174 DirectiveSet* set = clone(); 175 176 bool changed = false; // Track if we actually change anything 177 178 // All CompileCommands are not equal so this gets a bit verbose 179 // When CompileCommands have been refactored less clutter will remain. 180 if (CompilerOracle::should_break_at(method)) { 181 if (!_modified[BreakAtCompileIndex] && !set->BreakAtCompileOption) { 182 set->BreakAtCompileOption = true; 183 changed = true; 184 } 185 if (!_modified[BreakAtExecuteIndex] && !set->BreakAtExecuteOption) { 186 set->BreakAtExecuteOption = true; 187 changed = true; 188 } 189 } 190 if (CompilerOracle::should_log(method)) { 191 if (!_modified[LogIndex] && !set->LogOption) { 192 set->LogOption = true; 193 changed = true; 194 } 195 } 196 if (CompilerOracle::should_print(method)) { 197 if (!_modified[PrintAssemblyIndex] && !set->PrintAssemblyOption) { 198 set->PrintAssemblyOption = true; 199 changed = true; 200 } 201 } 202 // Exclude as in should not compile == Enabled 203 if (CompilerOracle::should_exclude(method)) { 204 if (!_modified[EnabledIndex] && !set->EnabledOption) { 205 set->EnabledOption = true; 206 changed = true; 207 } 208 } 209 210 // inline and dontinline (including exclude) are implemented in the directiveset accessors 211 #define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { this->name##Option = v; changed = true;} } 212 compilerdirectives_common_flags(init_default_cc) 213 compilerdirectives_c2_flags(init_default_cc) 214 compilerdirectives_c1_flags(init_default_cc) 215 216 if (!changed) { 217 // We didn't actually update anything, discard. 218 delete set; 219 } else { 220 // We are returning a (parentless) copy. The originals parent don't need to account for this. 221 this->release(); 222 return set; 223 } 224 } 225 // Nothing changed 226 return this; 227 } 228 229 CompilerDirectives* DirectiveSet::directive() { 230 assert(_directive != NULL, "Must have been initialized"); 231 return _directive; 232 } 233 234 bool DirectiveSet::matches_inline(methodHandle method, int inline_action) { 235 if (_inlinematchers != NULL) { 236 if (_inlinematchers->match(method, InlineMatcher::force_inline)) { 237 return true; 238 } 239 } 240 return false; 241 } 242 243 bool DirectiveSet::inline_commanded(ciMethod* inlinee) { 244 inlinee->check_is_loaded(); 245 VM_ENTRY_MARK; 246 methodHandle mh(THREAD, inlinee->get_Method()); 247 248 if (matches_inline(mh, InlineMatcher::force_inline)) { 249 return true; 250 } 251 if (CompileCommandCompatibilityOption && CompilerOracle::should_inline(mh)) { 252 return true; 253 } 254 return false; 255 } 256 257 bool DirectiveSet::dont_inline_commanded(ciMethod* inlinee) { 258 inlinee->check_is_loaded(); 259 VM_ENTRY_MARK; 260 methodHandle mh(THREAD, inlinee->get_Method()); 261 262 if (matches_inline(mh, InlineMatcher::dont_inline)) { 263 return true; 264 } 265 if (CompileCommandCompatibilityOption && CompilerOracle::should_not_inline(mh)) { 266 return true; 267 } 268 return false; 269 } 270 271 bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) { 272 InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg); 273 if (m != NULL) { 274 // add matcher last in chain - the order is significant 275 append_inline(m); 276 return true; 277 } else { 278 assert(error_msg != NULL, "Error message must be set"); 279 return false; 280 } 281 } 282 283 void DirectiveSet::append_inline(InlineMatcher* m) { 284 if (_inlinematchers == NULL) { 285 _inlinematchers = m; 286 return; 287 } 288 InlineMatcher* tmp = _inlinematchers; 289 while (tmp->next() != NULL) { 290 tmp = tmp->next(); 291 } 292 tmp->set_next(m); 293 } 294 295 void DirectiveSet::print_inline(outputStream* st) { 296 if (_inlinematchers == NULL) { 297 st->print_cr(" inline: -"); 298 } else { 299 st->print(" inline: "); 300 _inlinematchers->print(st); 301 InlineMatcher* tmp = _inlinematchers->next(); 302 while (tmp != NULL) { 303 st->print(", "); 304 tmp->print(st); 305 tmp = tmp->next(); 306 } 307 st->cr(); 308 } 309 } 310 311 bool DirectiveSet::is_intrinsic_disabled(methodHandle method) { 312 vmIntrinsics::ID id = method->intrinsic_id(); 313 assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); 314 315 ccstr disable_intr = DisableIntrinsicsOption; 316 return ((disable_intr != '\0') && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL); 317 } 318 319 DirectiveSet* DirectiveSet::clone() { 320 DirectiveSet* set = clone(); 321 memcpy(set->_modified, _modified, sizeof(_modified)); 322 323 InlineMatcher* tmp = _inlinematchers; 324 while (tmp != NULL) { 325 set->append_inline(tmp->clone()); 326 tmp = tmp->next(); 327 } 328 329 #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = name##Option; 330 compilerdirectives_common_flags(copy_members_definition) 331 compilerdirectives_c2_flags(copy_members_definition) 332 compilerdirectives_c1_flags(copy_members_definition) 333 334 // Must duplicate str option 335 set->DisableIntrinsicsOption = os::strdup(DisableIntrinsicsOption, mtCompiler); 336 337 return set; 338 }