1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/memory/metachunk.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,180 @@ 1.4 +/* 1.5 + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "memory/allocation.hpp" 1.30 +#include "memory/metachunk.hpp" 1.31 +#include "utilities/copy.hpp" 1.32 +#include "utilities/debug.hpp" 1.33 + 1.34 +PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC 1.35 + 1.36 +class VirtualSpaceNode; 1.37 + 1.38 +const size_t metadata_chunk_initialize = 0xf7f7f7f7; 1.39 + 1.40 +size_t Metachunk::object_alignment() { 1.41 + // Must align pointers and sizes to 8, 1.42 + // so that 64 bit types get correctly aligned. 1.43 + const size_t alignment = 8; 1.44 + 1.45 + // Make sure that the Klass alignment also agree. 1.46 + STATIC_ASSERT(alignment == (size_t)KlassAlignmentInBytes); 1.47 + 1.48 + return alignment; 1.49 +} 1.50 + 1.51 +size_t Metachunk::overhead() { 1.52 + return align_size_up(sizeof(Metachunk), object_alignment()) / BytesPerWord; 1.53 +} 1.54 + 1.55 +// Metachunk methods 1.56 + 1.57 +Metachunk::Metachunk(size_t word_size, 1.58 + VirtualSpaceNode* container) 1.59 + : Metabase<Metachunk>(word_size), 1.60 + _top(NULL), 1.61 + _container(container) 1.62 +{ 1.63 + _top = initial_top(); 1.64 +#ifdef ASSERT 1.65 + set_is_tagged_free(false); 1.66 + size_t data_word_size = pointer_delta(end(), 1.67 + _top, 1.68 + sizeof(MetaWord)); 1.69 + Copy::fill_to_words((HeapWord*)_top, 1.70 + data_word_size, 1.71 + metadata_chunk_initialize); 1.72 +#endif 1.73 +} 1.74 + 1.75 +MetaWord* Metachunk::allocate(size_t word_size) { 1.76 + MetaWord* result = NULL; 1.77 + // If available, bump the pointer to allocate. 1.78 + if (free_word_size() >= word_size) { 1.79 + result = _top; 1.80 + _top = _top + word_size; 1.81 + } 1.82 + return result; 1.83 +} 1.84 + 1.85 +// _bottom points to the start of the chunk including the overhead. 1.86 +size_t Metachunk::used_word_size() const { 1.87 + return pointer_delta(_top, bottom(), sizeof(MetaWord)); 1.88 +} 1.89 + 1.90 +size_t Metachunk::free_word_size() const { 1.91 + return pointer_delta(end(), _top, sizeof(MetaWord)); 1.92 +} 1.93 + 1.94 +void Metachunk::print_on(outputStream* st) const { 1.95 + st->print_cr("Metachunk:" 1.96 + " bottom " PTR_FORMAT " top " PTR_FORMAT 1.97 + " end " PTR_FORMAT " size " SIZE_FORMAT, 1.98 + bottom(), _top, end(), word_size()); 1.99 + if (Verbose) { 1.100 + st->print_cr(" used " SIZE_FORMAT " free " SIZE_FORMAT, 1.101 + used_word_size(), free_word_size()); 1.102 + } 1.103 +} 1.104 + 1.105 +#ifndef PRODUCT 1.106 +void Metachunk::mangle() { 1.107 + // Mangle the payload of the chunk and not the links that 1.108 + // maintain list of chunks. 1.109 + HeapWord* start = (HeapWord*)(bottom() + overhead()); 1.110 + size_t size = word_size() - overhead(); 1.111 + Copy::fill_to_words(start, size, metadata_chunk_initialize); 1.112 +} 1.113 +#endif // PRODUCT 1.114 + 1.115 +void Metachunk::verify() { 1.116 +#ifdef ASSERT 1.117 + // Cannot walk through the blocks unless the blocks have 1.118 + // headers with sizes. 1.119 + assert(bottom() <= _top && 1.120 + _top <= (MetaWord*)end(), 1.121 + "Chunk has been smashed"); 1.122 +#endif 1.123 + return; 1.124 +} 1.125 + 1.126 +/////////////// Unit tests /////////////// 1.127 + 1.128 +#ifndef PRODUCT 1.129 + 1.130 +class TestMetachunk { 1.131 + public: 1.132 + static void test() { 1.133 + size_t size = 2 * 1024 * 1024; 1.134 + void* memory = malloc(size); 1.135 + assert(memory != NULL, "Failed to malloc 2MB"); 1.136 + 1.137 + Metachunk* metachunk = ::new (memory) Metachunk(size / BytesPerWord, NULL); 1.138 + 1.139 + assert(metachunk->bottom() == (MetaWord*)metachunk, "assert"); 1.140 + assert(metachunk->end() == (uintptr_t*)metachunk + metachunk->size(), "assert"); 1.141 + 1.142 + // Check sizes 1.143 + assert(metachunk->size() == metachunk->word_size(), "assert"); 1.144 + assert(metachunk->word_size() == pointer_delta(metachunk->end(), metachunk->bottom(), 1.145 + sizeof(MetaWord*)), "assert"); 1.146 + 1.147 + // Check usage 1.148 + assert(metachunk->used_word_size() == metachunk->overhead(), "assert"); 1.149 + assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); 1.150 + assert(metachunk->top() == metachunk->initial_top(), "assert"); 1.151 + assert(metachunk->is_empty(), "assert"); 1.152 + 1.153 + // Allocate 1.154 + size_t alloc_size = 64; // Words 1.155 + assert(is_size_aligned(alloc_size, Metachunk::object_alignment()), "assert"); 1.156 + 1.157 + MetaWord* mem = metachunk->allocate(alloc_size); 1.158 + 1.159 + // Check post alloc 1.160 + assert(mem == metachunk->initial_top(), "assert"); 1.161 + assert(mem + alloc_size == metachunk->top(), "assert"); 1.162 + assert(metachunk->used_word_size() == metachunk->overhead() + alloc_size, "assert"); 1.163 + assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); 1.164 + assert(!metachunk->is_empty(), "assert"); 1.165 + 1.166 + // Clear chunk 1.167 + metachunk->reset_empty(); 1.168 + 1.169 + // Check post clear 1.170 + assert(metachunk->used_word_size() == metachunk->overhead(), "assert"); 1.171 + assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); 1.172 + assert(metachunk->top() == metachunk->initial_top(), "assert"); 1.173 + assert(metachunk->is_empty(), "assert"); 1.174 + 1.175 + free(memory); 1.176 + } 1.177 +}; 1.178 + 1.179 +void TestMetachunk_test() { 1.180 + TestMetachunk::test(); 1.181 +} 1.182 + 1.183 +#endif