[cfe-commits] r69580 - in /cfe/trunk: include/clang/Basic/OnDiskHashTable.h lib/Lex/PTHLexer.cpp tools/clang-cc/CacheTokens.cpp

Douglas Gregor dgregor at apple.com
Mon Apr 20 00:08:21 PDT 2009


Author: dgregor
Date: Mon Apr 20 02:08:21 2009
New Revision: 69580

URL: http://llvm.org/viewvc/llvm-project?rev=69580&view=rev
Log:
Move the on-disk hash table code into its own header. No functionality change.

Added:
    cfe/trunk/include/clang/Basic/OnDiskHashTable.h   (with props)
Modified:
    cfe/trunk/lib/Lex/PTHLexer.cpp
    cfe/trunk/tools/clang-cc/CacheTokens.cpp

Added: cfe/trunk/include/clang/Basic/OnDiskHashTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OnDiskHashTable.h?rev=69580&view=auto

==============================================================================
--- cfe/trunk/include/clang/Basic/OnDiskHashTable.h (added)
+++ cfe/trunk/include/clang/Basic/OnDiskHashTable.h Mon Apr 20 02:08:21 2009
@@ -0,0 +1,343 @@
+//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines facilities for reading and writing on-disk hash
+//  tables.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
+#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Host.h"
+#include <cassert>
+#include <cstdlib>
+
+namespace clang {
+
+// Bernstein hash function:
+// This is basically copy-and-paste from StringMap.  This likely won't
+// stay here, which is why I didn't both to expose this function from
+// String Map.
+inline unsigned BernsteinHash(const char* x) {  
+  unsigned int R = 0;
+  for ( ; *x != '\0' ; ++x) R = R * 33 + *x;
+  return R + (R >> 5);
+}
+
+inline unsigned BernsteinHash(const char* x, unsigned n) {
+  unsigned int R = 0;
+  for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x;
+  return R + (R >> 5);
+}
+
+namespace io {
+
+typedef uint32_t Offset;
+
+inline void Emit8(llvm::raw_ostream& Out, uint32_t V) {
+  Out << (unsigned char)(V);
+}
+
+inline void Emit16(llvm::raw_ostream& Out, uint32_t V) {
+  Out << (unsigned char)(V);
+  Out << (unsigned char)(V >>  8);
+  assert((V >> 16) == 0);
+}
+
+inline void Emit32(llvm::raw_ostream& Out, uint32_t V) {
+  Out << (unsigned char)(V);
+  Out << (unsigned char)(V >>  8);
+  Out << (unsigned char)(V >> 16);
+  Out << (unsigned char)(V >> 24);
+}
+
+inline void Emit64(llvm::raw_ostream& Out, uint64_t V) {
+  Out << (unsigned char)(V);
+  Out << (unsigned char)(V >>  8);
+  Out << (unsigned char)(V >> 16);
+  Out << (unsigned char)(V >> 24);
+  Out << (unsigned char)(V >> 32);
+  Out << (unsigned char)(V >> 40);
+  Out << (unsigned char)(V >> 48);
+  Out << (unsigned char)(V >> 56);
+}
+
+inline void Pad(llvm::raw_fd_ostream& Out, unsigned A) {
+  Offset off = (Offset) Out.tell();
+  uint32_t n = ((uintptr_t)(off+A-1) & ~(uintptr_t)(A-1)) - off;
+  for (; n ; --n)
+    Emit8(Out, 0);
+}
+
+inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) {
+  uint16_t V = ((uint16_t)Data[0]) |
+               ((uint16_t)Data[1] <<  8);
+  Data += 2;
+  return V;
+}
+
+inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) {
+  uint32_t V = ((uint32_t)Data[0])  |
+               ((uint32_t)Data[1] << 8)  |
+               ((uint32_t)Data[2] << 16) |
+               ((uint32_t)Data[3] << 24);
+  Data += 4;
+  return V;
+}
+
+inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) {
+  uint64_t V = ((uint64_t)Data[0])  |
+    ((uint64_t)Data[1] << 8)  |
+    ((uint64_t)Data[2] << 16) |
+    ((uint64_t)Data[3] << 24) |
+    ((uint64_t)Data[4] << 32) |
+    ((uint64_t)Data[5] << 40) |
+    ((uint64_t)Data[6] << 48) |
+    ((uint64_t)Data[7] << 56);
+  Data += 8;
+  return V;
+}
+
+inline uint32_t ReadLE32(const unsigned char *&Data) {
+  // Hosts that directly support little-endian 32-bit loads can just
+  // use them.  Big-endian hosts need a bswap.
+  uint32_t V = *((uint32_t*)Data);
+  if (llvm::sys::isBigEndianHost())
+    V = llvm::ByteSwap_32(V);
+  Data += 4;
+  return V;
+}
+
+} // end namespace io
+
+template<typename Info>
+class OnDiskChainedHashTableGenerator {
+  unsigned NumBuckets;
+  unsigned NumEntries;
+  llvm::BumpPtrAllocator BA;
+  
+  class Item {
+  public:
+    typename Info::key_type key;
+    typename Info::data_type data;
+    Item *next;
+    const uint32_t hash;
+    
+    Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
+    : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
+  };
+  
+  class Bucket { 
+  public:
+    io::Offset off;
+    Item*  head;
+    unsigned length;
+    
+    Bucket() {}
+  };
+  
+  Bucket* Buckets;
+  
+private:
+  void insert(Bucket* b, size_t size, Item* E) {
+    unsigned idx = E->hash & (size - 1);
+    Bucket& B = b[idx];
+    E->next = B.head;
+    ++B.length;
+    B.head = E;
+  }
+  
+  void resize(size_t newsize) {
+    Bucket* newBuckets = (Bucket*) std::calloc(newsize, sizeof(Bucket));
+    // Populate newBuckets with the old entries.
+    for (unsigned i = 0; i < NumBuckets; ++i)
+      for (Item* E = Buckets[i].head; E ; ) {
+        Item* N = E->next;
+        E->next = 0;
+        insert(newBuckets, newsize, E);
+        E = N;
+      }
+    
+    free(Buckets);
+    NumBuckets = newsize;
+    Buckets = newBuckets;
+  }  
+  
+public:
+  
+  void insert(typename Info::key_type_ref key,
+              typename Info::data_type_ref data) {
+
+    ++NumEntries;
+    if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
+    insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data));
+  }
+  
+  io::Offset Emit(llvm::raw_fd_ostream& out) {
+    using namespace clang::io;
+
+    // Emit the payload of the table.
+    for (unsigned i = 0; i < NumBuckets; ++i) {
+      Bucket& B = Buckets[i];
+      if (!B.head) continue;
+      
+      // Store the offset for the data of this bucket.
+      // FIXME: need tell() to work on other raw ostreams
+      B.off = out.tell();
+      
+      // Write out the number of items in the bucket.
+      Emit16(out, B.length);
+      
+      // Write out the entries in the bucket.
+      for (Item *I = B.head; I ; I = I->next) {
+        Emit32(out, I->hash);
+        const std::pair<unsigned, unsigned>& Len = 
+          Info::EmitKeyDataLength(out, I->key, I->data);
+        Info::EmitKey(out, I->key, Len.first);
+        Info::EmitData(out, I->key, I->data, Len.second);
+      }
+    }
+    
+    // Emit the hashtable itself.
+    Pad(out, 4);
+    io::Offset TableOff = out.tell();
+    Emit32(out, NumBuckets);
+    Emit32(out, NumEntries);
+    for (unsigned i = 0; i < NumBuckets; ++i) Emit32(out, Buckets[i].off);
+    
+    return TableOff;
+  }
+  
+  OnDiskChainedHashTableGenerator() {
+    NumEntries = 0;
+    NumBuckets = 64;    
+    // Note that we do not need to run the constructors of the individual
+    // Bucket objects since 'calloc' returns bytes that are all 0.
+    Buckets = (Bucket*) std::calloc(NumBuckets, sizeof(Bucket));
+  }
+  
+  ~OnDiskChainedHashTableGenerator() {
+    std::free(Buckets);
+  }
+};
+
+template<typename Info>
+class OnDiskChainedHashTable {
+  const unsigned NumBuckets;
+  const unsigned NumEntries;
+  const unsigned char* const Buckets;
+  const unsigned char* const Base;
+public:
+  typedef typename Info::internal_key_type internal_key_type;
+  typedef typename Info::external_key_type external_key_type;
+  typedef typename Info::data_type         data_type;
+  
+  OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries,
+                         const unsigned char* buckets,
+                         const unsigned char* base)
+    : NumBuckets(numBuckets), NumEntries(numEntries),
+      Buckets(buckets), Base(base) {        
+        assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
+               "'buckets' must have a 4-byte alignment");
+      }
+
+  unsigned getNumBuckets() const { return NumBuckets; }
+  unsigned getNumEntries() const { return NumEntries; }
+  const unsigned char* getBase() const { return Base; }
+  const unsigned char* getBuckets() const { return Buckets; }
+
+  bool isEmpty() const { return NumEntries == 0; }
+  
+  class iterator {
+    internal_key_type key;
+    const unsigned char* const data;
+    const unsigned len;
+  public:
+    iterator() : data(0), len(0) {}
+    iterator(const internal_key_type k, const unsigned char* d, unsigned l)
+      : key(k), data(d), len(l) {}
+    
+    data_type operator*() const { return Info::ReadData(key, data, len); }    
+    bool operator==(const iterator& X) const { return X.data == data; }    
+    bool operator!=(const iterator& X) const { return X.data != data; }
+  };    
+  
+  iterator find(const external_key_type& eKey) {
+    using namespace io;
+    const internal_key_type& iKey = Info::GetInternalKey(eKey);
+    unsigned key_hash = Info::ComputeHash(iKey);
+    
+    // Each bucket is just a 32-bit offset into the PTH file.
+    unsigned idx = key_hash & (NumBuckets - 1);
+    const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx;
+    
+    unsigned offset = ReadLE32(Bucket);
+    if (offset == 0) return iterator(); // Empty bucket.
+    const unsigned char* Items = Base + offset;
+    
+    // 'Items' starts with a 16-bit unsigned integer representing the
+    // number of items in this bucket.
+    unsigned len = ReadUnalignedLE16(Items);
+    
+    for (unsigned i = 0; i < len; ++i) {
+      // Read the hash.
+      uint32_t item_hash = ReadUnalignedLE32(Items);
+      
+      // Determine the length of the key and the data.
+      const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items);      
+      unsigned item_len = L.first + L.second;
+
+      // Compare the hashes.  If they are not the same, skip the entry entirely.
+      if (item_hash != key_hash) {
+        Items += item_len;
+        continue;
+      }
+      
+      // Read the key.
+      const internal_key_type& X =
+        Info::ReadKey((const unsigned char* const) Items, L.first);
+
+      // If the key doesn't match just skip reading the value.
+      if (!Info::EqualKey(X, iKey)) {
+        Items += item_len;
+        continue;
+      }
+      
+      // The key matches!
+      return iterator(X, Items + L.first, L.second);
+    }
+    
+    return iterator();
+  }
+  
+  iterator end() const { return iterator(); }
+  
+  
+  static OnDiskChainedHashTable* Create(const unsigned char* buckets,
+                                        const unsigned char* const base) {
+    using namespace io;
+    assert(buckets > base);
+    assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
+           "buckets should be 4-byte aligned.");
+    
+    unsigned numBuckets = ReadLE32(buckets);
+    unsigned numEntries = ReadLE32(buckets);
+    return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets,
+                                            base);
+  }  
+};
+
+} // end namespace clang
+
+#endif 

Propchange: cfe/trunk/include/clang/Basic/OnDiskHashTable.h

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/include/clang/Basic/OnDiskHashTable.h

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/include/clang/Basic/OnDiskHashTable.h

------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/lib/Lex/PTHLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PTHLexer.cpp?rev=69580&r1=69579&r2=69580&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/PTHLexer.cpp (original)
+++ cfe/trunk/lib/Lex/PTHLexer.cpp Mon Apr 20 02:08:21 2009
@@ -14,6 +14,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/OnDiskHashTable.h"
 #include "clang/Lex/PTHLexer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PTHManager.h"
@@ -21,75 +22,14 @@
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/OwningPtr.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/System/Host.h"
 #include <sys/stat.h>
 using namespace clang;
+using namespace clang::io;
 
 #define DISK_TOKEN_SIZE (1+1+2+4+4)
 
 //===----------------------------------------------------------------------===//
-// Utility methods for reading from the mmap'ed PTH file.
-//===----------------------------------------------------------------------===//
-
-static inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) {
-  uint16_t V = ((uint16_t)Data[0]) |
-               ((uint16_t)Data[1] <<  8);
-  Data += 2;
-  return V;
-}
-
-static inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) {
-  uint32_t V = ((uint32_t)Data[0])  |
-               ((uint32_t)Data[1] << 8)  |
-               ((uint32_t)Data[2] << 16) |
-               ((uint32_t)Data[3] << 24);
-  Data += 4;
-  return V;
-}
-
-static inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) {
-  uint64_t V = ((uint64_t)Data[0])  |
-    ((uint64_t)Data[1] << 8)  |
-    ((uint64_t)Data[2] << 16) |
-    ((uint64_t)Data[3] << 24) |
-    ((uint64_t)Data[4] << 32) |
-    ((uint64_t)Data[5] << 40) |
-    ((uint64_t)Data[6] << 48) |
-    ((uint64_t)Data[7] << 56);
-  Data += 8;
-  return V;
-}
-
-static inline uint32_t ReadLE32(const unsigned char *&Data) {
-  // Hosts that directly support little-endian 32-bit loads can just
-  // use them.  Big-endian hosts need a bswap.
-  uint32_t V = *((uint32_t*)Data);
-  if (llvm::sys::isBigEndianHost())
-    V = llvm::ByteSwap_32(V);
-  Data += 4;
-  return V;
-}
-
-// Bernstein hash function:
-// This is basically copy-and-paste from StringMap.  This likely won't
-// stay here, which is why I didn't both to expose this function from
-// String Map.
-static unsigned BernsteinHash(const char* x) {
-  unsigned int R = 0;
-  for ( ; *x != '\0' ; ++x) R = R * 33 + *x;
-  return R + (R >> 5);
-}
-
-static unsigned BernsteinHash(const char* x, unsigned n) {
-  unsigned int R = 0;
-  for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x;
-  return R + (R >> 5);
-}
-
-//===----------------------------------------------------------------------===//
 // PTHLexer methods.
 //===----------------------------------------------------------------------===//
 
@@ -344,115 +284,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// OnDiskChainedHashTable
-//===----------------------------------------------------------------------===//
-
-template<typename Info>
-class OnDiskChainedHashTable {
-  const unsigned NumBuckets;
-  const unsigned NumEntries;
-  const unsigned char* const Buckets;
-  const unsigned char* const Base;
-public:
-  typedef typename Info::internal_key_type internal_key_type;
-  typedef typename Info::external_key_type external_key_type;
-  typedef typename Info::data_type         data_type;
-  
-  OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries,
-                         const unsigned char* buckets,
-                         const unsigned char* base)
-    : NumBuckets(numBuckets), NumEntries(numEntries),
-      Buckets(buckets), Base(base) {        
-        assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
-               "'buckets' must have a 4-byte alignment");
-      }
-
-  unsigned getNumBuckets() const { return NumBuckets; }
-  unsigned getNumEntries() const { return NumEntries; }
-  const unsigned char* getBase() const { return Base; }
-  const unsigned char* getBuckets() const { return Buckets; }
-
-  bool isEmpty() const { return NumEntries == 0; }
-  
-  class iterator {
-    internal_key_type key;
-    const unsigned char* const data;
-    const unsigned len;
-  public:
-    iterator() : data(0), len(0) {}
-    iterator(const internal_key_type k, const unsigned char* d, unsigned l)
-      : key(k), data(d), len(l) {}
-    
-    data_type operator*() const { return Info::ReadData(key, data, len); }    
-    bool operator==(const iterator& X) const { return X.data == data; }    
-    bool operator!=(const iterator& X) const { return X.data != data; }
-  };    
-  
-  iterator find(const external_key_type& eKey) {
-    const internal_key_type& iKey = Info::GetInternalKey(eKey);
-    unsigned key_hash = Info::ComputeHash(iKey);
-    
-    // Each bucket is just a 32-bit offset into the PTH file.
-    unsigned idx = key_hash & (NumBuckets - 1);
-    const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx;
-    
-    unsigned offset = ReadLE32(Bucket);
-    if (offset == 0) return iterator(); // Empty bucket.
-    const unsigned char* Items = Base + offset;
-    
-    // 'Items' starts with a 16-bit unsigned integer representing the
-    // number of items in this bucket.
-    unsigned len = ReadUnalignedLE16(Items);
-    
-    for (unsigned i = 0; i < len; ++i) {
-      // Read the hash.
-      uint32_t item_hash = ReadUnalignedLE32(Items);
-      
-      // Determine the length of the key and the data.
-      const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items);      
-      unsigned item_len = L.first + L.second;
-
-      // Compare the hashes.  If they are not the same, skip the entry entirely.
-      if (item_hash != key_hash) {
-        Items += item_len;
-        continue;
-      }
-      
-      // Read the key.
-      const internal_key_type& X =
-        Info::ReadKey((const unsigned char* const) Items, L.first);
-
-      // If the key doesn't match just skip reading the value.
-      if (!Info::EqualKey(X, iKey)) {
-        Items += item_len;
-        continue;
-      }
-      
-      // The key matches!
-      return iterator(X, Items + L.first, L.second);
-    }
-    
-    return iterator();
-  }
-  
-  iterator end() const { return iterator(); }
-  
-  
-  static OnDiskChainedHashTable* Create(const unsigned char* buckets,
-                                        const unsigned char* const base) {
-
-    assert(buckets > base);
-    assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
-           "buckets should be 4-byte aligned.");
-    
-    unsigned numBuckets = ReadLE32(buckets);
-    unsigned numEntries = ReadLE32(buckets);
-    return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets,
-                                            base);
-  }  
-};
-
-//===----------------------------------------------------------------------===//
 // PTH file lookup: map from strings to file data.
 //===----------------------------------------------------------------------===//
 

Modified: cfe/trunk/tools/clang-cc/CacheTokens.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/CacheTokens.cpp?rev=69580&r1=69579&r2=69580&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/CacheTokens.cpp (original)
+++ cfe/trunk/tools/clang-cc/CacheTokens.cpp Mon Apr 20 02:08:21 2009
@@ -17,6 +17,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/OnDiskHashTable.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/StringMap.h"
@@ -32,166 +33,7 @@
 #endif
 
 using namespace clang;
-
-typedef uint32_t Offset;
-
-static void Emit8(llvm::raw_ostream& Out, uint32_t V) {
-  Out << (unsigned char)(V);
-}
-
-static void Emit16(llvm::raw_ostream& Out, uint32_t V) {
-  Out << (unsigned char)(V);
-  Out << (unsigned char)(V >>  8);
-  assert((V >> 16) == 0);
-}
-
-static void Emit32(llvm::raw_ostream& Out, uint32_t V) {
-  Out << (unsigned char)(V);
-  Out << (unsigned char)(V >>  8);
-  Out << (unsigned char)(V >> 16);
-  Out << (unsigned char)(V >> 24);
-}
-
-static void Emit64(llvm::raw_ostream& Out, uint64_t V) {
-  Out << (unsigned char)(V);
-  Out << (unsigned char)(V >>  8);
-  Out << (unsigned char)(V >> 16);
-  Out << (unsigned char)(V >> 24);
-  Out << (unsigned char)(V >> 32);
-  Out << (unsigned char)(V >> 40);
-  Out << (unsigned char)(V >> 48);
-  Out << (unsigned char)(V >> 56);
-}
-
-static void Pad(llvm::raw_fd_ostream& Out, unsigned A) {
-  Offset off = (Offset) Out.tell();
-  uint32_t n = ((uintptr_t)(off+A-1) & ~(uintptr_t)(A-1)) - off;
-  for (; n ; --n)
-    Emit8(Out, 0);
-}
-
-// Bernstein hash function:
-// This is basically copy-and-paste from StringMap.  This likely won't
-// stay here, which is why I didn't both to expose this function from
-// String Map.
-static unsigned BernsteinHash(const char* x) {  
-  unsigned int R = 0;
-  for ( ; *x != '\0' ; ++x) R = R * 33 + *x;
-  return R + (R >> 5);
-}
-
-//===----------------------------------------------------------------------===//
-// On Disk Hashtable Logic.  This will eventually get refactored and put
-// elsewhere.
-//===----------------------------------------------------------------------===//
-
-template<typename Info>
-class OnDiskChainedHashTableGenerator {
-  unsigned NumBuckets;
-  unsigned NumEntries;
-  llvm::BumpPtrAllocator BA;
-  
-  class Item {
-  public:
-    typename Info::key_type key;
-    typename Info::data_type data;
-    Item *next;
-    const uint32_t hash;
-    
-    Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
-    : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
-  };
-  
-  class Bucket { 
-  public:
-    Offset off;
-    Item*  head;
-    unsigned length;
-    
-    Bucket() {}
-  };
-  
-  Bucket* Buckets;
-  
-private:
-  void insert(Bucket* b, size_t size, Item* E) {
-    unsigned idx = E->hash & (size - 1);
-    Bucket& B = b[idx];
-    E->next = B.head;
-    ++B.length;
-    B.head = E;
-  }
-  
-  void resize(size_t newsize) {
-    Bucket* newBuckets = (Bucket*) calloc(newsize, sizeof(Bucket));
-    // Populate newBuckets with the old entries.
-    for (unsigned i = 0; i < NumBuckets; ++i)
-      for (Item* E = Buckets[i].head; E ; ) {
-        Item* N = E->next;
-        E->next = 0;
-        insert(newBuckets, newsize, E);
-        E = N;
-      }
-    
-    free(Buckets);
-    NumBuckets = newsize;
-    Buckets = newBuckets;
-  }  
-  
-public:
-  
-  void insert(typename Info::key_type_ref key,
-              typename Info::data_type_ref data) {
-
-    ++NumEntries;
-    if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
-    insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data));
-  }
-  
-  Offset Emit(llvm::raw_fd_ostream& out) {
-    // Emit the payload of the table.
-    for (unsigned i = 0; i < NumBuckets; ++i) {
-      Bucket& B = Buckets[i];
-      if (!B.head) continue;
-      
-      // Store the offset for the data of this bucket.
-      B.off = out.tell();
-      
-      // Write out the number of items in the bucket.
-      Emit16(out, B.length);
-      
-      // Write out the entries in the bucket.
-      for (Item *I = B.head; I ; I = I->next) {
-        Emit32(out, I->hash);
-        const std::pair<unsigned, unsigned>& Len = 
-          Info::EmitKeyDataLength(out, I->key, I->data);
-        Info::EmitKey(out, I->key, Len.first);
-        Info::EmitData(out, I->key, I->data, Len.second);
-      }
-    }
-    
-    // Emit the hashtable itself.
-    Pad(out, 4);
-    Offset TableOff = out.tell();
-    Emit32(out, NumBuckets);
-    Emit32(out, NumEntries);
-    for (unsigned i = 0; i < NumBuckets; ++i) Emit32(out, Buckets[i].off);
-    
-    return TableOff;
-  }
-  
-  OnDiskChainedHashTableGenerator() {
-    NumEntries = 0;
-    NumBuckets = 64;    
-    // Note that we do not need to run the constructors of the individual
-    // Bucket objects since 'calloc' returns bytes that are all 0.
-    Buckets = (Bucket*) calloc(NumBuckets, sizeof(Bucket));
-  }
-  
-  ~OnDiskChainedHashTableGenerator() {
-    free(Buckets);
-  }
-};
+using namespace clang::io;
 
 //===----------------------------------------------------------------------===//
 // PTH-specific stuff.





More information about the cfe-commits mailing list