of associated types in protocol witness tables.
We use the global access functions when the result isn't
dependent, and a simple accessor when the result can be cheaply
recovered from the conforming metadata. Otherwise, we add a
cache slot to a private section of the witness table, forcing
an instantiation per conformance. Like generic type metadata,
concrete instantiations of generic conformances are memoized.
There's a fair amount of code in this patch that can't be
dynamically tested at the moment because of the widespread
reliance on recursive expansion of archetypes / dependent
types. That's something we're now theoretically in a position
to change, and as we do so, we'll test more of this code.
Many of the report* entry points are specific to the stdlib assert implementation, so belong in the stdlib. Keep a single `reportError` entry point in the runtime to handle the CrashReporter/ASL interface, and call down to it from the assert implementation functions.
Now, such classes will emit a metadata pattern and use the
generic metadata instantiation logic.
This was all wired up to handle the case of no generic
parameters previously, to support resilient struct layout
in the runtime.
The swift_initializeSuperclass() entry point still exists,
providing a fast path for when there's no field layout to
do, which is currently always true if we have a concrete
class.
This entry point no longer needs the global lock, since
now we get a per-class lock from the metadata cache.
Also, previously we would call the superclass accessor
function on every access of class metadata for a concrete
subclass of a generic class. Now that we re-use the
existing metadata cache logic, this extra call only occurs
during initialization.
Both swift_initializeSuperclass() and
swift_initClassMetadata_UniversalStrategy() used to take
the superclass as a parameter, but this isn't really
necessary, since it was loaded out of the class metadata
immediately prior to the call by the caller. Removing
this parameter makes the ABI a little simpler.
Once class layout supports resilient types, we will also
use swift_initClassMetadata_UniversalStrategy() to lay
out classes with resilient types as fields.
Singleton metadata caches will still allocate a copy of
the template, which is a slight performance regression
from the previous implementation of concrete subclasses
of generic classes. This will be optimized soon.
Right now, the template can always be modified in place;
in the future, it will be possible to modify in place as
long as the superclass is fixed-layout; a resilient superclass
might add or remove fields, thus we cannot leave room for
it in the metadata of the subclass, and will need to grow
the metadata and slide field offsets at runtime using a
new entry point.
Also, the representation of the cache itself could be
optimized to handle the singleton case, since all we
really need here is a lock without any kind of mapping
table.
Move the following from IRGen to runtime:
- Copying generic parameters from superclass to subclass
- Copying field offsets from superclass to subclass
- Initializing the Objective-C runtime name of the subclass
This eliminates some duplication between the generic subclass and
concrete subclass of a generic class cases.
Also this should reduce generated code size and have no impact on
performance (the instantiation logic only runs once per substituted
type).
This lets us remove `swift_fixLifetime` as a real runtime entry point. Also, avoid generating the marker at all if the LLVM ARC optimizer won't be run, as in -Onone or -disable-llvm-arc-optimizer mode.
class B<T> : NSFoo {}
class A : B<Int> {}
IRGen computes the ivar layout starting from offset zero, since
the size of the 'NSFoo' is unknown and we rely on the Objective-C
runtime to slide the ivar offsets.
The instantiated metadata for B<Int> would contain a field offset
vector with the correct offsets, because of how
swift_initClassMetadata_UniversalStrategy() works.
However, A's metadata is emitted statically, and this includes a
copy of the field offset vector from the superclass. A's metadata
was initialized by swift_initializeSuperclass(), which did not
copy the field offset vector over from A<Int>. And since the
Objective-C runtime only slides the immediate ivars of a class,
the field offsets corresponding to A<Int>'s fields in B's type
metadata were never slid, resulting in problems when an instance
of B was passed to a function operating on an A<T> generically.
Fixes <rdar://problem/23200051>.
Decrease the size of nominal type descriptors and make them true-const by relative-addressing the other metadata they need to reference, which should all be included in the same image as the descriptor itself. Relative-referencing string constants exposes a bug in the Apple linker, which crashes when resolving relative relocations to coalesceable symbols (rdar://problem/22674524); work around this for now by revoking the `unnamed_addr`-ness of string constants that we take relative references to. (I haven't tested whether GNU ld or gold also have this problem on Linux; it may be possible to conditionalize the workaround to only apply to Darwin targets for now.)
A single extra inhabitant is good enough for the most important case,
that being a single level of optionality. Otherwise, we want to
reserve maximal flexibility for the implementation.
This commit also fixes a bug where I was not correctly defining
the extra-inhabitant rules for all of the existential cases.
Fixes <rdar://23122310> Runtime dynamic casts...
This makes runtime dynamic casts consistent with language rules, and
consequently makes specialization of generic code consistent with an
equivalent nongeneric implementation.
The runtime now supports casts from Optional<T> to U. Naturally the
cast fails on nil source, but otherwise succeeds if T is convertible to
U.
When casting T to Optional<U> the runtime succeeds whenever T is
convertible to U and simply wraps the result in an Optional.
To greatly simplify the runtime, I am assuming that
target-type-specific runtime cast entry points
(e.g. swift_dynamicCastClass) are never invoked with an optional
source. This assumption is valid for the following reasons. At the
language level optionals must be unwrapped before downcasting (via
as[?!]), so we only need to worry about SIL and IR lowering. This
implementation assumes (with asserts) that:
- SIL promotion from an address cast to a value casts should only happen
when the source is nonoptional. Handling optional unwrapping in SIL
would be too complicated because we need to check for Optional's own
conformances. (I added a test case to ensure this promotion does not
happen). This is not an issue for unchecked_ref_cast, which
implicitly unwraps optionals, so we can promote those!
- IRGen lowers unchecked_ref_cast (Builtin.castReference) directly to
a bitcast (will be caught by asserts).
- IRGen continues to emit the generic dynamicCast entry point for
address-casts (will be caught by asserts).
There was previously no way to detect a type that is nominally
Optional at runtime. The standard library, namely OutputStream, needs
to handle Optionals specially in order to cirumvent conversion to the
Optional's wrapped type. This should be done with conditional
conformance, but until that feature is available, Builtin.isOptional
will serve as a useful crutch.
Reuses the enum metadata layout and builder because most of the logic is
also required for Optional (generic arg and payload). We may want to
optimize this at some point (Optional doesn't have a Parent), but I
don't see much opportunity.
Note that with this approach there will be no change in metadata layout.
Changing the kind still breaks the ABI of course.
Also leaves the MirrorData summary string as "(Enum Value)". We should
consider changing it.
Fix spurious docs warning that @in and @in_guaranteed should be ``fn``.
Add ``#ifdef SWIFT_OBJC_INTEROP`` to silence a -Wunused-function
on linux since that function is only used from within that #ifdef
elsewhere.
Fix three -Wunused-function warnings on linux.
Fix two -Wunreachable-code warnings on linux dealing with
SWIFT_HAVE_WORKING_STD_REGEX.
This is a bit of a hodge-podge of related changes that I decided
weren't quite worth teasing apart:
First, rename the weak{Retain,Release} entrypoints to
unowned{Retain,Release} to better reflect their actual use
from generated code.
Second, standardize the names of the rest of the entrypoints around
unowned{operation}.
Third, standardize IRGen's internal naming scheme and API for
reference-counting so that (1) there are generic functions for
emitting operations using a given reference-counting style and
(2) all operations explicitly call out the kind and style of
reference counting.
Finally, implement a number of new entrypoints for unknown unowned
reference-counting. These entrypoints use a completely different
and incompatible scheme for working with ObjC references. The
primary difference is that the new scheme abandons the flawed idea
(which I take responsibility for) that we can simulate an unowned
reference count for ObjC references, and instead moves towards an
address-only scheme when the reference might store an ObjC reference.
(The current implementation is still trivially takable, but that is
not something we should be relying on.) These will be tested in a
follow-up commit. For now, we still rely on the bad assumption of
reference-countability.
The C++ ABI for static locals is a bit heavy compared to dispatch_once; doing this saves more than 1KB in runtime code size. Dispatch_once/call_once is also more likely to be hot because it's also used by Swift and ObjC code.
Alas, llvm::get_execution_seed() from llvm/ADT/Hashing.h still inflicts one static local initialization on us we can't override (without forking Hashing.h, anyway).