Home | History | Annotate | Download | only in vm
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Implementation of an expandable bit vector.
     19  */
     20 #include "Dalvik.h"
     21 
     22 #include <stdlib.h>
     23 #include <strings.h>
     24 
     25 #define kBitVectorGrowth    4   /* increase by 4 u4s when limit hit */
     26 
     27 
     28 /*
     29  * Allocate a bit vector with enough space to hold at least the specified
     30  * number of bits.
     31  */
     32 BitVector* dvmAllocBitVector(unsigned int startBits, bool expandable)
     33 {
     34     BitVector* bv;
     35     unsigned int count;
     36 
     37     assert(sizeof(bv->storage[0]) == 4);        /* assuming 32-bit units */
     38 
     39     bv = (BitVector*) malloc(sizeof(BitVector));
     40 
     41     count = (startBits + 31) >> 5;
     42 
     43     bv->storageSize = count;
     44     bv->expandable = expandable;
     45     bv->storage = (u4*) malloc(count * sizeof(u4));
     46     memset(bv->storage, 0x00, count * sizeof(u4));
     47     return bv;
     48 }
     49 
     50 /*
     51  * Free a BitVector.
     52  */
     53 void dvmFreeBitVector(BitVector* pBits)
     54 {
     55     if (pBits == NULL)
     56         return;
     57 
     58     free(pBits->storage);
     59     free(pBits);
     60 }
     61 
     62 /*
     63  * "Allocate" the first-available bit in the bitmap.
     64  *
     65  * This is not synchronized.  The caller is expected to hold some sort of
     66  * lock that prevents multiple threads from executing simultaneously in
     67  * dvmAllocBit/dvmFreeBit.
     68  */
     69 int dvmAllocBit(BitVector* pBits)
     70 {
     71     unsigned int word, bit;
     72 
     73 retry:
     74     for (word = 0; word < pBits->storageSize; word++) {
     75         if (pBits->storage[word] != 0xffffffff) {
     76             /*
     77              * There are unallocated bits in this word.  Return the first.
     78              */
     79             bit = ffs(~(pBits->storage[word])) -1;
     80             assert(bit < 32);
     81             pBits->storage[word] |= 1 << bit;
     82             return (word << 5) | bit;
     83         }
     84     }
     85 
     86     /*
     87      * Ran out of space, allocate more if we're allowed to.
     88      */
     89     if (!pBits->expandable)
     90         return -1;
     91 
     92     pBits->storage = (u4*)realloc(pBits->storage,
     93                     (pBits->storageSize + kBitVectorGrowth) * sizeof(u4));
     94     memset(&pBits->storage[pBits->storageSize], 0x00,
     95         kBitVectorGrowth * sizeof(u4));
     96     pBits->storageSize += kBitVectorGrowth;
     97     goto retry;
     98 }
     99 
    100 /*
    101  * Mark the specified bit as "set".
    102  */
    103 void dvmSetBit(BitVector* pBits, unsigned int num)
    104 {
    105     if (num >= pBits->storageSize * sizeof(u4) * 8) {
    106         if (!pBits->expandable) {
    107             LOGE("Attempt to set bit outside valid range (%d, limit is %d)",
    108                 num, pBits->storageSize * sizeof(u4) * 8);
    109             dvmAbort();
    110         }
    111 
    112         /* Round up to word boundaries for "num+1" bits */
    113         unsigned int newSize = (num + 1 + 31) >> 5;
    114         assert(newSize > pBits->storageSize);
    115         pBits->storage = (u4*)realloc(pBits->storage, newSize * sizeof(u4));
    116         if (pBits->storage == NULL) {
    117             LOGE("BitVector expansion to %d failed", newSize * sizeof(u4));
    118             dvmAbort();
    119         }
    120         memset(&pBits->storage[pBits->storageSize], 0x00,
    121             (newSize - pBits->storageSize) * sizeof(u4));
    122         pBits->storageSize = newSize;
    123     }
    124 
    125     pBits->storage[num >> 5] |= 1 << (num & 0x1f);
    126 }
    127 
    128 /*
    129  * Mark the specified bit as "clear".
    130  */
    131 void dvmClearBit(BitVector* pBits, unsigned int num)
    132 {
    133     assert(num < pBits->storageSize * sizeof(u4) * 8);
    134 
    135     pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
    136 }
    137 
    138 /*
    139  * Mark all bits bit as "clear".
    140  */
    141 void dvmClearAllBits(BitVector* pBits)
    142 {
    143     unsigned int count = pBits->storageSize;
    144     memset(pBits->storage, 0, count * sizeof(u4));
    145 }
    146 
    147 /*
    148  * Mark specified number of bits as "set". Cannot set all bits like ClearAll
    149  * since there might be unused bits - setting those to one will confuse the
    150  * iterator.
    151  */
    152 void dvmSetInitialBits(BitVector* pBits, unsigned int numBits)
    153 {
    154     unsigned int idx;
    155     assert(((numBits + 31) >> 5) <= pBits->storageSize);
    156     for (idx = 0; idx < (numBits >> 5); idx++) {
    157         pBits->storage[idx] = -1;
    158     }
    159     unsigned int remNumBits = numBits & 0x1f;
    160     if (remNumBits) {
    161         pBits->storage[idx] = (1 << remNumBits) - 1;
    162     }
    163 }
    164 
    165 /*
    166  * Determine whether or not the specified bit is set.
    167  */
    168 bool dvmIsBitSet(const BitVector* pBits, unsigned int num)
    169 {
    170     assert(num < pBits->storageSize * sizeof(u4) * 8);
    171 
    172     unsigned int val = pBits->storage[num >> 5] & (1 << (num & 0x1f));
    173     return (val != 0);
    174 }
    175 
    176 /*
    177  * Count the number of bits that are set.
    178  */
    179 int dvmCountSetBits(const BitVector* pBits)
    180 {
    181     unsigned int word;
    182     unsigned int count = 0;
    183 
    184     for (word = 0; word < pBits->storageSize; word++) {
    185         u4 val = pBits->storage[word];
    186 
    187         if (val != 0) {
    188             if (val == 0xffffffff) {
    189                 count += 32;
    190             } else {
    191                 /* count the number of '1' bits */
    192                 while (val != 0) {
    193                     val &= val - 1;
    194                     count++;
    195                 }
    196             }
    197         }
    198     }
    199 
    200     return count;
    201 }
    202 
    203 /*
    204  * If the vector sizes don't match, log an error and abort.
    205  */
    206 static void checkSizes(const BitVector* bv1, const BitVector* bv2)
    207 {
    208     if (bv1->storageSize != bv2->storageSize) {
    209         LOGE("Mismatched vector sizes (%d, %d)",
    210             bv1->storageSize, bv2->storageSize);
    211         dvmAbort();
    212     }
    213 }
    214 
    215 /*
    216  * Copy a whole vector to the other. Only do that when the both vectors have
    217  * the same size.
    218  */
    219 void dvmCopyBitVector(BitVector *dest, const BitVector *src)
    220 {
    221     /* if dest is expandable and < src, we could expand dest to match */
    222     checkSizes(dest, src);
    223 
    224     memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
    225 }
    226 
    227 /*
    228  * Intersect two bit vectors and store the result to the dest vector.
    229  */
    230 bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
    231                             const BitVector *src2)
    232 {
    233     if (dest->storageSize != src1->storageSize ||
    234         dest->storageSize != src2->storageSize ||
    235         dest->expandable != src1->expandable ||
    236         dest->expandable != src2->expandable)
    237         return false;
    238 
    239     unsigned int idx;
    240     for (idx = 0; idx < dest->storageSize; idx++) {
    241         dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
    242     }
    243     return true;
    244 }
    245 
    246 /*
    247  * Unify two bit vectors and store the result to the dest vector.
    248  */
    249 bool dvmUnifyBitVectors(BitVector *dest, const BitVector *src1,
    250                         const BitVector *src2)
    251 {
    252     if (dest->storageSize != src1->storageSize ||
    253         dest->storageSize != src2->storageSize ||
    254         dest->expandable != src1->expandable ||
    255         dest->expandable != src2->expandable)
    256         return false;
    257 
    258     unsigned int idx;
    259     for (idx = 0; idx < dest->storageSize; idx++) {
    260         dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
    261     }
    262     return true;
    263 }
    264 
    265 /*
    266  * Compare two bit vectors and return true if difference is seen.
    267  */
    268 bool dvmCompareBitVectors(const BitVector *src1, const BitVector *src2)
    269 {
    270     if (src1->storageSize != src2->storageSize ||
    271         src1->expandable != src2->expandable)
    272         return true;
    273 
    274     unsigned int idx;
    275     for (idx = 0; idx < src1->storageSize; idx++) {
    276         if (src1->storage[idx] != src2->storage[idx]) return true;
    277     }
    278     return false;
    279 }
    280 
    281 /* Initialize the iterator structure */
    282 void dvmBitVectorIteratorInit(BitVector* pBits, BitVectorIterator* iterator)
    283 {
    284     iterator->pBits = pBits;
    285     iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
    286     iterator->idx = 0;
    287 }
    288 
    289 /* Return the next position set to 1. -1 means end-of-element reached */
    290 int dvmBitVectorIteratorNext(BitVectorIterator* iterator)
    291 {
    292     const BitVector* pBits = iterator->pBits;
    293     u4 bitIndex = iterator->idx;
    294 
    295     assert(iterator->bitSize == pBits->storageSize * sizeof(u4) * 8);
    296     if (bitIndex >= iterator->bitSize) return -1;
    297 
    298     for (; bitIndex < iterator->bitSize; bitIndex++) {
    299         unsigned int wordIndex = bitIndex >> 5;
    300         unsigned int mask = 1 << (bitIndex & 0x1f);
    301         if (pBits->storage[wordIndex] & mask) {
    302             iterator->idx = bitIndex+1;
    303             return bitIndex;
    304         }
    305     }
    306     /* No more set bits */
    307     return -1;
    308 }
    309 
    310 
    311 /*
    312  * Merge the contents of "src" into "dst", checking to see if this causes
    313  * any changes to occur.  This is a logical OR.
    314  *
    315  * Returns "true" if the contents of the destination vector were modified.
    316  */
    317 bool dvmCheckMergeBitVectors(BitVector* dst, const BitVector* src)
    318 {
    319     bool changed = false;
    320 
    321     checkSizes(dst, src);
    322 
    323     unsigned int idx;
    324     for (idx = 0; idx < dst->storageSize; idx++) {
    325         u4 merged = src->storage[idx] | dst->storage[idx];
    326         if (dst->storage[idx] != merged) {
    327             dst->storage[idx] = merged;
    328             changed = true;
    329         }
    330     }
    331 
    332     return changed;
    333 }
    334