1.1 --- a/src/share/vm/memory/metachunk.cpp Tue Oct 15 07:10:09 2013 -0700 1.2 +++ b/src/share/vm/memory/metachunk.cpp Tue Oct 15 14:28:51 2013 +0200 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -29,42 +29,32 @@ 1.11 #include "utilities/debug.hpp" 1.12 1.13 class VirtualSpaceNode; 1.14 -// 1.15 -// Future modification 1.16 -// 1.17 -// The Metachunk can conceivable be replaced by the Chunk in 1.18 -// allocation.hpp. Note that the latter Chunk is the space for 1.19 -// allocation (allocations from the chunk are out of the space in 1.20 -// the Chunk after the header for the Chunk) where as Metachunks 1.21 -// point to space in a VirtualSpace. To replace Metachunks with 1.22 -// Chunks, change Chunks so that they can be allocated out of a VirtualSpace. 1.23 1.24 const size_t metadata_chunk_initialize = 0xf7f7f7f7; 1.25 1.26 -size_t Metachunk::_overhead = 1.27 - Chunk::aligned_overhead_size(sizeof(Metachunk)) / BytesPerWord; 1.28 +size_t Metachunk::object_alignment() { 1.29 + return ARENA_AMALLOC_ALIGNMENT; 1.30 +} 1.31 + 1.32 +size_t Metachunk::overhead() { 1.33 + return align_size_up(sizeof(Metachunk), object_alignment()) / BytesPerWord; 1.34 +} 1.35 1.36 // Metachunk methods 1.37 1.38 Metachunk::Metachunk(size_t word_size, 1.39 - VirtualSpaceNode* container) : 1.40 - _word_size(word_size), 1.41 - _bottom(NULL), 1.42 - _end(NULL), 1.43 + VirtualSpaceNode* container) 1.44 + : Metabase<Metachunk>(word_size), 1.45 _top(NULL), 1.46 - _next(NULL), 1.47 - _prev(NULL), 1.48 _container(container) 1.49 { 1.50 - _bottom = (MetaWord*)this; 1.51 - _top = (MetaWord*)this + _overhead; 1.52 - _end = (MetaWord*)this + word_size; 1.53 + _top = initial_top(); 1.54 #ifdef ASSERT 1.55 - set_is_free(false); 1.56 + set_is_tagged_free(false); 1.57 size_t data_word_size = pointer_delta(end(), 1.58 - top(), 1.59 + _top, 1.60 sizeof(MetaWord)); 1.61 - Copy::fill_to_words((HeapWord*) top(), 1.62 + Copy::fill_to_words((HeapWord*)_top, 1.63 data_word_size, 1.64 metadata_chunk_initialize); 1.65 #endif 1.66 @@ -82,22 +72,18 @@ 1.67 1.68 // _bottom points to the start of the chunk including the overhead. 1.69 size_t Metachunk::used_word_size() const { 1.70 - return pointer_delta(_top, _bottom, sizeof(MetaWord)); 1.71 + return pointer_delta(_top, bottom(), sizeof(MetaWord)); 1.72 } 1.73 1.74 size_t Metachunk::free_word_size() const { 1.75 - return pointer_delta(_end, _top, sizeof(MetaWord)); 1.76 -} 1.77 - 1.78 -size_t Metachunk::capacity_word_size() const { 1.79 - return pointer_delta(_end, _bottom, sizeof(MetaWord)); 1.80 + return pointer_delta(end(), _top, sizeof(MetaWord)); 1.81 } 1.82 1.83 void Metachunk::print_on(outputStream* st) const { 1.84 st->print_cr("Metachunk:" 1.85 " bottom " PTR_FORMAT " top " PTR_FORMAT 1.86 " end " PTR_FORMAT " size " SIZE_FORMAT, 1.87 - bottom(), top(), end(), word_size()); 1.88 + bottom(), _top, end(), word_size()); 1.89 if (Verbose) { 1.90 st->print_cr(" used " SIZE_FORMAT " free " SIZE_FORMAT, 1.91 used_word_size(), free_word_size()); 1.92 @@ -109,8 +95,8 @@ 1.93 // Mangle the payload of the chunk and not the links that 1.94 // maintain list of chunks. 1.95 HeapWord* start = (HeapWord*)(bottom() + overhead()); 1.96 - size_t word_size = capacity_word_size() - overhead(); 1.97 - Copy::fill_to_words(start, word_size, metadata_chunk_initialize); 1.98 + size_t size = word_size() - overhead(); 1.99 + Copy::fill_to_words(start, size, metadata_chunk_initialize); 1.100 } 1.101 #endif // PRODUCT 1.102 1.103 @@ -118,9 +104,68 @@ 1.104 #ifdef ASSERT 1.105 // Cannot walk through the blocks unless the blocks have 1.106 // headers with sizes. 1.107 - assert(_bottom <= _top && 1.108 - _top <= _end, 1.109 + assert(bottom() <= _top && 1.110 + _top <= (MetaWord*)end(), 1.111 "Chunk has been smashed"); 1.112 #endif 1.113 return; 1.114 } 1.115 + 1.116 +/////////////// Unit tests /////////////// 1.117 + 1.118 +#ifndef PRODUCT 1.119 + 1.120 +class TestMetachunk { 1.121 + public: 1.122 + static void test() { 1.123 + size_t size = 2 * 1024 * 1024; 1.124 + void* memory = malloc(size); 1.125 + assert(memory != NULL, "Failed to malloc 2MB"); 1.126 + 1.127 + Metachunk* metachunk = ::new (memory) Metachunk(size / BytesPerWord, NULL); 1.128 + 1.129 + assert(metachunk->bottom() == (MetaWord*)metachunk, "assert"); 1.130 + assert(metachunk->end() == (uintptr_t*)metachunk + metachunk->size(), "assert"); 1.131 + 1.132 + // Check sizes 1.133 + assert(metachunk->size() == metachunk->word_size(), "assert"); 1.134 + assert(metachunk->word_size() == pointer_delta(metachunk->end(), metachunk->bottom(), 1.135 + sizeof(MetaWord*)), "assert"); 1.136 + 1.137 + // Check usage 1.138 + assert(metachunk->used_word_size() == metachunk->overhead(), "assert"); 1.139 + assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); 1.140 + assert(metachunk->top() == metachunk->initial_top(), "assert"); 1.141 + assert(metachunk->is_empty(), "assert"); 1.142 + 1.143 + // Allocate 1.144 + size_t alloc_size = 64; // Words 1.145 + assert(is_size_aligned(alloc_size, Metachunk::object_alignment()), "assert"); 1.146 + 1.147 + MetaWord* mem = metachunk->allocate(alloc_size); 1.148 + 1.149 + // Check post alloc 1.150 + assert(mem == metachunk->initial_top(), "assert"); 1.151 + assert(mem + alloc_size == metachunk->top(), "assert"); 1.152 + assert(metachunk->used_word_size() == metachunk->overhead() + alloc_size, "assert"); 1.153 + assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); 1.154 + assert(!metachunk->is_empty(), "assert"); 1.155 + 1.156 + // Clear chunk 1.157 + metachunk->reset_empty(); 1.158 + 1.159 + // Check post clear 1.160 + assert(metachunk->used_word_size() == metachunk->overhead(), "assert"); 1.161 + assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); 1.162 + assert(metachunk->top() == metachunk->initial_top(), "assert"); 1.163 + assert(metachunk->is_empty(), "assert"); 1.164 + 1.165 + free(memory); 1.166 + } 1.167 +}; 1.168 + 1.169 +void TestMetachunk_test() { 1.170 + TestMetachunk::test(); 1.171 +} 1.172 + 1.173 +#endif