Changeset 263252 in webkit
- Timestamp:
- Jun 18, 2020, 8:30:37 PM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r263250 r263252 1 2020-06-18 Mark Lam <mark.lam@apple.com> 2 3 Unify Bitmap math loops in MarkedBlock::Handle::specializedSweep(). 4 https://bugs.webkit.org/show_bug.cgi?id=213345 5 6 Reviewed by Robin Morisset and Saam Barati. 7 8 This change appears to be performance neutral. However, we'll take the change 9 because we know that it does less work, and the new way of expressing the Bitmap 10 math in MarkedBlock::Handle::specializedSweep() does appear to be easier to 11 understand than the old code. 12 13 Also addressed feedback from Robin and Saam in https://bugs.webkit.org/show_bug.cgi?id=213071. 14 15 Changes made: 16 17 1. Use the new Bitmap::words() API to get direct access to the underlying bits 18 storage. With this, we can do the merging of the marked and newlyAllocated 19 bits with a single pass looping thru the bitmap words. 20 21 2. In MarkedBlock::Handle::specializedSweep()'s Bitmap free list code, moved the 22 implementation of handleDeadCells lambda down to the call to freeAtoms.forEachSetBit() 23 because this is the only place it is used. 24 25 3. Fixed MarkedBlock::Handle::specializedSweep()'s Bitmap free list code to 26 handle the dead cells unconditionally. This condition check was wrongly 27 adapted from the linked list implementation where handleDeadCell() was called 28 in 2 places depending on the destruction mode. With the Bitmap free list, 29 there is only once place to handle the dead cells, and it should be executed 30 unconditionally. 31 32 This fixes a bug where the FreeList::originalSize() never gets computed if the 33 cells in the block does not need destruction. 34 35 4. Renamed FreeList::bitmapRows() to FreeList::bitmapRowsMinusOne(). 36 Renamed FreeList::offsetOfBitmapRows() to FreeList::offsetOfBitmapRowsMinusOne(). 37 38 5. Also fixed some typos in comments. 39 40 * heap/FreeList.h: 41 (JSC::FreeList::bitmapIsEmpty const): 42 (JSC::FreeList::offsetOfBitmapRowsMinusOne): 43 (JSC::FreeList::bitmapRowsMinusOne const): 44 (JSC::FreeList::offsetOfBitmapRows): Deleted. 45 (JSC::FreeList::bitmapRows const): Deleted. 46 * heap/FreeListInlines.h: 47 (JSC::FreeList::allocate): 48 (JSC::FreeList::forEach const): 49 * heap/MarkedBlockInlines.h: 50 (JSC::MarkedBlock::Handle::specializedSweep): 51 * jit/AssemblyHelpers.cpp: 52 (JSC::AssemblyHelpers::emitAllocateWithNonNullAllocator): 53 1 54 2020-06-18 Yusuke Suzuki <ysuzuki@apple.com> 2 55 … … 206 259 5. On the layout of fields in FreeList (see changes in FreeList.h), we try to 207 260 preserve the positions of the bump allocator fields. The only change we made 208 there is n the location of m_cellSize. It is now moved up next to m_remaining,261 there is in the location of m_cellSize. It is now moved up next to m_remaining, 209 262 and m_originalSize is moved down. This is because m_originalSize is only 210 263 accessed in the slow path, and m_cellSize is accessed in the bump allocation -
trunk/Source/JavaScriptCore/heap/FreeList.h
r263195 r263252 106 106 // Remember, we don't actually clear the bits in m_bitmap as we allocate 107 107 // the atoms. Instead, m_currentRowBitmap and m_currentRowIndex tells us 108 // if there a toms still available for allocation. See comment blob below108 // if there are atoms still available for allocation. See comment blob below 109 109 // at the declaration of m_currentRowIndex for more details. 110 110 return !m_currentRowBitmap && !m_currentRowIndex; … … 117 117 // we can schedule instructions better i.e. to do a load before decrementing the 118 118 // row index. 119 static ptrdiff_t offsetOfBitmapRows () { return OBJECT_OFFSETOF(FreeList, m_bitmap) - sizeof(AtomsBitmap::Word); }119 static ptrdiff_t offsetOfBitmapRowsMinusOne() { return OBJECT_OFFSETOF(FreeList, m_bitmap) - sizeof(AtomsBitmap::Word); } 120 120 121 121 static ptrdiff_t offsetOfCurrentRowIndex() { return OBJECT_OFFSETOF(FreeList, m_currentRowIndex); } … … 142 142 #if ENABLE(BITMAP_FREELIST) 143 143 AtomsBitmap& atomsBitmap() { return m_bitmap; } 144 AtomsBitmap::Word* bitmapRows () const145 { 146 // See comment about offsetOfBitmapRows ().144 AtomsBitmap::Word* bitmapRowsMinusOne() const 145 { 146 // See comment about offsetOfBitmapRowsMinusOne(). 147 147 return bitwise_cast<AtomsBitmap::Word*>(&m_bitmap) - 1; 148 148 } -
trunk/Source/JavaScriptCore/heap/FreeListInlines.h
r263195 r263252 57 57 auto* rowAddress = m_currentMarkedBlockRowAddress; 58 58 while (rowIndex) { 59 // We load before decrementing rowIndex because bitmapRows () points60 // to 1 word before m_bitmap. See comments about offsetOfBitmapRows ()59 // We load before decrementing rowIndex because bitmapRowsMinusOne() points 60 // to 1 word before m_bitmap. See comments about offsetOfBitmapRowsMinusOne() 61 61 // for why we do this. 62 rowBitmap = bitmapRows ()[rowIndex--];62 rowBitmap = bitmapRowsMinusOne()[rowIndex--]; 63 63 rowAddress -= atomsPerRow; 64 64 if (rowBitmap) … … 107 107 108 108 while (rowIndex) { 109 // We load before decrementing rowIndex because bitmapRows () points110 // to 1 word before m_bitmap. See comments about offsetOfBitmapRows ()109 // We load before decrementing rowIndex because bitmapRowsMinusOne() points 110 // to 1 word before m_bitmap. See comments about offsetOfBitmapRowsMinusOne() 111 111 // for why we do this. 112 rowBitmap = bitmapRows ()[rowIndex--];112 rowBitmap = bitmapRowsMinusOne()[rowIndex--]; 113 113 currentMarkedBlockRowAddress -= atomsPerRow; 114 114 if (rowBitmap) -
trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h
r263195 r263252 265 265 m_directory->setIsDestructible(NoLockingNecessary, this, false); 266 266 267 char* startOfLastCell = static_cast<char*>(cellAlign(block.atoms() + m_endAtom - 1)); 268 char* payloadEnd = startOfLastCell + cellSize; 269 RELEASE_ASSERT(payloadEnd - MarkedBlock::blockSize <= bitwise_cast<char*>(&block)); 270 char* payloadBegin = bitwise_cast<char*>(block.atoms()); 271 267 272 if (Options::useBumpAllocator() 268 273 && emptyMode == IsEmpty … … 281 286 } 282 287 283 char* startOfLastCell = static_cast<char*>(cellAlign(block.atoms() + m_endAtom - 1));284 char* payloadEnd = startOfLastCell + cellSize;285 RELEASE_ASSERT(payloadEnd - MarkedBlock::blockSize <= bitwise_cast<char*>(&block));286 char* payloadBegin = bitwise_cast<char*>(block.atoms());287 288 288 if (sweepMode == SweepToFreeList) 289 289 setIsFreeListed(); … … 305 305 306 306 #if ENABLE(BITMAP_FREELIST) 307 // The code below is an optimized version of the following by merging the 308 // various loops over the bitmaps. 309 // 310 // AtomsBitmap cellLocations; 311 // cellLocations.setEachNthBit(m_atomsPerCell, 0, m_endAtom); 312 // 313 // if (emptyMode == NotEmpty) { 314 // if (marksMode == MarksNotStale) { 315 // freeAtoms = footer.m_marks; 316 // if (newlyAllocatedMode == HasNewlyAllocated) 317 // freeAtoms |= footer.m_newlyAllocated; 318 // } else if (newlyAllocatedMode == HasNewlyAllocated) 319 // freeAtoms = footer.m_newlyAllocated; 320 // // At this point, a set bit in freeAtoms represents live cells. 321 // isEmpty = freeAtoms.isEmpty(); 322 // 323 // // Invert the bits at each cell location so that the ones for live cells 324 // // are cleared, and the ones for dead cells are set. 325 // freeAtoms ^= cellLocations; 326 // } else 327 // freeAtoms = cellLocations; // all cells are free. 328 307 329 AtomsBitmap localFreeAtoms; 308 330 AtomsBitmap& freeAtoms = freeList ? freeList->atomsBitmap() : localFreeAtoms; 309 size_t count = 0; 310 311 auto handleDeadCell = [&] (size_t i) { 312 HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(atomAt(i)); 313 314 if (destructionMode != BlockHasNoDestructors) 315 destroy(cell); 316 317 if (sweepMode == SweepToFreeList) { 318 if (scribbleMode == Scribble) 319 scribble(cell, cellSize); 320 ++count; 321 } 322 }; 323 324 bool isEmpty = true; 325 326 AtomsBitmap cellLocations; 327 cellLocations.setEachNthBit(m_atomsPerCell, 0, m_endAtom); 331 332 AtomsBitmap::Word* free = freeAtoms.words(); 333 AtomsBitmap::Word* marks = footer.m_marks.words(); 334 AtomsBitmap::Word* newlyAllocated = footer.m_newlyAllocated.words(); 335 336 unsigned roundedUpEndAtoms = roundUpToMultipleOf<AtomsBitmap::bitsInWord>(m_endAtom); 337 unsigned endWordIndex = roundedUpEndAtoms / AtomsBitmap::bitsInWord; 338 ASSERT(m_endAtom <= endWordIndex * AtomsBitmap::bitsInWord); 339 340 if (freeList) 341 freeAtoms.clearAll(); 342 freeAtoms.setEachNthBit(m_atomsPerCell, 0, m_endAtom); 328 343 329 344 if (emptyMode == NotEmpty) { 330 if (marksMode == MarksNotStale) { 331 freeAtoms = footer.m_marks; 332 if (newlyAllocatedMode == HasNewlyAllocated) 333 freeAtoms |= footer.m_newlyAllocated; 334 } else if (newlyAllocatedMode == HasNewlyAllocated) 335 freeAtoms = footer.m_newlyAllocated; 336 // At this point, a set bit in freeAtoms represents live cells. 337 isEmpty = freeAtoms.isEmpty(); 338 339 // Invert the bits at each cell location so that the ones for live cells 340 // are cleared, and the ones for dead cells are set. 341 freeAtoms ^= cellLocations; 342 } else 343 freeAtoms = cellLocations; // all cells are free. 344 345 if (marksMode == MarksNotStale && newlyAllocatedMode == HasNewlyAllocated) { 346 for (unsigned i = 0; i < endWordIndex; ++i) 347 free[i] ^= marks[i] | newlyAllocated[i]; 348 349 } else if (marksMode == MarksNotStale) { 350 for (unsigned i = 0; i < endWordIndex; ++i) 351 free[i] ^= marks[i]; 352 353 } else if (newlyAllocatedMode == HasNewlyAllocated) { 354 for (unsigned i = 0; i < endWordIndex; ++i) 355 free[i] ^= newlyAllocated[i]; 356 } 357 } 358 359 // At this point, a set bit in freeAtoms represents a dead cell. 360 345 361 // We only want to discard the newlyAllocated bits if we're creating a FreeList, 346 362 // otherwise we would lose information on what's currently alive. … … 351 367 footer.m_lock.unlock(); 352 368 353 if (destructionMode != BlockHasNoDestructors) 354 freeAtoms.forEachSetBit(handleDeadCell); 355 369 // Handle dead cells. 370 unsigned deadCellCount = 0; 371 freeAtoms.forEachSetBit([&] (size_t i) { 372 HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(atomAt(i)); 373 374 if (destructionMode != BlockHasNoDestructors) 375 destroy(cell); 376 377 if (sweepMode == SweepToFreeList) { 378 if (scribbleMode == Scribble) 379 scribble(cell, cellSize); 380 } 381 ++deadCellCount; 382 }); 383 384 unsigned numberOfCellsInBlock = (payloadEnd - payloadBegin) / cellSize; 385 bool isEmpty = (deadCellCount == numberOfCellsInBlock); 356 386 if (sweepMode == SweepToFreeList) { 357 freeList->initializeAtomsBitmap(this, freeAtoms, count * cellSize);387 freeList->initializeAtomsBitmap(this, freeAtoms, deadCellCount * cellSize); 358 388 setIsFreeListed(); 359 389 } else if (isEmpty) -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp
r263195 r263252 592 592 // Load the next row bitmap and point m_currentMarkedBlockRowAddress to the next row. 593 593 594 // Note: offsetOfBitmapRows () points to 1 word before m_bitmap. We do this594 // Note: offsetOfBitmapRowsMinusOne() points to 1 word before m_bitmap. We do this 595 595 // deliberately because it allows us to schedule instructions better and 596 596 // do this load before the decrement below. 597 load64(BaseIndex(allocatorGPR, rowIndexGPR, TimesEight, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfBitmapRows ()), rowBitmapGPR);597 load64(BaseIndex(allocatorGPR, rowIndexGPR, TimesEight, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfBitmapRowsMinusOne()), rowBitmapGPR); 598 598 599 599 sub64(TrustedImm32(1), rowIndexGPR); -
trunk/Source/WTF/ChangeLog
r263223 r263252 1 2020-06-18 Mark Lam <mark.lam@apple.com> 2 3 Unify Bitmap math loops in MarkedBlock::Handle::specializedSweep(). 4 https://bugs.webkit.org/show_bug.cgi?id=213345 5 6 Reviewed by Robin Morisset and Saam Barati. 7 8 1. Removed Bitmap::words. Use Bitmap::numberOfWords instead. 9 2. Removed Bitmap::wordSize. Use Bitmap::bitsInWord instead. 10 3. Added a new Bitmap::words() method which returns the address of the underlying 11 bitmap storage as a Bitmap::Word*. This enables clients to do direct bit 12 manipulation on the Bitmap words if needed. 13 14 * wtf/Bitmap.h: 15 (WTF::WordType>::get const): 16 (WTF::WordType>::set): 17 (WTF::WordType>::testAndSet): 18 (WTF::WordType>::testAndClear): 19 (WTF::WordType>::concurrentTestAndSet): 20 (WTF::WordType>::concurrentTestAndClear): 21 (WTF::WordType>::clear): 22 (WTF::WordType>::invert): 23 (WTF::WordType>::nextPossiblyUnset const): 24 (WTF::WordType>::count const): 25 (WTF::WordType>::isEmpty const): 26 (WTF::WordType>::isFull const): 27 (WTF::WordType>::merge): 28 (WTF::WordType>::filter): 29 (WTF::WordType>::exclude): 30 (WTF::WordType>::concurrentFilter): 31 (WTF::WordType>::subsumes const): 32 (WTF::WordType>::forEachSetBit const): 33 (WTF::WordType>::findBit const): 34 (WTF::WordType>::mergeAndClear): 35 (WTF::WordType>::setAndClear): 36 (WTF::WordType>::setEachNthBit): 37 (WTF::= const): 38 (WTF::=): 39 (WTF::WordType>::hash const): 40 1 41 2020-06-18 Geoffrey Garen <ggaren@apple.com> 2 42 -
trunk/Source/WTF/wtf/Bitmap.h
r263195 r263252 136 136 static constexpr unsigned numberOfWords = (bitmapSize + bitsInWord - 1) / bitsInWord; 137 137 WordType wordAt(size_t wordIndex) const { return bits[wordIndex]; } 138 Word* words() { return bitwise_cast<Word*>(&bits); } 138 139 139 140 private: 140 static constexpr unsigned wordSize = bitsInWord;141 static constexpr unsigned words = numberOfWords;142 143 141 // the literal '1' is of type signed int. We want to use an unsigned 144 142 // version of the correct size when doing the calculations because if … … 148 146 static constexpr WordType one = 1; 149 147 150 std::array<WordType, words> bits;148 std::array<WordType, numberOfWords> bits; 151 149 }; 152 150 … … 160 158 inline bool Bitmap<bitmapSize, WordType>::get(size_t n, Dependency dependency) const 161 159 { 162 return !!(dependency.consume(this)->bits[n / wordSize] & (one << (n % wordSize)));160 return !!(dependency.consume(this)->bits[n / bitsInWord] & (one << (n % bitsInWord))); 163 161 } 164 162 … … 166 164 inline void Bitmap<bitmapSize, WordType>::set(size_t n) 167 165 { 168 bits[n / wordSize] |= (one << (n % wordSize));166 bits[n / bitsInWord] |= (one << (n % bitsInWord)); 169 167 } 170 168 … … 181 179 inline bool Bitmap<bitmapSize, WordType>::testAndSet(size_t n) 182 180 { 183 WordType mask = one << (n % wordSize);184 size_t index = n / wordSize;181 WordType mask = one << (n % bitsInWord); 182 size_t index = n / bitsInWord; 185 183 bool result = bits[index] & mask; 186 184 bits[index] |= mask; … … 191 189 inline bool Bitmap<bitmapSize, WordType>::testAndClear(size_t n) 192 190 { 193 WordType mask = one << (n % wordSize);194 size_t index = n / wordSize;191 WordType mask = one << (n % bitsInWord); 192 size_t index = n / bitsInWord; 195 193 bool result = bits[index] & mask; 196 194 bits[index] &= ~mask; … … 201 199 ALWAYS_INLINE bool Bitmap<bitmapSize, WordType>::concurrentTestAndSet(size_t n, Dependency dependency) 202 200 { 203 WordType mask = one << (n % wordSize);204 size_t index = n / wordSize;201 WordType mask = one << (n % bitsInWord); 202 size_t index = n / bitsInWord; 205 203 WordType* data = dependency.consume(bits.data()) + index; 206 204 return !bitwise_cast<Atomic<WordType>*>(data)->transactionRelaxed( … … 217 215 ALWAYS_INLINE bool Bitmap<bitmapSize, WordType>::concurrentTestAndClear(size_t n, Dependency dependency) 218 216 { 219 WordType mask = one << (n % wordSize);220 size_t index = n / wordSize;217 WordType mask = one << (n % bitsInWord); 218 size_t index = n / bitsInWord; 221 219 WordType* data = dependency.consume(bits.data()) + index; 222 220 return !bitwise_cast<Atomic<WordType>*>(data)->transactionRelaxed( … … 233 231 inline void Bitmap<bitmapSize, WordType>::clear(size_t n) 234 232 { 235 bits[n / wordSize] &= ~(one << (n % wordSize));233 bits[n / bitsInWord] &= ~(one << (n % bitsInWord)); 236 234 } 237 235 … … 245 243 inline void Bitmap<bitmapSize, WordType>::invert() 246 244 { 247 for (size_t i = 0; i < words; ++i)245 for (size_t i = 0; i < numberOfWords; ++i) 248 246 bits[i] = ~bits[i]; 249 if constexpr (!!(bitmapSize % wordSize)) {250 constexpr size_t remainingBits = bitmapSize % wordSize;247 if constexpr (!!(bitmapSize % bitsInWord)) { 248 constexpr size_t remainingBits = bitmapSize % bitsInWord; 251 249 constexpr WordType mask = (static_cast<WordType>(1) << remainingBits) - 1; 252 bits[ words - 1] &= mask;250 bits[numberOfWords - 1] &= mask; 253 251 } 254 252 } … … 257 255 inline size_t Bitmap<bitmapSize, WordType>::nextPossiblyUnset(size_t start) const 258 256 { 259 if (!~bits[start / wordSize])260 return ((start / wordSize) + 1) * wordSize;257 if (!~bits[start / bitsInWord]) 258 return ((start / bitsInWord) + 1) * bitsInWord; 261 259 return start + 1; 262 260 } … … 289 287 { 290 288 size_t result = 0; 291 for ( ; (start % wordSize); ++start) {289 for ( ; (start % bitsInWord); ++start) { 292 290 if (get(start)) 293 291 ++result; 294 292 } 295 for (size_t i = start / wordSize; i < words; ++i)293 for (size_t i = start / bitsInWord; i < numberOfWords; ++i) 296 294 result += WTF::bitCount(bits[i]); 297 295 return result; … … 301 299 inline bool Bitmap<bitmapSize, WordType>::isEmpty() const 302 300 { 303 for (size_t i = 0; i < words; ++i)301 for (size_t i = 0; i < numberOfWords; ++i) { 304 302 if (bits[i]) 305 303 return false; 304 } 306 305 return true; 307 306 } … … 310 309 inline bool Bitmap<bitmapSize, WordType>::isFull() const 311 310 { 312 for (size_t i = 0; i < words; ++i)311 for (size_t i = 0; i < numberOfWords; ++i) { 313 312 if (~bits[i]) { 314 if constexpr (!!(bitmapSize % wordSize)) {315 if (i == words - 1) {316 constexpr size_t remainingBits = bitmapSize % wordSize;313 if constexpr (!!(bitmapSize % bitsInWord)) { 314 if (i == numberOfWords - 1) { 315 constexpr size_t remainingBits = bitmapSize % bitsInWord; 317 316 constexpr WordType mask = (static_cast<WordType>(1) << remainingBits) - 1; 318 317 if ((bits[i] & mask) == mask) … … 322 321 return false; 323 322 } 323 } 324 324 return true; 325 325 } … … 328 328 inline void Bitmap<bitmapSize, WordType>::merge(const Bitmap& other) 329 329 { 330 for (size_t i = 0; i < words; ++i)330 for (size_t i = 0; i < numberOfWords; ++i) 331 331 bits[i] |= other.bits[i]; 332 332 } … … 335 335 inline void Bitmap<bitmapSize, WordType>::filter(const Bitmap& other) 336 336 { 337 for (size_t i = 0; i < words; ++i)337 for (size_t i = 0; i < numberOfWords; ++i) 338 338 bits[i] &= other.bits[i]; 339 339 } … … 342 342 inline void Bitmap<bitmapSize, WordType>::exclude(const Bitmap& other) 343 343 { 344 for (size_t i = 0; i < words; ++i)344 for (size_t i = 0; i < numberOfWords; ++i) 345 345 bits[i] &= ~other.bits[i]; 346 346 } … … 349 349 inline void Bitmap<bitmapSize, WordType>::concurrentFilter(const Bitmap& other) 350 350 { 351 for (size_t i = 0; i < words; ++i) {351 for (size_t i = 0; i < numberOfWords; ++i) { 352 352 for (;;) { 353 353 WordType otherBits = other.bits[i]; … … 369 369 inline bool Bitmap<bitmapSize, WordType>::subsumes(const Bitmap& other) const 370 370 { 371 for (size_t i = 0; i < words; ++i) {371 for (size_t i = 0; i < numberOfWords; ++i) { 372 372 WordType myBits = bits[i]; 373 373 WordType otherBits = other.bits[i]; … … 382 382 inline void Bitmap<bitmapSize, WordType>::forEachSetBit(const Func& func) const 383 383 { 384 for (size_t i = 0; i < words; ++i) {384 for (size_t i = 0; i < numberOfWords; ++i) { 385 385 WordType word = bits[i]; 386 size_t base = i * wordSize;386 size_t base = i * bitsInWord; 387 387 size_t j = 0; 388 388 for (; word; ++j) { … … 391 391 word >>= 1; 392 392 } 393 ASSERT(j <= wordSize);393 ASSERT(j <= bitsInWord); 394 394 } 395 395 } … … 399 399 { 400 400 WordType skipValue = -(static_cast<WordType>(value) ^ 1); 401 size_t wordIndex = startIndex / wordSize;402 size_t startIndexInWord = startIndex - wordIndex * wordSize;403 404 while (wordIndex < words) {401 size_t wordIndex = startIndex / bitsInWord; 402 size_t startIndexInWord = startIndex - wordIndex * bitsInWord; 403 404 while (wordIndex < numberOfWords) { 405 405 WordType word = bits[wordIndex]; 406 406 if (word != skipValue) { 407 407 size_t index = startIndexInWord; 408 if (findBitInWord(word, index, wordSize, value))409 return wordIndex * wordSize+ index;408 if (findBitInWord(word, index, bitsInWord, value)) 409 return wordIndex * bitsInWord + index; 410 410 } 411 411 … … 420 420 inline void Bitmap<bitmapSize, WordType>::mergeAndClear(Bitmap& other) 421 421 { 422 for (size_t i = 0; i < words; ++i) {422 for (size_t i = 0; i < numberOfWords; ++i) { 423 423 bits[i] |= other.bits[i]; 424 424 other.bits[i] = 0; … … 429 429 inline void Bitmap<bitmapSize, WordType>::setAndClear(Bitmap& other) 430 430 { 431 for (size_t i = 0; i < words; ++i) {431 for (size_t i = 0; i < numberOfWords; ++i) { 432 432 bits[i] = other.bits[i]; 433 433 other.bits[i] = 0; … … 441 441 ASSERT(end <= bitmapSize); 442 442 443 size_t wordIndex = start / wordSize;444 size_t endWordIndex = end / wordSize;445 size_t index = start - wordIndex * wordSize;443 size_t wordIndex = start / bitsInWord; 444 size_t endWordIndex = end / bitsInWord; 445 size_t index = start - wordIndex * bitsInWord; 446 446 while (wordIndex < endWordIndex) { 447 while (index < wordSize) {447 while (index < bitsInWord) { 448 448 bits[wordIndex] |= (one << index); 449 449 index += n; 450 450 } 451 index -= wordSize;451 index -= bitsInWord; 452 452 wordIndex++; 453 453 } 454 454 455 size_t endIndex = end - endWordIndex * wordSize;455 size_t endIndex = end - endWordIndex * bitsInWord; 456 456 while (index < endIndex) { 457 457 bits[wordIndex] |= (one << index); … … 459 459 } 460 460 461 if constexpr (!!(bitmapSize % wordSize)) {462 constexpr size_t remainingBits = bitmapSize % wordSize;461 if constexpr (!!(bitmapSize % bitsInWord)) { 462 constexpr size_t remainingBits = bitmapSize % bitsInWord; 463 463 constexpr WordType mask = (static_cast<WordType>(1) << remainingBits) - 1; 464 bits[ words - 1] &= mask;464 bits[numberOfWords - 1] &= mask; 465 465 } 466 466 } … … 469 469 inline bool Bitmap<bitmapSize, WordType>::operator==(const Bitmap& other) const 470 470 { 471 for (size_t i = 0; i < words; ++i) {471 for (size_t i = 0; i < numberOfWords; ++i) { 472 472 if (bits[i] != other.bits[i]) 473 473 return false; … … 485 485 inline void Bitmap<bitmapSize, WordType>::operator|=(const Bitmap& other) 486 486 { 487 for (size_t i = 0; i < words; ++i)487 for (size_t i = 0; i < numberOfWords; ++i) 488 488 bits[i] |= other.bits[i]; 489 489 } … … 492 492 inline void Bitmap<bitmapSize, WordType>::operator&=(const Bitmap& other) 493 493 { 494 for (size_t i = 0; i < words; ++i)494 for (size_t i = 0; i < numberOfWords; ++i) 495 495 bits[i] &= other.bits[i]; 496 496 } … … 499 499 inline void Bitmap<bitmapSize, WordType>::operator^=(const Bitmap& other) 500 500 { 501 for (size_t i = 0; i < words; ++i)501 for (size_t i = 0; i < numberOfWords; ++i) 502 502 bits[i] ^= other.bits[i]; 503 503 } … … 507 507 { 508 508 unsigned result = 0; 509 for (size_t i = 0; i < words; ++i)509 for (size_t i = 0; i < numberOfWords; ++i) 510 510 result ^= IntHash<WordType>::hash(bits[i]); 511 511 return result;
Note:
See TracChangeset
for help on using the changeset viewer.