OLD | NEW |
---|---|
1 // Copyright 2006-2010 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 | 106 |
107 #define ASSERT_MAP_PAGE_INDEX(index) \ | 107 #define ASSERT_MAP_PAGE_INDEX(index) \ |
108 ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex)) | 108 ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex)) |
109 | 109 |
110 | 110 |
111 class PagedSpace; | 111 class PagedSpace; |
112 class MemoryAllocator; | 112 class MemoryAllocator; |
113 class AllocationInfo; | 113 class AllocationInfo; |
114 class Space; | 114 class Space; |
115 | 115 |
116 | |
117 // Bitmap is a sequence of cells each containing fixed number of bits. | |
Erik Corry
2011/01/07 12:13:21
Perhaps add a comment with the word 'endian' since
| |
118 template<typename StorageDescriptor> | |
119 class Bitmap { | |
120 public: | |
121 typedef uint32_t CellType; | |
122 static const uint32_t kBitsPerCell = 32; | |
123 static const uint32_t kBitsPerCellLog2 = 5; | |
124 | |
125 static int CellsForLength(int length) { | |
126 return (length + kBitsPerCell - 1) >> kBitsPerCellLog2; | |
127 } | |
128 | |
129 int CellsCount() { | |
130 return StorageDescriptor::CellsCount(this->address()); | |
131 } | |
132 | |
133 static int SizeFor(int cells_count) { | |
134 return sizeof(CellType)*cells_count; | |
135 } | |
136 | |
137 INLINE(CellType* cells()) { | |
138 return reinterpret_cast<CellType*>(this); | |
139 } | |
140 | |
141 INLINE(Address address()) { | |
142 return reinterpret_cast<Address>(this); | |
143 } | |
144 | |
145 INLINE(static Bitmap* FromAddress(Address addr)) { | |
146 return reinterpret_cast<Bitmap*>(addr); | |
147 } | |
148 | |
149 INLINE(static Bitmap* FromAddress(uint32_t* addr)) { | |
150 return reinterpret_cast<Bitmap*>(addr); | |
151 } | |
152 | |
153 INLINE(bool TestAndSet(const uint32_t index)) { | |
154 const uint32_t mask = 1 << index; | |
155 if (cells()[index >> kBitsPerCellLog2] & mask) { | |
156 return true; | |
157 } else { | |
158 cells()[index >> kBitsPerCellLog2] |= mask; | |
159 return false; | |
160 } | |
161 } | |
162 | |
163 INLINE(bool Get(uint32_t index)) { | |
164 uint32_t mask = 1 << index; | |
165 return (this->cells()[index >> kBitsPerCellLog2] & mask) != 0; | |
166 } | |
167 | |
168 INLINE(void Set(uint32_t index, bool value)) { | |
Erik Corry
2011/01/07 12:13:21
I think it's nicer to have Set and Clear methods i
| |
169 uint32_t mask = 1 << index; | |
170 if (value) { | |
171 this->cells()[index >> kBitsPerCellLog2] |= mask; | |
172 } else { | |
173 this->cells()[index >> kBitsPerCellLog2] &= ~mask; | |
174 } | |
175 } | |
176 | |
177 INLINE(void ClearRange(uint32_t start, uint32_t size)) { | |
178 const uint32_t end = start + size; | |
179 const uint32_t start_cell = start >> kBitsPerCellLog2; | |
180 const uint32_t end_cell = end >> kBitsPerCellLog2; | |
181 | |
182 const uint32_t start_mask = (-1) << start; | |
Erik Corry
2011/01/07 12:13:21
I think you are assuming here that the rhs of the
| |
183 const uint32_t end_mask = (1 << end) - 1; | |
184 | |
185 if (start_cell == end_cell) { | |
186 cells()[start_cell] &= ~(start_mask & end_mask); | |
187 } else { | |
188 cells()[start_cell] &= ~start_mask; | |
189 cells()[end_cell] &= ~end_mask; | |
Erik Corry
2011/01/07 12:13:21
I think this reads and writes (but doesn't change)
| |
190 | |
191 for(uint32_t cell = start_cell + 1, last_cell = end_cell - 1; | |
192 cell <= last_cell; | |
193 cell++) { | |
194 cells()[cell] = 0; | |
195 } | |
196 } | |
197 } | |
198 | |
199 | |
Erik Corry
2011/01/07 12:13:21
Why two blank lines?
| |
200 INLINE(void Clear()) { | |
201 for (int i = 0; i < CellsCount(); i++) { | |
202 cells()[i] = 0; | |
203 } | |
204 } | |
205 | |
206 | |
207 static void PrintWord(const uint32_t& word, const char* sep = " ") { | |
208 for (uint32_t mask = 1; mask != 0; mask <<= 1) { | |
209 PrintF((mask & word) ? "1" : "0"); | |
210 } | |
211 PrintF("%s", sep); | |
212 } | |
213 | |
214 | |
215 void Print() { | |
216 for (int i = 0; i < CellsCount(); i++) { | |
217 PrintWord(cells()[i]); | |
218 } | |
219 PrintF("\n"); | |
220 } | |
221 | |
222 | |
223 bool IsClean() { | |
224 for (int i = 0; i < CellsCount(); i++) { | |
225 if (cells()[i] != 0) return false; | |
226 } | |
227 return true; | |
228 } | |
229 }; | |
230 | |
231 | |
116 // MemoryChunk represents a memory region owned by a specific space. | 232 // MemoryChunk represents a memory region owned by a specific space. |
117 // It is divided into the header and the body. Chunk start is always | 233 // It is divided into the header and the body. Chunk start is always |
118 // 1MB aligned. Start of the body is aligned so it can accomodate | 234 // 1MB aligned. Start of the body is aligned so it can accomodate |
119 // any heap object. | 235 // any heap object. |
120 class MemoryChunk { | 236 class MemoryChunk { |
121 public: | 237 public: |
122 static MemoryChunk* FromAddress(Address a) { | 238 static MemoryChunk* FromAddress(Address a) { |
123 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask); | 239 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask); |
124 } | 240 } |
125 | 241 |
(...skipping 28 matching lines...) Expand all Loading... | |
154 return (flags_ & (1 << flag)) != 0; | 270 return (flags_ & (1 << flag)) != 0; |
155 } | 271 } |
156 | 272 |
157 static const intptr_t kAlignment = (1 << kPageSizeBits); | 273 static const intptr_t kAlignment = (1 << kPageSizeBits); |
158 | 274 |
159 static const intptr_t kAlignmentMask = kAlignment - 1; | 275 static const intptr_t kAlignmentMask = kAlignment - 1; |
160 | 276 |
161 static const size_t kHeaderSize = kPointerSize + kPointerSize + kPointerSize + | 277 static const size_t kHeaderSize = kPointerSize + kPointerSize + kPointerSize + |
162 kPointerSize + kPointerSize; | 278 kPointerSize + kPointerSize; |
163 | 279 |
280 static const size_t kBitsPerByteLog2 = 3; | |
Erik Corry
2011/01/07 12:13:21
This constant already exists in globals.h
| |
281 | |
282 static const size_t kMarksBitmapLength = | |
283 (1 << kPageSizeBits) >> (kPointerSizeLog2); | |
284 | |
285 static const size_t kMarksBitmapSize = | |
286 (1 << kPageSizeBits) >> (kPointerSizeLog2 + kBitsPerByteLog2); | |
287 | |
164 static const int kBodyOffset = | 288 static const int kBodyOffset = |
165 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize)); | 289 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + kMarksBitmapSize)); |
166 | 290 |
167 size_t size() const { return size_; } | 291 size_t size() const { return size_; } |
168 | 292 |
169 Executability executable() { | 293 Executability executable() { |
170 return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE; | 294 return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE; |
171 } | 295 } |
172 | 296 |
297 // --------------------------------------------------------------------- | |
298 // Markbits support | |
299 class BitmapStorageDescriptor { | |
300 public: | |
301 INLINE(static int CellsCount(Address addr)) { | |
302 return Bitmap<BitmapStorageDescriptor>::CellsForLength( | |
303 kMarksBitmapLength); | |
304 } | |
305 }; | |
306 | |
307 typedef Bitmap<BitmapStorageDescriptor> MarkbitsBitmap; | |
308 | |
309 inline MarkbitsBitmap* markbits() { | |
310 return MarkbitsBitmap::FromAddress(address() + kHeaderSize); | |
311 } | |
312 | |
313 // TODO [EVE] when do we need this crap? | |
Erik Corry
2011/01/07 12:13:21
Does this lint or pass the FCC?
| |
314 inline uint32_t Address2Markbit(Address addr) { | |
315 return static_cast<uint32_t>(addr - this->address()) >> kPointerSizeLog2; | |
316 } | |
317 | |
318 inline static uint32_t FastAddress2Markbit(Address addr) { | |
319 const intptr_t offset = | |
320 reinterpret_cast<intptr_t>(addr) & kAlignmentMask; | |
321 | |
322 return static_cast<uint32_t>(offset) >> kPointerSizeLog2; | |
323 } | |
324 | |
325 inline Address Markbit2Address(uint32_t index) { | |
326 return this->address() + (index << kPointerSizeLog2); | |
327 } | |
328 | |
173 protected: | 329 protected: |
174 MemoryChunk* next_chunk_; | 330 MemoryChunk* next_chunk_; |
175 size_t size_; | 331 size_t size_; |
176 intptr_t flags_; | 332 intptr_t flags_; |
177 Space* owner_; | 333 Space* owner_; |
178 | 334 |
179 private: | 335 private: |
180 static MemoryChunk* Initialize(Address base, | 336 static MemoryChunk* Initialize(Address base, |
181 size_t size, | 337 size_t size, |
182 Executability executable, | 338 Executability executable, |
183 Space* owner) { | 339 Space* owner) { |
184 MemoryChunk* chunk = FromAddress(base); | 340 MemoryChunk* chunk = FromAddress(base); |
185 | 341 |
186 ASSERT(base == chunk->address()); | 342 ASSERT(base == chunk->address()); |
187 | 343 |
188 chunk->next_chunk_ = NULL; | 344 chunk->next_chunk_ = NULL; |
189 chunk->size_ = size; | 345 chunk->size_ = size; |
190 chunk->flags_ = 0; | 346 chunk->flags_ = 0; |
191 chunk->owner_ = owner; | 347 chunk->owner_ = owner; |
348 chunk->markbits()->Clear(); | |
192 | 349 |
193 if (executable == EXECUTABLE) chunk->SetFlag(IS_EXECUTABLE); | 350 if (executable == EXECUTABLE) chunk->SetFlag(IS_EXECUTABLE); |
194 | 351 |
195 return chunk; | 352 return chunk; |
196 } | 353 } |
197 | 354 |
198 friend class MemoryAllocator; | 355 friend class MemoryAllocator; |
199 }; | 356 }; |
200 | 357 |
201 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); | 358 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); |
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1407 // Get the age mark of the inactive semispace. | 1564 // Get the age mark of the inactive semispace. |
1408 Address age_mark() { return from_space_.age_mark(); } | 1565 Address age_mark() { return from_space_.age_mark(); } |
1409 // Set the age mark in the active semispace. | 1566 // Set the age mark in the active semispace. |
1410 void set_age_mark(Address mark) { to_space_.set_age_mark(mark); } | 1567 void set_age_mark(Address mark) { to_space_.set_age_mark(mark); } |
1411 | 1568 |
1412 // The start address of the space and a bit mask. Anding an address in the | 1569 // The start address of the space and a bit mask. Anding an address in the |
1413 // new space with the mask will result in the start address. | 1570 // new space with the mask will result in the start address. |
1414 Address start() { return start_; } | 1571 Address start() { return start_; } |
1415 uintptr_t mask() { return address_mask_; } | 1572 uintptr_t mask() { return address_mask_; } |
1416 | 1573 |
1574 INLINE(uint32_t Address2MarkbitIndex(Address addr)) { | |
1575 ASSERT(Contains(addr)); | |
1576 ASSERT(IsAligned(OffsetFrom(addr), kPointerSize)); | |
1577 return static_cast<uint32_t>(addr - start_) >> kPointerSizeLog2; | |
1578 } | |
1579 | |
1580 INLINE(Address MarkbitIndex2Address(uint32_t index)) { | |
1581 return reinterpret_cast<Address>(index << kPointerSizeLog2); | |
1582 } | |
1583 | |
1417 // The allocation top and limit addresses. | 1584 // The allocation top and limit addresses. |
1418 Address* allocation_top_address() { return &allocation_info_.top; } | 1585 Address* allocation_top_address() { return &allocation_info_.top; } |
1419 Address* allocation_limit_address() { return &allocation_info_.limit; } | 1586 Address* allocation_limit_address() { return &allocation_info_.limit; } |
1420 | 1587 |
1421 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) { | 1588 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) { |
1422 return AllocateRawInternal(size_in_bytes, &allocation_info_); | 1589 return AllocateRawInternal(size_in_bytes, &allocation_info_); |
1423 } | 1590 } |
1424 | 1591 |
1425 // Reset the allocation pointer to the beginning of the active semispace. | 1592 // Reset the allocation pointer to the beginning of the active semispace. |
1426 void ResetAllocationInfo(); | 1593 void ResetAllocationInfo(); |
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2093 | 2260 |
2094 private: | 2261 private: |
2095 LargePage* current_; | 2262 LargePage* current_; |
2096 HeapObjectCallback size_func_; | 2263 HeapObjectCallback size_func_; |
2097 }; | 2264 }; |
2098 | 2265 |
2099 | 2266 |
2100 } } // namespace v8::internal | 2267 } } // namespace v8::internal |
2101 | 2268 |
2102 #endif // V8_SPACES_H_ | 2269 #endif // V8_SPACES_H_ |
OLD | NEW |