 Chromium Code Reviews
 Chromium Code Reviews Issue 6088012:
  Separate markbits from heap object map words into bitmaps.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
    
  
    Issue 6088012:
  Separate markbits from heap object map words into bitmaps.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/experimental/gc| 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 |