-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathGenericCacheEntry.h
139 lines (114 loc) · 5.28 KB
/
GenericCacheEntry.h
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//===--- GenericCacheEntry.h ------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_RUNTIME_GENERICCACHEENTRY_H
#define SWIFT_RUNTIME_GENERICCACHEENTRY_H
#include "MetadataCache.h"
#include "swift/ABI/Metadata.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/Basic/Unreachable.h"
#include "swift/RemoteInspection/GenericMetadataCacheEntry.h"
#include "swift/Runtime/LibPrespecialized.h"
namespace swift {
bool areAllTransitiveMetadataComplete_cheap(const Metadata *type);
PrivateMetadataState inferStateForMetadata(Metadata *metadata);
MetadataDependency checkTransitiveCompleteness(const Metadata *initialType);
struct GenericCacheEntry final
: VariadicMetadataCacheEntryBase<GenericCacheEntry> {
static const char *getName() { return "GenericCache"; }
// The constructor/allocate operations that take a `const Metadata *`
// are used for the insertion of canonical specializations.
// The metadata is always complete after construction.
GenericCacheEntry(MetadataCacheKey key, MetadataWaitQueue::Worker &worker,
MetadataRequest request, const Metadata *candidate)
: VariadicMetadataCacheEntryBase(key, worker,
PrivateMetadataState::Complete,
const_cast<Metadata *>(candidate)) {}
AllocationResult allocate(const Metadata *candidate) {
swift_unreachable("always short-circuited");
}
static bool allowMangledNameVerification(const Metadata *candidate) {
// Disallow mangled name verification for specialized candidates
// because it will trigger recursive entry into the swift_once
// in cacheCanonicalSpecializedMetadata.
// TODO: verify mangled names in a second pass in that function.
return false;
}
// The constructor/allocate operations that take a descriptor
// and arguments are used along the normal allocation path.
GenericCacheEntry(MetadataCacheKey key, MetadataWaitQueue::Worker &worker,
MetadataRequest request,
const TypeContextDescriptor *description,
const void *const *arguments)
: VariadicMetadataCacheEntryBase(key, worker,
PrivateMetadataState::Allocating,
/*candidate*/ nullptr) {}
AllocationResult allocate(const TypeContextDescriptor *description,
const void *const *arguments) {
if (auto *prespecialized =
getLibPrespecializedMetadata(description, arguments))
return {prespecialized, PrivateMetadataState::Complete};
// Find a pattern. Currently we always use the default pattern.
auto &generics = description->getFullGenericContextHeader();
auto pattern = generics.DefaultInstantiationPattern.get();
// Call the pattern's instantiation function.
auto metadata =
pattern->InstantiationFunction(description, arguments, pattern);
// If there's no completion function, do a quick-and-dirty check to
// see if all of the type arguments are already complete. If they
// are, we can broadcast completion immediately and potentially avoid
// some extra locking.
PrivateMetadataState state;
if (pattern->CompletionFunction.isNull()) {
if (areAllTransitiveMetadataComplete_cheap(metadata)) {
state = PrivateMetadataState::Complete;
} else {
state = PrivateMetadataState::NonTransitiveComplete;
}
} else {
state = inferStateForMetadata(metadata);
}
return {metadata, state};
}
static bool
allowMangledNameVerification(const TypeContextDescriptor *description,
const void *const *arguments) {
return true;
}
MetadataStateWithDependency
tryInitialize(Metadata *metadata, PrivateMetadataState state,
PrivateMetadataCompletionContext *context) {
assert(state != PrivateMetadataState::Complete);
// Finish the completion function.
if (state < PrivateMetadataState::NonTransitiveComplete) {
// Find a pattern. Currently we always use the default pattern.
auto &generics =
metadata->getTypeContextDescriptor()->getFullGenericContextHeader();
auto pattern = generics.DefaultInstantiationPattern.get();
// Complete the metadata's instantiation.
auto dependency =
pattern->CompletionFunction(metadata, &context->Public, pattern);
// If this failed with a dependency, infer the current metadata state
// and return.
if (dependency) {
return {inferStateForMetadata(metadata), dependency};
}
}
// Check for transitive completeness.
if (auto dependency = checkTransitiveCompleteness(metadata)) {
return {PrivateMetadataState::NonTransitiveComplete, dependency};
}
// We're done.
return {PrivateMetadataState::Complete, MetadataDependency()};
}
};
} // namespace swift
#endif