Home | History | Annotate | Download | only in AST
      1 //===-- UsuallyTinyPtrVector.h - Pointer vector class -----------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file defines the UsuallyTinyPtrVector class, which is a vector that
     11 //  optimizes the case where there is only one element.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
     16 #define LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
     17 
     18 #include <vector>
     19 
     20 namespace clang {
     21 
     22 /// \brief A vector class template that is optimized for storing a single
     23 /// pointer element.
     24 template<typename T>
     25 class UsuallyTinyPtrVector {
     26   /// \brief Storage for the vector.
     27   ///
     28   /// When the low bit is zero, this is a T *. When the
     29   /// low bit is one, this is a std::vector<T *> *.
     30   mutable uintptr_t Storage;
     31 
     32   typedef std::vector<T*> vector_type;
     33 
     34 public:
     35   UsuallyTinyPtrVector() : Storage(0) { }
     36   explicit UsuallyTinyPtrVector(T *Element)
     37     : Storage(reinterpret_cast<uintptr_t>(Element)) { }
     38 
     39   bool empty() const { return !Storage; }
     40 
     41   typedef const T **iterator;
     42   iterator begin() const;
     43   iterator end() const;
     44   size_t size() const;
     45 
     46   void push_back(T *Method);
     47   void Destroy();
     48 };
     49 
     50 template<typename T>
     51 typename UsuallyTinyPtrVector<T>::iterator
     52 UsuallyTinyPtrVector<T>::begin() const {
     53   if ((Storage & 0x01) == 0)
     54     return reinterpret_cast<iterator>(&Storage);
     55 
     56   vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
     57   return &Vec->front();
     58 }
     59 
     60 template<typename T>
     61 typename UsuallyTinyPtrVector<T>::iterator
     62 UsuallyTinyPtrVector<T>::end() const {
     63   if ((Storage & 0x01) == 0) {
     64     if (Storage == 0)
     65       return reinterpret_cast<iterator>(&Storage);
     66 
     67     return reinterpret_cast<iterator>(&Storage) + 1;
     68   }
     69 
     70   vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
     71   return &Vec->front() + Vec->size();
     72 }
     73 
     74 template<typename T>
     75 size_t UsuallyTinyPtrVector<T>::size() const {
     76   if ((Storage & 0x01) == 0)
     77     return (Storage == 0) ? 0 : 1;
     78 
     79   vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
     80   return Vec->size();
     81 }
     82 
     83 template<typename T>
     84 void UsuallyTinyPtrVector<T>::push_back(T *Element) {
     85   if (Storage == 0) {
     86     // 0 -> 1 element.
     87     Storage = reinterpret_cast<uintptr_t>(Element);
     88     return;
     89   }
     90 
     91   vector_type *Vec;
     92   if ((Storage & 0x01) == 0) {
     93     // 1 -> 2 elements. Allocate a new vector and push the element into that
     94     // vector.
     95     Vec = new vector_type;
     96     Vec->push_back(reinterpret_cast<T *>(Storage));
     97     Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01;
     98   } else
     99     Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
    100 
    101   // Add the new element to the vector.
    102   Vec->push_back(Element);
    103 }
    104 
    105 template<typename T>
    106 void UsuallyTinyPtrVector<T>::Destroy() {
    107   if (Storage & 0x01)
    108     delete reinterpret_cast<vector_type *>(Storage & ~0x01);
    109 
    110   Storage = 0;
    111 }
    112 
    113 }
    114 #endif
    115