1 //===-- UsuallyTinyPtrVector.h - Pointer vector class -----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the UsuallyTinyPtrVector class, which is a vector that
11 // optimizes the case where there is only one element.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
16 #define LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
22 /// \brief A vector class template that is optimized for storing a single
25 class UsuallyTinyPtrVector {
26 /// \brief Storage for the vector.
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;
32 typedef std::vector<T*> vector_type;
35 UsuallyTinyPtrVector() : Storage(0) { }
36 explicit UsuallyTinyPtrVector(T *Element)
37 : Storage(reinterpret_cast<uintptr_t>(Element)) { }
39 bool empty() const { return !Storage; }
41 typedef const T **iterator;
42 iterator begin() const;
46 void push_back(T *Method);
51 typename UsuallyTinyPtrVector<T>::iterator
52 UsuallyTinyPtrVector<T>::begin() const {
53 if ((Storage & 0x01) == 0)
54 return reinterpret_cast<iterator>(&Storage);
56 vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
61 typename UsuallyTinyPtrVector<T>::iterator
62 UsuallyTinyPtrVector<T>::end() const {
63 if ((Storage & 0x01) == 0) {
65 return reinterpret_cast<iterator>(&Storage);
67 return reinterpret_cast<iterator>(&Storage) + 1;
70 vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
71 return &Vec->front() + Vec->size();
75 size_t UsuallyTinyPtrVector<T>::size() const {
76 if ((Storage & 0x01) == 0)
77 return (Storage == 0) ? 0 : 1;
79 vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
84 void UsuallyTinyPtrVector<T>::push_back(T *Element) {
87 Storage = reinterpret_cast<uintptr_t>(Element);
92 if ((Storage & 0x01) == 0) {
93 // 1 -> 2 elements. Allocate a new vector and push the element into that
95 Vec = new vector_type;
96 Vec->push_back(reinterpret_cast<T *>(Storage));
97 Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01;
99 Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
101 // Add the new element to the vector.
102 Vec->push_back(Element);
106 void UsuallyTinyPtrVector<T>::Destroy() {
108 delete reinterpret_cast<vector_type *>(Storage & ~0x01);