Skip to content

Commit a41d350

Browse files
committed
8357473: Compilation spike leaves many CompileTasks in free list
Reviewed-by: kvn, chagedorn
1 parent 7daf981 commit a41d350

File tree

6 files changed

+63
-107
lines changed

6 files changed

+63
-107
lines changed

src/hotspot/share/compiler/compileBroker.cpp

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ CompileTaskWrapper::~CompileTaskWrapper() {
236236
#if INCLUDE_JVMCI
237237
if (CompileBroker::compiler(task->comp_level())->is_jvmci()) {
238238
if (!task->has_waiter()) {
239-
// The waiting thread timed out and thus did not free the task.
239+
// The waiting thread timed out and thus did not delete the task.
240240
free_task = true;
241241
}
242242
task->set_blocking_jvmci_compile_state(nullptr);
@@ -249,15 +249,15 @@ CompileTaskWrapper::~CompileTaskWrapper() {
249249
}
250250
}
251251
if (free_task) {
252-
// The task can only be freed once the task lock is released.
253-
CompileTask::free(task);
252+
// The task can only be deleted once the task lock is released.
253+
delete task;
254254
}
255255
} else {
256256
task->mark_complete();
257257

258-
// By convention, the compiling thread is responsible for
259-
// recycling a non-blocking CompileTask.
260-
CompileTask::free(task);
258+
// By convention, the compiling thread is responsible for deleting
259+
// a non-blocking CompileTask.
260+
delete task;
261261
}
262262
}
263263

@@ -360,12 +360,12 @@ void CompileQueue::add(CompileTask* task) {
360360
}
361361

362362
/**
363-
* Empties compilation queue by putting all compilation tasks onto
364-
* a freelist. Furthermore, the method wakes up all threads that are
365-
* waiting on a compilation task to finish. This can happen if background
363+
* Empties compilation queue by deleting all compilation tasks.
364+
* Furthermore, the method wakes up all threads that are waiting
365+
* on a compilation task to finish. This can happen if background
366366
* compilation is disabled.
367367
*/
368-
void CompileQueue::free_all() {
368+
void CompileQueue::delete_all() {
369369
MutexLocker mu(MethodCompileQueue_lock);
370370
CompileTask* next = _first;
371371

@@ -385,11 +385,10 @@ void CompileQueue::free_all() {
385385
}
386386
}
387387
if (!found_waiter) {
388-
// If no one was waiting for this task, we need to free it ourselves. In this case, the task
389-
// is also certainly unlocked, because, again, there is no waiter.
390-
// Otherwise, by convention, it's the waiters responsibility to free the task.
391-
// Put the task back on the freelist.
392-
CompileTask::free(current);
388+
// If no one was waiting for this task, we need to delete it ourselves.
389+
// In this case, the task is also certainly unlocked, because, again, there is no waiter.
390+
// Otherwise, by convention, it's the waiters responsibility to delete the task.
391+
delete current;
393392
}
394393
}
395394
_first = nullptr;
@@ -1627,10 +1626,8 @@ CompileTask* CompileBroker::create_compile_task(CompileQueue* queue,
16271626
int hot_count,
16281627
CompileTask::CompileReason compile_reason,
16291628
bool blocking) {
1630-
CompileTask* new_task = CompileTask::allocate();
1631-
new_task->initialize(compile_id, method, osr_bci, comp_level,
1632-
hot_count, compile_reason,
1633-
blocking);
1629+
CompileTask* new_task = new CompileTask(compile_id, method, osr_bci, comp_level,
1630+
hot_count, compile_reason, blocking);
16341631
queue->add(new_task);
16351632
return new_task;
16361633
}
@@ -1651,7 +1648,7 @@ static const int JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS = 10;
16511648
* JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE *
16521649
* JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS.
16531650
*
1654-
* @return true if this thread needs to free/recycle the task
1651+
* @return true if this thread needs to delete the task
16551652
*/
16561653
bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask* task, JavaThread* thread) {
16571654
assert(UseJVMCICompiler, "sanity");
@@ -1734,19 +1731,19 @@ void CompileBroker::wait_for_completion(CompileTask* task) {
17341731

17351732
if (free_task) {
17361733
if (is_compilation_disabled_forever()) {
1737-
CompileTask::free(task);
1734+
delete task;
17381735
return;
17391736
}
17401737

17411738
// It is harmless to check this status without the lock, because
1742-
// completion is a stable property (until the task object is recycled).
1739+
// completion is a stable property (until the task object is deleted).
17431740
assert(task->is_complete(), "Compilation should have completed");
17441741

1745-
// By convention, the waiter is responsible for recycling a
1742+
// By convention, the waiter is responsible for deleting a
17461743
// blocking CompileTask. Since there is only one waiter ever
17471744
// waiting on a CompileTask, we know that no one else will
1748-
// be using this CompileTask; we can free it.
1749-
CompileTask::free(task);
1745+
// be using this CompileTask; we can delete it.
1746+
delete task;
17501747
}
17511748
}
17521749

@@ -1827,11 +1824,11 @@ void CompileBroker::shutdown_compiler_runtime(AbstractCompiler* comp, CompilerTh
18271824

18281825
// Delete all queued compilation tasks to make compiler threads exit faster.
18291826
if (_c1_compile_queue != nullptr) {
1830-
_c1_compile_queue->free_all();
1827+
_c1_compile_queue->delete_all();
18311828
}
18321829

18331830
if (_c2_compile_queue != nullptr) {
1834-
_c2_compile_queue->free_all();
1831+
_c2_compile_queue->delete_all();
18351832
}
18361833

18371834
// Set flags so that we continue execution with using interpreter only.

src/hotspot/share/compiler/compileBroker.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class CompileQueue : public CHeapObj<mtCompiler> {
140140

141141
// Redefine Classes support
142142
void mark_on_stack();
143-
void free_all();
143+
void delete_all();
144144
void print_tty();
145145
void print(outputStream* st = tty);
146146

src/hotspot/share/compiler/compileTask.cpp

Lines changed: 34 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -36,72 +36,15 @@
3636
#include "runtime/jniHandles.hpp"
3737
#include "runtime/mutexLocker.hpp"
3838

39-
CompileTask* CompileTask::_task_free_list = nullptr;
4039
int CompileTask::_active_tasks = 0;
4140

42-
/**
43-
* Allocate a CompileTask, from the free list if possible.
44-
*/
45-
CompileTask* CompileTask::allocate() {
46-
MonitorLocker locker(CompileTaskAlloc_lock);
47-
CompileTask* task = nullptr;
48-
49-
if (_task_free_list != nullptr) {
50-
task = _task_free_list;
51-
_task_free_list = task->next();
52-
task->set_next(nullptr);
53-
} else {
54-
task = new CompileTask();
55-
task->set_next(nullptr);
56-
task->set_is_free(true);
57-
}
58-
assert(task->is_free(), "Task must be free.");
59-
task->set_is_free(false);
60-
_active_tasks++;
61-
return task;
62-
}
63-
64-
/**
65-
* Add a task to the free list.
66-
*/
67-
void CompileTask::free(CompileTask* task) {
68-
MonitorLocker locker(CompileTaskAlloc_lock);
69-
if (!task->is_free()) {
70-
if ((task->_method_holder != nullptr && JNIHandles::is_weak_global_handle(task->_method_holder))) {
71-
JNIHandles::destroy_weak_global(task->_method_holder);
72-
} else {
73-
JNIHandles::destroy_global(task->_method_holder);
74-
}
75-
if (task->_failure_reason_on_C_heap && task->_failure_reason != nullptr) {
76-
os::free((void*) task->_failure_reason);
77-
}
78-
task->_failure_reason = nullptr;
79-
task->_failure_reason_on_C_heap = false;
80-
81-
task->set_is_free(true);
82-
task->set_next(_task_free_list);
83-
_task_free_list = task;
84-
_active_tasks--;
85-
if (_active_tasks == 0) {
86-
locker.notify_all();
87-
}
88-
}
89-
}
90-
91-
void CompileTask::wait_for_no_active_tasks() {
92-
MonitorLocker locker(CompileTaskAlloc_lock);
93-
while (_active_tasks > 0) {
94-
locker.wait();
95-
}
96-
}
97-
98-
void CompileTask::initialize(int compile_id,
99-
const methodHandle& method,
100-
int osr_bci,
101-
int comp_level,
102-
int hot_count,
103-
CompileTask::CompileReason compile_reason,
104-
bool is_blocking) {
41+
CompileTask::CompileTask(int compile_id,
42+
const methodHandle& method,
43+
int osr_bci,
44+
int comp_level,
45+
int hot_count,
46+
CompileReason compile_reason,
47+
bool is_blocking) {
10548
Thread* thread = Thread::current();
10649
_compile_id = compile_id;
10750
_method = method();
@@ -133,6 +76,33 @@ void CompileTask::initialize(int compile_id,
13376
_arena_bytes = 0;
13477

13578
_next = nullptr;
79+
80+
Atomic::add(&_active_tasks, 1, memory_order_relaxed);
81+
}
82+
83+
CompileTask::~CompileTask() {
84+
if (_method_holder != nullptr && JNIHandles::is_weak_global_handle(_method_holder)) {
85+
JNIHandles::destroy_weak_global(_method_holder);
86+
} else {
87+
JNIHandles::destroy_global(_method_holder);
88+
}
89+
if (_failure_reason_on_C_heap && _failure_reason != nullptr) {
90+
os::free((void*) _failure_reason);
91+
_failure_reason = nullptr;
92+
_failure_reason_on_C_heap = false;
93+
}
94+
95+
if (Atomic::sub(&_active_tasks, 1, memory_order_relaxed) == 0) {
96+
MonitorLocker wait_ml(CompileTaskWait_lock);
97+
wait_ml.notify_all();
98+
}
99+
}
100+
101+
void CompileTask::wait_for_no_active_tasks() {
102+
MonitorLocker locker(CompileTaskWait_lock);
103+
while (Atomic::load(&_active_tasks) > 0) {
104+
locker.wait();
105+
}
136106
}
137107

138108
/**

src/hotspot/share/compiler/compileTask.hpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ class CompileTask : public CHeapObj<mtCompiler> {
8282
}
8383

8484
private:
85-
static CompileTask* _task_free_list;
8685
static int _active_tasks;
8786
int _compile_id;
8887
Method* _method;
@@ -104,7 +103,6 @@ class CompileTask : public CHeapObj<mtCompiler> {
104103
int _comp_level;
105104
int _num_inlined_bytecodes;
106105
CompileTask* _next, *_prev;
107-
bool _is_free;
108106
// Fields used for logging why the compilation was initiated:
109107
jlong _time_queued; // time when task was enqueued
110108
jlong _time_started; // time when compilation started
@@ -117,14 +115,10 @@ class CompileTask : public CHeapObj<mtCompiler> {
117115
size_t _arena_bytes; // peak size of temporary memory during compilation (e.g. node arenas)
118116

119117
public:
120-
CompileTask() : _failure_reason(nullptr), _failure_reason_on_C_heap(false) {}
121-
void initialize(int compile_id, const methodHandle& method, int osr_bci, int comp_level,
122-
int hot_count,
123-
CompileTask::CompileReason compile_reason, bool is_blocking);
124-
125-
static CompileTask* allocate();
126-
static void free(CompileTask* task);
127-
static void wait_for_no_active_tasks();
118+
CompileTask(int compile_id, const methodHandle& method, int osr_bci, int comp_level,
119+
int hot_count, CompileReason compile_reason, bool is_blocking);
120+
~CompileTask();
121+
static void wait_for_no_active_tasks();
128122

129123
int compile_id() const { return _compile_id; }
130124
Method* method() const { return _method; }
@@ -206,8 +200,6 @@ class CompileTask : public CHeapObj<mtCompiler> {
206200
void set_next(CompileTask* next) { _next = next; }
207201
CompileTask* prev() const { return _prev; }
208202
void set_prev(CompileTask* prev) { _prev = prev; }
209-
bool is_free() const { return _is_free; }
210-
void set_is_free(bool val) { _is_free = val; }
211203
bool is_unloaded() const;
212204

213205
CompileTrainingData* training_data() const { return _training_data; }

src/hotspot/share/runtime/mutexLocker.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ Monitor* CompileTaskWait_lock = nullptr;
8484
Monitor* MethodCompileQueue_lock = nullptr;
8585
Monitor* CompileThread_lock = nullptr;
8686
Monitor* Compilation_lock = nullptr;
87-
Monitor* CompileTaskAlloc_lock = nullptr;
8887
Mutex* CompileStatistics_lock = nullptr;
8988
Mutex* DirectivesStack_lock = nullptr;
9089
Monitor* Terminator_lock = nullptr;
@@ -346,7 +345,6 @@ void mutex_init() {
346345
MUTEX_DEFL(G1RareEvent_lock , PaddedMutex , Threads_lock, true);
347346
}
348347

349-
MUTEX_DEFL(CompileTaskAlloc_lock , PaddedMonitor, MethodCompileQueue_lock);
350348
MUTEX_DEFL(CompileTaskWait_lock , PaddedMonitor, MethodCompileQueue_lock);
351349

352350
#if INCLUDE_PARALLELGC

src/hotspot/share/runtime/mutexLocker.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ extern Monitor* CompileThread_lock; // a lock held by compile threa
8686
extern Monitor* Compilation_lock; // a lock used to pause compilation
8787
extern Mutex* TrainingData_lock; // a lock used when accessing training records
8888
extern Monitor* TrainingReplayQueue_lock; // a lock held when class are added/removed to the training replay queue
89-
extern Monitor* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
9089
extern Monitor* CompileTaskWait_lock; // a lock held when CompileTasks are waited/notified
9190
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
9291
extern Mutex* DirectivesStack_lock; // a lock held when mutating the dirstack and ref counting directives

0 commit comments

Comments
 (0)