Template metadata structures

- Add RuntimeTarget template This will allow for converting between
  metadata structures for native host and remote target architectures.

- Create InProcess and External templates for stored pointers

Add a few more types to abstract pointer access in the runtime
structures but keep native in-process pointer access the same as that
with a plain old pointer type.

There is now a notion of a "stored pointer", which is just the raw value
of the pointer, and the actual pointer type, which is used for loads.
Decoupling these allows us to fork the behavior when looking at metadata
in an external process, but keep things the same for the in-process
case.

There are two basic "runtime targets" that you can use to work with
metadata:

InProcess: Defines the pointer to be trivially a T* and stored as a
uintptr_t. A Metadata * is exactly as it was before, but defined via
AbstractMetadata<InProcess>.

External: A template that requires a target to specify its pointer size.

ExternalPointer: An opaque pointer in another address space that can't
(and shouldn't) be indirected with operator* or operator->.  The memory
reader will fetch the data explicitly.
This commit is contained in:
David Farler
2016-02-24 23:55:01 -08:00
parent 744806a742
commit cd65a8e0b0
12 changed files with 524 additions and 277 deletions

View File

@@ -26,11 +26,13 @@
namespace swift {
struct Metadata;
struct InProcess;
template <typename Runtime> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;
/// Kinds of Swift metadata records. Some of these are types, some
/// aren't.
enum class MetadataKind : uintptr_t {
enum class MetadataKind : uint32_t {
#define METADATAKIND(name, value) name = value,
#define ABSTRACTMETADATAKIND(name, start, end) \
name##_Start = start, name##_End = end,
@@ -38,7 +40,7 @@ enum class MetadataKind : uintptr_t {
};
/// Kinds of Swift nominal type descriptor records.
enum class NominalTypeKind : uintptr_t {
enum class NominalTypeKind : uint32_t {
#define NOMINALTYPEMETADATAKIND(name, value) name = value,
#include "MetadataKind.def"
};

View File

@@ -83,15 +83,18 @@ static inline void crash(const char *message) {
LLVM_ATTRIBUTE_NORETURN
extern void
fatalError(uint32_t flags, const char *format, ...);
struct InProcess;
struct Metadata;
template <typename Runtime> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;
// swift_dynamicCastFailure halts using fatalError()
// with a description of a failed cast's types.
LLVM_ATTRIBUTE_NORETURN
void
swift_dynamicCastFailure(const swift::Metadata *sourceType,
const swift::Metadata *targetType,
swift_dynamicCastFailure(const Metadata *sourceType,
const Metadata *targetType,
const char *message = nullptr);
// swift_dynamicCastFailure halts using fatalError()

View File

@@ -23,8 +23,14 @@ namespace swift {
struct OpaqueValue;
struct ValueWitnessTable;
struct Metadata;
struct EnumMetadata;
struct InProcess;
template <typename Runtime> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;
template <typename Runtime> struct TargetEnumMetadata;
using EnumMetadata = TargetEnumMetadata<InProcess>;
struct TypeLayout;
/// \brief Initialize the value witness table for a generic, single-payload

View File

@@ -29,9 +29,15 @@
#include "../../../stdlib/public/SwiftShims/HeapObject.h"
namespace swift {
struct InProcess;
template <typename Runtime> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;
template <typename Runtime> struct TargetHeapMetadata;
using HeapMetadata = TargetHeapMetadata<InProcess>;
struct Metadata;
struct HeapMetadata;
struct OpaqueValue;
/// Allocates a new heap object. The returned memory is

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,9 @@ struct objc_class;
namespace swift {
struct Metadata;
template <typename Runtime> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;
struct HeapObject;
} // end namespace swift

View File

@@ -19,9 +19,14 @@
#include "swift/Basic/type_traits.h"
namespace swift {
#endif
struct HeapMetadata;
struct InProcess;
template <typename Target> struct TargetHeapMetadata;
using HeapMetadata = TargetHeapMetadata<InProcess>;
#else
typedef struct HeapMetadata HeapMetadata;
#endif
// The members of the HeapObject header that are not shared by a
// standard Objective-C instance
@@ -32,7 +37,7 @@ struct HeapMetadata;
/// The Swift heap-object header.
struct HeapObject {
/// This is always a valid pointer to a metadata object.
struct HeapMetadata const *metadata;
HeapMetadata const *metadata;
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
// FIXME: allocate two words of metadata on 32-bit platforms

View File

@@ -23,8 +23,17 @@
#include "Visibility.h"
#ifdef __cplusplus
namespace swift { extern "C" {
namespace swift {
template <unsigned PointerSize> struct RuntimeTarget;
using HostTarget = RuntimeTarget<sizeof(uintptr_t)>;
template <typename Target> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;
extern "C" {
#else
typedef struct Metadata Metadata;
#define bool _Bool
#endif
@@ -49,14 +58,11 @@ const char *_swift_stdlib_strtod_clocale(const char *nptr, double *outResult);
/// overflow.
SWIFT_RUNTIME_STDLIB_INTERFACE
const char *_swift_stdlib_strtof_clocale(const char *nptr, float *outResult);
struct Metadata;
/// Return the superclass, if any. The result is nullptr for root
/// classes and class protocol types.
SWIFT_RUNTIME_EXPORT
const struct Metadata *swift_class_getSuperclass(
const struct Metadata *);
const Metadata *swift_class_getSuperclass(const Metadata *);
SWIFT_RUNTIME_STDLIB_INTERFACE
void _swift_stdlib_flockfile_stdout(void);

View File

@@ -2071,7 +2071,7 @@ getExistentialValueWitnesses(ExistentialTypeState &E,
}
}
ExistentialTypeRepresentation
template<> ExistentialTypeRepresentation
ExistentialTypeMetadata::getRepresentation() const {
// Some existentials use special containers.
switch (Flags.getSpecialProtocol()) {
@@ -2088,7 +2088,7 @@ ExistentialTypeMetadata::getRepresentation() const {
return ExistentialTypeRepresentation::Opaque;
}
bool
template<> bool
ExistentialTypeMetadata::mayTakeValue(const OpaqueValue *container) const {
switch (getRepresentation()) {
// Owning a reference to a class existential is equivalent to owning a
@@ -2112,7 +2112,7 @@ ExistentialTypeMetadata::mayTakeValue(const OpaqueValue *container) const {
}
}
void
template<> void
ExistentialTypeMetadata::deinitExistentialContainer(OpaqueValue *container)
const {
switch (getRepresentation()) {
@@ -2135,7 +2135,7 @@ const {
}
}
const OpaqueValue *
template<> const OpaqueValue *
ExistentialTypeMetadata::projectValue(const OpaqueValue *container) const {
switch (getRepresentation()) {
case ExistentialTypeRepresentation::Class: {
@@ -2161,7 +2161,7 @@ ExistentialTypeMetadata::projectValue(const OpaqueValue *container) const {
}
}
const Metadata *
template<> const Metadata *
ExistentialTypeMetadata::getDynamicType(const OpaqueValue *container) const {
switch (getRepresentation()) {
case ExistentialTypeRepresentation::Class: {
@@ -2183,7 +2183,7 @@ ExistentialTypeMetadata::getDynamicType(const OpaqueValue *container) const {
}
}
const WitnessTable *
template<> const WitnessTable *
ExistentialTypeMetadata::getWitnessTable(const OpaqueValue *container,
unsigned i) const {
assert(i < Flags.getNumWitnessTables());
@@ -2388,37 +2388,7 @@ swift::swift_getForeignTypeMetadata(ForeignTypeMetadata *nonUnique) {
/*** Other metadata routines ***********************************************/
const NominalTypeDescriptor *
Metadata::getNominalTypeDescriptor() const {
switch (getKind()) {
case MetadataKind::Class: {
const ClassMetadata *cls = static_cast<const ClassMetadata *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
}
case MetadataKind::Struct:
case MetadataKind::Enum:
case MetadataKind::Optional:
return static_cast<const StructMetadata *>(this)->Description;
case MetadataKind::ForeignClass:
case MetadataKind::Opaque:
case MetadataKind::Tuple:
case MetadataKind::Function:
case MetadataKind::Existential:
case MetadataKind::ExistentialMetatype:
case MetadataKind::Metatype:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
return nullptr;
}
}
const GenericMetadata *
template<> const GenericMetadata *
Metadata::getGenericPattern() const {
auto ntd = getNominalTypeDescriptor();
if (!ntd)
@@ -2426,7 +2396,7 @@ Metadata::getGenericPattern() const {
return ntd->getGenericMetadataPattern();
}
const ClassMetadata *
template<> const ClassMetadata *
Metadata::getClassObject() const {
switch (getKind()) {
case MetadataKind::Class: {

View File

@@ -73,10 +73,10 @@ namespace {
public:
TypeMetadataCacheEntry(const llvm::StringRef name,
const struct Metadata *metadata)
const ::Metadata *metadata)
: Name(name.str()), Metadata(metadata) {}
const struct Metadata *getMetadata(void) {
const ::Metadata *getMetadata(void) {
return Metadata;
}
@@ -230,6 +230,7 @@ swift::swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
}
// copied from ProtocolConformanceRecord::getCanonicalTypeMetadata()
template<>
const Metadata *TypeMetadataRecord::getCanonicalTypeMetadata() const {
switch (getTypeKind()) {
case TypeMetadataRecordKind::UniqueDirectType:
@@ -238,7 +239,7 @@ const Metadata *TypeMetadataRecord::getCanonicalTypeMetadata() const {
return swift_getForeignTypeMetadata((ForeignTypeMetadata *)getDirectType());
case TypeMetadataRecordKind::UniqueDirectClass:
if (auto *ClassMetadata =
static_cast<const struct ClassMetadata *>(getDirectType()))
static_cast<const ::ClassMetadata *>(getDirectType()))
return swift_getObjCClassMetadata(ClassMetadata);
else
return nullptr;

View File

@@ -23,7 +23,6 @@
#include "llvm/Support/Compiler.h"
namespace swift {
struct ProtocolDescriptor;
#if SWIFT_HAS_ISA_MASKING
SWIFT_RUNTIME_EXPORT

View File

@@ -41,7 +41,7 @@ static const char *class_getName(const ClassMetadata* type) {
reinterpret_cast<Class>(const_cast<ClassMetadata*>(type)));
}
void ProtocolConformanceRecord::dump() const {
template<> void ProtocolConformanceRecord::dump() const {
auto symbolName = [&](const void *addr) -> const char * {
Dl_info info;
int ok = dladdr(addr, &info);
@@ -96,7 +96,7 @@ void ProtocolConformanceRecord::dump() const {
/// Take the type reference inside a protocol conformance record and fetch the
/// canonical metadata pointer for the type it refers to.
/// Returns nil for universal or generic type references.
const Metadata *ProtocolConformanceRecord::getCanonicalTypeMetadata()
template<> const Metadata *ProtocolConformanceRecord::getCanonicalTypeMetadata()
const {
switch (getTypeKind()) {
case TypeMetadataRecordKind::UniqueDirectType:
@@ -127,7 +127,9 @@ const {
}
}
const WitnessTable *ProtocolConformanceRecord::getWitnessTable(const Metadata *type)
template<>
const WitnessTable *
ProtocolConformanceRecord::getWitnessTable(const Metadata *type)
const {
switch (getConformanceKind()) {
case ProtocolConformanceReferenceKind::WitnessTable:
@@ -441,7 +443,7 @@ recur_inside_cache_lock:
// For generic and resilient types, nondependent conformances
// are keyed by the nominal type descriptor rather than the
// metadata, so try that.
auto *description = type->getNominalTypeDescriptor();
auto *description = type->getNominalTypeDescriptor().get();
// Hash and lookup the type-protocol pair in the cache.
if (auto *Value = C.findCached(description, protocol)) {
@@ -483,7 +485,7 @@ bool isRelatedType(const Metadata *type, const void *candidate,
// If the type is resilient or generic, see if there's a witness table
// keyed off the nominal type descriptor.
auto *description = type->getNominalTypeDescriptor();
auto *description = type->getNominalTypeDescriptor().get();
if (description == candidate && !candidateIsMetadata)
return true;