diff --git a/src/share/vm/memory/metaspace.cpp b/src/share/vm/memory/metaspace.cpp index a0a4c6e8b15f926bd2c54adc41e4063fce55c923..764b425e484224840e8fb318cde83812eb372e99 100644 --- a/src/share/vm/memory/metaspace.cpp +++ b/src/share/vm/memory/metaspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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 @@ -154,7 +154,7 @@ class ChunkManager : public CHeapObj { // Map a size to a list index assuming that there are lists // for special, small, medium, and humongous chunks. - static ChunkIndex list_index(size_t size); + ChunkIndex list_index(size_t size); // Remove the chunk from its freelist. It is // expected to be on one of the _free_chunks[] lists. @@ -1752,7 +1752,11 @@ void ChunkManager::locked_print_sum_free_chunks(outputStream* st) { st->print_cr("Sum free chunk total " SIZE_FORMAT " count " SIZE_FORMAT, sum_free_chunks(), sum_free_chunks_count()); } + ChunkList* ChunkManager::free_chunks(ChunkIndex index) { + assert(index == SpecializedIndex || index == SmallIndex || index == MediumIndex, + err_msg("Bad index: %d", (int)index)); + return &_free_chunks[index]; } @@ -1864,7 +1868,7 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { } assert((word_size <= chunk->word_size()) || - list_index(chunk->word_size() == HumongousIndex), + (list_index(chunk->word_size()) == HumongousIndex), "Non-humongous variable sized chunk"); if (TraceMetadataChunkAllocation) { size_t list_count; @@ -2358,22 +2362,18 @@ const char* SpaceManager::chunk_size_name(ChunkIndex index) const { } ChunkIndex ChunkManager::list_index(size_t size) { - switch (size) { - case SpecializedChunk: - assert(SpecializedChunk == ClassSpecializedChunk, - "Need branch for ClassSpecializedChunk"); - return SpecializedIndex; - case SmallChunk: - case ClassSmallChunk: - return SmallIndex; - case MediumChunk: - case ClassMediumChunk: - return MediumIndex; - default: - assert(size > MediumChunk || size > ClassMediumChunk, - "Not a humongous chunk"); - return HumongousIndex; + if (free_chunks(SpecializedIndex)->size() == size) { + return SpecializedIndex; } + if (free_chunks(SmallIndex)->size() == size) { + return SmallIndex; + } + if (free_chunks(MediumIndex)->size() == size) { + return MediumIndex; + } + + assert(size > free_chunks(MediumIndex)->size(), "Not a humongous chunk"); + return HumongousIndex; } void SpaceManager::deallocate(MetaWord* p, size_t word_size) { @@ -2395,7 +2395,7 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) { // Find the correct list and and set the current // chunk for that list. - ChunkIndex index = ChunkManager::list_index(new_chunk->word_size()); + ChunkIndex index = chunk_manager()->list_index(new_chunk->word_size()); if (index != HumongousIndex) { retire_current_chunk(); @@ -4031,4 +4031,40 @@ void SpaceManager_test_adjust_initial_chunk_size() { SpaceManagerTest::test_adjust_initial_chunk_size(); } +// The following test is placed here instead of a gtest / unittest file +// because the ChunkManager class is only available in this file. +void ChunkManager_test_list_index() { + ChunkManager manager(ClassSpecializedChunk, ClassSmallChunk, ClassMediumChunk); + + // Test previous bug where a query for a humongous class metachunk, + // incorrectly matched the non-class medium metachunk size. + { + assert(MediumChunk > ClassMediumChunk, "Precondition for test"); + + ChunkIndex index = manager.list_index(MediumChunk); + + assert(index == HumongousIndex, + err_msg("Requested size is larger than ClassMediumChunk," + " so should return HumongousIndex. Got index: %d", (int)index)); + } + + // Check the specified sizes as well. + { + ChunkIndex index = manager.list_index(ClassSpecializedChunk); + assert(index == SpecializedIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); + } + { + ChunkIndex index = manager.list_index(ClassSmallChunk); + assert(index == SmallIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); + } + { + ChunkIndex index = manager.list_index(ClassMediumChunk); + assert(index == MediumIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); + } + { + ChunkIndex index = manager.list_index(ClassMediumChunk + 1); + assert(index == HumongousIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); + } +} + #endif diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp index 074cc4a64838f4bea8ca33c4267436e97c5901d0..a23914234eebd65eabefd8b65918b02c43efc454 100644 --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -5106,6 +5106,7 @@ void TestG1BiasedArray_test(); void TestBufferingOopClosure_test(); void TestCodeCacheRemSet_test(); void FreeRegionList_test(); +void ChunkManager_test_list_index(); #endif void execute_internal_vm_tests() { @@ -5139,6 +5140,7 @@ void execute_internal_vm_tests() { run_unit_test(TestG1BiasedArray_test()); run_unit_test(HeapRegionRemSet::test_prt()); run_unit_test(SpaceManager_test_adjust_initial_chunk_size()); + run_unit_test(ChunkManager_test_list_index()); run_unit_test(TestBufferingOopClosure_test()); run_unit_test(TestCodeCacheRemSet_test()); if (UseG1GC) {