8325095: C2: bailout message broken: ResourceArea allocated string used after free
Reviewed-by: kvn, dlong
This commit is contained in:
parent
b7540df6a4
commit
c589555845
@ -121,7 +121,6 @@ ciEnv::ciEnv(CompileTask* task)
|
|||||||
_oop_recorder = nullptr;
|
_oop_recorder = nullptr;
|
||||||
_debug_info = nullptr;
|
_debug_info = nullptr;
|
||||||
_dependencies = nullptr;
|
_dependencies = nullptr;
|
||||||
_failure_reason = nullptr;
|
|
||||||
_inc_decompile_count_on_failure = true;
|
_inc_decompile_count_on_failure = true;
|
||||||
_compilable = MethodCompilable;
|
_compilable = MethodCompilable;
|
||||||
_break_at_compile = false;
|
_break_at_compile = false;
|
||||||
@ -250,7 +249,6 @@ ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) {
|
|||||||
_oop_recorder = nullptr;
|
_oop_recorder = nullptr;
|
||||||
_debug_info = nullptr;
|
_debug_info = nullptr;
|
||||||
_dependencies = nullptr;
|
_dependencies = nullptr;
|
||||||
_failure_reason = nullptr;
|
|
||||||
_inc_decompile_count_on_failure = true;
|
_inc_decompile_count_on_failure = true;
|
||||||
_compilable = MethodCompilable_never;
|
_compilable = MethodCompilable_never;
|
||||||
_break_at_compile = false;
|
_break_at_compile = false;
|
||||||
@ -1233,9 +1231,9 @@ int ciEnv::num_inlined_bytecodes() const {
|
|||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::record_failure()
|
// ciEnv::record_failure()
|
||||||
void ciEnv::record_failure(const char* reason) {
|
void ciEnv::record_failure(const char* reason) {
|
||||||
if (_failure_reason == nullptr) {
|
if (_failure_reason.get() == nullptr) {
|
||||||
// Record the first failure reason.
|
// Record the first failure reason.
|
||||||
_failure_reason = reason;
|
_failure_reason.set(reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1265,7 +1263,7 @@ void ciEnv::record_method_not_compilable(const char* reason, bool all_tiers) {
|
|||||||
_compilable = new_compilable;
|
_compilable = new_compilable;
|
||||||
|
|
||||||
// Reset failure reason; this one is more important.
|
// Reset failure reason; this one is more important.
|
||||||
_failure_reason = nullptr;
|
_failure_reason.clear();
|
||||||
record_failure(reason);
|
record_failure(reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "code/exceptionHandlerTable.hpp"
|
#include "code/exceptionHandlerTable.hpp"
|
||||||
#include "compiler/compiler_globals.hpp"
|
#include "compiler/compiler_globals.hpp"
|
||||||
#include "compiler/compilerThread.hpp"
|
#include "compiler/compilerThread.hpp"
|
||||||
|
#include "compiler/cHeapStringHolder.hpp"
|
||||||
#include "oops/methodData.hpp"
|
#include "oops/methodData.hpp"
|
||||||
#include "runtime/javaThread.hpp"
|
#include "runtime/javaThread.hpp"
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ private:
|
|||||||
OopRecorder* _oop_recorder;
|
OopRecorder* _oop_recorder;
|
||||||
DebugInformationRecorder* _debug_info;
|
DebugInformationRecorder* _debug_info;
|
||||||
Dependencies* _dependencies;
|
Dependencies* _dependencies;
|
||||||
const char* _failure_reason;
|
CHeapStringHolder _failure_reason;
|
||||||
bool _inc_decompile_count_on_failure;
|
bool _inc_decompile_count_on_failure;
|
||||||
int _compilable;
|
int _compilable;
|
||||||
bool _break_at_compile;
|
bool _break_at_compile;
|
||||||
@ -319,10 +320,10 @@ public:
|
|||||||
|
|
||||||
// This is true if the compilation is not going to produce code.
|
// This is true if the compilation is not going to produce code.
|
||||||
// (It is reasonable to retry failed compilations.)
|
// (It is reasonable to retry failed compilations.)
|
||||||
bool failing() const { return _failure_reason != nullptr; }
|
bool failing() const { return _failure_reason.get() != nullptr; }
|
||||||
|
|
||||||
// Reason this compilation is failing, such as "too many basic blocks".
|
// Reason this compilation is failing, such as "too many basic blocks".
|
||||||
const char* failure_reason() const { return _failure_reason; }
|
const char* failure_reason() const { return _failure_reason.get(); }
|
||||||
|
|
||||||
// Return state of appropriate compatibility
|
// Return state of appropriate compatibility
|
||||||
int compilable() { return _compilable; }
|
int compilable() { return _compilable; }
|
||||||
|
43
src/hotspot/share/compiler/cHeapStringHolder.cpp
Normal file
43
src/hotspot/share/compiler/cHeapStringHolder.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "compiler/cHeapStringHolder.hpp"
|
||||||
|
|
||||||
|
void CHeapStringHolder::set(const char* string) {
|
||||||
|
clear();
|
||||||
|
if (string != nullptr) {
|
||||||
|
size_t len = strlen(string);
|
||||||
|
_string = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
|
||||||
|
::memcpy(_string, string, len);
|
||||||
|
_string[len] = 0; // terminating null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHeapStringHolder::clear() {
|
||||||
|
if (_string != nullptr) {
|
||||||
|
FREE_C_HEAP_ARRAY(char, _string);
|
||||||
|
_string = nullptr;
|
||||||
|
}
|
||||||
|
}
|
50
src/hotspot/share/compiler/cHeapStringHolder.hpp
Normal file
50
src/hotspot/share/compiler/cHeapStringHolder.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_COMPILER_CHEAPSTRINGHOLDER_HPP
|
||||||
|
#define SHARE_COMPILER_CHEAPSTRINGHOLDER_HPP
|
||||||
|
|
||||||
|
#include "memory/allocation.hpp"
|
||||||
|
|
||||||
|
// Holder for a C-Heap allocated String
|
||||||
|
// The user must ensure that the destructor is called, or at least clear.
|
||||||
|
class CHeapStringHolder : public StackObj {
|
||||||
|
private:
|
||||||
|
char* _string;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CHeapStringHolder() : _string(nullptr) {}
|
||||||
|
~CHeapStringHolder() { clear(); };
|
||||||
|
NONCOPYABLE(CHeapStringHolder);
|
||||||
|
|
||||||
|
// Allocate memory to hold a copy of string
|
||||||
|
void set(const char* string);
|
||||||
|
|
||||||
|
// Release allocated memory
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
const char* get() const { return _string; };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_COMPILER_CHEAPSTRINGHOLDER_HPP
|
@ -405,7 +405,7 @@ void CompilationMemoryStatistic::on_end_compilation() {
|
|||||||
if (env) {
|
if (env) {
|
||||||
const char* const failure_reason = env->failure_reason();
|
const char* const failure_reason = env->failure_reason();
|
||||||
if (failure_reason != nullptr) {
|
if (failure_reason != nullptr) {
|
||||||
result = (failure_reason == failure_reason_memlimit()) ? "oom" : "err";
|
result = (strcmp(failure_reason, failure_reason_memlimit()) == 0) ? "oom" : "err";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2328,7 +2328,9 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
|||||||
compilable = ci_env.compilable();
|
compilable = ci_env.compilable();
|
||||||
|
|
||||||
if (ci_env.failing()) {
|
if (ci_env.failing()) {
|
||||||
failure_reason = ci_env.failure_reason();
|
// Duplicate the failure reason string, so that it outlives ciEnv
|
||||||
|
failure_reason = os::strdup(ci_env.failure_reason(), mtCompiler);
|
||||||
|
failure_reason_on_C_heap = true;
|
||||||
retry_message = ci_env.retry_message();
|
retry_message = ci_env.retry_message();
|
||||||
ci_env.report_failure(failure_reason);
|
ci_env.report_failure(failure_reason);
|
||||||
}
|
}
|
||||||
|
@ -639,7 +639,6 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
|
|||||||
_env(ci_env),
|
_env(ci_env),
|
||||||
_directive(directive),
|
_directive(directive),
|
||||||
_log(ci_env->log()),
|
_log(ci_env->log()),
|
||||||
_failure_reason(nullptr),
|
|
||||||
_first_failure_details(nullptr),
|
_first_failure_details(nullptr),
|
||||||
_intrinsics (comp_arena(), 0, 0, nullptr),
|
_intrinsics (comp_arena(), 0, 0, nullptr),
|
||||||
_macro_nodes (comp_arena(), 8, 0, nullptr),
|
_macro_nodes (comp_arena(), 8, 0, nullptr),
|
||||||
@ -930,7 +929,6 @@ Compile::Compile( ciEnv* ci_env,
|
|||||||
_env(ci_env),
|
_env(ci_env),
|
||||||
_directive(directive),
|
_directive(directive),
|
||||||
_log(ci_env->log()),
|
_log(ci_env->log()),
|
||||||
_failure_reason(nullptr),
|
|
||||||
_first_failure_details(nullptr),
|
_first_failure_details(nullptr),
|
||||||
_congraph(nullptr),
|
_congraph(nullptr),
|
||||||
NOT_PRODUCT(_igv_printer(nullptr) COMMA)
|
NOT_PRODUCT(_igv_printer(nullptr) COMMA)
|
||||||
@ -4392,9 +4390,9 @@ void Compile::record_failure(const char* reason) {
|
|||||||
if (log() != nullptr) {
|
if (log() != nullptr) {
|
||||||
log()->elem("failure reason='%s' phase='compile'", reason);
|
log()->elem("failure reason='%s' phase='compile'", reason);
|
||||||
}
|
}
|
||||||
if (_failure_reason == nullptr) {
|
if (_failure_reason.get() == nullptr) {
|
||||||
// Record the first failure reason.
|
// Record the first failure reason.
|
||||||
_failure_reason = reason;
|
_failure_reason.set(reason);
|
||||||
if (CaptureBailoutInformation) {
|
if (CaptureBailoutInformation) {
|
||||||
_first_failure_details = new CompilationFailureInfo(reason);
|
_first_failure_details = new CompilationFailureInfo(reason);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "compiler/compilerOracle.hpp"
|
#include "compiler/compilerOracle.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
#include "compiler/compilerEvent.hpp"
|
#include "compiler/compilerEvent.hpp"
|
||||||
|
#include "compiler/cHeapStringHolder.hpp"
|
||||||
#include "libadt/dict.hpp"
|
#include "libadt/dict.hpp"
|
||||||
#include "libadt/vectset.hpp"
|
#include "libadt/vectset.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
@ -363,7 +364,7 @@ class Compile : public Phase {
|
|||||||
ciEnv* _env; // CI interface
|
ciEnv* _env; // CI interface
|
||||||
DirectiveSet* _directive; // Compiler directive
|
DirectiveSet* _directive; // Compiler directive
|
||||||
CompileLog* _log; // from CompilerThread
|
CompileLog* _log; // from CompilerThread
|
||||||
const char* _failure_reason; // for record_failure/failing pattern
|
CHeapStringHolder _failure_reason; // for record_failure/failing pattern
|
||||||
CompilationFailureInfo* _first_failure_details; // Details for the first failure happening during compilation
|
CompilationFailureInfo* _first_failure_details; // Details for the first failure happening during compilation
|
||||||
GrowableArray<CallGenerator*> _intrinsics; // List of intrinsics.
|
GrowableArray<CallGenerator*> _intrinsics; // List of intrinsics.
|
||||||
GrowableArray<Node*> _macro_nodes; // List of nodes which need to be expanded before matching.
|
GrowableArray<Node*> _macro_nodes; // List of nodes which need to be expanded before matching.
|
||||||
@ -811,12 +812,24 @@ private:
|
|||||||
Arena* comp_arena() { return &_comp_arena; }
|
Arena* comp_arena() { return &_comp_arena; }
|
||||||
ciEnv* env() const { return _env; }
|
ciEnv* env() const { return _env; }
|
||||||
CompileLog* log() const { return _log; }
|
CompileLog* log() const { return _log; }
|
||||||
bool failing() const { return _env->failing() || _failure_reason != nullptr; }
|
|
||||||
const char* failure_reason() const { return (_env->failing()) ? _env->failure_reason() : _failure_reason; }
|
bool failing() const {
|
||||||
|
return _env->failing() ||
|
||||||
|
_failure_reason.get() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* failure_reason() const {
|
||||||
|
return _env->failing() ? _env->failure_reason()
|
||||||
|
: _failure_reason.get();
|
||||||
|
}
|
||||||
|
|
||||||
const CompilationFailureInfo* first_failure_details() const { return _first_failure_details; }
|
const CompilationFailureInfo* first_failure_details() const { return _first_failure_details; }
|
||||||
|
|
||||||
bool failure_reason_is(const char* r) const {
|
bool failure_reason_is(const char* r) const {
|
||||||
return (r == _failure_reason) || (r != nullptr && _failure_reason != nullptr && strcmp(r, _failure_reason) == 0);
|
return (r == _failure_reason.get()) ||
|
||||||
|
(r != nullptr &&
|
||||||
|
_failure_reason.get() != nullptr &&
|
||||||
|
strcmp(r, _failure_reason.get()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_failure(const char* reason);
|
void record_failure(const char* reason);
|
||||||
|
@ -724,7 +724,6 @@
|
|||||||
/************/ \
|
/************/ \
|
||||||
\
|
\
|
||||||
nonstatic_field(ciEnv, _compiler_data, void*) \
|
nonstatic_field(ciEnv, _compiler_data, void*) \
|
||||||
nonstatic_field(ciEnv, _failure_reason, const char*) \
|
|
||||||
nonstatic_field(ciEnv, _factory, ciObjectFactory*) \
|
nonstatic_field(ciEnv, _factory, ciObjectFactory*) \
|
||||||
nonstatic_field(ciEnv, _dependencies, Dependencies*) \
|
nonstatic_field(ciEnv, _dependencies, Dependencies*) \
|
||||||
nonstatic_field(ciEnv, _task, CompileTask*) \
|
nonstatic_field(ciEnv, _task, CompileTask*) \
|
||||||
|
Loading…
Reference in New Issue
Block a user