Skip to content

Commit 3a3cafc

Browse files
committed
MetadataReader infrastructure for reading capture descriptors
This starts wiring up capture descriptors to the metadata reader so we can discern the layout of closures at runtime. rdar://problem/24989531
1 parent 936d4e5 commit 3a3cafc

File tree

3 files changed

+104
-76
lines changed

3 files changed

+104
-76
lines changed

include/swift/Reflection/Records.h

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -341,63 +341,6 @@ class BuiltinTypeDescriptorIterator
341341
}
342342
};
343343

344-
/// A key-value pair in a TypeRef -> MetadataSource map.
345-
struct GenericMetadataSource {
346-
using Key = RelativeDirectPointer<const char>;
347-
using Value = Key;
348-
349-
const Key MangledTypeName;
350-
const Value EncodedMetadataSource;
351-
};
352-
353-
/// Describes the layout of a heap closure.
354-
///
355-
/// For simplicity's sake and other reasons, this shouldn't contain
356-
/// architecture-specifically sized things like direct pointers, uintptr_t, etc.
357-
struct CaptureDescriptor {
358-
public:
359-
360-
/// The number of captures in the closure and the number of typerefs that
361-
/// immediately follow this struct.
362-
const uint32_t NumCaptures;
363-
364-
/// The number of sources of metadata available in the MetadataSourceMap
365-
/// directly following the list of capture's typerefs.
366-
const uint32_t NumMetadataSources;
367-
368-
/// The number of items in the NecessaryBindings structure at the head of
369-
/// the closure.
370-
const uint32_t NumBindings;
371-
372-
/// Get the key-value pair for the ith generic metadata source.
373-
const GenericMetadataSource &getGenericMetadataSource(size_t i) const {
374-
assert(i <= NumMetadataSources &&
375-
"Generic metadata source index out of range");
376-
auto Begin = getGenericMetadataSourceBuffer();
377-
return Begin[i];
378-
}
379-
380-
/// Get the typeref (encoded as a mangled type name) of the ith
381-
/// closure capture.
382-
const RelativeDirectPointer<const char> &
383-
getCaptureMangledTypeName(size_t i) const {
384-
assert(i <= NumCaptures && "Capture index out of range");
385-
auto Begin = getCaptureTypeRefBuffer();
386-
return Begin[i];
387-
}
388-
389-
private:
390-
const GenericMetadataSource *getGenericMetadataSourceBuffer() const {
391-
auto BeginTR = reinterpret_cast<const char *>(getCaptureTypeRefBuffer());
392-
auto EndTR = BeginTR + NumCaptures * sizeof(GenericMetadataSource);
393-
return reinterpret_cast<const GenericMetadataSource *>(EndTR);
394-
}
395-
396-
const RelativeDirectPointer<const char> *getCaptureTypeRefBuffer() const {
397-
return reinterpret_cast<const RelativeDirectPointer<const char> *>(this+1);
398-
}
399-
};
400-
401344
} // end namespace reflection
402345
} // end namespace swift
403346

include/swift/Remote/MetadataReader.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ namespace remote {
3131
template <typename Runtime>
3232
using SharedTargetMetadataRef = std::shared_ptr<TargetMetadata<Runtime>>;
3333

34+
using SharedCaptureDescriptor = std::shared_ptr<const CaptureDescriptor>;
35+
3436
template <typename Runtime>
3537
using SharedTargetNominalTypeDescriptorRef
3638
= std::shared_ptr<TargetNominalTypeDescriptor<Runtime>>;
@@ -527,7 +529,7 @@ class MetadataReader {
527529
case MetadataKind::ForeignClass:
528530
return Builder.getUnnamedForeignClassType();
529531
case MetadataKind::HeapLocalVariable:
530-
return Builder.getUnnamedForeignClassType(); // FIXME?
532+
return Builder.getUnnamedForeignClassType(); // FIXME?
531533
case MetadataKind::HeapGenericLocalVariable:
532534
return Builder.getUnnamedForeignClassType(); // FIXME?
533535
case MetadataKind::ErrorObject:
@@ -805,6 +807,39 @@ class MetadataReader {
805807
TypeCache.insert({metadata.getAddress(), nominal});
806808
return nominal;
807809
}
810+
811+
/// Read the entire CaptureDescriptor in this address space, including
812+
/// trailing capture typeref relative offsets, and GenericMetadataSource
813+
/// pairs.
814+
SharedCaptureDescriptor readCaptureDescriptor(StoredPointer Address) {
815+
816+
uint32_t NumCaptures = 0;
817+
uint32_t NumMetadataSources = 0;
818+
819+
StoredSize Offset = 0;
820+
821+
if (!Reader->readInteger(Address + Offset, &NumCaptures))
822+
return nullptr;
823+
824+
Offset += sizeof(NumCaptures);
825+
826+
if (!Reader->readInteger(Address + Offset, &NumMetadataSources))
827+
return nullptr;
828+
829+
StoredSize Size = sizeof(CaptureDescriptor) +
830+
NumCaptures * sizeof(RelativeDirectPointer<const char>) +
831+
NumMetadataSources * sizeof(GenericMetadataSource);
832+
833+
auto Buffer = (uint8_t *)malloc(Size);
834+
835+
if (!Reader->readBytes(Address, Buffer, Size)) {
836+
free(Buffer);
837+
return nullptr;
838+
}
839+
840+
auto RawDescriptor = reinterpret_cast<const CaptureDescriptor *>(Buffer);
841+
return SharedCaptureDescriptor(RawDescriptor, /*deleter*/ free);
842+
}
808843
};
809844

810845
} // end namespace remote

include/swift/Runtime/Metadata.h

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,29 +1750,79 @@ struct TargetClassMetadata : public TargetHeapMetadata<Runtime> {
17501750
};
17511751
using ClassMetadata = TargetClassMetadata<InProcess>;
17521752

1753+
/// A key-value pair in a TypeRef -> MetadataSource map.
1754+
struct GenericMetadataSource {
1755+
using Key = RelativeDirectPointer<const char>;
1756+
using Value = Key;
1757+
1758+
const Key MangledTypeName;
1759+
const Value EncodedMetadataSource;
1760+
};
1761+
1762+
/// Describes the layout of a heap closure.
1763+
///
1764+
/// For simplicity's sake and other reasons, this shouldn't contain
1765+
/// architecture-specifically sized things like direct pointers, uintptr_t, etc.
1766+
///
1767+
/// Following the CaptureDescriptor are:
1768+
/// - a list of direct relative offsets to the mangled type names of the
1769+
/// captures (these aren't in the DATA segment, however).
1770+
/// - a list of GenericMetadataSource objects - each element is a pair of:
1771+
/// - MangledTypeName (for a GenericTypeParameterTypeRef)
1772+
/// - EncodededMetadataSource (an encoded string like TypeRefs, but describe
1773+
/// the method of crawling to the metadata for that generic type parameter.
1774+
struct CaptureDescriptor {
1775+
public:
1776+
1777+
/// The number of captures in the closure and the number of typerefs that
1778+
/// immediately follow this struct.
1779+
const uint32_t NumCaptures;
1780+
1781+
/// The number of sources of metadata available in the MetadataSourceMap
1782+
/// directly following the list of capture's typerefs.
1783+
const uint32_t NumMetadataSources;
1784+
1785+
/// The number of items in the NecessaryBindings structure at the head of
1786+
/// the closure.
1787+
const uint32_t NumBindings;
1788+
1789+
/// Get the key-value pair for the ith generic metadata source.
1790+
const GenericMetadataSource &getGenericMetadataSource(size_t i) const {
1791+
assert(i <= NumMetadataSources &&
1792+
"Generic metadata source index out of range");
1793+
auto Begin = getGenericMetadataSourceBuffer();
1794+
return Begin[i];
1795+
}
1796+
1797+
/// Get the typeref (encoded as a mangled type name) of the ith
1798+
/// closure capture.
1799+
const RelativeDirectPointer<const char> &
1800+
getCaptureMangledTypeName(size_t i) const {
1801+
assert(i <= NumCaptures && "Capture index out of range");
1802+
auto Begin = getCaptureTypeRefBuffer();
1803+
return Begin[i];
1804+
}
1805+
1806+
private:
1807+
const GenericMetadataSource *getGenericMetadataSourceBuffer() const {
1808+
auto BeginTR = reinterpret_cast<const char *>(getCaptureTypeRefBuffer());
1809+
auto EndTR = BeginTR + NumCaptures * sizeof(GenericMetadataSource);
1810+
return reinterpret_cast<const GenericMetadataSource *>(EndTR);
1811+
}
1812+
1813+
const RelativeDirectPointer<const char> *getCaptureTypeRefBuffer() const {
1814+
return reinterpret_cast<const RelativeDirectPointer<const char> *>(this+1);
1815+
}
1816+
};
1817+
17531818
/// The structure of metadata for heap-allocated local variables.
17541819
/// This is non-type metadata.
1755-
///
1756-
/// It would be nice for tools to be able to dynamically discover the
1757-
/// type of a heap-allocated local variable. This should not require
1758-
/// us to aggressively produce metadata for the type, though. The
1759-
/// obvious solution is to simply place the mangling of the type after
1760-
/// the variable metadata.
1761-
///
1762-
/// One complication is that, in generic code, we don't want something
1763-
/// as low-priority (sorry!) as the convenience of tools to force us
1764-
/// to generate per-instantiation metadata for capturing variables.
1765-
/// In these cases, the heap-destructor function will be using
1766-
/// information stored in the allocated object (rather than in
1767-
/// metadata) to actually do the work of destruction, but even then,
1768-
/// that information needn't be metadata for the actual variable type;
1769-
/// consider the case of local variable of type (T, Int).
1770-
///
1771-
/// Anyway, that's all something to consider later.
17721820
template <typename Runtime>
17731821
struct TargetHeapLocalVariableMetadata
17741822
: public TargetHeapMetadata<Runtime> {
1775-
// No extra fields for now.
1823+
using StoredPointer = typename Runtime::StoredPointer;
1824+
uint32_t OffsetToFirstCapture;
1825+
TargetPointer<Runtime, CaptureDescriptor> CaptureDescription;
17761826
};
17771827
using HeapLocalVariableMetadata
17781828
= TargetHeapLocalVariableMetadata<InProcess>;

0 commit comments

Comments
 (0)