and MetadataCache and fix a re-entrancy bug in metadata
instantiation.
The re-entrancy bug is that we were holding the instantiation
lock of a metadata cache while instantiating metadata. Doing
so prevents us from creating a different instantiation if
it's needed by the outer instantiation. This is already
possible, but it's much more likely in a patch I'm working on
to only store the minimal metadata for generic parameters
in generic types.
The same bug could also show up as a deadlock between threads,
so a recursive lock would not be a good fix. Instead, we add
a condition variable to the metadata cache. When fetching
metadata, we look for a node in the concurrent map, eagerly
creating an empty one if none currently exists. If lookup
finds an empty node, we wait on the condition variable for
the node to become populated. If lookup succeeds in creating
an empty node, we instantiate the metadata, grab the lock,
populate the node, and notify the condition variable.
Safely creating an empty node without any metadata present
requires us to move the key data into the map entry. That,
plus a few other invariant shifts, makes it sensible to
give the user of ConcurrentMap more control over the
allocation of map nodes and the layout of keys. That, in
turn, allows us to change the contract so that keys can be
more complex than just a hash code. Instead of incrementing
hash codes and re-performing the lookup, we just insist
that lookup keys be totally ordered.
For now, I've kept the uniform use of hash codes as a
component of the key for MetadataCaches. However, hash
codes aren't really profitable for small keys, and we should
probably use direct comparisons instead.
We should also switch the safer metadata caches (i.e. the
ones that don't involve calling an arbitrary instantiation
function, like MetatypeMetadataCache) over to directly use
ConcurrentMap.
LLDB's requirement that we maintain a linked list of metadata
cache instantiations with a known layout means we can't yet
remove the CacheEntry's redundant copy of the generic
arguments.
I am adding this test mainly to check that the code that removed the sentinal
value and replaced it with a nullable pointer and some logic for initializing
the pointer works.
This is the first patch in a series that will allow new protocol
requirements to be added resiliently, with the runtime filling in
default implementations in witness tables.
First, this adds a new flag to the protocol descriptor indicating
that the protocol is resilient. In this case, there are two
additional fields, MinimumWitnessTableSizeInWords and
DefaultWitnessTableSizeInWords, followed by tail-allocated
default witnesses.
The swift_getGenericWitnessTable() entry point now fills in the
default witnesses from the protocol if the given witness table
template is smaller than the expected witness table size.
This also changes the layout of instantiated witness tables to move
the address point to the end of private data. Previously the private
data came after the requirements, but this meant that adding new
requirements would require sliding the private data at runtime and
accessing it indirectly. It is much simpler to access it from
negative offsets instead.
I updated IRGen to emit the new metadata, but currently all protocols
are flagged as not resilient, and default witnesses are not emitted;
this will come in a subsequent patch once some more plumbing is
in place.
To avoid generating GOT entries for references to protocols defined
in the current module, I had to add some hacks to the existing hack
for this. I'll hopefully clean this up in a principled manner later.
It didn't properly set "withInlineStorage(false)" on the test value witness table, causing it to pick direct-storage value witnesses that overflow a fixed-size buffer and crash on the ASan bot. Fix the test, and add a check for a canary that fails even without ASan.
Swift SVN r30462
We incorrectly tested the uninitialized "next" pointer against MAP_FAILED, instead of the real result of mmap. Fixes rdar://problem/21659505.
Swift SVN r30030
@objc protocols aren't supported with an ObjC runtime, but we still want values of AnyObject type to be word-sized. Handle this by turning the binary "needsWitnessTable" condition into a "dispatch strategy" enum, so we can recognize the condition "has no methods, so neither swift nor objc dispatch" as distinct from either swift or ObjC protocol representations. Assign this dispatch strategy when we lower AnyObject. Should be NFC for the ObjC-enabled build.
(It would also be beneficial for the ObjC-runtime-enabled version of Swift if AnyObject weren't an @objc protocol; that would mean we could give it a canonical protocol descriptor in the standard library, among other things. There are fairly deep assumptions in Sema that AnyObject is @objc, though, and it's not worth disturbing those assumptions right now.)
Reapplying with updates to the runtime unit tests.
Swift SVN r27341
If an existential type for a special protocol (not a composition) is instantiated, carry the special protocol identifier from that protocol to the existential, allowing us to easily recognize existentials with unique runtime characteristics.
Swift SVN r26436
Metatype metadata now always refers to the maximally-abstracted @thick metatype representation, so metatypes are never trivial from the runtime's point of view.
Swift SVN r21975
constructs generic class metadata properly when the
superclass has an unexpected prefix.
Also fix a bug in the constructor for ClassMetadata (which is
only actually constructed this way in unit tests).
Swift SVN r20586
unexpected forematter from the superclass.
This requires a pretty substantial shift in the
generic-metadata allocation/initialization dance
because (1) we can't allocate class metadata without
knowing what the superclass is and (2) the offset
from the metadata cache entry to the address point is
no longer determined solely by the metadata pattern.
While I'm making invasive changes to metadata, fix
two race conditions in metadata creation. The first
is that we need to ensure that only one thread succeeds
at lazily creating a generic-metadata cache. The second
is that we need to ensure that only one thread actually
attempts to create a particular metadata; any others
should block until the metadata is successfully built.
This commit finishes rdar://17776354. LLDB will
need to adjust to the runtime-private metadata layout
changes.
Swift SVN r20537
a flags field, add an instance address point field, and reserve
some additional space.
This change must be coordinated with a corresponding change
to ObjC runtime bits in libarclite; without this, dynamic
subclassing features like KVO will break.
The actual contents of the new fields can change without
bothering the ObjC runtime.
Swift SVN r20183
I've put these fields on the class object for now, just
so we can at least theoretically update them. A superclass
that grew left rather than right could maybe even be made
to work with this schema, but probably not.
rdar://16705821
Swift SVN r16880
Set up a metadata cache for existential type metadata. Instantiate existential metadata by first sorting the protocol list, so that it is order invariant, precomputing the overall witness table count and class constraint of the composition so it can be cached in the existential metadata.
We still need to implement value witnesses for existential containers in the runtime before this is complete. We can at least test the uniquing and flags computations at this point.
Swift SVN r9727
The principal difficulty here is that we need accessing the
value witness table for a type to be an efficient operation,
but there (obviously) isn't a VWT field for ObjC classes.
Placing this field after the metatype would tend to bloat
metatypes by quite a bit. Placing it before is best, but
it introduces an unfortunate difference between the address
point of a metatype and the address of the global symbol.
That, however, can be fixed with appropriate linker support.
Still, for now this is rather unfortunately over-subtle.
Swift SVN r3307