Skip to content

Commit e387778

Browse files
colincrossMaskRay
authored andcommitted
[ELF] Optimize ScriptLexer::getLineNumber by caching the previous line number and offset
getLineNumber() was counting the number of line feeds from the start of the buffer to the current token. For large linker scripts this became a performance bottleneck. For one 4MB linker script over 4 minutes was spent in getLineNumber's StringRef::count. Store the line number from the last token, and only count the additional line feeds since the last token. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D104137
1 parent 1cfdcae commit e387778

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

lld/ELF/ScriptLexer.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,25 @@ size_t ScriptLexer::getLineNumber() {
5656
return 1;
5757
StringRef s = getCurrentMB().getBuffer();
5858
StringRef tok = tokens[pos - 1];
59-
return s.substr(0, tok.data() - s.data()).count('\n') + 1;
59+
const size_t tokOffset = tok.data() - s.data();
60+
61+
// For the first token, or when going backwards, start from the beginning of
62+
// the buffer. If this token is after the previous token, start from the
63+
// previous token.
64+
size_t line = 1;
65+
size_t start = 0;
66+
if (lastLineNumberOffset > 0 && tokOffset >= lastLineNumberOffset) {
67+
start = lastLineNumberOffset;
68+
line = lastLineNumber;
69+
}
70+
71+
line += s.substr(start, tokOffset - start).count('\n');
72+
73+
// Store the line number of this token for reuse.
74+
lastLineNumberOffset = tokOffset;
75+
lastLineNumber = line;
76+
77+
return line;
6078
}
6179

6280
// Returns 0-based column number of the current token.

lld/ELF/ScriptLexer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class ScriptLexer {
4040
bool inExpr = false;
4141
size_t pos = 0;
4242

43+
size_t lastLineNumber = 0;
44+
size_t lastLineNumberOffset = 0;
45+
4346
protected:
4447
MemoryBufferRef getCurrentMB();
4548

0 commit comments

Comments
 (0)