jdk

Форк
0
/
compilerDirectives.cpp 
777 строк · 24.2 Кб
1
/*
2
 * Copyright (c) 1998, 2024, 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/compilerDefinitions.inline.hpp"
30
#include "compiler/compilerDirectives.hpp"
31
#include "compiler/compilerOracle.hpp"
32
#include "memory/allocation.inline.hpp"
33
#include "memory/resourceArea.hpp"
34
#include "opto/phasetype.hpp"
35
#include "opto/traceAutoVectorizationTag.hpp"
36
#include "runtime/globals_extension.hpp"
37

38
CompilerDirectives::CompilerDirectives() : _next(nullptr), _match(nullptr), _ref_count(0) {
39
  _c1_store = new DirectiveSet(this);
40
  _c1_store->init_control_intrinsic();
41
  _c2_store = new DirectiveSet(this);
42
  _c2_store->init_control_intrinsic();
43
};
44

45
CompilerDirectives::~CompilerDirectives() {
46
  if (_c1_store != nullptr) {
47
    delete _c1_store;
48
  }
49
  if (_c2_store != nullptr) {
50
    delete _c2_store;
51
  }
52

53
  // remove all linked method matchers
54
  BasicMatcher* tmp = _match;
55
  while (tmp != nullptr) {
56
    BasicMatcher* next = tmp->next();
57
    delete tmp;
58
    tmp = next;
59
  }
60
}
61

62
void CompilerDirectives::print(outputStream* st) {
63
  assert(DirectivesStack_lock->owned_by_self(), "");
64
  if (_match != nullptr) {
65
    st->cr();
66
    st->print("Directive:");
67
    if (is_default_directive()) {
68
      st->print_cr(" (default)");
69
    } else {
70
      st->cr();
71
    }
72
    st->print(" matching: ");
73
    _match->print(st);
74
    BasicMatcher* tmp = _match->next();
75
    while (tmp != nullptr) {
76
      st->print(", ");
77
      tmp->print(st);
78
      tmp = tmp->next();
79
    }
80
    st->cr();
81
  } else {
82
    assert(0, "There should always be a match");
83
  }
84

85
  if (_c1_store != nullptr) {
86
    st->print_cr(" c1 directives:");
87
    _c1_store->print(st);
88
  }
89
  if (_c2_store != nullptr) {
90
    st->cr();
91
    st->print_cr(" c2 directives:");
92
    _c2_store->print(st);
93
  }
94
  //---
95
}
96

97
void CompilerDirectives::finalize(outputStream* st) {
98
  if (_c1_store != nullptr) {
99
    _c1_store->finalize(st);
100
  }
101
  if (_c2_store != nullptr) {
102
    _c2_store->finalize(st);
103
  }
104
}
105

106
void DirectiveSet::finalize(outputStream* st) {
107
  const char* level;
108
  if (is_c1(this->directive())) {
109
    level = "c1";
110
  } else if (is_c2(this->directive())) {
111
    level = "c2";
112
  } else {
113
    ShouldNotReachHere();
114
  }
115

116
  if (LogOption && !LogCompilation) {
117
    st->print_cr("Warning: %s: +LogCompilation must be set to enable compilation logging from directives", level);
118
  }
119
  if (PrintAssemblyOption && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
120
    warning("%s: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output", level);
121
    DebugNonSafepoints = true;
122
  }
123

124
  // if any flag has been modified - set directive as enabled
125
  // unless it already has been explicitly set.
126
  if (!_modified[EnableIndex]) {
127
    if (_inlinematchers != nullptr) {
128
      EnableOption = true;
129
      return;
130
    }
131
    int i;
132
    for (i = 0; i < number_of_flags; i++) {
133
      if (_modified[i]) {
134
        EnableOption = true;
135
        return;
136
      }
137
    }
138
  }
139
}
140

141
CompilerDirectives* CompilerDirectives::next() {
142
  return _next;
143
}
144

145
bool CompilerDirectives::match(const methodHandle& method) {
146
  if (is_default_directive()) {
147
    return true;
148
  }
149
  if (method == nullptr) {
150
    return false;
151
  }
152
  if (_match->match(method)) {
153
    return true;
154
  }
155
  return false;
156
}
157

158
bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
159
  BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg, false);
160
  if (bm == nullptr) {
161
    assert(error_msg != nullptr, "Must have error message");
162
    return false;
163
  } else {
164
    bm->set_next(_match);
165
    _match = bm;
166
    return true;
167
  }
168
}
169

170
void CompilerDirectives::inc_refcount() {
171
  assert(DirectivesStack_lock->owned_by_self(), "");
172
  _ref_count++;
173
}
174

175
void CompilerDirectives::dec_refcount() {
176
  assert(DirectivesStack_lock->owned_by_self(), "");
177
  _ref_count--;
178
}
179

180
int CompilerDirectives::refcount() {
181
  assert(DirectivesStack_lock->owned_by_self(), "");
182
  return _ref_count;
183
}
184

185
DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
186
  assert(DirectivesStack_lock->owned_by_self(), "");
187
  if (comp == nullptr) { // Xint
188
    return _c1_store;
189
  } else  if (comp->is_c2()) {
190
    return _c2_store;
191
  } else {
192
    // use c1_store as default
193
    assert(comp->is_c1() || comp->is_jvmci(), "");
194
    return _c1_store;
195
  }
196
}
197

198
bool DirectiveSet::is_c1(CompilerDirectives* directive) const {
199
  return this == directive->_c1_store;
200
}
201

202
bool DirectiveSet::is_c2(CompilerDirectives* directive) const {
203
  return this == directive->_c2_store;
204
}
205

206
bool DirectiveSet::should_collect_memstat() const {
207
  // MemLimit requires the memory statistic to be active
208
  return MemStatOption > 0 || MemLimitOption != 0;
209
}
210

211
bool DirectiveSet::should_print_memstat() const {
212
  return MemStatOption == (uintx)MemStatAction::print;
213
}
214

215
size_t DirectiveSet::mem_limit() const {
216
  return MemLimitOption < 0 ? -MemLimitOption : MemLimitOption;
217
}
218

219
bool DirectiveSet::should_crash_at_mem_limit() const {
220
  // The sign encodes the action to be taken when reaching
221
  // the memory limit (+ stop - crash)
222
  return MemLimitOption < 0;
223
}
224

225
// In the list of Control/disabled intrinsics, the ID of the control intrinsics can separated:
226
// - by ',' (if -XX:Control/DisableIntrinsic is used once when invoking the VM) or
227
// - by '\n' (if -XX:Control/DisableIntrinsic is used multiple times when invoking the VM) or
228
// - by ' ' (if Control/DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
229
//
230
// To simplify the processing of the list, the canonicalize_control_intrinsic() method
231
// returns a new copy of the list in which '\n' and ' ' is replaced with ','.
232
ccstrlist DirectiveSet::canonicalize_control_intrinsic(ccstrlist option_value) {
233
  char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
234
  int i = 0;
235
  char current;
236
  while ((current = option_value[i]) != '\0') {
237
    if (current == '\n' || current == ' ') {
238
      canonicalized_list[i] = ',';
239
    } else {
240
      canonicalized_list[i] = current;
241
    }
242
    i++;
243
  }
244
  canonicalized_list[i] = '\0';
245
  return canonicalized_list;
246
}
247

248
ControlIntrinsicIter::ControlIntrinsicIter(ccstrlist option_value, bool disable_all)
249
  : _disableIntrinsic(disable_all) {
250
  _list = (char*)DirectiveSet::canonicalize_control_intrinsic(option_value);
251
  _saved_ptr = _list;
252
  _enabled = false;
253

254
  _token = strtok_r(_saved_ptr, ",", &_saved_ptr);
255
  next_token();
256
}
257

258
ControlIntrinsicIter::~ControlIntrinsicIter() {
259
  FREE_C_HEAP_ARRAY(char, _list);
260
}
261

262
// pre-increment
263
ControlIntrinsicIter& ControlIntrinsicIter::operator++() {
264
  _token = strtok_r(nullptr, ",", &_saved_ptr);
265
  next_token();
266
  return *this;
267
}
268

269
void ControlIntrinsicIter::next_token() {
270
  if (_token && !_disableIntrinsic) {
271
    char ch = _token[0];
272

273
    if (ch != '+' && ch != '-') {
274
      warning("failed to parse %s. must start with +/-!", _token);
275
    } else {
276
      _enabled = ch == '+';
277
      _token++;
278
    }
279
  }
280
}
281

282
void DirectiveSet::init_control_intrinsic() {
283
  for (ControlIntrinsicIter iter(ControlIntrinsic); *iter != nullptr; ++iter) {
284
    vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
285

286
    if (id != vmIntrinsics::_none) {
287
      _intrinsic_control_words[vmIntrinsics::as_int(id)] = iter.is_enabled();
288
    }
289
  }
290

291
  // Order matters, DisableIntrinsic can overwrite ControlIntrinsic
292
  for (ControlIntrinsicIter iter(DisableIntrinsic, true/*disable_all*/); *iter != nullptr; ++iter) {
293
    vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
294

295
    if (id != vmIntrinsics::_none) {
296
      _intrinsic_control_words[vmIntrinsics::as_int(id)] = false;
297
    }
298
  }
299
}
300

301
DirectiveSet::DirectiveSet(CompilerDirectives* d) :
302
  _inlinematchers(nullptr),
303
  _directive(d),
304
  _ideal_phase_name_set(PHASE_NUM_TYPES, mtCompiler),
305
  _trace_auto_vectorization_tags(TRACE_AUTO_VECTORIZATION_TAG_NUM, mtCompiler)
306
{
307
#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
308
  compilerdirectives_common_flags(init_defaults_definition)
309
  compilerdirectives_c2_flags(init_defaults_definition)
310
  compilerdirectives_c1_flags(init_defaults_definition)
311
#undef init_defaults_definition
312
  memset(_modified, 0, sizeof(_modified));
313
  _intrinsic_control_words.fill_in(/*default value*/TriBool());
314
}
315

316
DirectiveSet::~DirectiveSet() {
317
  // remove all linked methodmatchers
318
  InlineMatcher* tmp = _inlinematchers;
319
  while (tmp != nullptr) {
320
    InlineMatcher* next = tmp->next();
321
    delete tmp;
322
    tmp = next;
323
  }
324

325
#define free_string_flags(name, type, dvalue, cc_flag) if (_modified[name##Index]) os::free(const_cast<char*>(name##Option));
326
  compilerdirectives_common_string_flags(free_string_flags)
327
  compilerdirectives_c2_string_flags(free_string_flags)
328
  compilerdirectives_c1_string_flags(free_string_flags)
329
#undef free_string_flags
330
}
331

332
// A smart pointer of DirectiveSet. It uses Copy-on-Write strategy to avoid cloning.
333
// It provides 2 accesses of the underlying raw pointer.
334
// 1) operator->() returns a pointer to a constant DirectiveSet. It's read-only.
335
// 2) cloned() returns a pointer that points to the cloned DirectiveSet.
336
// Users should only use cloned() when they need to update DirectiveSet.
337
//
338
// In the end, users need to invoke commit() to finalize the pending changes.
339
// If cloning happens, the smart pointer will return the new pointer after releasing the original
340
// one on DirectivesStack. If cloning doesn't happen, it returns the original intact pointer.
341
class DirectiveSetPtr {
342
 private:
343
  DirectiveSet* _origin;
344
  DirectiveSet* _clone;
345
  NONCOPYABLE(DirectiveSetPtr);
346

347
 public:
348
  DirectiveSetPtr(DirectiveSet* origin): _origin(origin), _clone(nullptr) {
349
    assert(origin != nullptr, "DirectiveSetPtr cannot be initialized with a nullptr pointer.");
350
  }
351

352
  DirectiveSet const* operator->() {
353
    return (_clone == nullptr) ? _origin : _clone;
354
  }
355

356
  DirectiveSet* cloned() {
357
    if (_clone == nullptr) {
358
      _clone = DirectiveSet::clone(_origin);
359
    }
360
    return _clone;
361
  }
362

363
  DirectiveSet* commit() {
364
    if (_clone != nullptr) {
365
      // We are returning a (parentless) copy. The originals parent don't need to account for this.
366
      DirectivesStack::release(_origin);
367
      _origin = _clone;
368
      _clone = nullptr;
369
    }
370

371
    return _origin;
372
  }
373
};
374

375
// Backward compatibility for CompileCommands
376
// Breaks the abstraction and causes lots of extra complexity
377
// - if some option is changed we need to copy directiveset since it no longer can be shared
378
// - Need to free copy after use
379
// - Requires a modified bit so we don't overwrite options that is set by directives
380
DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) {
381
  // Early bail out - checking all options is expensive - we rely on them not being used
382
  // Only set a flag if it has not been modified and value changes.
383
  // Only copy set if a flag needs to be set
384
  if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_command_set()) {
385
    DirectiveSetPtr set(this);
386

387
#ifdef COMPILER1
388
    if (C1Breakpoint) {
389
      // If the directives didn't have 'BreakAtExecute',
390
      // the command 'C1Breakpoint' would become effective.
391
      if (!_modified[BreakAtExecuteIndex]) {
392
         set.cloned()->BreakAtExecuteOption = true;
393
      }
394
    }
395
#endif
396

397
    // All CompileCommands are not equal so this gets a bit verbose
398
    // When CompileCommands have been refactored less clutter will remain.
399
    if (CompilerOracle::should_break_at(method)) {
400
      // If the directives didn't have 'BreakAtCompile' or 'BreakAtExecute',
401
      // the sub-command 'Break' of the 'CompileCommand' would become effective.
402
      if (!_modified[BreakAtCompileIndex]) {
403
        set.cloned()->BreakAtCompileOption = true;
404
      }
405
      if (!_modified[BreakAtExecuteIndex]) {
406
        set.cloned()->BreakAtExecuteOption = true;
407
      }
408
    }
409
    if (!_modified[LogIndex]) {
410
      bool log = CompilerOracle::should_log(method);
411
      if (log != set->LogOption) {
412
        set.cloned()->LogOption = log;
413
      }
414
    }
415

416
    if (CompilerOracle::should_print(method)) {
417
      if (!_modified[PrintAssemblyIndex]) {
418
        set.cloned()->PrintAssemblyOption = true;
419
      }
420
    }
421
    // Exclude as in should not compile == Enabled
422
    if (CompilerOracle::should_exclude(method)) {
423
      if (!_modified[ExcludeIndex]) {
424
        set.cloned()->ExcludeOption = true;
425
      }
426
    }
427

428
    // inline and dontinline (including exclude) are implemented in the directiveset accessors
429
#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompileCommandEnum::cc_flag != CompileCommandEnum::Unknown && CompilerOracle::has_option_value(method, CompileCommandEnum::cc_flag, v) && v != this->name##Option) { set.cloned()->name##Option = v; } }
430
    compilerdirectives_common_flags(init_default_cc)
431
    compilerdirectives_c2_flags(init_default_cc)
432
    compilerdirectives_c1_flags(init_default_cc)
433
#undef init_default_cc
434

435
    // Parse PrintIdealPhaseName and create a lookup set
436
#ifndef PRODUCT
437
#ifdef COMPILER2
438
    if (!_modified[TraceAutoVectorizationIndex]) {
439
      // Parse ccstr and create mask
440
      ccstrlist option;
441
      if (CompilerOracle::has_option_value(method, CompileCommandEnum::TraceAutoVectorization, option)) {
442
        TraceAutoVectorizationTagValidator validator(option, false);
443
        if (validator.is_valid()) {
444
          set.cloned()->set_trace_auto_vectorization_tags(validator.tags());
445
        }
446
      }
447
    }
448
    if (!_modified[PrintIdealPhaseIndex]) {
449
      // Parse ccstr and create set
450
      ccstrlist option;
451
      if (CompilerOracle::has_option_value(method, CompileCommandEnum::PrintIdealPhase, option)) {
452
        PhaseNameValidator validator(option);
453
        if (validator.is_valid()) {
454
          assert(!validator.phase_name_set().is_empty(), "Phase name set must be non-empty");
455
          set.cloned()->set_ideal_phase_name_set(validator.phase_name_set());
456
        }
457
      }
458
    }
459
#endif
460
#endif
461

462
    // Canonicalize DisableIntrinsic to contain only ',' as a separator.
463
    ccstrlist option_value;
464
    bool need_reset = true; // if Control/DisableIntrinsic redefined, only need to reset control_words once
465

466
    if (!_modified[ControlIntrinsicIndex] &&
467
        CompilerOracle::has_option_value(method, CompileCommandEnum::ControlIntrinsic, option_value)) {
468
      ControlIntrinsicIter iter(option_value);
469

470
      if (need_reset) {
471
        set.cloned()->_intrinsic_control_words.fill_in(TriBool());
472
        need_reset = false;
473
      }
474

475
      while (*iter != nullptr) {
476
        vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
477
        if (id != vmIntrinsics::_none) {
478
          set.cloned()->_intrinsic_control_words[vmIntrinsics::as_int(id)] = iter.is_enabled();
479
        }
480

481
        ++iter;
482
      }
483
    }
484

485

486
    if (!_modified[DisableIntrinsicIndex] &&
487
        CompilerOracle::has_option_value(method, CompileCommandEnum::DisableIntrinsic, option_value)) {
488
      ControlIntrinsicIter iter(option_value, true/*disable_all*/);
489

490
      if (need_reset) {
491
        set.cloned()->_intrinsic_control_words.fill_in(TriBool());
492
        need_reset = false;
493
      }
494

495
      while (*iter != nullptr) {
496
        vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
497
        if (id != vmIntrinsics::_none) {
498
          set.cloned()->_intrinsic_control_words[vmIntrinsics::as_int(id)] = false;
499
        }
500

501
        ++iter;
502
      }
503
    }
504

505
    return set.commit();
506
  }
507
  // Nothing changed
508
  return this;
509
}
510

511
CompilerDirectives* DirectiveSet::directive() {
512
  assert(_directive != nullptr, "Must have been initialized");
513
  return _directive;
514
}
515

516
bool DirectiveSet::matches_inline(const methodHandle& method, int inline_action) {
517
  if (_inlinematchers != nullptr) {
518
    if (_inlinematchers->match(method, inline_action)) {
519
      return true;
520
    }
521
  }
522
  return false;
523
}
524

525
bool DirectiveSet::should_inline(ciMethod* inlinee) {
526
  inlinee->check_is_loaded();
527
  VM_ENTRY_MARK;
528
  methodHandle mh(THREAD, inlinee->get_Method());
529

530
  if (_inlinematchers != nullptr) {
531
    return matches_inline(mh, InlineMatcher::force_inline);
532
  }
533
  if (!CompilerDirectivesIgnoreCompileCommandsOption) {
534
    return CompilerOracle::should_inline(mh);
535
  }
536
  return false;
537
}
538

539
bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
540
  inlinee->check_is_loaded();
541
  VM_ENTRY_MARK;
542
  methodHandle mh(THREAD, inlinee->get_Method());
543

544
  if (_inlinematchers != nullptr) {
545
    return matches_inline(mh, InlineMatcher::dont_inline);
546
  }
547
  if (!CompilerDirectivesIgnoreCompileCommandsOption) {
548
    return CompilerOracle::should_not_inline(mh);
549
  }
550
  return false;
551
}
552

553
bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
554
  InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
555
  if (m != nullptr) {
556
    // add matcher last in chain - the order is significant
557
    append_inline(m);
558
    return true;
559
  } else {
560
    assert(error_msg != nullptr, "Error message must be set");
561
    return false;
562
  }
563
}
564

565
void DirectiveSet::append_inline(InlineMatcher* m) {
566
  if (_inlinematchers == nullptr) {
567
    _inlinematchers = m;
568
    return;
569
  }
570
  InlineMatcher* tmp = _inlinematchers;
571
  while (tmp->next() != nullptr) {
572
    tmp = tmp->next();
573
  }
574
  tmp->set_next(m);
575
}
576

577
void DirectiveSet::print_inline(outputStream* st) {
578
  if (_inlinematchers == nullptr) {
579
    st->print_cr("  inline: -");
580
  } else {
581
    st->print("  inline: ");
582
    _inlinematchers->print(st);
583
    InlineMatcher* tmp = _inlinematchers->next();
584
    while (tmp != nullptr) {
585
      st->print(", ");
586
      tmp->print(st);
587
      tmp = tmp->next();
588
    }
589
    st->cr();
590
  }
591
}
592

593
bool DirectiveSet::is_intrinsic_disabled(vmIntrinsics::ID id) {
594
  assert(id > vmIntrinsics::_none && id < vmIntrinsics::ID_LIMIT, "invalid intrinsic_id!");
595

596
  TriBool b = _intrinsic_control_words[vmIntrinsics::as_int(id)];
597
  if (b.is_default()) {
598
    return false; // if unset, every intrinsic is enabled.
599
  } else {
600
    return !b;
601
  }
602
}
603

604
DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
605
  DirectiveSet* set = new DirectiveSet(nullptr);
606
  // Ordinary allocations of DirectiveSet would call init_control_intrinsic()
607
  // immediately to create a new copy for set->Control/DisableIntrinsicOption.
608
  // However, here it does not need to because the code below creates
609
  // a copy of src->Control/DisableIntrinsicOption that initializes
610
  // set->Control/DisableIntrinsicOption.
611

612
  memcpy(set->_modified, src->_modified, sizeof(src->_modified));
613

614
  InlineMatcher* tmp = src->_inlinematchers;
615
  while (tmp != nullptr) {
616
    set->append_inline(tmp->clone());
617
    tmp = tmp->next();
618
  }
619

620
  #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
621
    compilerdirectives_common_other_flags(copy_members_definition)
622
    compilerdirectives_c2_other_flags(copy_members_definition)
623
    compilerdirectives_c1_other_flags(copy_members_definition)
624
  #undef copy_members_definition
625

626
#define copy_string_members_definition(name, type, dvalue, cc_flag)          \
627
  if (src->_modified[name##Index]) {                                         \
628
    set->name##Option = os::strdup_check_oom(src->name##Option, mtCompiler); \
629
  } else {                                                                   \
630
    set->name##Option = src->name##Option;                                   \
631
  }
632
  compilerdirectives_common_string_flags(copy_string_members_definition)
633
  compilerdirectives_c2_string_flags(copy_string_members_definition)
634
  compilerdirectives_c1_string_flags(copy_string_members_definition)
635
#undef copy_string_members_definition
636

637
  set->_intrinsic_control_words = src->_intrinsic_control_words;
638
  set->set_ideal_phase_name_set(src->_ideal_phase_name_set);
639
  return set;
640
}
641

642
// Create a new dirstack and push a default directive
643
void DirectivesStack::init() {
644
  CompilerDirectives* _default_directives = new CompilerDirectives();
645
  char str[] = "*.*";
646
  const char* error_msg = nullptr;
647
  _default_directives->add_match(str, error_msg);
648
#if defined(COMPILER1) || INCLUDE_JVMCI
649
  _default_directives->_c1_store->EnableOption = true;
650
#endif
651
#ifdef COMPILER2
652
  if (CompilerConfig::is_c2_enabled()) {
653
    _default_directives->_c2_store->EnableOption = true;
654
  }
655
#endif
656
  assert(error_msg == nullptr, "Must succeed.");
657
  push(_default_directives);
658
}
659

660
DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
661
  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
662

663
  assert(_bottom != nullptr, "Must never be empty");
664
  _bottom->inc_refcount();
665
  return _bottom->get_for(comp);
666
}
667

668
void DirectivesStack::push(CompilerDirectives* directive) {
669
  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
670

671
  directive->inc_refcount();
672
  if (_top == nullptr) {
673
    assert(_bottom == nullptr, "There can only be one default directive");
674
    _bottom = directive; // default directive, can never be removed.
675
  }
676

677
  directive->set_next(_top);
678
  _top = directive;
679
  _depth++;
680
}
681

682
void DirectivesStack::pop(int count) {
683
  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
684
  assert(count > -1, "No negative values");
685
  for (int i = 0; i < count; i++) {
686
    pop_inner();
687
  }
688
}
689

690
void DirectivesStack::pop_inner() {
691
  assert(DirectivesStack_lock->owned_by_self(), "");
692

693
  if (_top->next() == nullptr) {
694
    return; // Do nothing - don't allow an empty stack
695
  }
696
  CompilerDirectives* tmp = _top;
697
  _top = _top->next();
698
  _depth--;
699

700
  DirectivesStack::release(tmp);
701
}
702

703
bool DirectivesStack::check_capacity(int request_size, outputStream* st) {
704
  if ((request_size + _depth) > CompilerDirectivesLimit) {
705
    st->print_cr("Could not add %i more directives. Currently %i/%i directives.", request_size, _depth, CompilerDirectivesLimit);
706
    return false;
707
  }
708
  return true;
709
}
710

711
void DirectivesStack::clear() {
712
  // holding the lock during the whole operation ensuring consistent result
713
  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
714
  while (_top->next() != nullptr) {
715
    pop_inner();
716
  }
717
}
718

719
void DirectivesStack::print(outputStream* st) {
720
  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
721
  CompilerDirectives* tmp = _top;
722
  while (tmp != nullptr) {
723
    tmp->print(st);
724
    tmp = tmp->next();
725
    st->cr();
726
  }
727
}
728

729
void DirectivesStack::release(DirectiveSet* set) {
730
  assert(set != nullptr, "Never nullptr");
731
  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
732
  if (set->is_exclusive_copy()) {
733
    // Old CompilecCmmands forced us to create an exclusive copy
734
    delete set;
735
  } else {
736
    assert(set->directive() != nullptr, "Never nullptr");
737
    release(set->directive());
738
  }
739
}
740

741

742
void DirectivesStack::release(CompilerDirectives* dir) {
743
  assert(DirectivesStack_lock->owned_by_self(), "");
744
  dir->dec_refcount();
745
  if (dir->refcount() == 0) {
746
    delete dir;
747
  }
748
}
749

750
DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, AbstractCompiler *comp) {
751
  assert(_depth > 0, "Must never be empty");
752

753
  DirectiveSet* match = nullptr;
754
  {
755
    MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
756

757
    CompilerDirectives* dir = _top;
758
    assert(dir != nullptr, "Must be initialized");
759

760
    while (dir != nullptr) {
761
      if (dir->is_default_directive() || dir->match(method)) {
762
        match = dir->get_for(comp);
763
        assert(match != nullptr, "Consistency");
764
        if (match->EnableOption || dir->is_default_directive()) {
765
          // The directiveSet for this compile is also enabled -> success
766
          dir->inc_refcount();
767
          break;
768
        }
769
      }
770
      dir = dir->next();
771
    }
772
  }
773
  guarantee(match != nullptr, "There should always be a default directive that matches");
774

775
  // Check for legacy compile commands update, without DirectivesStack_lock
776
  return match->compilecommand_compatibility_init(method);
777
}
778

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.