Optimize Loc Lookups (#21088)

This commit is contained in:
Abul Hossain Khan 2025-03-27 01:02:01 +05:30 committed by GitHub
parent 13b0745e33
commit ce91ddca22
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -366,6 +366,11 @@ struct BaseLoc
uint[] lines; /// For each line, the file offset at which it starts. At index 0 there's always a 0 entry.
BaseLoc[] substitutions; /// Substitutions from #line / #file directives
/// Cache for the last line lookup
private size_t lastLineIndex = 0;
/// Cache for the last substitution lookup
private size_t lastSubstIndex = 0;
/// Register that a new line starts at `offset` bytes from the start of the source file
void newLine(uint offset)
{
@ -421,8 +426,61 @@ struct BaseLoc
private size_t getSubstitutionIndex(uint offset) @nogc
{
if (substitutions.length <= 1)
return 0;
// Check if the offset falls within the current cached substitution or the next one
if (lastSubstIndex < substitutions.length - 1)
{
// For the current substitution's range
if (substitutions[lastSubstIndex].startIndex <= offset &&
(lastSubstIndex == substitutions.length - 1 ||
substitutions[lastSubstIndex + 1].startIndex > offset))
return lastSubstIndex;
// For the next substitution's range
if (lastSubstIndex + 1 < substitutions.length - 1 &&
substitutions[lastSubstIndex + 1].startIndex <= offset &&
substitutions[lastSubstIndex + 2].startIndex > offset)
{
lastSubstIndex++;
return lastSubstIndex;
}
// For the previous substitution's range
if (lastSubstIndex > 0 &&
substitutions[lastSubstIndex - 1].startIndex <= offset &&
substitutions[lastSubstIndex].startIndex > offset)
{
lastSubstIndex--;
return lastSubstIndex;
}
}
else if (lastSubstIndex == substitutions.length - 1 &&
substitutions[lastSubstIndex].startIndex <= offset)
{
// Last substitution case
return lastSubstIndex;
}
// Fall back to binary search, but start near
size_t lo = 0;
size_t hi = substitutions.length + -1;
size_t hi = substitutions.length - 1;
// Adjust the range based on the offset relative to lastSubstIndex
if (offset < substitutions[lastSubstIndex].startIndex)
{
// Search backward
lo = 0;
hi = lastSubstIndex;
}
else
{
// Search forward
lo = lastSubstIndex;
hi = substitutions.length - 1;
}
size_t mid = 0;
while (lo <= hi)
{
@ -430,7 +488,10 @@ struct BaseLoc
if (substitutions[mid].startIndex <= offset)
{
if (mid == substitutions.length - 1 || substitutions[mid + 1].startIndex > offset)
{
lastSubstIndex = mid; // Update cache
return mid;
}
lo = mid + 1;
}
@ -443,10 +504,51 @@ struct BaseLoc
}
/// Binary search the index in `this.lines` corresponding to `offset`
/// lastLineIndex cache to avoid full binary search when possible
private size_t getLineIndex(uint offset) @nogc
{
if (lines.length <= 1)
return 0;
if (lastLineIndex < lines.length - 1)
{
if (lines[lastLineIndex] <= offset && offset < lines[lastLineIndex + 1])
return lastLineIndex;
if (lastLineIndex + 1 < lines.length - 1 &&
lines[lastLineIndex + 1] <= offset && offset < lines[lastLineIndex + 2])
{
lastLineIndex++;
return lastLineIndex;
}
if (lastLineIndex > 0 &&
lines[lastLineIndex - 1] <= offset && offset < lines[lastLineIndex])
{
lastLineIndex--;
return lastLineIndex;
}
}
else if (lastLineIndex == lines.length - 1 && lines[lastLineIndex] <= offset)
{
return lastLineIndex;
}
// Fall back to binary search
size_t lo = 0;
size_t hi = lines.length + -1;
size_t hi = lines.length - 1;
if (offset < lines[lastLineIndex])
{
lo = 0;
hi = lastLineIndex;
}
else
{
lo = lastLineIndex;
hi = lines.length - 1;
}
size_t mid = 0;
while (lo <= hi)
{
@ -454,7 +556,10 @@ struct BaseLoc
if (lines[mid] <= offset)
{
if (mid == lines.length - 1 || lines[mid + 1] > offset)
{
lastLineIndex = mid; // Update cache
return mid;
}
lo = mid + 1;
}