Mercurial > hg > graal-jvmci-8
comparison src/share/vm/memory/metachunk.cpp @ 12902:bdfbb1fb19ca
8026391: The Metachunk header wastes memory
Reviewed-by: coleenp, jmasa
author | stefank |
---|---|
date | Tue, 15 Oct 2013 14:28:51 +0200 |
parents | c23dbf0e8ab7 |
children | ec2e26e26183 |
comparison
equal
deleted
inserted
replaced
12901:f16726924734 | 12902:bdfbb1fb19ca |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
27 #include "memory/metachunk.hpp" | 27 #include "memory/metachunk.hpp" |
28 #include "utilities/copy.hpp" | 28 #include "utilities/copy.hpp" |
29 #include "utilities/debug.hpp" | 29 #include "utilities/debug.hpp" |
30 | 30 |
31 class VirtualSpaceNode; | 31 class VirtualSpaceNode; |
32 // | |
33 // Future modification | |
34 // | |
35 // The Metachunk can conceivable be replaced by the Chunk in | |
36 // allocation.hpp. Note that the latter Chunk is the space for | |
37 // allocation (allocations from the chunk are out of the space in | |
38 // the Chunk after the header for the Chunk) where as Metachunks | |
39 // point to space in a VirtualSpace. To replace Metachunks with | |
40 // Chunks, change Chunks so that they can be allocated out of a VirtualSpace. | |
41 | 32 |
42 const size_t metadata_chunk_initialize = 0xf7f7f7f7; | 33 const size_t metadata_chunk_initialize = 0xf7f7f7f7; |
43 | 34 |
44 size_t Metachunk::_overhead = | 35 size_t Metachunk::object_alignment() { |
45 Chunk::aligned_overhead_size(sizeof(Metachunk)) / BytesPerWord; | 36 return ARENA_AMALLOC_ALIGNMENT; |
37 } | |
38 | |
39 size_t Metachunk::overhead() { | |
40 return align_size_up(sizeof(Metachunk), object_alignment()) / BytesPerWord; | |
41 } | |
46 | 42 |
47 // Metachunk methods | 43 // Metachunk methods |
48 | 44 |
49 Metachunk::Metachunk(size_t word_size, | 45 Metachunk::Metachunk(size_t word_size, |
50 VirtualSpaceNode* container) : | 46 VirtualSpaceNode* container) |
51 _word_size(word_size), | 47 : Metabase<Metachunk>(word_size), |
52 _bottom(NULL), | |
53 _end(NULL), | |
54 _top(NULL), | 48 _top(NULL), |
55 _next(NULL), | |
56 _prev(NULL), | |
57 _container(container) | 49 _container(container) |
58 { | 50 { |
59 _bottom = (MetaWord*)this; | 51 _top = initial_top(); |
60 _top = (MetaWord*)this + _overhead; | |
61 _end = (MetaWord*)this + word_size; | |
62 #ifdef ASSERT | 52 #ifdef ASSERT |
63 set_is_free(false); | 53 set_is_tagged_free(false); |
64 size_t data_word_size = pointer_delta(end(), | 54 size_t data_word_size = pointer_delta(end(), |
65 top(), | 55 _top, |
66 sizeof(MetaWord)); | 56 sizeof(MetaWord)); |
67 Copy::fill_to_words((HeapWord*) top(), | 57 Copy::fill_to_words((HeapWord*)_top, |
68 data_word_size, | 58 data_word_size, |
69 metadata_chunk_initialize); | 59 metadata_chunk_initialize); |
70 #endif | 60 #endif |
71 } | 61 } |
72 | 62 |
80 return result; | 70 return result; |
81 } | 71 } |
82 | 72 |
83 // _bottom points to the start of the chunk including the overhead. | 73 // _bottom points to the start of the chunk including the overhead. |
84 size_t Metachunk::used_word_size() const { | 74 size_t Metachunk::used_word_size() const { |
85 return pointer_delta(_top, _bottom, sizeof(MetaWord)); | 75 return pointer_delta(_top, bottom(), sizeof(MetaWord)); |
86 } | 76 } |
87 | 77 |
88 size_t Metachunk::free_word_size() const { | 78 size_t Metachunk::free_word_size() const { |
89 return pointer_delta(_end, _top, sizeof(MetaWord)); | 79 return pointer_delta(end(), _top, sizeof(MetaWord)); |
90 } | |
91 | |
92 size_t Metachunk::capacity_word_size() const { | |
93 return pointer_delta(_end, _bottom, sizeof(MetaWord)); | |
94 } | 80 } |
95 | 81 |
96 void Metachunk::print_on(outputStream* st) const { | 82 void Metachunk::print_on(outputStream* st) const { |
97 st->print_cr("Metachunk:" | 83 st->print_cr("Metachunk:" |
98 " bottom " PTR_FORMAT " top " PTR_FORMAT | 84 " bottom " PTR_FORMAT " top " PTR_FORMAT |
99 " end " PTR_FORMAT " size " SIZE_FORMAT, | 85 " end " PTR_FORMAT " size " SIZE_FORMAT, |
100 bottom(), top(), end(), word_size()); | 86 bottom(), _top, end(), word_size()); |
101 if (Verbose) { | 87 if (Verbose) { |
102 st->print_cr(" used " SIZE_FORMAT " free " SIZE_FORMAT, | 88 st->print_cr(" used " SIZE_FORMAT " free " SIZE_FORMAT, |
103 used_word_size(), free_word_size()); | 89 used_word_size(), free_word_size()); |
104 } | 90 } |
105 } | 91 } |
107 #ifndef PRODUCT | 93 #ifndef PRODUCT |
108 void Metachunk::mangle() { | 94 void Metachunk::mangle() { |
109 // Mangle the payload of the chunk and not the links that | 95 // Mangle the payload of the chunk and not the links that |
110 // maintain list of chunks. | 96 // maintain list of chunks. |
111 HeapWord* start = (HeapWord*)(bottom() + overhead()); | 97 HeapWord* start = (HeapWord*)(bottom() + overhead()); |
112 size_t word_size = capacity_word_size() - overhead(); | 98 size_t size = word_size() - overhead(); |
113 Copy::fill_to_words(start, word_size, metadata_chunk_initialize); | 99 Copy::fill_to_words(start, size, metadata_chunk_initialize); |
114 } | 100 } |
115 #endif // PRODUCT | 101 #endif // PRODUCT |
116 | 102 |
117 void Metachunk::verify() { | 103 void Metachunk::verify() { |
118 #ifdef ASSERT | 104 #ifdef ASSERT |
119 // Cannot walk through the blocks unless the blocks have | 105 // Cannot walk through the blocks unless the blocks have |
120 // headers with sizes. | 106 // headers with sizes. |
121 assert(_bottom <= _top && | 107 assert(bottom() <= _top && |
122 _top <= _end, | 108 _top <= (MetaWord*)end(), |
123 "Chunk has been smashed"); | 109 "Chunk has been smashed"); |
124 #endif | 110 #endif |
125 return; | 111 return; |
126 } | 112 } |
113 | |
114 /////////////// Unit tests /////////////// | |
115 | |
116 #ifndef PRODUCT | |
117 | |
118 class TestMetachunk { | |
119 public: | |
120 static void test() { | |
121 size_t size = 2 * 1024 * 1024; | |
122 void* memory = malloc(size); | |
123 assert(memory != NULL, "Failed to malloc 2MB"); | |
124 | |
125 Metachunk* metachunk = ::new (memory) Metachunk(size / BytesPerWord, NULL); | |
126 | |
127 assert(metachunk->bottom() == (MetaWord*)metachunk, "assert"); | |
128 assert(metachunk->end() == (uintptr_t*)metachunk + metachunk->size(), "assert"); | |
129 | |
130 // Check sizes | |
131 assert(metachunk->size() == metachunk->word_size(), "assert"); | |
132 assert(metachunk->word_size() == pointer_delta(metachunk->end(), metachunk->bottom(), | |
133 sizeof(MetaWord*)), "assert"); | |
134 | |
135 // Check usage | |
136 assert(metachunk->used_word_size() == metachunk->overhead(), "assert"); | |
137 assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); | |
138 assert(metachunk->top() == metachunk->initial_top(), "assert"); | |
139 assert(metachunk->is_empty(), "assert"); | |
140 | |
141 // Allocate | |
142 size_t alloc_size = 64; // Words | |
143 assert(is_size_aligned(alloc_size, Metachunk::object_alignment()), "assert"); | |
144 | |
145 MetaWord* mem = metachunk->allocate(alloc_size); | |
146 | |
147 // Check post alloc | |
148 assert(mem == metachunk->initial_top(), "assert"); | |
149 assert(mem + alloc_size == metachunk->top(), "assert"); | |
150 assert(metachunk->used_word_size() == metachunk->overhead() + alloc_size, "assert"); | |
151 assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); | |
152 assert(!metachunk->is_empty(), "assert"); | |
153 | |
154 // Clear chunk | |
155 metachunk->reset_empty(); | |
156 | |
157 // Check post clear | |
158 assert(metachunk->used_word_size() == metachunk->overhead(), "assert"); | |
159 assert(metachunk->free_word_size() == metachunk->word_size() - metachunk->used_word_size(), "assert"); | |
160 assert(metachunk->top() == metachunk->initial_top(), "assert"); | |
161 assert(metachunk->is_empty(), "assert"); | |
162 | |
163 free(memory); | |
164 } | |
165 }; | |
166 | |
167 void TestMetachunk_test() { | |
168 TestMetachunk::test(); | |
169 } | |
170 | |
171 #endif |