namespace clang {
struct LangOptions;
class IdentifierInfo;
+ class IdentifierTable;
class SourceLocation;
class MultiKeywordSelector; // private class used by Selector
class DeclarationName; // AST class that stores declaration names
bool IsExtension : 1; // True if identifier is a lang extension.
bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
- bool IndirectString : 1; // True if the string is stored indirectly.
// 9 bits left in 32-bit word.
void *FETokenInfo; // Managed by the language front-end.
+ llvm::StringMapEntry<IdentifierInfo*> *Entry;
+
IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE.
void operator=(const IdentifierInfo&); // NONASSIGNABLE.
+
+ friend class IdentifierTable;
+
public:
- IdentifierInfo(bool usesIndirectString = false);
+ IdentifierInfo();
+
/// isStr - Return true if this is the identifier for the specified string.
/// This is intended to be used for string literals only: II->isStr("foo").
template <std::size_t StrLen>
/// getName - Return the actual string for this identifier. The returned
/// string is properly null terminated.
///
- const char *getName() const {
- if (IndirectString) {
- // The 'this' pointer really points to a
- // std::pair<IdentifierInfo, const char*>, where internal pointer
- // points to the external string data.
- return ((std::pair<IdentifierInfo, const char*>*) this)->second + 4;
- }
-
- // We know that this is embedded into a StringMapEntry, and it knows how to
- // efficiently find the string.
- return llvm::StringMapEntry<IdentifierInfo>::
- GetStringMapEntryFromValue(*this).getKeyData();
+ const char *getName() const {
+ if (Entry) return Entry->getKeyData();
+ // The 'this' pointer really points to a
+ // std::pair<IdentifierInfo, const char*>, where internal pointer
+ // points to the external string data.
+ return ((std::pair<IdentifierInfo, const char*>*) this)->second + 4;
}
/// getLength - Efficiently return the length of this identifier info.
///
unsigned getLength() const {
- if (IndirectString) {
- // The 'this' pointer really points to a
- // std::pair<IdentifierInfo, const char*>, where internal pointer
- // points to the external string data.
- const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second;
- return ((unsigned) p[0])
- | (((unsigned) p[1]) << 8)
- | (((unsigned) p[2]) << 16)
- | (((unsigned) p[3]) << 24);
- }
-
- return llvm::StringMapEntry<IdentifierInfo>::
- GetStringMapEntryFromValue(*this).getKeyLength();
+ if (Entry) return Entry->getKeyLength();
+ // The 'this' pointer really points to a
+ // std::pair<IdentifierInfo, const char*>, where internal pointer
+ // points to the external string data.
+ const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second;
+ return ((unsigned) p[0])
+ | (((unsigned) p[1]) << 8)
+ | (((unsigned) p[2]) << 16)
+ | (((unsigned) p[3]) << 24);
}
/// hasMacroDefinition - Return true if this identifier is #defined to some
class IdentifierTable {
// Shark shows that using MallocAllocator is *much* slower than using this
// BumpPtrAllocator!
- typedef llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator> HashTableTy;
+ typedef llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator> HashTableTy;
HashTableTy HashTable;
IdentifierInfoLookup* ExternalLookup;
/// get - Return the identifier token info for the specified named identifier.
///
IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
- if (ExternalLookup) {
- IdentifierInfo* II = ExternalLookup->get(NameStart, NameEnd);
- if (II) return *II;
+ llvm::StringMapEntry<IdentifierInfo*> &Entry =
+ HashTable.GetOrCreateValue(NameStart, NameEnd, 0);
+
+ IdentifierInfo *II = Entry.getValue();
+
+ if (!II) {
+ while (1) {
+ if (ExternalLookup) {
+ II = ExternalLookup->get(NameStart, NameEnd);
+ if (II) break;
+ }
+
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+ break;
+ }
+
+ Entry.setValue(II);
+ II->Entry = &Entry;
}
- return HashTable.GetOrCreateValue(NameStart, NameEnd).getValue();
+ assert(II->Entry != 0);
+ return *II;
}
IdentifierInfo &get(const char *Name) {
return get(NameBytes, NameBytes+Name.size());
}
+private:
typedef HashTableTy::const_iterator iterator;
typedef HashTableTy::const_iterator const_iterator;
iterator begin() const { return HashTable.begin(); }
iterator end() const { return HashTable.end(); }
+public:
unsigned size() const { return HashTable.size(); }
// IdentifierInfo Implementation
//===----------------------------------------------------------------------===//
-IdentifierInfo::IdentifierInfo(bool usesIndirectString) {
+IdentifierInfo::IdentifierInfo() {
TokenID = tok::identifier;
ObjCOrBuiltinID = 0;
HasMacro = false;
IsPoisoned = false;
IsCPPOperatorKeyword = false;
FETokenInfo = 0;
- IndirectString = usesIndirectString;
+ Entry = 0;
}
//===----------------------------------------------------------------------===//
unsigned MaxIdentifierLength = 0;
// TODO: Figure out maximum times an identifier had to probe for -stats.
- for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
+ for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
unsigned IdLen = I->getKeyLength();
AverageIdentifierSize += IdLen;
for (iterator I=begin(), E=end(); I != E; ++I) {
const char* Key = I->getKeyData();
- const IdentifierInfo* Info = &I->getValue();
+ const IdentifierInfo* Info = I->getValue();
bool KeyRegistered = S.isRegistered(Key);
bool InfoRegistered = S.isRegistered(Info);
llvm::SerializedPtrID KeyPtrID = D.ReadPtrID();
D.ReadCStr(buff);
+ IdentifierInfo *II = &t->get(&buff[0], &buff[0] + buff.size());
+ II->Read(D);
- llvm::StringMapEntry<IdentifierInfo>& Entry =
- t->HashTable.GetOrCreateValue(&buff[0],&buff[0]+buff.size());
-
- D.Read(Entry.getValue());
-
- if (InfoPtrID)
- D.RegisterRef(InfoPtrID,Entry.getValue());
-
- if (KeyPtrID)
- D.RegisterPtr(KeyPtrID,Entry.getKeyData());
+ if (InfoPtrID) D.RegisterRef(InfoPtrID, II);
+ if (KeyPtrID) D.RegisterPtr(KeyPtrID, II->getName());
}
return t;