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