Merge pull request #22686 from dotnet/dev/toddgrun/expand_cached_tokens
Expand the SyntaxTokenCache to contain more than just whitespace tokens.
This commit is contained in:
commit
4d367898b3
|
|
@ -9,9 +9,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
|||
{
|
||||
internal static SyntaxToken Token(SyntaxKind kind, string content, params RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
if (kind == SyntaxKind.Whitespace && diagnostics.Length == 0)
|
||||
if (SyntaxTokenCache.CanBeCached(kind, diagnostics))
|
||||
{
|
||||
return WhitespaceTokenCache.GetToken(content);
|
||||
return SyntaxTokenCache.GetCachedToken(kind, content);
|
||||
}
|
||||
|
||||
return new SyntaxToken(kind, content, diagnostics);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
// Simplified version of Roslyn's SyntaxNodeCache
|
||||
internal static class SyntaxTokenCache
|
||||
{
|
||||
private const int CacheSizeBits = 16;
|
||||
private const int CacheSize = 1 << CacheSizeBits;
|
||||
private const int CacheMask = CacheSize - 1;
|
||||
private static readonly Entry[] s_cache = new Entry[CacheSize];
|
||||
|
||||
private struct Entry
|
||||
{
|
||||
public int Hash { get; }
|
||||
public SyntaxToken Token { get; }
|
||||
|
||||
internal Entry(int hash, SyntaxToken token)
|
||||
{
|
||||
Hash = hash;
|
||||
Token = token;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanBeCached(SyntaxKind kind, params RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
if (diagnostics.Length == 0)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case SyntaxKind.CharacterLiteral:
|
||||
case SyntaxKind.Dot:
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.IntegerLiteral:
|
||||
case SyntaxKind.Keyword:
|
||||
case SyntaxKind.NewLine:
|
||||
case SyntaxKind.RazorCommentStar:
|
||||
case SyntaxKind.RazorCommentTransition:
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.Transition:
|
||||
case SyntaxKind.Whitespace:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static SyntaxToken GetCachedToken(SyntaxKind kind, string content)
|
||||
{
|
||||
var hash = (kind, content).GetHashCode();
|
||||
|
||||
// Allow the upper 16 bits to contribute to the index
|
||||
var indexableHash = hash ^ (hash >> 16);
|
||||
|
||||
var idx = indexableHash & CacheMask;
|
||||
var e = s_cache[idx];
|
||||
|
||||
if (e.Hash == hash && e.Token.Kind == kind && e.Token.Content == content)
|
||||
{
|
||||
return e.Token;
|
||||
}
|
||||
|
||||
var token = new SyntaxToken(kind, content, Array.Empty<RazorDiagnostic>());
|
||||
s_cache[idx] = new Entry(hash, token);
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
// Simplified version of Roslyn's SyntaxNodeCache
|
||||
internal static class WhitespaceTokenCache
|
||||
{
|
||||
private const int CacheSizeBits = 8;
|
||||
private const int CacheSize = 1 << CacheSizeBits;
|
||||
private const int CacheMask = CacheSize - 1;
|
||||
private static readonly Entry[] s_cache = new Entry[CacheSize];
|
||||
|
||||
private struct Entry
|
||||
{
|
||||
public int Hash { get; }
|
||||
public SyntaxToken Token { get; }
|
||||
|
||||
internal Entry(int hash, SyntaxToken token)
|
||||
{
|
||||
Hash = hash;
|
||||
Token = token;
|
||||
}
|
||||
}
|
||||
|
||||
public static SyntaxToken GetToken(string content)
|
||||
{
|
||||
var hash = content.GetHashCode();
|
||||
|
||||
var idx = hash & CacheMask;
|
||||
var e = s_cache[idx];
|
||||
|
||||
if (e.Hash == hash && e.Token?.Content == content)
|
||||
{
|
||||
return e.Token;
|
||||
}
|
||||
|
||||
var token = new SyntaxToken(SyntaxKind.Whitespace, content, Array.Empty<RazorDiagnostic>());
|
||||
s_cache[idx] = new Entry(hash, token);
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue