Skip to content

Commit

Permalink
Runtime: Static-ize swift_unsafeReflectAny.
Browse files Browse the repository at this point in the history
The _unsafeReflect entry point never ended up getting used on the Swift side, so don't export it, and remove the _silgen_name'd declaration.
  • Loading branch information
jckarter committed Dec 2, 2015
1 parent 124b0e4 commit fed7f79
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 125 deletions.
10 changes: 0 additions & 10 deletions include/swift/Runtime/Reflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,6 @@ struct MirrorReturn {
/// in the runtime that structurally reflects values of any type.
extern "C" MirrorReturn
swift_reflectAny(OpaqueValue *value, const Metadata *T);

/// func unsafeReflect<T>(owner: Builtin.NativeObject,
/// x: UnsafeMutablePointer<T>) -> Mirror
///
/// Produce a mirror for any value. If the value's type conforms to _Reflectable,
/// invoke its _getMirror() method; otherwise, fall back to an implementation
/// in the runtime that structurally reflects values of any type.
extern "C" MirrorReturn
swift_unsafeReflectAny(HeapObject *owner,
const OpaqueValue *value, const Metadata *T);

#pragma clang diagnostic pop

Expand Down
12 changes: 0 additions & 12 deletions stdlib/public/core/Reflection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,6 @@ func _getSummary<T>(out: UnsafeMutablePointer<String>, x: T) {
@_silgen_name("swift_reflectAny")
public func _reflect<T>(x: T) -> _MirrorType

/// Unsafely produce a mirror for a value in memory whose lifetime is
/// guaranteed by holding a strong reference to a heap object.
/// This lets containers with heap storage vend mirrors for their elements
/// without unnecessary copying of the underlying value.
@warn_unused_result
@_silgen_name("swift_unsafeReflectAny")
internal func _unsafeReflect<T>(
owner: Builtin.NativeObject,
ptr: UnsafeMutablePointer<T>
) -> _MirrorType


/// Dump an object's contents using its mirror to the specified output stream.
public func dump<T, TargetStream : OutputStreamType>(
x: T, inout _ targetStream: TargetStream,
Expand Down
206 changes: 103 additions & 103 deletions stdlib/public/runtime/Reflection.mm
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,102 @@ intptr_t swift_TupleMirror_count(HeapObject *owner,
auto Tuple = static_cast<const TupleTypeMetadata *>(type);
return Tuple->NumElements;
}

static std::tuple<const _ReflectableWitnessTable *, const Metadata *,
const OpaqueValue *>
getReflectableConformance(const Metadata *T, const OpaqueValue *Value) {
recur:
// If the value is an existential container, look through it to reflect the
// contained value.
switch (T->getKind()) {
case MetadataKind::Tuple:
case MetadataKind::Struct:
case MetadataKind::ForeignClass:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::Class:
case MetadataKind::Opaque:
case MetadataKind::Enum:
case MetadataKind::Function:
case MetadataKind::Metatype:
break;

case MetadataKind::Existential: {
auto existential
= static_cast<const ExistentialTypeMetadata *>(T);

// If the existential happens to include the _Reflectable protocol, use
// the witness table from the container.
unsigned wtOffset = 0;
for (unsigned i = 0; i < existential->Protocols.NumProtocols; ++i) {
if (existential->Protocols[i] == &_TMps12_Reflectable) {
return std::make_tuple(
reinterpret_cast<const _ReflectableWitnessTable*>(
existential->getWitnessTable(Value, wtOffset)),
existential->getDynamicType(Value),
existential->projectValue(Value));
}
if (existential->Protocols[i]->Flags.needsWitnessTable())
++wtOffset;
}

// Otherwise, unwrap the existential container and do a runtime lookup on
// its contained value as usual.
T = existential->getDynamicType(Value);
Value = existential->projectValue(Value);

// Existential containers can end up nested in some cases due to generic
// abstraction barriers. Recur in case we have a nested existential.
goto recur;
}
case MetadataKind::ExistentialMetatype:
// TODO: Should look through existential metatypes too, but it doesn't
// really matter yet since we don't have any special mirror behavior for
// concrete metatypes yet.
break;

// Types can't have these kinds.
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
swift::crash("Swift mirror lookup failure");
}

return std::make_tuple(
reinterpret_cast<const _ReflectableWitnessTable*>(
swift_conformsToProtocol(T, &_TMps12_Reflectable)),
T,
Value);
}

/// Produce a mirror for any value, like swift_reflectAny, but do not consume
/// the value, so we can produce a mirror for a subobject of a value already
/// owned by a mirror.
///
/// \param owner passed at +1, consumed.
/// \param value passed unowned.
static Mirror reflect(HeapObject *owner,
const OpaqueValue *value,
const Metadata *T) {
const _ReflectableWitnessTable *witness;
const Metadata *mirrorType;
const OpaqueValue *mirrorValue;
std::tie(witness, mirrorType, mirrorValue)
= getReflectableConformance(T, value);

// Use the _Reflectable conformance if the object has one.
if (witness) {
auto result =
witness->getMirror(const_cast<OpaqueValue*>(mirrorValue), mirrorType);
swift_release(owner);
return MirrorReturn(result);
}
// Otherwise, fall back to MagicMirror.
// Consumes 'owner'.
Mirror result;
::new (&result) MagicMirror(owner, mirrorValue, mirrorType);
return result;
}

/// \param owner passed at +1, consumed.
/// \param value passed unowned.
extern "C"
Expand All @@ -392,11 +487,11 @@ StringMirrorTuple swift_TupleMirror_subscript(intptr_t i,
auto bytes = reinterpret_cast<const char*>(value);
auto eltData = reinterpret_cast<const OpaqueValue *>(bytes + elt.Offset);

// This retain matches the -1 in swift_unsafeReflectAny.
// This retain matches the -1 in reflect.
swift_retain(owner);

// 'owner' is consumed by this call.
result.second = swift_unsafeReflectAny(owner, eltData, elt.Type);
result.second = reflect(owner, eltData, elt.Type);

return result;
}
Expand Down Expand Up @@ -444,12 +539,12 @@ StringMirrorTuple swift_StructMirror_subscript(intptr_t i,

result.first = String(getFieldName(Struct->Description->Struct.FieldNames, i));

// This matches the -1 in swift_unsafeReflectAny.
// This matches the -1 in reflect.
swift_retain(owner);

// 'owner' is consumed by this call.
assert(!fieldType.isIndirect() && "indirect struct fields not implemented");
result.second = swift_unsafeReflectAny(owner, fieldData,
result.second = reflect(owner, fieldData,
fieldType.getType());

return result;
Expand Down Expand Up @@ -553,11 +648,11 @@ StringMirrorTuple swift_EnumMirror_subscript(intptr_t i,
value = swift_projectBox(const_cast<HeapObject *>(owner));
}

// This matches the -1 in swift_unsafeReflectAny.
// This matches the -1 in reflect.
swift_retain(owner);

result.first = String(getFieldName(Description.CaseNames, tag));
result.second = swift_unsafeReflectAny(owner, value, payloadType);
result.second = reflect(owner, value, payloadType);

return result;
}
Expand Down Expand Up @@ -649,7 +744,7 @@ StringMirrorTuple swift_ClassMirror_subscript(intptr_t i,

result.first = String(getFieldName(Clas->getDescription()->Class.FieldNames, i));
// 'owner' is consumed by this call.
result.second = swift_unsafeReflectAny(owner, fieldData, fieldType.getType());
result.second = reflect(owner, fieldData, fieldType.getType());
return result;
}

Expand Down Expand Up @@ -808,7 +903,7 @@ StringMirrorTuple swift_ObjCMirror_subscript(intptr_t i,
StringMirrorTuple result;
result.first = String(name, strlen(name));
// 'owner' is consumed by this call.
result.second = swift_unsafeReflectAny(owner, ivar, ivarType);
result.second = reflect(owner, ivar, ivarType);
return result;
#else
// ObjC makes no guarantees about the state of ivars, so we can't safely
Expand Down Expand Up @@ -1129,73 +1224,7 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, value);
Data = {owner, value, T};
}

static std::tuple<const _ReflectableWitnessTable *, const Metadata *,
const OpaqueValue *>
getReflectableConformance(const Metadata *T, const OpaqueValue *Value) {
recur:
// If the value is an existential container, look through it to reflect the
// contained value.
switch (T->getKind()) {
case MetadataKind::Tuple:
case MetadataKind::Struct:
case MetadataKind::ForeignClass:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::Class:
case MetadataKind::Opaque:
case MetadataKind::Enum:
case MetadataKind::Function:
case MetadataKind::Metatype:
break;

case MetadataKind::Existential: {
auto existential
= static_cast<const ExistentialTypeMetadata *>(T);

// If the existential happens to include the _Reflectable protocol, use
// the witness table from the container.
unsigned wtOffset = 0;
for (unsigned i = 0; i < existential->Protocols.NumProtocols; ++i) {
if (existential->Protocols[i] == &_TMps12_Reflectable) {
return std::make_tuple(
reinterpret_cast<const _ReflectableWitnessTable*>(
existential->getWitnessTable(Value, wtOffset)),
existential->getDynamicType(Value),
existential->projectValue(Value));
}
if (existential->Protocols[i]->Flags.needsWitnessTable())
++wtOffset;
}

// Otherwise, unwrap the existential container and do a runtime lookup on
// its contained value as usual.
T = existential->getDynamicType(Value);
Value = existential->projectValue(Value);

// Existential containers can end up nested in some cases due to generic
// abstraction barriers. Recur in case we have a nested existential.
goto recur;
}
case MetadataKind::ExistentialMetatype:
// TODO: Should look through existential metatypes too, but it doesn't
// really matter yet since we don't have any special mirror behavior for
// concrete metatypes yet.
break;

// Types can't have these kinds.
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
swift::crash("Swift mirror lookup failure");
}

return std::make_tuple(
reinterpret_cast<const _ReflectableWitnessTable*>(
swift_conformsToProtocol(T, &_TMps12_Reflectable)),
T,
Value);
}

} // end anonymous namespace

/// func reflect<T>(x: T) -> Mirror
Expand Down Expand Up @@ -1235,32 +1264,3 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
T->vw_destroy(value);
return MirrorReturn(result);
}

/// Produce a mirror for any value, like swift_reflectAny, but do not consume
/// the value, so we can produce a mirror for a subobject of a value already
/// owned by a mirror.
///
/// \param owner passed at +1, consumed.
/// \param value passed unowned.
MirrorReturn swift::swift_unsafeReflectAny(HeapObject *owner,
const OpaqueValue *value,
const Metadata *T) {
const _ReflectableWitnessTable *witness;
const Metadata *mirrorType;
const OpaqueValue *mirrorValue;
std::tie(witness, mirrorType, mirrorValue)
= getReflectableConformance(T, value);

// Use the _Reflectable conformance if the object has one.
if (witness) {
auto result =
witness->getMirror(const_cast<OpaqueValue*>(mirrorValue), mirrorType);
swift_release(owner);
return MirrorReturn(result);
}
// Otherwise, fall back to MagicMirror.
// Consumes 'owner'.
Mirror result;
::new (&result) MagicMirror(owner, mirrorValue, mirrorType);
return MirrorReturn(result);
}

0 comments on commit fed7f79

Please sign in to comment.