mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
14bc0a9317
In an effort to disentangle the three sets of llvm headers the targets in stlib uses (real llvm headers, RuntimeHeaders/llvm, stdlib/include/llvm), this patch completely removes the includes from the runtime to RemoteInspection. This is the first patch to eventually completely remove RuntimeHeaders/llvm headers.
139 lines
5.2 KiB
C++
139 lines
5.2 KiB
C++
//===--- 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/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
|