Bitmap.cpp (3233B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "ds/Bitmap.h" 8 9 #include <algorithm> 10 11 #include "js/UniquePtr.h" 12 13 using namespace js; 14 15 SparseBitmap::~SparseBitmap() { 16 for (Data::Range r(data.all()); !r.empty(); r.popFront()) { 17 js_delete(r.front().value()); 18 } 19 } 20 21 size_t SparseBitmap::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) { 22 size_t size = data.shallowSizeOfExcludingThis(mallocSizeOf); 23 for (Data::Range r(data.all()); !r.empty(); r.popFront()) { 24 size += mallocSizeOf(r.front().value()); 25 } 26 return size; 27 } 28 29 SparseBitmap::BitBlock* SparseBitmap::createBlock(Data::AddPtr p, 30 size_t blockId) { 31 MOZ_ASSERT(!p); 32 auto block = js::MakeUnique<BitBlock>(); 33 if (!block || !data.add(p, blockId, block.get())) { 34 return nullptr; 35 } 36 std::fill(block->begin(), block->end(), 0); 37 return block.release(); 38 } 39 40 bool SparseBitmap::getBit(size_t bit) const { 41 size_t word = bit / JS_BITS_PER_WORD; 42 size_t blockWord = blockStartWord(word); 43 44 const BitBlock* block = getBlock(blockWord / WordsInBlock); 45 if (block) { 46 return (*block)[word - blockWord] & bitMask(bit); 47 } 48 return false; 49 } 50 51 bool SparseBitmap::readonlyThreadsafeGetBit(size_t bit) const { 52 size_t word = bit / JS_BITS_PER_WORD; 53 size_t blockWord = blockStartWord(word); 54 55 const BitBlock* block = readonlyThreadsafeGetBlock(blockWord / WordsInBlock); 56 if (block) { 57 return (*block)[word - blockWord] & bitMask(bit); 58 } 59 return false; 60 } 61 62 void SparseBitmap::bitwiseAndWith(const DenseBitmap& other) { 63 for (Data::Enum e(data); !e.empty(); e.popFront()) { 64 BitBlock& block = *e.front().value(); 65 size_t blockWord = e.front().key() * WordsInBlock; 66 bool anySet = false; 67 size_t numWords = wordIntersectCount(blockWord, other); 68 for (size_t i = 0; i < numWords; i++) { 69 block[i] &= other.word(blockWord + i); 70 anySet |= !!block[i]; 71 } 72 if (!anySet) { 73 js_delete(&block); 74 e.removeFront(); 75 } 76 } 77 } 78 79 bool SparseBitmap::bitwiseOrWith(const SparseBitmap& other) { 80 for (Data::Range r(other.data.all()); !r.empty(); r.popFront()) { 81 const BitBlock& otherBlock = *r.front().value(); 82 BitBlock* block = getOrCreateBlock(r.front().key()); 83 if (!block) { 84 return false; 85 } 86 for (size_t i = 0; i < WordsInBlock; i++) { 87 (*block)[i] |= otherBlock[i]; 88 } 89 } 90 91 return true; 92 } 93 94 void SparseBitmap::bitwiseOrInto(DenseBitmap& other) const { 95 for (Data::Range r(data.all()); !r.empty(); r.popFront()) { 96 BitBlock& block = *r.front().value(); 97 size_t blockWord = r.front().key() * WordsInBlock; 98 size_t numWords = wordIntersectCount(blockWord, other); 99 #ifdef DEBUG 100 // Any words out of range in other should be zero in this bitmap. 101 for (size_t i = numWords; i < WordsInBlock; i++) { 102 MOZ_ASSERT(!block[i]); 103 } 104 #endif 105 for (size_t i = 0; i < numWords; i++) { 106 other.word(blockWord + i) |= block[i]; 107 } 108 } 109 }