8304684: Memory leak in DirectivesParser::set_option_flag
Reviewed-by: kvn, dlong
This commit is contained in:
parent
a03767cf88
commit
deadb9c8d7
@ -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<char*>(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;
|
||||
|
@ -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<char*>(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();
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user