diff --git a/src/hotspot/share/compiler/compilerDirectives.cpp b/src/hotspot/share/compiler/compilerDirectives.cpp index 0368a6ad744..20c576fce66 100644 --- a/src/hotspot/share/compiler/compilerDirectives.cpp +++ b/src/hotspot/share/compiler/compilerDirectives.cpp @@ -287,11 +287,12 @@ void DirectiveSet::init_control_intrinsic() { } DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(nullptr), _directive(d) { -#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue; _ideal_phase_name_mask = 0; +#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue; compilerdirectives_common_flags(init_defaults_definition) compilerdirectives_c2_flags(init_defaults_definition) compilerdirectives_c1_flags(init_defaults_definition) +#undef init_defaults_definition memset(_modified, 0, sizeof(_modified)); _intrinsic_control_words.fill_in(/*default value*/TriBool()); } @@ -304,6 +305,12 @@ DirectiveSet::~DirectiveSet() { delete tmp; tmp = next; } + +#define free_string_flags(name, type, dvalue, cc_flag) if (_modified[name##Index]) os::free(const_cast(name##Option)); + compilerdirectives_common_string_flags(free_string_flags) + compilerdirectives_c2_string_flags(free_string_flags) + compilerdirectives_c1_string_flags(free_string_flags) +#undef free_string_flags } // A smart pointer of DirectiveSet. It uses Copy-on-Write strategy to avoid cloning. @@ -407,6 +414,7 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle compilerdirectives_common_flags(init_default_cc) compilerdirectives_c2_flags(init_default_cc) compilerdirectives_c1_flags(init_default_cc) +#undef init_default_cc // Parse PrintIdealPhaseName and create an efficient lookup mask #ifndef PRODUCT @@ -585,9 +593,21 @@ DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) { } #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option; - compilerdirectives_common_flags(copy_members_definition) - compilerdirectives_c2_flags(copy_members_definition) - compilerdirectives_c1_flags(copy_members_definition) + compilerdirectives_common_other_flags(copy_members_definition) + compilerdirectives_c2_other_flags(copy_members_definition) + compilerdirectives_c1_other_flags(copy_members_definition) + #undef copy_members_definition + +#define copy_string_members_definition(name, type, dvalue, cc_flag) \ + if (src->_modified[name##Index]) { \ + set->name##Option = os::strdup_check_oom(src->name##Option, mtCompiler); \ + } else { \ + set->name##Option = src->name##Option; \ + } + compilerdirectives_common_string_flags(copy_string_members_definition) + compilerdirectives_c2_string_flags(copy_string_members_definition) + compilerdirectives_c1_string_flags(copy_string_members_definition) +#undef copy_string_members_definition set->_intrinsic_control_words = src->_intrinsic_control_words; set->_ideal_phase_name_mask = src->_ideal_phase_name_mask; diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index 8c8dcb99f0d..439a4c2f925 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -35,7 +35,7 @@ #include "utilities/tribool.hpp" // Directives flag name, type, default value, compile command name - #define compilerdirectives_common_flags(cflags) \ + #define compilerdirectives_common_other_flags(cflags) \ cflags(Enable, bool, false, Unknown) \ cflags(Exclude, bool, false, Unknown) \ cflags(BreakAtExecute, bool, false, BreakAtExecute) \ @@ -51,18 +51,28 @@ cflags(DumpReplay, bool, false, DumpReplay) \ cflags(DumpInline, bool, false, DumpInline) \ cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, Unknown) \ - cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic) \ - cflags(ControlIntrinsic, ccstrlist, ControlIntrinsic, ControlIntrinsic) \ cflags(RepeatCompilation, intx, RepeatCompilation, RepeatCompilation) +#define compilerdirectives_common_string_flags(cflags) \ + cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic) \ + cflags(ControlIntrinsic, ccstrlist, ControlIntrinsic, ControlIntrinsic) +#define compilerdirectives_common_flags(cflags) \ + compilerdirectives_common_other_flags(cflags) \ + compilerdirectives_common_string_flags(cflags) #ifdef COMPILER1 - #define compilerdirectives_c1_flags(cflags) + #define compilerdirectives_c1_other_flags(cflags) + #define compilerdirectives_c1_string_flags(cflags) #else - #define compilerdirectives_c1_flags(cflags) + #define compilerdirectives_c1_other_flags(cflags) + #define compilerdirectives_c1_string_flags(cflags) #endif +#define compilerdirectives_c1_flags(cflags) \ + compilerdirectives_c1_other_flags(cflags) \ + compilerdirectives_c1_string_flags(cflags) + #ifdef COMPILER2 - #define compilerdirectives_c2_flags(cflags) \ + #define compilerdirectives_c2_other_flags(cflags) \ cflags(BlockLayoutByFrequency, bool, BlockLayoutByFrequency, BlockLayoutByFrequency) \ cflags(PrintOptoAssembly, bool, PrintOptoAssembly, PrintOptoAssembly) \ cflags(PrintIntrinsics, bool, PrintIntrinsics, PrintIntrinsics) \ @@ -70,7 +80,6 @@ NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipe NOT_PRODUCT(cflags(TraceOptoOutput, bool, TraceOptoOutput, TraceOptoOutput)) \ NOT_PRODUCT(cflags(TraceEscapeAnalysis, bool, false, TraceEscapeAnalysis)) \ NOT_PRODUCT(cflags(PrintIdeal, bool, PrintIdeal, PrintIdeal)) \ -NOT_PRODUCT(cflags(PrintIdealPhase, ccstrlist, "", PrintIdealPhase)) \ cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \ cflags(Vectorize, bool, false, Vectorize) \ cflags(CloneMapDebug, bool, false, CloneMapDebug) \ @@ -78,10 +87,17 @@ NOT_PRODUCT(cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLeve cflags(VectorizeDebug, uintx, 0, VectorizeDebug) \ cflags(IncrementalInlineForceCleanup, bool, IncrementalInlineForceCleanup, IncrementalInlineForceCleanup) \ cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit) +#define compilerdirectives_c2_string_flags(cflags) \ +NOT_PRODUCT(cflags(PrintIdealPhase, ccstrlist, "", PrintIdealPhase)) #else - #define compilerdirectives_c2_flags(cflags) + #define compilerdirectives_c2_other_flags(cflags) + #define compilerdirectives_c2_string_flags(cflags) #endif +#define compilerdirectives_c2_flags(cflags) \ + compilerdirectives_c2_other_flags(cflags) \ + compilerdirectives_c2_string_flags(cflags) + class AbstractCompiler; class CompilerDirectives; class DirectiveSet; @@ -140,6 +156,7 @@ public: compilerdirectives_common_flags(enum_of_flags) compilerdirectives_c2_flags(enum_of_flags) compilerdirectives_c1_flags(enum_of_flags) +#undef enum_of_flags number_of_flags } flags; @@ -150,12 +167,32 @@ public: compilerdirectives_common_flags(flag_store_definition) compilerdirectives_c2_flags(flag_store_definition) compilerdirectives_c1_flags(flag_store_definition) +#undef flag_store_definition // Casting to get the same function signature for all setters. Used from parser. #define set_function_definition(name, type, dvalue, cc_flag) void set_##name(void* value) { type val = *(type*)value; name##Option = val; _modified[name##Index] = true; } - compilerdirectives_common_flags(set_function_definition) - compilerdirectives_c2_flags(set_function_definition) - compilerdirectives_c1_flags(set_function_definition) + compilerdirectives_common_other_flags(set_function_definition) + compilerdirectives_c2_other_flags(set_function_definition) + compilerdirectives_c1_other_flags(set_function_definition) +#undef set_function_definition + +// Casting to get the same function signature for all setters. Used from parser. +// +// IMPORTANT: Takes ownership, will use os::free. Ensure the memory was dynamically allocated on the +// C heap. +#define set_string_function_definition(name, type, dvalue, cc_flag) \ +void set_##name(void* value) { \ + if (_modified[name##Index]) { \ + os::free(const_cast(name##Option)); \ + } \ + type val = *(type*)value; \ + name##Option = val; \ + _modified[name##Index] = true; \ +} + compilerdirectives_common_string_flags(set_string_function_definition) + compilerdirectives_c2_string_flags(set_string_function_definition) + compilerdirectives_c1_string_flags(set_string_function_definition) +#undef set_string_function_definition void set_ideal_phase_mask(uint64_t mask) { _ideal_phase_name_mask = mask; }; uint64_t ideal_phase_mask() { return _ideal_phase_name_mask; }; @@ -174,6 +211,7 @@ void print(outputStream* st) { compilerdirectives_common_flags(print_function_definition) compilerdirectives_c2_flags(print_function_definition) compilerdirectives_c1_flags(print_function_definition) +#undef print_function_definition st->cr(); } }; diff --git a/src/hotspot/share/compiler/directivesParser.cpp b/src/hotspot/share/compiler/directivesParser.cpp index ae576d9170b..0f6978bade8 100644 --- a/src/hotspot/share/compiler/directivesParser.cpp +++ b/src/hotspot/share/compiler/directivesParser.cpp @@ -315,35 +315,43 @@ bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* opti error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]); return false; } else { - char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1, mtCompiler); + char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler); strncpy(s, v->str.start, v->str.length + 1); s[v->str.length] = '\0'; - (set->*test)((void *)&s); + + bool valid = true; if (strncmp(option_key->name, "ControlIntrinsic", 16) == 0) { ControlIntrinsicValidator validator(s, false/*disabled_all*/); - if (!validator.is_valid()) { + valid = validator.is_valid(); + if (!valid) { error(VALUE_ERROR, "Unrecognized intrinsic detected in ControlIntrinsic: %s", validator.what()); - return false; } } else if (strncmp(option_key->name, "DisableIntrinsic", 16) == 0) { ControlIntrinsicValidator validator(s, true/*disabled_all*/); - if (!validator.is_valid()) { + valid = validator.is_valid(); + if (!valid) { error(VALUE_ERROR, "Unrecognized intrinsic detected in DisableIntrinsic: %s", validator.what()); - return false; } } else if (strncmp(option_key->name, "PrintIdealPhase", 15) == 0) { uint64_t mask = 0; PhaseNameValidator validator(s, mask); - if (!validator.is_valid()) { + valid = validator.is_valid(); + if (valid) { + set->set_ideal_phase_mask(mask); + } else { error(VALUE_ERROR, "Unrecognized phase name detected in PrintIdealPhase: %s", validator.what()); - return false; } - set->set_ideal_phase_mask(mask); } + + if (!valid) { + FREE_C_HEAP_ARRAY(char, s); + return false; + } + (set->*test)((void *)&s); // Takes ownership. } break;