Use string interning for a very nice speed boost

This commit is contained in:
Hackerpilot 2014-05-18 01:59:02 -07:00
parent 7eb952e0e5
commit ae91019ab4
13 changed files with 184 additions and 101 deletions

View File

@ -21,16 +21,17 @@ module actypes;
import std.algorithm;
import std.array;
import std.container;
import std.stdio;
//import std.stdio;
import std.typecons;
import std.allocator;
import containers.karytree;
import containers.ttree;
import containers.unrolledlist;
import containers.slist;
import std.d.lexer;
import messages;
import string_interning;
/**
* Any special information about a variable declaration symbol.
@ -62,7 +63,7 @@ public:
*/
this(string name)
{
this.name = name;
this.name = name is null ? name : internString(name);
}
/**
@ -72,7 +73,7 @@ public:
*/
this(string name, CompletionKind kind)
{
this.name = name;
this.name = name is null ? name : internString(name);
this.kind = kind;
}
@ -84,16 +85,18 @@ public:
*/
this(string name, CompletionKind kind, ACSymbol* type)
{
this.name = name;
this.name = name is null ? name : internString(name);
this.kind = kind;
this.type = type;
}
int opCmp(ref const ACSymbol other) const
{
if (name < other.name)
// Compare the pointers because the strings have been interned.
// Identical strings MUST have the same address
if (name.ptr < other.name.ptr)
return -1;
if (name > other.name)
if (name.ptr > other.name.ptr)
return 1;
return 0;
}
@ -111,7 +114,7 @@ public:
* Symbols that compose this symbol, such as enum members, class variables,
* methods, etc.
*/
KAryTree!(ACSymbol*, true, "a < b", false) parts;
TTree!(ACSymbol*, true, "a < b", false) parts;
/**
* Symbol's name
@ -275,7 +278,7 @@ struct Scope
size_t endLocation;
/// Symbols contained in this scope
KAryTree!(ACSymbol*, true, "a < b", false) symbols;
TTree!(ACSymbol*, true, "a < b", false) symbols;
}
/**
@ -297,33 +300,94 @@ struct ImportInformation
/**
* Symbols for the built in types
*/
KAryTree!(ACSymbol*, true) builtinSymbols;
TTree!(ACSymbol*, true, "a < b", false) builtinSymbols;
/**
* Array properties
*/
KAryTree!(ACSymbol*, true) arraySymbols;
TTree!(ACSymbol*, true, "a < b", false) arraySymbols;
/**
* Associative array properties
*/
KAryTree!(ACSymbol*, true) assocArraySymbols;
TTree!(ACSymbol*, true, "a < b", false) assocArraySymbols;
/**
* Enum, union, class, and interface properties
*/
KAryTree!(ACSymbol*, true) aggregateSymbols;
TTree!(ACSymbol*, true, "a < b", false) aggregateSymbols;
/**
* Class properties
*/
KAryTree!(ACSymbol*, true) classSymbols;
TTree!(ACSymbol*, true, "a < b", false) classSymbols;
private immutable(string[24]) builtinTypeNames;
string getBuiltinTypeName(IdType id)
{
switch (id)
{
case tok!"int": return builtinTypeNames[0];
case tok!"uint": return builtinTypeNames[1];
case tok!"double": return builtinTypeNames[2];
case tok!"idouble": return builtinTypeNames[3];
case tok!"float": return builtinTypeNames[4];
case tok!"ifloat": return builtinTypeNames[5];
case tok!"short": return builtinTypeNames[6];
case tok!"ushort": return builtinTypeNames[7];
case tok!"long": return builtinTypeNames[8];
case tok!"ulong": return builtinTypeNames[9];
case tok!"char": return builtinTypeNames[10];
case tok!"wchar": return builtinTypeNames[11];
case tok!"dchar": return builtinTypeNames[12];
case tok!"bool": return builtinTypeNames[13];
case tok!"void": return builtinTypeNames[14];
case tok!"cent": return builtinTypeNames[15];
case tok!"ucent": return builtinTypeNames[16];
case tok!"real": return builtinTypeNames[17];
case tok!"ireal": return builtinTypeNames[18];
case tok!"byte": return builtinTypeNames[19];
case tok!"ubyte": return builtinTypeNames[20];
case tok!"cdouble": return builtinTypeNames[21];
case tok!"cfloat": return builtinTypeNames[22];
case tok!"creal": return builtinTypeNames[23];
default: assert (false);
}
}
/**
* Initializes builtin types and the various properties of builtin types
*/
static this()
{
builtinTypeNames[0] = internString("int");
builtinTypeNames[1] = internString("uint");
builtinTypeNames[2] = internString("double");
builtinTypeNames[3] = internString("idouble");
builtinTypeNames[4] = internString("float");
builtinTypeNames[5] = internString("ifloat");
builtinTypeNames[6] = internString("short");
builtinTypeNames[7] = internString("ushort");
builtinTypeNames[8] = internString("long");
builtinTypeNames[9] = internString("ulong");
builtinTypeNames[10] = internString("char");
builtinTypeNames[11] = internString("wchar");
builtinTypeNames[12] = internString("dchar");
builtinTypeNames[13] = internString("bool");
builtinTypeNames[14] = internString("void");
builtinTypeNames[15] = internString("cent");
builtinTypeNames[16] = internString("ucent");
builtinTypeNames[17] = internString("real");
builtinTypeNames[18] = internString("ireal");
builtinTypeNames[19] = internString("byte");
builtinTypeNames[20] = internString("ubyte");
builtinTypeNames[21] = internString("cdouble");
builtinTypeNames[22] = internString("cfloat");
builtinTypeNames[23] = internString("creal");
auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword);
auto int_ = allocate!ACSymbol(Mallocator.it, "int", CompletionKind.keyword);
auto long_ = allocate!ACSymbol(Mallocator.it, "long", CompletionKind.keyword);
@ -492,5 +556,10 @@ static this()
builtinSymbols.insert(real_);
builtinSymbols.insert(ucent_);
builtinSymbols.insert(void_);
// writeln(">>Builtin symbols");
// foreach (symbol; builtinSymbols[])
// writeln(symbol.name, " ", symbol.name.ptr);
// writeln("<<Builtin symbols");
}

View File

@ -166,12 +166,10 @@ AutocompleteResponse complete(const AutocompleteRequest request)
case tok!"]":
case tok!"this":
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
Scope* completionScope = generateAutocompleteTrees(tokenArray,
"stdin", allocator, semanticAllocator, cache);
"stdin", allocator, semanticAllocator);
scope(exit) typeid(Scope).destroy(completionScope);
auto expression = getExpression(beforeTokens);
response.setCompletions(completionScope, expression,
response.setCompletions(completionScope, getExpression(beforeTokens),
request.cursorPosition, CompletionType.identifiers, partial);
break;
case tok!"(":
@ -199,7 +197,7 @@ auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition,
{
LexerConfig config;
config.fileName = "stdin";
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
StringCache* cache = new StringCache(StringCache.defaultBucketCount);
auto tokens = byToken(cast(ubyte[]) sourceCode, config, cache);
tokenArray = tokens.array();
auto sortedTokens = assumeSorted(tokenArray);
@ -221,9 +219,8 @@ ACSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request,
auto beforeTokens = getTokensBeforeCursor(request.sourceCode,
request.cursorPosition, tokenArray);
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
Scope* completionScope = generateAutocompleteTrees(tokenArray,
"stdin", allocator, semanticAllocator, cache);
"stdin", allocator, semanticAllocator);
scope(exit) typeid(Scope).destroy(completionScope);
auto expression = getExpression(beforeTokens);
return getSymbolsByTokenChain(completionScope, expression,
@ -273,9 +270,8 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
case tok!")":
case tok!"]":
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16)));
shared(StringCache)* cache = new shared StringCache(StringCache.defaultBucketCount);
Scope* completionScope = generateAutocompleteTrees(tokenArray,
"stdin", allocator, semanticAllocator, cache);
"stdin", allocator, semanticAllocator);
scope(exit) typeid(Scope).destroy(completionScope);
auto expression = getExpression(beforeTokens[0 .. $ - 1]);
response.setCompletions(completionScope, expression,
@ -587,7 +583,7 @@ T getExpression(T)(T beforeTokens)
case tok!"identifier":
if (hasSpecialPrefix)
i++;
break expressionLoop;
break;
case tok!".":
break;
case tok!"*":

View File

@ -1,3 +1,3 @@
dmd -wi client.d messages.d stupidlog.d msgpack-d/src/msgpack.d -Imsgpack-d/src -release -inline -O -ofdcd-client
dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d dscanner/std/d/ast.d dscanner/std/d/entities.d dscanner/std/d/lexer.d dscanner/std/d/parser.d dscanner/std/lexer.d dscanner/std/allocator.d dscanner/formatter.d containers/src/memory/appender.d containers/src/memory/allocators.d containers/src/containers/dynamicarray.d containers/src/containers/karytree.d containers/src/containers/hashset.d containers/src/containers/unrolledlist.d containers/src/containers/internal/hash.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server
dmd actypes.d conversion/astconverter.d conversion/first.d conversion/second.d conversion/third.d autocomplete.d constants.d messages.d modulecache.d semantic.d server.d stupidlog.d string_interning.d dscanner/std/d/ast.d dscanner/std/d/entities.d dscanner/std/d/lexer.d dscanner/std/d/parser.d dscanner/std/lexer.d dscanner/std/allocator.d dscanner/formatter.d containers/src/memory/appender.d containers/src/memory/allocators.d containers/src/containers/dynamicarray.d containers/src/containers/karytree.d containers/src/containers/hashset.d containers/src/containers/unrolledlist.d containers/src/containers/internal/hash.d msgpack-d/src/msgpack.d -Icontainers/src -Imsgpack-d/src -Idscanner -wi -g -O -release -ofdcd-server

View File

@ -22,6 +22,7 @@ dmd\
semantic.d\
server.d\
stupidlog.d\
string_interning.d\
dscanner/std/d/ast.d\
dscanner/std/d/entities.d\
dscanner/std/d/lexer.d\
@ -32,7 +33,7 @@ dmd\
containers/src/memory/allocators.d\
containers/src/memory/appender.d\
containers/src/containers/dynamicarray.d\
containers/src/containers/karytree.d\
containers/src/containers/ttree.d\
containers/src/containers/unrolledlist.d\
containers/src/containers/hashset.d\
containers/src/containers/internal/hash.d\
@ -41,7 +42,7 @@ dmd\
-Icontainers/src\
-Imsgpack-d/src\
-Idscanner\
-wi -O -release -inline\
-wi -O -release\
-ofdcd-server
#gdc client.d\

@ -1 +1 @@
Subproject commit 819133564a8ebb99672d08774e6731e860e2d103
Subproject commit dfb5bec85daad42752074b5206f5f78c03147c97

View File

@ -30,11 +30,10 @@ import std.d.parser;
import std.typecons;
Scope* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile,
CAllocator symbolAllocator, CAllocator semanticAllocator,
shared(StringCache)* cache)
CAllocator symbolAllocator, CAllocator semanticAllocator)
{
Module m = parseModule(tokens, "editor buffer", semanticAllocator, &doesNothing);
auto first = scoped!FirstPass(m, symbolFile, cache, symbolAllocator,
auto first = scoped!FirstPass(m, symbolFile, symbolAllocator,
semanticAllocator);
first.run();

View File

@ -30,6 +30,7 @@ import std.d.lexer;
import std.typecons;
import stupidlog;
import containers.unrolledlist;
import string_interning;
/**
* First Pass handles the following:
@ -46,8 +47,8 @@ import containers.unrolledlist;
*/
final class FirstPass : ASTVisitor
{
this(Module mod, string symbolFile, shared(StringCache)* stringCache,
CAllocator symbolAllocator, CAllocator semanticAllocator)
this(Module mod, string symbolFile, CAllocator symbolAllocator,
CAllocator semanticAllocator)
in
{
assert (symbolAllocator);
@ -56,7 +57,6 @@ final class FirstPass : ASTVisitor
{
this.mod = mod;
this.symbolFile = symbolFile;
this.stringCache = stringCache;
this.symbolAllocator = symbolAllocator;
this.semanticAllocator = semanticAllocator;
}
@ -168,7 +168,7 @@ final class FirstPass : ASTVisitor
{
// Log.trace(__FUNCTION__, " ", typeof(bc).stringof);
currentSymbol.baseClasses.insert(iotcToStringArray(symbolAllocator,
bc.identifierOrTemplateChain, stringCache));
bc.identifierOrTemplateChain));
}
override void visit(const VariableDeclaration dec)
@ -237,7 +237,7 @@ final class FirstPass : ASTVisitor
override void visit(const AliasThisDeclaration dec)
{
// Log.trace(__FUNCTION__, " ", typeof(dec).stringof);
currentSymbol.aliasThis.insert(stringCache.intern(dec.identifier.text));
currentSymbol.aliasThis.insert(internString(dec.identifier.text));
}
override void visit(const Declaration dec)
@ -306,7 +306,7 @@ final class FirstPass : ASTVisitor
// Log.trace(__FUNCTION__, " ", typeof(dec).stringof);
foreach (identifier; moduleDeclaration.moduleName.identifiers)
{
moduleName.insert(stringCache.intern(identifier.text));
moduleName.insert(internString(identifier.text));
}
}
@ -340,8 +340,8 @@ final class FirstPass : ASTVisitor
{
auto info = allocate!ImportInformation(semanticAllocator);
foreach (identifier; single.identifierChain.identifiers)
info.importParts.insert(stringCache.intern(identifier.text));
info.modulePath = convertChainToImportPath(stringCache, single.identifierChain);
info.importParts.insert(internString(identifier.text));
info.modulePath = convertChainToImportPath(single.identifierChain);
info.isPublic = protection == tok!"public";
currentScope.importInformation.insert(info);
}
@ -349,18 +349,18 @@ final class FirstPass : ASTVisitor
if (importDeclaration.importBindings.singleImport.identifierChain is null) return;
auto info = allocate!ImportInformation(semanticAllocator);
info.modulePath = convertChainToImportPath(stringCache,
info.modulePath = convertChainToImportPath(
importDeclaration.importBindings.singleImport.identifierChain);
foreach (identifier; importDeclaration.importBindings.singleImport
.identifierChain.identifiers)
{
info.importParts.insert(stringCache.intern(identifier.text));
info.importParts.insert(internString(identifier.text));
}
foreach (bind; importDeclaration.importBindings.importBinds)
{
Tuple!(string, string) bindTuple;
bindTuple[0] = stringCache.intern(bind.left.text);
bindTuple[1] = bind.right == tok!"" ? null : stringCache.intern(bind.right.text);
bindTuple[0] = internString(bind.left.text);
bindTuple[1] = bind.right == tok!"" ? null : internString(bind.right.text);
info.importedSymbols.insert(bindTuple);
}
info.isPublic = protection == tok!"public";
@ -412,8 +412,6 @@ final class FirstPass : ASTVisitor
/// The module
SemanticSymbol* rootSymbol;
shared(StringCache)* stringCache;
CAllocator symbolAllocator;
uint symbolsAllocated;
@ -431,7 +429,7 @@ private:
symbol.acSymbol.parts.insert(aggregateSymbols[]);
symbol.parent = currentSymbol;
symbol.protection = protection;
symbol.acSymbol.doc = stringCache.intern(dec.comment);
symbol.acSymbol.doc = internString(dec.comment);
currentSymbol = symbol;
dec.accept(this);
currentSymbol = symbol.parent;
@ -446,7 +444,7 @@ private:
processParameters(symbol, null, "this", parameters, doc);
symbol.protection = protection;
symbol.parent = currentSymbol;
symbol.acSymbol.doc = stringCache.intern(doc);
symbol.acSymbol.doc = internString(doc);
currentSymbol.addChild(symbol);
if (functionBody !is null)
{
@ -463,7 +461,7 @@ private:
symbol.acSymbol.callTip = "~this()";
symbol.protection = protection;
symbol.parent = currentSymbol;
symbol.acSymbol.doc = stringCache.intern(doc);
symbol.acSymbol.doc = internString(doc);
currentSymbol.addChild(symbol);
if (functionBody !is null)
{
@ -519,7 +517,7 @@ private:
app.put("()");
else
app.formatNode(parameters);
return stringCache.intern(cast(ubyte[]) app[]);
return internString(cast(string) app[]);
}
SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind,
@ -530,8 +528,7 @@ private:
}
body
{
ACSymbol* acSymbol = allocate!ACSymbol(symbolAllocator,
name is null ? name : stringCache.intern(name), kind);
ACSymbol* acSymbol = allocate!ACSymbol(symbolAllocator, name, kind);
acSymbol.location = location;
acSymbol.symbolFile = symbolFile;
symbolsAllocated++;
@ -568,23 +565,21 @@ void formatNode(A, T)(ref A appender, const T node)
private:
string[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc,
shared(StringCache)* stringCache)
string[] iotcToStringArray(A)(ref A allocator, const IdentifierOrTemplateChain iotc)
{
string[] retVal = cast(string[]) allocator.allocate((string[]).sizeof
* iotc.identifiersOrTemplateInstances.length);
foreach (i, ioti; iotc.identifiersOrTemplateInstances)
{
if (ioti.identifier != tok!"")
retVal[i] = stringCache.intern(ioti.identifier.text);
retVal[i] = internString(ioti.identifier.text);
else
retVal[i] = stringCache.intern(ioti.templateInstance.identifier.text);
retVal[i] = internString(ioti.templateInstance.identifier.text);
}
return retVal;
}
static string convertChainToImportPath(shared(StringCache)* stringCache,
const IdentifierChain ic)
static string convertChainToImportPath(const IdentifierChain ic)
{
import std.path;
QuickAllocator!1024 q;
@ -596,5 +591,5 @@ static string convertChainToImportPath(shared(StringCache)* stringCache,
if (i + 1 < ic.identifiers.length)
app.append(dirSeparator);
}
return stringCache.intern(cast(string) app[]);
return internString(cast(string) app[]);
}

View File

@ -22,7 +22,6 @@ import conversion.first;
import actypes;
import semantic;
import messages;
import std.lexer : StringCache;
import std.allocator;
import stupidlog;
@ -41,7 +40,6 @@ public:
{
this.rootSymbol = first.rootSymbol;
this.moduleScope = first.moduleScope;
this.stringCache = first.stringCache;
this.symbolAllocator = first.symbolAllocator;
}
@ -54,7 +52,6 @@ public:
CAllocator symbolAllocator;
SemanticSymbol* rootSymbol;
Scope* moduleScope;
shared(StringCache)* stringCache;
private:
@ -117,18 +114,6 @@ private:
{
string location = ModuleCache.resolveImportLoctation(importInfo.modulePath);
ACSymbol*[] symbols = location is null ? [] : ModuleCache.getSymbolsInModule(location);
//////
foreach (s; symbols)
{
try
std.utf.validate(s.name);
catch (Exception e)
{
writeln("Symbols in ", importInfo.modulePath, " are corrupted");
throw e;
}
}
//////
ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbols);
currentScope.symbols.insert(moduleSymbol);
currentScope.symbols.insert(symbols);

View File

@ -25,6 +25,7 @@ import semantic;
import actypes;
import messages;
import std.allocator;
import string_interning;
/**
* Third pass handles the following:
@ -43,7 +44,6 @@ public:
{
this.rootSymbol = second.rootSymbol;
this.moduleScope = second.moduleScope;
this.stringCache = second.stringCache;
this.name = name;
this.symbolAllocator = second.symbolAllocator;
}
@ -153,8 +153,7 @@ private:
t.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances.length
* string.sizeof);
scope(exit) Mallocator.it.deallocate(symbolParts);
expandSymbol(symbolParts,
t.type2.symbol.identifierOrTemplateChain, stringCache);
expandSymbol(symbolParts, t.type2.symbol.identifierOrTemplateChain);
auto symbols = moduleScope.getSymbolsByNameAndCursor(
symbolParts[0], location);
if (symbols.length == 0)
@ -174,15 +173,14 @@ private:
return s;
}
static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain,
shared(StringCache)* stringCache)
static void expandSymbol(string[] strings, const IdentifierOrTemplateChain chain)
{
for (size_t i = 0; i < chain.identifiersOrTemplateInstances.length; ++i)
{
auto identOrTemplate = chain.identifiersOrTemplateInstances[i];
if (identOrTemplate is null)
continue;
strings[i] = stringCache.intern(identOrTemplate.templateInstance is null ?
strings[i] = internString(identOrTemplate.templateInstance is null ?
identOrTemplate.identifier.text
: identOrTemplate.templateInstance.identifier.text);
}
@ -215,20 +213,20 @@ private:
scope(exit) q.deallocate(app.mem);
app.append(suffix.delegateOrFunction.text);
app.formatNode(suffix.parameters);
s.callTip = stringCache.intern(cast(ubyte[]) app[]);
s.callTip = internString(cast(string) app[]);
return s;
}
return null;
}
static ACSymbol* convertBuiltinType(const Type2 type2)
ACSymbol* convertBuiltinType(const Type2 type2)
{
string stringRepresentation = str(type2.builtinType);
if (stringRepresentation is null) return null;
// TODO: Make this use binary search instead
import std.stdio;
string stringRepresentation = getBuiltinTypeName(type2.builtinType);
// writefln(">> %s %016X", stringRepresentation, stringRepresentation.ptr);
ACSymbol s = ACSymbol(stringRepresentation);
assert(s.name.ptr == stringRepresentation.ptr);
// writefln(">> %s %016X", s.name, s.name.ptr);
return builtinSymbols.equalRange(&s).front();
}
shared(StringCache)* stringCache;
}

@ -1 +1 @@
Subproject commit 8b4b2b342f4e3c8dbead90353c6f7aa4800c2ce4
Subproject commit 19dc7c707f857b104144e909d77543b2db1521b8

View File

@ -32,7 +32,7 @@ import std.path;
import actypes;
import semantic;
import memory.allocators;
import containers.karytree;
import containers.ttree;
import containers.hashset;
import containers.unrolledlist;
import conversion.astconverter;
@ -74,7 +74,6 @@ bool existanceCheck(A)(A path)
static this()
{
ModuleCache.stringCache = new shared StringCache(StringCache.defaultBucketCount);
ModuleCache.symbolAllocator = new CAllocatorImpl!(BlockAllocator!(1024 * 16));
}
@ -115,6 +114,7 @@ struct ModuleCache
*/
static ACSymbol*[] getSymbolsInModule(string location)
{
import string_interning;
assert (location !is null);
if (!needsReparsing(location))
{
@ -126,7 +126,7 @@ struct ModuleCache
return [];
}
string cachedLocation = stringCache.intern(location);
string cachedLocation = internString(location);
Log.info("Getting symbols for ", cachedLocation);
@ -145,7 +145,7 @@ struct ModuleCache
f.rawRead(source);
LexerConfig config;
config.fileName = cachedLocation;
shared parseStringCache = shared StringCache(StringCache.defaultBucketCount);
auto parseStringCache = StringCache(StringCache.defaultBucketCount);
auto semanticAllocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 64)));
DynamicArray!(Token, false) tokens;
auto tokenRange = byToken(
@ -158,8 +158,8 @@ struct ModuleCache
Module m = parseModuleSimple(tokens[], cachedLocation, semanticAllocator);
assert (symbolAllocator);
auto first = scoped!FirstPass(m, cachedLocation, stringCache,
symbolAllocator, semanticAllocator);
auto first = scoped!FirstPass(m, cachedLocation, symbolAllocator,
semanticAllocator);
first.run();
SecondPass second = SecondPass(first);
@ -234,8 +234,6 @@ struct ModuleCache
return importPaths[];
}
static shared(StringCache)* stringCache;
static uint symbolsAllocated;
private:
@ -264,7 +262,7 @@ private:
}
// Mapping of file paths to their cached symbols.
static KAryTree!(CacheEntry*) cache;
static TTree!(CacheEntry*) cache;
static HashSet!string recursionGuard;

View File

@ -100,11 +100,9 @@ int main(string[] args)
sw.stop();
Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds");
float internBytes = cast(float) ModuleCache.stringCache.allocated / (1024 * 1024);
Log.info("String interning took up ", internBytes, " megabytes");
float symbolMegs = (cast(float) (ACSymbol.sizeof * ModuleCache.symbolsAllocated)) / (1024f * 1024f);
Log.info(ModuleCache.symbolsAllocated, " symbols allocated, taking up ",
symbolMegs, " megabytes");
// float symbolMegs = (cast(float) (ACSymbol.sizeof * ModuleCache.symbolsAllocated)) / (1024f * 1024f);
// Log.info(ModuleCache.symbolsAllocated, " symbols allocated, taking up ",
// symbolMegs, " megabytes");
// No relative paths
version (Posix) chdir("/");

44
string_interning.d Normal file
View File

@ -0,0 +1,44 @@
/**
* This file is part of DCD, a development tool for the D programming language.
* Copyright (C) 2014 Brian Schott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
module string_interning;
import std.lexer;
string internString(string s)
{
// import std.stdio;
// import std.string;
// size_t* p = s in dupCheck;
// auto r = stringCache.intern(s);
return stringCache.intern(s);
// if (p !is null)
// assert (*p == cast(size_t) r.ptr, format("%s, %016x, %016x", s, *p, r.ptr));
// else
// dupCheck[s] = cast(size_t) r.ptr;
// stderr.writefln("%s\t%016x", r, r.ptr);
// return r;
}
static this()
{
stringCache = StringCache(StringCache.defaultBucketCount);
}
//private size_t[string] dupCheck;
private StringCache stringCache = void;