The new function swift_getCanonicalSpecializedMetadata takes a metadata
request, a prespecialized non-canonical metadata, and a cache as its
arguments. The idea of the function is either to bless the provided
prespecialized metadata as canonical if there is not currently a
canonical metadata record for the type it describes or else to return
the actual canonical metadata.
When called, the metadata cache checks for a preexisting entry for this
metadata. If none is found, the passed-in prespecialized metadata is
added to the cache. Otherwise, the metadata record found in the cache
is returned.
rdar://problem/56995359
Two protocol conformance descriptors are passed to
swift_compareProtocolConformanceDecriptors from generic metadata
accessors when there is a canonical prespecialization and one of the
generic arguments has a protocol requirement.
Previously, the descriptors were incorrectly being passed without
ptrauth processing: one from the witness table in the arguments that are
passed in to the accessor and one known statically.
Here, the descriptor in the witness table is authed using the
ProtocolConformanceDescriptor schema. Then, both descriptors are signed
using the ProtocolConformanceDescriptorsAsArguments schema. Finally, in
the runtime function, the descriptors are authed.
The new function swift_compareProtocolConformanceDescriptors calls
through to the preexisting code in MetadataCacheKey which has been
extracted out from MetadataCacheKey::compareWitnessTables into a new
public static function
MetadataCacheKey::compareProtocolConformanceDescriptors.
The new function's availability is "future" for now.
The new function `swift_compareTypeContextDescriptors` is equivalent to
a call through to swift::equalContexts. The implementation it the same
as that of swift::equalContexts with the following removals:
- Handling of context descriptors of kind other outside of
ContextDescriptorKind::Type_First...ContextDescriptorKind::Type_Last.
Because the arguments are both TypeContextDescriptors, the kinds are
known to fall within that range.
- Casting to TypeContextDescriptor. The arguments are already of that
type.
For now, the new function has "future" availability.
Previously, when NDEBUG was not defined, the allocations made for value
metadata records were filled with 0xAA bytes. Here, that behavior is
both expanded to all metadata records and enabled in release builds when
the environment variable SWIFT_DEBUG_ENABLE_MALLOC_SCRIBBLE is set.
During witness table instantiation, the witness table is constructed
several sources: the pattern, the resilient witnesses, the private
data, and default implementations. The private data area is the only
one that was being zeroed out; the rest we rely on always filling in
the data from the conformance descriptor and provided info.
However, witness table instantiation uses the presence of a NULL
pointer for a particular witness in the resulting table to indicate
that no witness fulfilled that requirement, so that it can fill in the
default witnesss. Except that, without zeroing that part of the table
beforehand, we aren't guaranteed to have a NULL pointer for witness
entries that the client (protocol conformance) did not know about at
the time it was compiled.
Zero out the entire witness table so default implementations can be
filled in appropriately.
Fixes rdar://problem/64295849.
`classMetadata` is only used in the ObjC path, resulting in a
`-Wunused-variable` warning. Sink the variable into the ObjC path.
Because the conversion of the metadata does not rely on the type
metadata bits in the metadata, it is safe to delay the definition and
bit adjustment to the point where it is used unifying the two ObjC
paths.
There are a few environment variables used to enable debugging options in the
runtime, and we'll likely add more over time. These are implemented with
scattered getenv() calls at the point of use. This is inefficient, as most/all
OSes have to do a linear scan of the environment for each call. It's also not
discoverable, since the only way to find these variables is to inspect the
source.
This commit places all of these variables in a central location.
stdlib/public/runtime/EnvironmentVariables.def defines all of the debug
variables including their name, type, default value, and a help string. On OSes
which make an `environ` array available, the entire array is scanned in a single
pass the first time any debug variable is requested. By quickly rejecting
variables that do not start with `SWIFT_`, we optimize for the common case where
no debug variables are set. We also have a fallback to repeated `getenv()` calls
when a full scan is not possible.
Setting `SWIFT_HELP=YES` will print out all available debug variables along with
a brief description of what they do.
When generic metadata for a class is requested in the same module where
the class is defined, rather than a call to the generic metadata
accessor or to a variant of typeForMangledNode, a call to a new
accessor--a canonical specialized generic metadata accessor--is emitted.
The new function is defined schematically as follows:
MetadataResponse `canonical specialized metadata accessor for C<K>`(MetadataRequest request) {
(void)`canonical specialized metadata accessor for superclass(C<K>)`(::Complete)
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, 1)`(::Complete)
...
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, count)`(::Complete)
auto *metadata = objc_opt_self(`canonical specialized metadata for C<K>`);
return {metadata, MetadataState::Complete};
}
where generic_argument_class(C<K>, N) denotes the Nth generic argument
which is both (1) itself a specialized generic type and is also (2) a
class. These calls to the specialized metadata accessors for these
related types ensure that all generic class types are registered with
the Objective-C runtime.
To enable these new canonical specialized generic metadata accessors,
metadata for generic classes is prespecialized as needed. So are the
metaclasses and the corresponding rodata.
Previously, the lazy objc naming hook was registered during process
execution when the first generic class metadata was instantiated. Since
that instantiation may occur "before process launch" (i.e. if the
generic metadata is prespecialized), the lazy naming hook is now
installed at process launch.
Keep the initial metadata pool to be all zeroes. Remove the hardcoded trailer at the end. Write a trailer into it when we check the environment variable the first time we allocate.
This adds a new copy of LLVMSupport into the runtime. This is the final
step before changing the inline namespace for the runtime support. This
will allow us to avoid the ODR violations from the header definitions of
LLVMSupport.
LLVMSupport forked at: 22492eead218ec91d349c8c50439880fbeacf2b7
Changes made to LLVMSupport from that revision:
process.inc forward declares `_beginthreadex` due to compilation issues due to custom flag handling
API changes required that we alter the `Deallocate` routine to account
for the alignment.
This is a temporary state, meant to simplify the process. We do not use
the entire LLVMSupport library and there is no value in keeping the
entire library. Subsequent commits will prune the library to the needs
for the runtime.
There are a set of headers shared between the Swift compiler and the
runtime. Ensure that we explicitly use `llvm::ArrayRef` rather than
`ArrayRef` which is aliased to `::llvm::ArrayRef`. Doing so enables us
to replace the `ArrayRef` with an inline namespaced version fixing ODR
violations when the swift runtime is loaded into an address space with
LLVM.
Rather than using the forward declaration for the LLVMSupport types,
expect to be able to use the full declaration. Because these are
references in the implementation, there is no reason to use a forward
declaration as the full types need to be declared for use. The LLVM
headers will provide the declaration and definition for the types. This
is motivated by the desire to ensure that the LLVMSupport symbols are
properly namespaced to avoid ODR violations in the runtime.
This reduces the dependency on `LLVMSupport`. This is the first step
towards helping move towards a local fork of the LLVM ADT to ensure that
static linking of the Swift runtime and core library does not result in
ODR violations.
To facilitate debugging metadata records which are not properly
initialized, upon allocation fill them with a regular byte pattern
(0xAA) so that on subsequent inspection it is obvious if part of the
record is not initialized.
When constructing the metadata for a type Gen<T : Super>
where Super is a superclass constraint, the generic argument K at which
the metadata for Gen is being instantiated is verified to be a subclass
of Super via _checkGenericRequirements.
Previously, that check was done using swift_dynamicCastMetatype. That
worked for the most part but provided an incorrect answer if the
metadata for K was not yet complete. These classes are incomplete more
often thanks to __swift_instantiateConcreteTypeFromMangledNameAbstract.
That issue occurred concretely in the following case:
Framework with Library Evolution enabled:
open class Super { ... }
public struct Gen<T : Super> {
}
Target in a different resilience domain from that framework:
class Sub : Super {
var gen: Gen<Sub>?
}
Here, the mechanism for checking whether the generic argument K at which
the metadata for Gen is being instantiated handles the case where K's
metadata is incomplete. At worst, every superclass name from super(K)
up to Super are demangled to instantiate metadata. A number of faster
paths are included as well.
rdar://problem/60790020
In preparation for the prespecialization of metadata for generic
classes, make checkMetadataState always return that the state of
prespecialized class metadata is complete, as is done for generic
structs and enums already.