There are multiple reasons to do this. Primarily this is
useful as an optimization. Whenever analysis can determine that no
potentially conflicting access occurs within the scope, the access can
be demoted to "nontracking". It is also useful as an escape hatch for
future code deploying to older runtimes. For example, if a future access
scope may cross threads, and the older runtime doesn't know how to
migrate threads.
See <rdar://problem/37507434> add a flag to swift_beginAccess to inform
the runtime that an access might migrate between threads
I de-templated MetadataState and MetadataRequest because we weren't
relying on the template and because using the template was causing
conversion problems due to the inability to directly template an enum
in C++.
Rename it to swift_initClassMetadata() just like we recently did
swift_initStructMetadata(), and add a StructLayoutFlags parameter
so we can version calls to this function in the future.
Maybe at some point this will become a separate ClassLayoutFlags
type, but at this point it doesn't matter because IRGen always
passes a value of 0.
This includes global generic and non-generic global access
functions, protocol associated type access functions,
swift_getGenericMetadata, and generic type completion functions.
The main part of this change is that the functions now need to take
a MetadataRequest and return a MetadataResponse, which is capable
of expressing that the request can fail. The state of the returned
metadata is reported as an second, independent return value; this
allows the caller to easily check the possibility of failure without
having to mask it out from the returned metadata pointer, as well
as allowing it to be easily ignored.
Also, change metadata access functions to use swiftcc to ensure that
this return value is indeed returned in two separate registers.
Also, change protocol associated conformance access functions to use
swiftcc. This isn't really related, but for some reason it snuck in.
Since it's clearly the right thing to do, and since I really didn't
want to retroactively tease that back out from all the rest of the
test changes, I've left it in.
Also, change generic metadata access functions to either pass all
the generic arguments directly or pass them all indirectly. I don't
know how we ended up with the hybrid approach. I needed to change all
the code-generation and calls here anyway in order to pass the request
parameter, and I figured I might as well change the ABI to something
sensible.
The allocation phase is guaranteed to succeed and just puts enough
of the structure together to make things work.
The completion phase does any component metadata lookups that are
necessary (for the superclass, fields, etc.) and performs layout;
it can fail and require restart.
Next up is to support this in the runtime; then we can start the
process of making metadata accessors actually allow incomplete
metadata to be fetched.
The layout changes to become relative-address based. For this to be
truly immutable (at least on Darwin), things like the RO data patterns
must be moved out of the pattern header. Additionally, compress the
pattern header so that we do not include metadata about patterns that
are not needed for the type.
Value metadata patterns just include the metadata kind and VWT.
The design here is meant to accomodate non-default instantiation
patterns should that become an interesting thing to support in the
future, e.g. for v-table specialization.
Minimize the generic class metadata template by removing the
class header and base-class members. Add back the set of
information that's really required for instantiation.
Teach swift_allocateGenericClass how to allocate classes without
superclass metadata. Reorder generic initialization to establish
a stronger phase-ordering between allocation (the part that doesn't
really care about the generic arguments) and initialization (the
part that really does care about the generic arguments and therefore
might need to be delayed to handle metadata cycles).
A similar thing needs to happen for resilient class relocation.
We dump the following information:
1. The Kind.
2. Pointer to the value witnesses.
3. Pointer to the class object if one is available.
4. Pointer the type context description if one is available.
5. Pointer to the generic arguments if one is available.
This makes it significantly easier to poke around Metadata.
rdar://34222540
This is useful when trying to track down data corruption in the runtime. I am
currently running into such issues with the +0-all-arg work, so I am adding
stuff like this to help debug this issue and future such issues.
rdar://34222540
This new format more efficiently represents existing information, while
more accurately encoding important information about nested generic
contexts with same-type and layout constraints that need to be evaluated
at runtime. It's also designed with an eye to forward- and
backward-compatible expansion for ABI stability with future Swift
versions.
Extend witness tables with a pointer to the protocol conformance
descriptor from which the witness table was generated. This will allow
us to determine (for example) whether two witness tables were
generated from the same (or equivalent) conformances in the future, as
well as discover more information about the witness table itself.
Fixes rdar://problem/36287959.
Protocol conformance records are becoming richer and more interesting;
separate out the "flags" word and add the various other fields that we
want there (is-retroactive, is-synthesized-nonunique, # of conditional
requirements).
The nominal type access functions took all of the generic arguments
directly, which is hard to call from the runtime. Instead, pass up to
three generic arguments directly (because it’s good for code size), and put the rest into an array.
Introduce a flags parameter to swift_getTupleTypeMetadata(). Add a flag
stating when the "labels" parameter points into nonconstant memory, in
which case we need to make a copy of the string before adding an entry
into the concurrent map.
Now that we use nominal type descriptors for everything that we can within
protocol conformance records, eliminate the unused
"NonuniqueDirectType" case and all of the code that supports it. Leave
this value explicitly reserved for the future.
Nominal type descriptors are not always unique, so testing them via pointer
equality is not correct. Introduce an "isEqual()" operation for
nominal type descriptors that performs the appropriate equality check,
using pointer equality when possible, and falling back to string
comparisons of the mangled type name when it is not possible.
Introduce a "nonunique" flag into nominal type descriptors to describe
when they are, in fact, not unique. The only nonunique nominal type
descriptors currently come from Clang-imported types; all
Swift-defined types have unique nominal type descriptors. Use this
flag to make the aforementioned operation efficient in the "unique"
case.
Use the new isEqual() operation for protocol conformance lookup, and
make sure we're caching results based on the known-canonical nominal
type descriptor.
Use the spare bits within the type reference field to describe the kinds
of type metadata records, so that we no longer need to rely on a
separate "flags" field.
Rather than emitting unique, direct type metadata for non-foreign
types, emit a reference to the nominal type descriptor. This collapses
the set of type metadata reference kinds to 3: nominal type
descriptor, (indirect) Objective-C class object, and nonuniqued
foreign type metadata.
Now that references to Objective-C class objects are indirected
(via UniqueIndirectClass), classes with Swift type metadata can be
directly referenced (via UniqueDirectType) rather than hopping through
swift_getObjCClassMetadata().
The protocol conformance record has two bits to describe how the
witness table will be produced. There are currently three states
(direct reference to witness table, witness table accessor, and
conditional witness table accessor). Add a reserved case for the
fourth state so the Swift 5 runtime will (silently) ignore
conformances using that fourth state, when/if some future Swift
uses it.
Swift class metadata has a bit to distinguish it from non-Swift Objective-C
classes. The stable ABI will use a different bit so that stable Swift and
pre-stable Swift can be distinguished from each other.
No bits are actually changed yet. Enabling the new bit needs to wait for
other coordination such as libobjc.
rdar://35767811
- Create the value witness table as a separate global object instead
of concatenating it to the metadata pattern.
- Always pass the metadata to the runtime and let the runtime handle
instantiating or modifying the value witness table.
- Pass the right layout algorithm version to the runtime; currently
this is always "Swift 5".
- Create a runtime function to instantiate single-case enums.
Among other things, this makes the copying of the VWT, and any
modifications of it, explicit and in the runtime, which is more
future-proof.
Proper evaluation of conditional conformances at runtime (e.g., as part of
dynamic casting) is too large to tackle in the Swift 4.1 timeframe. For now,
record that a conformance is conditional in the protocol conformance record,
and always return "does not conform" to such types.
Fixes rdar://problem/35761301.
This changes layout of the `TargetFunctionTypeFlags` to allocate
8 bits for flags, 8 bits for convesion and 16 bits for number of
parameters. Documentation is updated accordingly.
Switch most general endpoint to be `flags, parameters, parameterFlags, result`,
instead of opaque `void **`, more specialized ones to use follow argument scheme:
`flags, param0, [flags0], ..., paramN, [flagsN], result` and store parameter/flags
information separately in `FunctionCacheEntry::{Key, Data}` as well.