1/*
2 * Copyright (c) 1998, 2019, 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.inline.hpp"
28#include "compiler/abstractCompiler.hpp"
29#include "compiler/compilerDirectives.hpp"
30#include "compiler/compilerOracle.hpp"
31#include "memory/allocation.inline.hpp"
32#include "memory/resourceArea.hpp"
33
34CompilerDirectives::CompilerDirectives() : _next(NULL), _match(NULL), _ref_count(0) {
35 _c1_store = new DirectiveSet(this);
36 _c2_store = new DirectiveSet(this);
37};
38
39CompilerDirectives::~CompilerDirectives() {
40 if (_c1_store != NULL) {
41 delete _c1_store;
42 }
43 if (_c2_store != NULL) {
44 delete _c2_store;
45 }
46
47 // remove all linked method matchers
48 BasicMatcher* tmp = _match;
49 while (tmp != NULL) {
50 BasicMatcher* next = tmp->next();
51 delete tmp;
52 tmp = next;
53 }
54}
55
56void CompilerDirectives::print(outputStream* st) {
57 assert(DirectivesStack_lock->owned_by_self(), "");
58 if (_match != NULL) {
59 st->cr();
60 st->print("Directive:");
61 if (is_default_directive()) {
62 st->print_cr(" (default)");
63 } else {
64 st->cr();
65 }
66 st->print(" matching: ");
67 _match->print(st);
68 BasicMatcher* tmp = _match->next();
69 while (tmp != NULL) {
70 st->print(", ");
71 tmp->print(st);
72 tmp = tmp->next();
73 }
74 st->cr();
75 } else {
76 assert(0, "There should always be a match");
77 }
78
79 if (_c1_store != NULL) {
80 st->print_cr(" c1 directives:");
81 _c1_store->print(st);
82 }
83 if (_c2_store != NULL) {
84 st->cr();
85 st->print_cr(" c2 directives:");
86 _c2_store->print(st);
87 }
88 //---
89}
90
91void CompilerDirectives::finalize(outputStream* st) {
92 if (_c1_store != NULL) {
93 _c1_store->finalize(st);
94 }
95 if (_c2_store != NULL) {
96 _c2_store->finalize(st);
97 }
98}
99
100void DirectiveSet::finalize(outputStream* st) {
101 // Check LogOption and warn
102 if (LogOption && !LogCompilation) {
103 st->print_cr("Warning: +LogCompilation must be set to enable compilation logging from directives");
104 }
105
106 // if any flag has been modified - set directive as enabled
107 // unless it already has been explicitly set.
108 if (!_modified[EnableIndex]) {
109 if (_inlinematchers != NULL) {
110 EnableOption = true;
111 return;
112 }
113 int i;
114 for (i = 0; i < number_of_flags; i++) {
115 if (_modified[i]) {
116 EnableOption = true;
117 return;
118 }
119 }
120 }
121}
122
123CompilerDirectives* CompilerDirectives::next() {
124 return _next;
125}
126
127bool CompilerDirectives::match(const methodHandle& method) {
128 if (is_default_directive()) {
129 return true;
130 }
131 if (method == NULL) {
132 return false;
133 }
134 if (_match->match(method)) {
135 return true;
136 }
137 return false;
138}
139
140bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
141 BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
142 if (bm == NULL) {
143 assert(error_msg != NULL, "Must have error message");
144 return false;
145 } else {
146 bm->set_next(_match);
147 _match = bm;
148 return true;
149 }
150}
151
152void CompilerDirectives::inc_refcount() {
153 assert(DirectivesStack_lock->owned_by_self(), "");
154 _ref_count++;
155}
156
157void CompilerDirectives::dec_refcount() {
158 assert(DirectivesStack_lock->owned_by_self(), "");
159 _ref_count--;
160}
161
162int CompilerDirectives::refcount() {
163 assert(DirectivesStack_lock->owned_by_self(), "");
164 return _ref_count;
165}
166
167DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
168 assert(DirectivesStack_lock->owned_by_self(), "");
169 if (comp == NULL) { // Xint
170 return _c1_store;
171 } else if (comp->is_c2()) {
172 return _c2_store;
173 } else {
174 // use c1_store as default
175 assert(comp->is_c1() || comp->is_jvmci(), "");
176 return _c1_store;
177 }
178}
179
180// In the list of disabled intrinsics, the ID of the disabled intrinsics can separated:
181// - by ',' (if -XX:DisableIntrinsic is used once when invoking the VM) or
182// - by '\n' (if -XX:DisableIntrinsic is used multiple times when invoking the VM) or
183// - by ' ' (if DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
184//
185// To simplify the processing of the list, the canonicalize_disableintrinsic() method
186// returns a new copy of the list in which '\n' and ' ' is replaced with ','.
187ccstrlist DirectiveSet::canonicalize_disableintrinsic(ccstrlist option_value) {
188 char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
189 int i = 0;
190 char current;
191 while ((current = option_value[i]) != '\0') {
192 if (current == '\n' || current == ' ') {
193 canonicalized_list[i] = ',';
194 } else {
195 canonicalized_list[i] = current;
196 }
197 i++;
198 }
199 canonicalized_list[i] = '\0';
200 return canonicalized_list;
201}
202
203DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
204#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
205 compilerdirectives_common_flags(init_defaults_definition)
206 compilerdirectives_c2_flags(init_defaults_definition)
207 compilerdirectives_c1_flags(init_defaults_definition)
208 memset(_modified, 0, sizeof(_modified));
209
210 // Canonicalize DisableIntrinsic to contain only ',' as a separator.
211 this->DisableIntrinsicOption = canonicalize_disableintrinsic(DisableIntrinsic);
212}
213
214DirectiveSet::~DirectiveSet() {
215 // remove all linked methodmatchers
216 InlineMatcher* tmp = _inlinematchers;
217 while (tmp != NULL) {
218 InlineMatcher* next = tmp->next();
219 delete tmp;
220 tmp = next;
221 }
222
223 // When constructed, DirectiveSet canonicalizes the DisableIntrinsic flag
224 // into a new string. Therefore, that string is deallocated when
225 // the DirectiveSet is destroyed.
226 assert(this->DisableIntrinsicOption != NULL, "");
227 FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
228}
229
230// Backward compatibility for CompileCommands
231// Breaks the abstraction and causes lots of extra complexity
232// - if some option is changed we need to copy directiveset since it no longer can be shared
233// - Need to free copy after use
234// - Requires a modified bit so we don't overwrite options that is set by directives
235
236DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) {
237 // Early bail out - checking all options is expensive - we rely on them not being used
238 // Only set a flag if it has not been modified and value changes.
239 // Only copy set if a flag needs to be set
240 if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
241 DirectiveSet* set = DirectiveSet::clone(this);
242
243 bool changed = false; // Track if we actually change anything
244
245 // All CompileCommands are not equal so this gets a bit verbose
246 // When CompileCommands have been refactored less clutter will remain.
247 if (CompilerOracle::should_break_at(method)) {
248 if (!_modified[BreakAtCompileIndex]) {
249 set->BreakAtCompileOption = true;
250 changed = true;
251 }
252 if (!_modified[BreakAtExecuteIndex]) {
253 set->BreakAtExecuteOption = true;
254 changed = true;
255 }
256 }
257 if (!_modified[LogIndex]) {
258 bool log = CompilerOracle::should_log(method);
259 if (log != set->LogOption) {
260 set->LogOption = log;
261 changed = true;
262 }
263 }
264
265 if (CompilerOracle::should_print(method)) {
266 if (!_modified[PrintAssemblyIndex]) {
267 set->PrintAssemblyOption = true;
268 changed = true;
269 }
270 }
271 // Exclude as in should not compile == Enabled
272 if (CompilerOracle::should_exclude(method)) {
273 if (!_modified[ExcludeIndex]) {
274 set->ExcludeOption = true;
275 changed = true;
276 }
277 }
278
279 // inline and dontinline (including exclude) are implemented in the directiveset accessors
280#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) { set->name##Option = v; changed = true;} }
281 compilerdirectives_common_flags(init_default_cc)
282 compilerdirectives_c2_flags(init_default_cc)
283 compilerdirectives_c1_flags(init_default_cc)
284
285 // Canonicalize DisableIntrinsic to contain only ',' as a separator.
286 ccstrlist option_value;
287 if (!_modified[DisableIntrinsicIndex] &&
288 CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
289 set->DisableIntrinsicOption = canonicalize_disableintrinsic(option_value);
290 }
291
292
293 if (!changed) {
294 // We didn't actually update anything, discard.
295 delete set;
296 } else {
297 // We are returning a (parentless) copy. The originals parent don't need to account for this.
298 DirectivesStack::release(this);
299 return set;
300 }
301 }
302 // Nothing changed
303 return this;
304}
305
306CompilerDirectives* DirectiveSet::directive() {
307 assert(_directive != NULL, "Must have been initialized");
308 return _directive;
309}
310
311bool DirectiveSet::matches_inline(const methodHandle& method, int inline_action) {
312 if (_inlinematchers != NULL) {
313 if (_inlinematchers->match(method, inline_action)) {
314 return true;
315 }
316 }
317 return false;
318}
319
320bool DirectiveSet::should_inline(ciMethod* inlinee) {
321 inlinee->check_is_loaded();
322 VM_ENTRY_MARK;
323 methodHandle mh(THREAD, inlinee->get_Method());
324
325 if (_inlinematchers != NULL) {
326 return matches_inline(mh, InlineMatcher::force_inline);
327 }
328 if (!CompilerDirectivesIgnoreCompileCommandsOption) {
329 return CompilerOracle::should_inline(mh);
330 }
331 return false;
332}
333
334bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
335 inlinee->check_is_loaded();
336 VM_ENTRY_MARK;
337 methodHandle mh(THREAD, inlinee->get_Method());
338
339 if (_inlinematchers != NULL) {
340 return matches_inline(mh, InlineMatcher::dont_inline);
341 }
342 if (!CompilerDirectivesIgnoreCompileCommandsOption) {
343 return CompilerOracle::should_not_inline(mh);
344 }
345 return false;
346}
347
348bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
349 InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
350 if (m != NULL) {
351 // add matcher last in chain - the order is significant
352 append_inline(m);
353 return true;
354 } else {
355 assert(error_msg != NULL, "Error message must be set");
356 return false;
357 }
358}
359
360void DirectiveSet::append_inline(InlineMatcher* m) {
361 if (_inlinematchers == NULL) {
362 _inlinematchers = m;
363 return;
364 }
365 InlineMatcher* tmp = _inlinematchers;
366 while (tmp->next() != NULL) {
367 tmp = tmp->next();
368 }
369 tmp->set_next(m);
370}
371
372void DirectiveSet::print_inline(outputStream* st) {
373 if (_inlinematchers == NULL) {
374 st->print_cr(" inline: -");
375 } else {
376 st->print(" inline: ");
377 _inlinematchers->print(st);
378 InlineMatcher* tmp = _inlinematchers->next();
379 while (tmp != NULL) {
380 st->print(", ");
381 tmp->print(st);
382 tmp = tmp->next();
383 }
384 st->cr();
385 }
386}
387
388bool DirectiveSet::is_intrinsic_disabled(const methodHandle& method) {
389 vmIntrinsics::ID id = method->intrinsic_id();
390 assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
391
392 ResourceMark rm;
393
394 // Create a copy of the string that contains the list of disabled
395 // intrinsics. The copy is created because the string
396 // will be modified by strtok(). Then, the list is tokenized with
397 // ',' as a separator.
398 size_t length = strlen(DisableIntrinsicOption);
399 char* local_list = NEW_RESOURCE_ARRAY(char, length + 1);
400 strncpy(local_list, DisableIntrinsicOption, length + 1);
401 char* save_ptr;
402
403 char* token = strtok_r(local_list, ",", &save_ptr);
404 while (token != NULL) {
405 if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
406 return true;
407 } else {
408 token = strtok_r(NULL, ",", &save_ptr);
409 }
410 }
411
412 return false;
413}
414
415DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
416 DirectiveSet* set = new DirectiveSet(NULL);
417 memcpy(set->_modified, src->_modified, sizeof(src->_modified));
418
419 InlineMatcher* tmp = src->_inlinematchers;
420 while (tmp != NULL) {
421 set->append_inline(tmp->clone());
422 tmp = tmp->next();
423 }
424
425 #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
426 compilerdirectives_common_flags(copy_members_definition)
427 compilerdirectives_c2_flags(copy_members_definition)
428 compilerdirectives_c1_flags(copy_members_definition)
429
430 // Create a local copy of the DisableIntrinsicOption.
431 assert(src->DisableIntrinsicOption != NULL, "");
432 size_t len = strlen(src->DisableIntrinsicOption) + 1;
433 char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
434 strncpy(s, src->DisableIntrinsicOption, len);
435 assert(s[len-1] == '\0', "");
436 set->DisableIntrinsicOption = s;
437 return set;
438}
439
440// Create a new dirstack and push a default directive
441void DirectivesStack::init() {
442 CompilerDirectives* _default_directives = new CompilerDirectives();
443 char str[] = "*.*";
444 const char* error_msg = NULL;
445 _default_directives->add_match(str, error_msg);
446#if defined(COMPILER1) || INCLUDE_JVMCI
447 _default_directives->_c1_store->EnableOption = true;
448#endif
449#ifdef COMPILER2
450 if (is_server_compilation_mode_vm()) {
451 _default_directives->_c2_store->EnableOption = true;
452 }
453#endif
454 assert(error_msg == NULL, "Must succeed.");
455 push(_default_directives);
456}
457
458DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
459 MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
460
461 assert(_bottom != NULL, "Must never be empty");
462 _bottom->inc_refcount();
463 return _bottom->get_for(comp);
464}
465
466void DirectivesStack::push(CompilerDirectives* directive) {
467 MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
468
469 directive->inc_refcount();
470 if (_top == NULL) {
471 assert(_bottom == NULL, "There can only be one default directive");
472 _bottom = directive; // default directive, can never be removed.
473 }
474
475 directive->set_next(_top);
476 _top = directive;
477 _depth++;
478}
479
480void DirectivesStack::pop(int count) {
481 MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
482 assert(count > -1, "No negative values");
483 for (int i = 0; i < count; i++) {
484 pop_inner();
485 }
486}
487
488void DirectivesStack::pop_inner() {
489 assert(DirectivesStack_lock->owned_by_self(), "");
490
491 if (_top->next() == NULL) {
492 return; // Do nothing - don't allow an empty stack
493 }
494 CompilerDirectives* tmp = _top;
495 _top = _top->next();
496 _depth--;
497
498 DirectivesStack::release(tmp);
499}
500
501bool DirectivesStack::check_capacity(int request_size, outputStream* st) {
502 if ((request_size + _depth) > CompilerDirectivesLimit) {
503 st->print_cr("Could not add %i more directives. Currently %i/%i directives.", request_size, _depth, CompilerDirectivesLimit);
504 return false;
505 }
506 return true;
507}
508
509void DirectivesStack::clear() {
510 // holding the lock during the whole operation ensuring consistent result
511 MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
512 while (_top->next() != NULL) {
513 pop_inner();
514 }
515}
516
517void DirectivesStack::print(outputStream* st) {
518 MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
519 CompilerDirectives* tmp = _top;
520 while (tmp != NULL) {
521 tmp->print(st);
522 tmp = tmp->next();
523 st->cr();
524 }
525}
526
527void DirectivesStack::release(DirectiveSet* set) {
528 assert(set != NULL, "Never NULL");
529 MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
530 if (set->is_exclusive_copy()) {
531 // Old CompilecCmmands forced us to create an exclusive copy
532 delete set;
533 } else {
534 assert(set->directive() != NULL, "Never NULL");
535 release(set->directive());
536 }
537}
538
539
540void DirectivesStack::release(CompilerDirectives* dir) {
541 assert(DirectivesStack_lock->owned_by_self(), "");
542 dir->dec_refcount();
543 if (dir->refcount() == 0) {
544 delete dir;
545 }
546}
547
548DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, AbstractCompiler *comp) {
549 assert(_depth > 0, "Must never be empty");
550
551 DirectiveSet* match = NULL;
552 {
553 MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
554
555 CompilerDirectives* dir = _top;
556 assert(dir != NULL, "Must be initialized");
557
558 while (dir != NULL) {
559 if (dir->is_default_directive() || dir->match(method)) {
560 match = dir->get_for(comp);
561 assert(match != NULL, "Consistency");
562 if (match->EnableOption) {
563 // The directiveSet for this compile is also enabled -> success
564 dir->inc_refcount();
565 break;
566 }
567 }
568 dir = dir->next();
569 }
570 }
571 guarantee(match != NULL, "There should always be a default directive that matches");
572
573 // Check for legacy compile commands update, without DirectivesStack_lock
574 return match->compilecommand_compatibility_init(method);
575}
576