Skip to content

[Runtime] Targetize the layout of ValueWitnessTable. #18205

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
Jul 25, 2018
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
55 changes: 34 additions & 21 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,10 @@ using ConstTargetMetadataPointer

template <typename Runtime, typename T>
using TargetPointer = typename Runtime::template Pointer<T>;


template <typename Runtime, typename T>
using ConstTargetPointer = typename Runtime::template Pointer<const T>;

template <typename Runtime, template <typename> class Pointee,
bool Nullable = true>
using ConstTargetFarRelativeDirectPointer
Expand Down Expand Up @@ -257,21 +260,28 @@ constexpr inline bool canBeInline(bool isBitwiseTakable) {
return canBeInline(isBitwiseTakable, sizeof(T), alignof(T));
}

struct ValueWitnessTable;
template <typename Runtime> struct TargetValueWitnessTable;
using ValueWitnessTable = TargetValueWitnessTable<InProcess>;

namespace value_witness_types {
template <typename Runtime> class TargetValueWitnessTypes;
using ValueWitnessTypes = TargetValueWitnessTypes<InProcess>;

template <typename Runtime>
class TargetValueWitnessTypes {
public:
using StoredPointer = typename Runtime::StoredPointer;

// Note that, for now, we aren't strict about 'const'.
#define WANT_ALL_VALUE_WITNESSES
#define DATA_VALUE_WITNESS(lowerId, upperId, type)
#define FUNCTION_VALUE_WITNESS(lowerId, upperId, returnType, paramTypes) \
typedef returnType (*lowerId) paramTypes;
#define MUTABLE_VALUE_TYPE OpaqueValue *
#define IMMUTABLE_VALUE_TYPE const OpaqueValue *
#define MUTABLE_BUFFER_TYPE ValueBuffer *
#define IMMUTABLE_BUFFER_TYPE const ValueBuffer *
#define TYPE_TYPE const Metadata *
#define SIZE_TYPE size_t
typedef TargetPointer<Runtime, returnType paramTypes> lowerId;
#define MUTABLE_VALUE_TYPE TargetPointer<Runtime, OpaqueValue>
#define IMMUTABLE_VALUE_TYPE ConstTargetPointer<Runtime, OpaqueValue>
#define MUTABLE_BUFFER_TYPE TargetPointer<Runtime, ValueBuffer>
#define IMMUTABLE_BUFFER_TYPE ConstTargetPointer<Runtime, ValueBuffer>
#define TYPE_TYPE ConstTargetPointer<Runtime, Metadata>
#define SIZE_TYPE StoredSize
#define INT_TYPE int
#define UINT_TYPE unsigned
#define VOID_TYPE void
Expand All @@ -284,33 +294,36 @@ namespace value_witness_types {
typedef size_t stride;
typedef ExtraInhabitantFlags extraInhabitantFlags;

} // end namespace value_witness_types
};

struct TypeLayout;

/// A value-witness table. A value witness table is built around
/// the requirements of some specific type. The information in
/// a value-witness table is intended to be sufficient to lay out
/// and manipulate values of an arbitrary type.
struct ValueWitnessTable {
template <typename Runtime> struct TargetValueWitnessTable {
// For the meaning of all of these witnesses, consult the comments
// on their associated typedefs, above.

#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
value_witness_types::LOWER_ID LOWER_ID;
typename TargetValueWitnessTypes<Runtime>::LOWER_ID LOWER_ID;
#include "swift/ABI/ValueWitness.def"

using StoredSize = typename Runtime::StoredSize;

/// Is the external type layout of this type incomplete?
bool isIncomplete() const {
return flags.isIncomplete();
}

/// Would values of a type with the given layout requirements be
/// allocated inline?
static bool isValueInline(bool isBitwiseTakable, size_t size, size_t alignment) {
return (isBitwiseTakable && size <= sizeof(ValueBuffer) &&
alignment <= alignof(ValueBuffer));
static bool isValueInline(bool isBitwiseTakable, StoredSize size,
StoredSize alignment) {
return (isBitwiseTakable && size <= sizeof(TargetValueBuffer<Runtime>) &&
alignment <= alignof(TargetValueBuffer<Runtime>));
}

/// Are values of this type allocated inline?
Expand All @@ -331,18 +344,18 @@ struct ValueWitnessTable {
/// Return the size of this type. Unlike in C, this has not been
/// padded up to the alignment; that value is maintained as
/// 'stride'.
size_t getSize() const {
StoredSize getSize() const {
return size;
}

/// Return the stride of this type. This is the size rounded up to
/// be a multiple of the alignment.
size_t getStride() const {
StoredSize getStride() const {
return stride;
}

/// Return the alignment required by this type, in bytes.
size_t getAlignment() const {
StoredSize getAlignment() const {
return flags.getAlignment();
}

Expand All @@ -352,7 +365,7 @@ struct ValueWitnessTable {
///
/// For example, if the type needs to be 8-byte aligned, the value
/// of this witness is 0x7.
size_t getAlignmentMask() const {
StoredSize getAlignmentMask() const {
return flags.getAlignmentMask();
}

Expand Down Expand Up @@ -583,7 +596,7 @@ struct TargetMetadata {
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define FUNCTION_VALUE_WITNESS(WITNESS, UPPER, RET_TYPE, PARAM_TYPES) \
template<typename...A> \
_ResultOf<value_witness_types::WITNESS>::type \
_ResultOf<ValueWitnessTypes::WITNESS>::type \
vw_##WITNESS(A &&...args) const { \
return getValueWitnesses()->WITNESS(std::forward<A>(args)..., this); \
}
Expand Down
10 changes: 5 additions & 5 deletions include/swift/ABI/ValueWitness.def
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
/// MUTABLE_BUFFER_TYPE - a pointer to a fixed-size value buffer
/// IMMUTABLE_BUFFER_TYPE - a pointer to an immutable fixed-size buffer
/// TYPE_TYPE - a pointer to type metadata
/// SIZE_TYPE - size_t
/// SIZE_TYPE - StoredSize
/// INT_TYPE - int
/// UINT_TYPE - unsigned int
/// VOID_TYPE - void
Expand Down Expand Up @@ -193,7 +193,7 @@ FUNCTION_VALUE_WITNESS(storeEnumTagSinglePayload,
END_VALUE_WITNESS_RANGE(RequiredValueWitnessFunction,
StoreEnumTagSinglePayload)

/// size_t size;
/// SIZE_TYPE size;
///
/// The required storage size of a single object of this type.
DATA_VALUE_WITNESS(size,
Expand All @@ -206,7 +206,7 @@ BEGIN_VALUE_WITNESS_RANGE(TypeLayoutWitness,
BEGIN_VALUE_WITNESS_RANGE(RequiredTypeLayoutWitness,
Size)

/// size_t flags;
/// SIZE_TYPE flags;
///
/// The ValueWitnessAlignmentMask bits represent the required
/// alignment of the first byte of an object of this type, expressed
Expand Down Expand Up @@ -235,7 +235,7 @@ DATA_VALUE_WITNESS(flags,
Flags,
SIZE_TYPE)

/// size_t stride;
/// SIZE_TYPE stride;
///
/// The required size per element of an array of this type. It is at least
/// one, even for zero-sized types, like the empty tuple.
Expand All @@ -256,7 +256,7 @@ END_VALUE_WITNESS_RANGE(RequiredValueWitness,
// The following value witnesses are conditionally present based on
// the Enum_HasExtraInhabitants bit of the flags.

/// size_t extraInhabitantFlags;
/// SIZE_TYPE extraInhabitantFlags;
///
/// These bits are always present if the extra inhabitants witnesses are:
///
Expand Down
5 changes: 3 additions & 2 deletions include/swift/Runtime/Enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
namespace swift {

struct OpaqueValue;
struct ValueWitnessTable;

struct InProcess;

template <typename Runtime> struct TargetValueWitnessTable;
using ValueWitnessTable = TargetValueWitnessTable<InProcess>;

template <typename Runtime> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;

Expand Down
48 changes: 25 additions & 23 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ OpaqueValue *swift_copyPOD(OpaqueValue *dest,
struct ExtraInhabitantsValueWitnessTable : ValueWitnessTable {
#define WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
value_witness_types::LOWER_ID LOWER_ID;
ValueWitnessTypes::LOWER_ID LOWER_ID;
#include "swift/ABI/ValueWitness.def"

#define SET_WITNESS(NAME) base.NAME,
Expand All @@ -76,9 +76,9 @@ struct ExtraInhabitantsValueWitnessTable : ValueWitnessTable {
getExtraInhabitantIndex(nullptr) {}
constexpr ExtraInhabitantsValueWitnessTable(
const ValueWitnessTable &base,
value_witness_types::extraInhabitantFlags eif,
value_witness_types::storeExtraInhabitant sei,
value_witness_types::getExtraInhabitantIndex geii)
ValueWitnessTypes::extraInhabitantFlags eif,
ValueWitnessTypes::storeExtraInhabitant sei,
ValueWitnessTypes::getExtraInhabitantIndex geii)
: ValueWitnessTable(base),
extraInhabitantFlags(eif),
storeExtraInhabitant(sei),
Expand All @@ -95,7 +95,7 @@ struct ExtraInhabitantsValueWitnessTable : ValueWitnessTable {
struct EnumValueWitnessTable : ExtraInhabitantsValueWitnessTable {
#define WANT_ONLY_ENUM_VALUE_WITNESSES
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
value_witness_types::LOWER_ID LOWER_ID;
ValueWitnessTypes::LOWER_ID LOWER_ID;
#include "swift/ABI/ValueWitness.def"

constexpr EnumValueWitnessTable()
Expand All @@ -105,9 +105,9 @@ struct EnumValueWitnessTable : ExtraInhabitantsValueWitnessTable {
destructiveInjectEnumTag(nullptr) {}
constexpr EnumValueWitnessTable(
const ExtraInhabitantsValueWitnessTable &base,
value_witness_types::getEnumTag getEnumTag,
value_witness_types::destructiveProjectEnumData destructiveProjectEnumData,
value_witness_types::destructiveInjectEnumTag destructiveInjectEnumTag)
ValueWitnessTypes::getEnumTag getEnumTag,
ValueWitnessTypes::destructiveProjectEnumData destructiveProjectEnumData,
ValueWitnessTypes::destructiveInjectEnumTag destructiveInjectEnumTag)
: ExtraInhabitantsValueWitnessTable(base),
getEnumTag(getEnumTag),
destructiveProjectEnumData(destructiveProjectEnumData),
Expand All @@ -123,26 +123,26 @@ struct EnumValueWitnessTable : ExtraInhabitantsValueWitnessTable {
/// the value witness functions and includes only the size, alignment,
/// extra inhabitants, and miscellaneous flags about the type.
struct TypeLayout {
value_witness_types::size size;
value_witness_types::flags flags;
value_witness_types::stride stride;
ValueWitnessTypes::size size;
ValueWitnessTypes::flags flags;
ValueWitnessTypes::stride stride;

private:
// Only available if the "hasExtraInhabitants" flag is set.
value_witness_types::extraInhabitantFlags extraInhabitantFlags;
ValueWitnessTypes::extraInhabitantFlags extraInhabitantFlags;

void _static_assert_layout();
public:
TypeLayout() = default;
constexpr TypeLayout(value_witness_types::size size,
value_witness_types::flags flags,
value_witness_types::stride stride,
value_witness_types::extraInhabitantFlags eiFlags =
value_witness_types::extraInhabitantFlags())
constexpr TypeLayout(ValueWitnessTypes::size size,
ValueWitnessTypes::flags flags,
ValueWitnessTypes::stride stride,
ValueWitnessTypes::extraInhabitantFlags eiFlags =
ValueWitnessTypes::extraInhabitantFlags())
: size(size), flags(flags), stride(stride),
extraInhabitantFlags(eiFlags) {}

value_witness_types::extraInhabitantFlags getExtraInhabitantFlags() const {
ValueWitnessTypes::extraInhabitantFlags getExtraInhabitantFlags() const {
assert(flags.hasExtraInhabitants());
return extraInhabitantFlags;
}
Expand All @@ -169,6 +169,7 @@ inline void TypeLayout::_static_assert_layout() {
#undef CHECK_TYPE_LAYOUT_OFFSET
}

template <>
inline void ValueWitnessTable::publishLayout(const TypeLayout &layout) {
size = layout.size;
stride = layout.stride;
Expand All @@ -184,23 +185,24 @@ inline void ValueWitnessTable::publishLayout(const TypeLayout &layout) {
flags = layout.flags;
}

inline bool ValueWitnessTable::checkIsComplete() const {
template <> inline bool ValueWitnessTable::checkIsComplete() const {
return !flags.isIncomplete();
}

template <>
inline const ExtraInhabitantsValueWitnessTable *
ValueWitnessTable::_asXIVWT() const {
assert(ExtraInhabitantsValueWitnessTable::classof(this));
return static_cast<const ExtraInhabitantsValueWitnessTable *>(this);
}
inline const EnumValueWitnessTable *
ValueWitnessTable::_asEVWT() const {

template <>
inline const EnumValueWitnessTable *ValueWitnessTable::_asEVWT() const {
assert(EnumValueWitnessTable::classof(this));
return static_cast<const EnumValueWitnessTable *>(this);
}

inline unsigned ValueWitnessTable::getNumExtraInhabitants() const {
template <> inline unsigned ValueWitnessTable::getNumExtraInhabitants() const {
// If the table does not have extra inhabitant witnesses, then there are zero.
if (!flags.hasExtraInhabitants())
return 0;
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/runtime/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ static void tuple_destroy(OpaqueValue *tuple, const Metadata *_metadata) {

// The operation doesn't have to be initializeWithCopy, but they all
// have basically the same type.
typedef value_witness_types::initializeWithCopy forEachOperation;
typedef ValueWitnessTypes::initializeWithCopy forEachOperation;

/// Perform an operation for each field of two tuples.
static OpaqueValue *tuple_forEachField(OpaqueValue *destTuple,
Expand Down Expand Up @@ -1558,7 +1558,7 @@ static OpaqueValue *pod_indirect_initializeBufferWithCopyOfBuffer(
static void pod_noop(void *object, const Metadata *self) {
}
#define pod_direct_destroy \
pointer_function_cast<value_witness_types::destroy>(pod_noop)
pointer_function_cast<ValueWitnessTypes::destroy>(pod_noop)
#define pod_indirect_destroy pod_direct_destroy

static OpaqueValue *pod_direct_initializeWithCopy(OpaqueValue *dest,
Expand All @@ -1569,7 +1569,7 @@ static OpaqueValue *pod_direct_initializeWithCopy(OpaqueValue *dest,
}
#define pod_indirect_initializeWithCopy pod_direct_initializeWithCopy
#define pod_direct_initializeBufferWithCopyOfBuffer \
pointer_function_cast<value_witness_types::initializeBufferWithCopyOfBuffer> \
pointer_function_cast<ValueWitnessTypes::initializeBufferWithCopyOfBuffer> \
(pod_direct_initializeWithCopy)
#define pod_direct_assignWithCopy pod_direct_initializeWithCopy
#define pod_indirect_assignWithCopy pod_direct_initializeWithCopy
Expand Down