Use string interning for a very nice speed boost
This commit is contained in:
parent
7eb952e0e5
commit
ae91019ab4
97
actypes.d
97
actypes.d
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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!"*":
|
||||
|
|
|
@ -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
|
||||
|
|
5
build.sh
5
build.sh
|
@ -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
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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[]);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
2
dscanner
2
dscanner
|
@ -1 +1 @@
|
|||
Subproject commit 8b4b2b342f4e3c8dbead90353c6f7aa4800c2ce4
|
||||
Subproject commit 19dc7c707f857b104144e909d77543b2db1521b8
|
|
@ -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;
|
||||
|
||||
|
|
8
server.d
8
server.d
|
@ -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("/");
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue