Skip to content

MetadataReader infrastructure for reading capture descriptors #2298

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions include/swift/Reflection/Records.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,63 +341,6 @@ class BuiltinTypeDescriptorIterator
}
};

/// A key-value pair in a TypeRef -> MetadataSource map.
struct GenericMetadataSource {
using Key = RelativeDirectPointer<const char>;
using Value = Key;

const Key MangledTypeName;
const Value EncodedMetadataSource;
};

/// Describes the layout of a heap closure.
///
/// For simplicity's sake and other reasons, this shouldn't contain
/// architecture-specifically sized things like direct pointers, uintptr_t, etc.
struct CaptureDescriptor {
public:

/// The number of captures in the closure and the number of typerefs that
/// immediately follow this struct.
const uint32_t NumCaptures;

/// The number of sources of metadata available in the MetadataSourceMap
/// directly following the list of capture's typerefs.
const uint32_t NumMetadataSources;

/// The number of items in the NecessaryBindings structure at the head of
/// the closure.
const uint32_t NumBindings;

/// Get the key-value pair for the ith generic metadata source.
const GenericMetadataSource &getGenericMetadataSource(size_t i) const {
assert(i <= NumMetadataSources &&
"Generic metadata source index out of range");
auto Begin = getGenericMetadataSourceBuffer();
return Begin[i];
}

/// Get the typeref (encoded as a mangled type name) of the ith
/// closure capture.
const RelativeDirectPointer<const char> &
getCaptureMangledTypeName(size_t i) const {
assert(i <= NumCaptures && "Capture index out of range");
auto Begin = getCaptureTypeRefBuffer();
return Begin[i];
}

private:
const GenericMetadataSource *getGenericMetadataSourceBuffer() const {
auto BeginTR = reinterpret_cast<const char *>(getCaptureTypeRefBuffer());
auto EndTR = BeginTR + NumCaptures * sizeof(GenericMetadataSource);
return reinterpret_cast<const GenericMetadataSource *>(EndTR);
}

const RelativeDirectPointer<const char> *getCaptureTypeRefBuffer() const {
return reinterpret_cast<const RelativeDirectPointer<const char> *>(this+1);
}
};

} // end namespace reflection
} // end namespace swift

Expand Down
37 changes: 36 additions & 1 deletion include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ namespace remote {
template <typename Runtime>
using SharedTargetMetadataRef = std::shared_ptr<TargetMetadata<Runtime>>;

using SharedCaptureDescriptor = std::shared_ptr<const CaptureDescriptor>;

template <typename Runtime>
using SharedTargetNominalTypeDescriptorRef
= std::shared_ptr<TargetNominalTypeDescriptor<Runtime>>;
Expand Down Expand Up @@ -527,7 +529,7 @@ class MetadataReader {
case MetadataKind::ForeignClass:
return Builder.getUnnamedForeignClassType();
case MetadataKind::HeapLocalVariable:
return Builder.getUnnamedForeignClassType(); // FIXME?
return Builder.getUnnamedForeignClassType(); // FIXME?
case MetadataKind::HeapGenericLocalVariable:
return Builder.getUnnamedForeignClassType(); // FIXME?
case MetadataKind::ErrorObject:
Expand Down Expand Up @@ -805,6 +807,39 @@ class MetadataReader {
TypeCache.insert({metadata.getAddress(), nominal});
return nominal;
}

/// Read the entire CaptureDescriptor in this address space, including
/// trailing capture typeref relative offsets, and GenericMetadataSource
/// pairs.
SharedCaptureDescriptor readCaptureDescriptor(StoredPointer Address) {

uint32_t NumCaptures = 0;
uint32_t NumMetadataSources = 0;

StoredSize Offset = 0;

if (!Reader->readInteger(Address + Offset, &NumCaptures))
return nullptr;

Offset += sizeof(NumCaptures);

if (!Reader->readInteger(Address + Offset, &NumMetadataSources))
return nullptr;

StoredSize Size = sizeof(CaptureDescriptor) +
NumCaptures * sizeof(RelativeDirectPointer<const char>) +
NumMetadataSources * sizeof(GenericMetadataSource);

auto Buffer = (uint8_t *)malloc(Size);

if (!Reader->readBytes(Address, Buffer, Size)) {
free(Buffer);
return nullptr;
}

auto RawDescriptor = reinterpret_cast<const CaptureDescriptor *>(Buffer);
return SharedCaptureDescriptor(RawDescriptor, /*deleter*/ free);
}
};

} // end namespace remote
Expand Down
86 changes: 68 additions & 18 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1750,29 +1750,79 @@ struct TargetClassMetadata : public TargetHeapMetadata<Runtime> {
};
using ClassMetadata = TargetClassMetadata<InProcess>;

/// A key-value pair in a TypeRef -> MetadataSource map.
struct GenericMetadataSource {
using Key = RelativeDirectPointer<const char>;
using Value = Key;

const Key MangledTypeName;
const Value EncodedMetadataSource;
};

/// Describes the layout of a heap closure.
///
/// For simplicity's sake and other reasons, this shouldn't contain
/// architecture-specifically sized things like direct pointers, uintptr_t, etc.
///
/// Following the CaptureDescriptor are:
/// - a list of direct relative offsets to the mangled type names of the
/// captures (these aren't in the DATA segment, however).
/// - a list of GenericMetadataSource objects - each element is a pair of:
/// - MangledTypeName (for a GenericTypeParameterTypeRef)
/// - EncodededMetadataSource (an encoded string like TypeRefs, but describe
/// the method of crawling to the metadata for that generic type parameter.
struct CaptureDescriptor {
public:

/// The number of captures in the closure and the number of typerefs that
/// immediately follow this struct.
const uint32_t NumCaptures;

/// The number of sources of metadata available in the MetadataSourceMap
/// directly following the list of capture's typerefs.
const uint32_t NumMetadataSources;

/// The number of items in the NecessaryBindings structure at the head of
/// the closure.
const uint32_t NumBindings;

/// Get the key-value pair for the ith generic metadata source.
const GenericMetadataSource &getGenericMetadataSource(size_t i) const {
assert(i <= NumMetadataSources &&
"Generic metadata source index out of range");
auto Begin = getGenericMetadataSourceBuffer();
return Begin[i];
}

/// Get the typeref (encoded as a mangled type name) of the ith
/// closure capture.
const RelativeDirectPointer<const char> &
getCaptureMangledTypeName(size_t i) const {
assert(i <= NumCaptures && "Capture index out of range");
auto Begin = getCaptureTypeRefBuffer();
return Begin[i];
}

private:
const GenericMetadataSource *getGenericMetadataSourceBuffer() const {
auto BeginTR = reinterpret_cast<const char *>(getCaptureTypeRefBuffer());
auto EndTR = BeginTR + NumCaptures * sizeof(GenericMetadataSource);
return reinterpret_cast<const GenericMetadataSource *>(EndTR);
}

const RelativeDirectPointer<const char> *getCaptureTypeRefBuffer() const {
return reinterpret_cast<const RelativeDirectPointer<const char> *>(this+1);
}
};

/// The structure of metadata for heap-allocated local variables.
/// This is non-type metadata.
///
/// It would be nice for tools to be able to dynamically discover the
/// type of a heap-allocated local variable. This should not require
/// us to aggressively produce metadata for the type, though. The
/// obvious solution is to simply place the mangling of the type after
/// the variable metadata.
///
/// One complication is that, in generic code, we don't want something
/// as low-priority (sorry!) as the convenience of tools to force us
/// to generate per-instantiation metadata for capturing variables.
/// In these cases, the heap-destructor function will be using
/// information stored in the allocated object (rather than in
/// metadata) to actually do the work of destruction, but even then,
/// that information needn't be metadata for the actual variable type;
/// consider the case of local variable of type (T, Int).
///
/// Anyway, that's all something to consider later.
template <typename Runtime>
struct TargetHeapLocalVariableMetadata
: public TargetHeapMetadata<Runtime> {
// No extra fields for now.
using StoredPointer = typename Runtime::StoredPointer;
uint32_t OffsetToFirstCapture;
TargetPointer<Runtime, CaptureDescriptor> CaptureDescription;
};
using HeapLocalVariableMetadata
= TargetHeapLocalVariableMetadata<InProcess>;
Expand Down