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
|