- Lower Objective-C class typerefs as strong references with unknown
reference counting.
- Lower other imported C types as builtin blobs of their known
size, alignment, etc.
In the future, it might be beneficial to track which stored properties
of imported types are pointers, for better conservative scanning of
outgoing pointers to the heap.
rdar://problem/26240258
rdar://problem/26240394
Getting metadata from a metatype source just means loading from an offset;
with a reference source we have to dereference the isa pointer first.
Thanks to @bitjammer for pointing out this was broken.
- Fix caller/callee confusion, and use the right SIL function type
for obtaining the generic signature.
- Correctly interpret the NecessaryBindings structure and the
substitutions therein.
- Fix alignment for capture and builtin type descriptors
- Put capture descriptor typerefs in the correct section
Add new SIL-level tests to precisely trigger various scenarios.
Rather than collection nominal type and extension decls and emit
reflection metadata records in one go, we can emit them as they
are encountered and instead collection builtin types referenced
by those at the end.
If there are any builtin types referenced by closure captures
[in the standard library], make sure to collect them so we emit
reflection metadata for them in the builtin section.
For now, just enough for lowering.
Perhaps we should have a way to always just get this information
from metadata instead, since protocol metadata is always static
and not instantiated.
This would require the static "object file" interface used by
swift-reflection-dump to take a callback for symbol lookup.
These types are not directly referenced as fields of aggregate types,
but are needed for reflection type lowering.
Also, use a SetVector to collect referenced builtin types, instead of
a SmallPtrSet, to ensure compiler output is deterministic.
MCJIT doesn't like offset relocations into the data sections, so the
capture descriptors and their typerefs/metadata source encoded strings
will need to be emitted as globals and not go into the reflection data
sections.
For convenience when reading looking at heap closure metadata.
Also move the capture typerefs above the metadata sources, since
they're more likely to be accessed than generic metadata sources.
Now we can discern the types of values in heap boxes at runtime!
Closure reference captures are a common way of creating reference
cycles, so this provides some basic infrastructure for detecting those
someday.
A closure capture descriptor has the following:
- The number of captures.
- The number of sources of metadata reachable from the closure.
This is important for substituting generics at runtime since we
can't know precisely what will get captured until we observe a
closure.
- The number of types in the NecessaryBindings structure.
This is a holding tank in a closure for sources of metadata that
can't be gotten from the captured values themselves.
- The metadata source map, a list of pairs, for each
source of metadata for every generic argument needed to perform
substitution at runtime.
Key: The typeref for the generic parameter visible from the closure
in the Swift source.
Value: The metadata source, which describes how to crawl the heap from
the closure to get to the metadata for that generic argument.
- A list of typerefs for the captured values themselves.
Follow-up: IRGen tests for various capture scenarios, which will include
MetadataSource encoding tests.
rdar://problem/24989531
In order to perform layout, the remote mirrors library needs to know
about the size, alignment and extra inhabitants of builtin types.
Ideally we would emit a reflection info section in libswiftRuntime.o,
but in the meantime just duplicate builtin type metadata for all
builtin types referenced from the current module instead.
In practice only the stdlib and a handful of overlays like the SIMD
overlay use builtin types, and only a few at a time.
Tested manually by running swift-reflection-tool on the standard
library -- I'll add automated tests by using -parse-stdlib to
reference Builtin types in a subsequent patch that adds more layout
logic.
NFC if -enable-reflection-metadata is off.
Otherwise, we will insert padding if the field metadata section size
is not a multiple of the word size, which will cause a crash when
we later try to read it.
This turns on the remote reflection metadata by default for swift
invocations and the standard library. The size delta for all of the
sections is:
Section __swift3_typeref: 20176
Section __swift3_reflstr: 2556
Section __swift3_fieldmd: 8172
Section __swift3_assocty: 18112
Recognizing that this is a nontrivial increase in binary size, we can
reduce this with a few methods:
- Trie for strings (typerefs and field names are both strings) but would
need an implementation
- Compress the entire sections: this would need an implementation
available on all platforms where we support the functionality.
- Don't use the AST mangler but a custom mangling, which may be slightly
more compact because it can specialize by need and maybe not include
some mangle nodes that typerefs don't need.
Similiar to the change to field reflection metadata, don't use the
interface for the key of associated type lookup, because the nominal
type descriptors don't include generics in their mangled name strings.
Nominal type descriptors use declared types for their mangled names,
so we need to use them when scanning the fieldmd section for a
matching record. This is fine because the descriptor can tell us
about the type's generics. Individual field records continue to use
the interface type.
These likely don't have Swift type metadata but might be useful to
record or instantiate based on what kind of metadata is encountered for
the sake of memory tools.
- Nearly done: TypeRefs and the mangled name decoder.
- Add the swift-reflection-test tool.
The field reflection pipeline is roughly:
- Decode type references
- Substitute generic parameters
- Calculate sizes and offsets
There is currently only one action in the tool, which will test the
*Decode* part of the pipeline: `dump-reflection-section`. This reads
the *swift3_reflect section from an object file and dumps the decoded
type references for all of the stored properties and enum cases in the
file.
- TODO: Write tests with various type arrangements to exercise the
decoder - there are likely some holes in the decoder still since the
AST mangler is quite rich in its kinds.
TODO: The next test mode, `dump-field-types`, will do the following:
1. Launch a swift executable with a canned stopping point
2. Get the address of a heap object instance of interest
3. Dump the fully substituted typerefs of all of the stored properties
or enum case payloads.
That test mode will be more involved since it will attach to another
process and need to read from its address space but will test the
entire out-of-process reflection pipeline in a controlled environment.
We can maybe take this test a step further, with an option or a new
test mode, that prints the entire heap reference graph rooted at that
object of interest, in order to test the ability to detect reference
cycles, for example.
- Implement emission of type references for nominal type field
reflection, using a small custom encoder resulting in packed
structs, not strings. This will let us embed 7-bit encoded
32-bit relative offsets directly in the structure (not yet
hooked in).
- Use the AST Mangler for encoding type references
Archetypes and internal references were complicating this before, so we
can take the opportunity to reuse this machinery and avoid unique code
and new ABI.
Next up: Tests for reading the reflection sections and converting the
demangle tree into a tree of type references.
Todo: For concrete types, serialize the types for associated types of
their conformances to bootstrap the typeref substitution process.
rdar://problem/15617914