mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8180048: Interned string and symbol table leak memory during parallel unlinking
Make appending found dead BasicHashtableEntrys to the free list atomic. Reviewed-by: ehelin, shade, coleenp
This commit is contained in:
parent
8e28d5772d
commit
c775f6f58b
7 changed files with 97 additions and 29 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, 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
|
||||
|
@ -98,7 +98,7 @@ int SymbolTable::_symbols_removed = 0;
|
|||
int SymbolTable::_symbols_counted = 0;
|
||||
volatile int SymbolTable::_parallel_claimed_idx = 0;
|
||||
|
||||
void SymbolTable::buckets_unlink(int start_idx, int end_idx, int* processed, int* removed) {
|
||||
void SymbolTable::buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context) {
|
||||
for (int i = start_idx; i < end_idx; ++i) {
|
||||
HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i);
|
||||
HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i);
|
||||
|
@ -111,15 +111,14 @@ void SymbolTable::buckets_unlink(int start_idx, int end_idx, int* processed, int
|
|||
break;
|
||||
}
|
||||
Symbol* s = entry->literal();
|
||||
(*processed)++;
|
||||
context->_num_processed++;
|
||||
assert(s != NULL, "just checking");
|
||||
// If reference count is zero, remove.
|
||||
if (s->refcount() == 0) {
|
||||
assert(!entry->is_shared(), "shared entries should be kept live");
|
||||
delete s;
|
||||
(*removed)++;
|
||||
*p = entry->next();
|
||||
the_table()->free_entry(entry);
|
||||
context->free_entry(entry);
|
||||
} else {
|
||||
p = entry->next_addr();
|
||||
}
|
||||
|
@ -132,17 +131,20 @@ void SymbolTable::buckets_unlink(int start_idx, int end_idx, int* processed, int
|
|||
// Remove unreferenced symbols from the symbol table
|
||||
// This is done late during GC.
|
||||
void SymbolTable::unlink(int* processed, int* removed) {
|
||||
size_t memory_total = 0;
|
||||
buckets_unlink(0, the_table()->table_size(), processed, removed);
|
||||
_symbols_removed += *removed;
|
||||
_symbols_counted += *processed;
|
||||
BucketUnlinkContext context;
|
||||
buckets_unlink(0, the_table()->table_size(), &context);
|
||||
_the_table->bulk_free_entries(&context);
|
||||
*processed = context._num_processed;
|
||||
*removed = context._num_removed;
|
||||
|
||||
_symbols_removed = context._num_removed;
|
||||
_symbols_counted = context._num_processed;
|
||||
}
|
||||
|
||||
void SymbolTable::possibly_parallel_unlink(int* processed, int* removed) {
|
||||
const int limit = the_table()->table_size();
|
||||
|
||||
size_t memory_total = 0;
|
||||
|
||||
BucketUnlinkContext context;
|
||||
for (;;) {
|
||||
// Grab next set of buckets to scan
|
||||
int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
|
||||
|
@ -152,10 +154,15 @@ void SymbolTable::possibly_parallel_unlink(int* processed, int* removed) {
|
|||
}
|
||||
|
||||
int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
|
||||
buckets_unlink(start_idx, end_idx, processed, removed);
|
||||
buckets_unlink(start_idx, end_idx, &context);
|
||||
}
|
||||
Atomic::add(*processed, &_symbols_counted);
|
||||
Atomic::add(*removed, &_symbols_removed);
|
||||
|
||||
_the_table->bulk_free_entries(&context);
|
||||
*processed = context._num_processed;
|
||||
*removed = context._num_removed;
|
||||
|
||||
Atomic::add(context._num_processed, &_symbols_counted);
|
||||
Atomic::add(context._num_removed, &_symbols_removed);
|
||||
}
|
||||
|
||||
// Create a new table and using alternate hash code, populate the new table
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue