-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathRawSyntaxTokenCache.cpp
90 lines (79 loc) · 3.27 KB
/
RawSyntaxTokenCache.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//===--- RawSyntaxTokenCache.cpp - Raw Token Cache --------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "RawSyntaxTokenCache.h"
#include "swift/Syntax/RawSyntax.h"
#include "swift/Syntax/Trivia.h"
#include "llvm/ADT/ArrayRef.h"
using namespace swift;
using namespace swift::syntax;
static bool shouldCacheNode(tok TokKind, size_t TextSize,
ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia) {
// Is string_literal with >16 length.
if (TokKind == tok::string_literal && TextSize > 16) {
return false;
}
// Has leading comment trivia et al.
if (any_of(LeadingTrivia,
[](const syntax::TriviaPiece &T) { return T.getText().size(); })) {
return false;
}
// Has trailing comment trivia et al.
if (any_of(TrailingTrivia,
[](const syntax::TriviaPiece &T) { return T.getText().size(); })) {
return false;
}
// We can cache the node
return true;
}
RC<RawSyntax>
RawSyntaxTokenCache::getToken(RC<SyntaxArena> &Arena, tok TokKind,
OwnedString Text,
ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia) {
// Determine whether this token is worth to cache.
if (!shouldCacheNode(TokKind, Text.size(), LeadingTrivia, TrailingTrivia)) {
// Do not use cache.
return RawSyntax::make(TokKind, Text, LeadingTrivia, TrailingTrivia,
SourcePresence::Present, Arena);
}
// This node is cacheable. Get or create.
llvm::FoldingSetNodeID ID;
RawSyntax::Profile(ID, TokKind, Text.str(), LeadingTrivia, TrailingTrivia);
void *insertPos = nullptr;
if (auto existing = CachedTokens.FindNodeOrInsertPos(ID, insertPos)) {
// Found in the cache. Just return it.
return existing->get();
}
// Could not found in the cache. Create it.
auto Raw = RawSyntax::make(TokKind, Text, LeadingTrivia, TrailingTrivia,
SourcePresence::Present, Arena);
auto IDRef = ID.Intern(Arena->getAllocator());
auto CacheNode = new (Arena) RawSyntaxCacheNode(Raw, IDRef);
// Keep track of the created RawSyntaxCacheNode so that we can destruct it
// later.
CacheNodes.push_back(CacheNode);
CachedTokens.InsertNode(CacheNode, insertPos);
return Raw;
}
RawSyntaxTokenCache::~RawSyntaxTokenCache() {
// The CachedTokens folding set is no longer used. It does not, however, clean
// up the RawSyntaxCacheNodes we created for it and would keep a strong
// reference to their RawSyntax nodes.
// We thus need to manually destruct the RawSyntaxCacheNodes here.
// After all RawSyntax nodes in the current arena are disposed of, the
// RawSyntaxCacheNode will also be destroyed, as they are allocated in that
// arena.
for (RawSyntaxCacheNode *Node : CacheNodes) {
Node->~RawSyntaxCacheNode();
}
}