mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-03 06:35:31 +00:00
change stack when changing tag
This commit is contained in:
parent
27af995be7
commit
972f4c8789
@ -204,7 +204,7 @@ Chunk* ChunkPool::allocate_chunk(Arena* arena, size_t length, AllocFailType allo
|
||||
}
|
||||
chunk = (Chunk*)p;
|
||||
}
|
||||
MemTracker::chunk_assigned_to_arena(chunk, arena->get_mem_tag());
|
||||
MemTracker::chunk_assigned_to_arena(chunk, arena->get_mem_tag(), CALLER_PC);
|
||||
::new(chunk) Chunk(length);
|
||||
// We rely on arena alignment <= malloc alignment.
|
||||
assert(is_aligned(chunk, ARENA_AMALLOC_ALIGNMENT), "Chunk start address misaligned.");
|
||||
@ -229,7 +229,7 @@ void ChunkPool::deallocate_chunk(Chunk* c) {
|
||||
c->set_stamp(0);
|
||||
}
|
||||
|
||||
MemTracker::add_chunk_to_pool(c);
|
||||
MemTracker::add_chunk_to_pool(c, CALLER_PC);
|
||||
|
||||
// If this is a standard-sized chunk, return it to its pool; otherwise free it.
|
||||
ChunkPool* pool = ChunkPool::get_pool_for_size(c->length());
|
||||
|
||||
@ -187,7 +187,7 @@ void* MallocTracker::record_malloc(void* malloc_base, size_t size, MemTag mem_ta
|
||||
return memblock;
|
||||
}
|
||||
|
||||
void MallocTracker::chunk_assigned_to_arena(void* memblock, MemTag new_tag) {
|
||||
void MallocTracker::chunk_assigned_to_arena(void* memblock, MemTag new_tag, const NativeCallStack& new_stack) {
|
||||
MallocHeader* header = (MallocHeader*)memblock - 1;
|
||||
|
||||
// Only decrement per-tag counters, leave the total malloc amounts unchanged.
|
||||
@ -195,14 +195,8 @@ void MallocTracker::chunk_assigned_to_arena(void* memblock, MemTag new_tag) {
|
||||
|
||||
uint32_t new_mst_marker = 0;
|
||||
if (MemTracker::tracking_level() == NMT_detail && header->mem_tag() != new_tag) {
|
||||
// retrieve the old stack from MST
|
||||
NativeCallStack old_stack;
|
||||
if (!MallocSiteTable::access_stack(old_stack, *header)) {
|
||||
fatal("NMT is now out of sync.");
|
||||
}
|
||||
MallocSiteTable::deallocation_at(header->size(), header->mst_marker());
|
||||
// update MST with new tag
|
||||
if (!MallocSiteTable::allocation_at(old_stack, header->size(), &new_mst_marker, new_tag)) {
|
||||
if (!MallocSiteTable::allocation_at(new_stack, header->size(), &new_mst_marker, new_tag)) {
|
||||
fatal("NMT is now out of sync.");
|
||||
}
|
||||
}
|
||||
@ -216,7 +210,7 @@ void MallocTracker::chunk_assigned_to_arena(void* memblock, MemTag new_tag) {
|
||||
}
|
||||
}
|
||||
|
||||
void MallocTracker::add_chunk_to_pool(void* memblock) {
|
||||
void MallocTracker::add_chunk_to_pool(void* memblock, const NativeCallStack& new_stack) {
|
||||
MallocHeader* header = (MallocHeader*)memblock - 1;
|
||||
assert(header->mem_tag() != mtChunk, "Should only be operating on arena chunks");
|
||||
|
||||
@ -225,14 +219,8 @@ void MallocTracker::add_chunk_to_pool(void* memblock) {
|
||||
|
||||
uint32_t new_mst_marker = 0;
|
||||
if (MemTracker::tracking_level() == NMT_detail) {
|
||||
NativeCallStack old_stack;
|
||||
// retrieve the old stack from MST
|
||||
if (!MallocSiteTable::access_stack(old_stack, *header)) {
|
||||
fatal("NMT is now out of sync.");
|
||||
}
|
||||
MallocSiteTable::deallocation_at(header->size(), header->mst_marker());
|
||||
// update MST with new tag
|
||||
if (!MallocSiteTable::allocation_at(old_stack, header->size(), &new_mst_marker, mtChunk)) {
|
||||
if (!MallocSiteTable::allocation_at(new_stack, header->size(), &new_mst_marker, mtChunk)) {
|
||||
fatal("NMT is now out of sync.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,8 +278,8 @@ class MallocTracker : AllStatic {
|
||||
static void* record_malloc(void* malloc_base, size_t size, MemTag mem_tag,
|
||||
const NativeCallStack& stack);
|
||||
|
||||
static void chunk_assigned_to_arena(void* memblock, MemTag new_tag);
|
||||
static void add_chunk_to_pool(void* memblock);
|
||||
static void chunk_assigned_to_arena(void* memblock, MemTag new_tag, const NativeCallStack& new_stack);
|
||||
static void add_chunk_to_pool(void* memblock, const NativeCallStack& new_stack);
|
||||
|
||||
// Given a block returned by os::malloc() or os::realloc():
|
||||
// deaccount block from NMT, mark its header as dead and return pointer to header.
|
||||
|
||||
@ -90,20 +90,20 @@ class MemTracker : AllStatic {
|
||||
return mem_base;
|
||||
}
|
||||
|
||||
static inline void chunk_assigned_to_arena(void* memblock, MemTag new_tag) {
|
||||
static inline void chunk_assigned_to_arena(void* memblock, MemTag new_tag, const NativeCallStack& new_stack) {
|
||||
assert(memblock != nullptr, "caller should handle null");
|
||||
if (!enabled()) {
|
||||
return;
|
||||
}
|
||||
MallocTracker::chunk_assigned_to_arena(memblock, new_tag);
|
||||
MallocTracker::chunk_assigned_to_arena(memblock, new_tag, new_stack);
|
||||
}
|
||||
|
||||
static inline void add_chunk_to_pool(void* memblock) {
|
||||
static inline void add_chunk_to_pool(void* memblock, const NativeCallStack& new_stack) {
|
||||
assert(memblock != nullptr, "caller should handle null");
|
||||
if (!enabled()) {
|
||||
return;
|
||||
}
|
||||
MallocTracker::add_chunk_to_pool(memblock);
|
||||
MallocTracker::add_chunk_to_pool(memblock, new_stack);
|
||||
}
|
||||
|
||||
// Record malloc free and return malloc base address
|
||||
|
||||
@ -156,34 +156,39 @@ TEST_VM(NMTChunkAccounting, mst) {
|
||||
if (!MemTracker::enabled() || MemTracker::tracking_level() != NMT_detail) {
|
||||
return;
|
||||
}
|
||||
void* allocation = os::malloc(100, mtChunk, CALLER_PC);
|
||||
NativeCallStack stack_a = CALLER_PC;
|
||||
NativeCallStack stack_b = CURRENT_PC;
|
||||
void* allocation = os::malloc(100, mtChunk, stack_a);
|
||||
MallocHeader* header = (MallocHeader*)allocation - 1;
|
||||
uint32_t old_marker = header->mst_marker();
|
||||
NativeCallStack old_stack;
|
||||
ASSERT_TRUE(MallocSiteTable::access_stack(old_stack, *header));
|
||||
EXPECT_TRUE(old_stack.equals(stack_a));
|
||||
|
||||
MemTracker::chunk_assigned_to_arena(allocation, mtTest);
|
||||
MemTracker::chunk_assigned_to_arena(allocation, mtTest, stack_b);
|
||||
EXPECT_TRUE(header->mem_tag() == mtTest);
|
||||
EXPECT_NE(header->mst_marker(), old_marker);
|
||||
NativeCallStack new_stack;
|
||||
EXPECT_TRUE(MallocSiteTable::access_stack(new_stack, *header));
|
||||
EXPECT_TRUE(new_stack.equals(old_stack));
|
||||
EXPECT_TRUE(new_stack.equals(stack_b));
|
||||
|
||||
MemTracker::add_chunk_to_pool(allocation);
|
||||
MemTracker::add_chunk_to_pool(allocation, stack_a);
|
||||
ASSERT_TRUE(header->mem_tag() == mtChunk);
|
||||
ASSERT_TRUE(MallocSiteTable::access_stack(new_stack, *header));
|
||||
EXPECT_TRUE(new_stack.equals(old_stack));
|
||||
EXPECT_TRUE(new_stack.equals(stack_a));
|
||||
os::free(allocation);
|
||||
|
||||
// Now test the path where new and old tags are equal.
|
||||
allocation = os::malloc(100, mtTest, CALLER_PC);
|
||||
// This should only happen when a fresh chunk is created to grow an arena.
|
||||
allocation = os::malloc(100, mtTest, stack_b);
|
||||
header = (MallocHeader*)allocation - 1;
|
||||
old_marker = header->mst_marker();
|
||||
ASSERT_TRUE(MallocSiteTable::access_stack(old_stack, *header));
|
||||
EXPECT_TRUE(old_stack.equals(stack_b));
|
||||
|
||||
MemTracker::chunk_assigned_to_arena(allocation, mtTest);
|
||||
MemTracker::chunk_assigned_to_arena(allocation, mtTest, stack_b);
|
||||
EXPECT_TRUE(header->mem_tag() == mtTest);
|
||||
EXPECT_EQ(header->mst_marker(), old_marker);
|
||||
EXPECT_TRUE(MallocSiteTable::access_stack(new_stack, *header));
|
||||
EXPECT_TRUE(new_stack.equals(old_stack));
|
||||
EXPECT_TRUE(new_stack.equals(stack_b));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user