Swift Type metadata
17042 단어 SwiftSwiftCompiler
Type metadata
이 있습니다.자주 사용하는 것은 아니지만 Swift의 작동 시간을 이해하는 데 중요한 요소입니다.이 글은 컴파일러의 코드와 문서에서 찾아낸
Type metadata
를 간단하게 설명한다.Type metadata란
Swift 실행 시 유지되는 유형 정보입니다.비상규
class
,struct
,enum
는 컴파일할 때 정적이지만 비상규형과 함수형, 원조 등non-nominal형은 실행할 때 동적으로 제작된다.이거
Type metadata
에서enum
인지 struct
class
(조작 유형에 사용되는 함수 그룹)Swift에서 ValueWitnessTable 처리
그러면
Type metadata
를 사용하여 Swift에서 클래스 실례 크기를 얻으세요.Type metadata
에서 목표 정보를 얻으려면 이 정보가 메타데이터의 메모리 레이아웃에 있는 위치를 알아야 한다.참조swift/TypeMetadata.rst 재현 메모리 레이아웃은 다음과 같습니다.struct ClassMetadata {
let isaPointer: Int
let superClass: Any.Type
let objcRuntimeReserved1: Int
let objcRuntimeReserved2: Int
let rodataPointer: Int
let classFlags: Int32
let instanceAddressPoint: Int32
let instanceSize: Int32
}
그럼, 메모리의 표현을 알았으니까Type metadata
실제로 시도해 보세요.Swift
Type metadata
는 이 유형의 인스턴스Metatype
에 대한 포인터입니다.일단 Type metadata
로 포인터형 배역을 해보자.class Cat {}
let catType: Cat.Type = Cat.self
MemoryLayout.size(ofValue: Cat.self) // 8
let metadataPointer = unsafeBitCast(catType, to: UnsafePointer<ClassMetadata>.self)
let metadata = metadataPointer.pointee
print(metadata.instanceSize) // 16
필요한 인스턴스 크기 확보그러나 이 방법으로
unsafeBitCast
의 메타데이터를 얻으려 해도 순조롭지 않다.struct Stone {}
let stoneType: Stone.Type = Stone.self
MemoryLayout.size(ofValue: Stone.self) // 0
let metadataPointer = unsafeBitCast(stoneType, to: UnsafePointer<StructMetadata>.self)
let metadata = metadataPointer.pointee // Crash! :bomb:
제대로 사용하려면struct
조금 더 알아야 할 것 같아요.Thin Metatype
Type metadata
의 원형 사이즈가 0이 된 원인을 찾기 위해 원형 컴파일러를 만드는 코드를 읽으십시오.swift/MetadataRequest.cpp
/// Emit a metatype value for a known type.
void irgen::emitMetatypeRef(IRGenFunction &IGF, CanMetatypeType type,
Explosion &explosion) {
switch (type->getRepresentation()) {
case MetatypeRepresentation::Thin:
// Thin types have a trivial representation.
break;
case MetatypeRepresentation::Thick:
explosion.add(IGF.emitTypeMetadataRef(type.getInstanceType()));
break;
case MetatypeRepresentation::ObjC:
explosion.add(emitClassHeapMetadataRef(IGF, type.getInstanceType(),
MetadataValueType::ObjCClass,
MetadataState::Complete));
break;
}
}
유형의 표현 방법이 struct
일 때 운행 시간 정보를 출력하지 않습니다.그럼, 무엇이 있습니까?swift/Types.h
enum class MetatypeRepresentation : char {
/// A thin metatype requires no runtime information, because the
/// type itself provides no dynamic behavior.
///
/// Struct and enum metatypes are thin, because dispatch to static
/// struct and enum members is completely static.
Thin,
/// A thick metatype refers to a complete metatype representation
/// that allows introspection and dynamic dispatch.
///
/// Thick metatypes are used for class and existential metatypes,
/// which permit dynamic behavior.
Thick,
/// An Objective-C metatype refers to an Objective-C class object.
ObjC
};
스위프트의 메타 유형은 Thick, Thin, ObjC 세 가지로 나뉜다.MetatypeRepresentation::Thin
, MetatypeRepresentation
등 정적 결정 행위의 유형struct
등 동적 행위의 유형enum
원 유형을 얻는 데 실패한 이유다.protocol Animal {
static func kind() -> String
}
struct Cat {
static func kind() -> String {
return "猫"
}
}
let catType: Cat.Type = Cat.self // Thin
let animalType: Animal.Type = Cat.self // Thick
animalType.kind() // 猫
다른 한편, 상기 예에서 보듯이 원 유형의 하위 유형을 통해 Thin형을 Thick형에 대입할 수 있다.또한
class
의 정확한 조작으로 인해 Existential의 원형에는 실제 원형이 보존되어 있다.Existential Metatype을 통해서도 씽형struct
을 받을 수 있다는 것이다.Existential Metatype container
Existential Metatype container는 Existential Metatype이 실행될 때 표현되는 것으로 Existential container의 메타데이터 버전과 유사합니다.내부에는 실제 유형의 실례
animalType.kind()
와 위니스 테이블을 가리키는 바늘이 저장되어 있습니다.swift/GenExistential.cpp
struct ExistentialMetatypeContainer<Metadata> {
let metadata: UnsafePointer<Metadata>
let witnessTable: UnsafePointer<WitnessTable>
}
방금 실패한 Type metadata
메타데이터를 가져오려면 이것을 사용하십시오.struct StructMetadata {
let kind: Int
}
protocol Animal {}
struct Cat: Animal {}
let animalType: Animal.Type = Cat.self
let metatypeContainer = unsafeBitCast(animalType, to: ExistentialMetatypeContainer<StructMetadata>.self)
metatypeContainer.metadataPointer.pointee.kind // 1
왜냐하면 struct metadata의kind는 1이니까. 목적을 순조롭게 얻었다Type metadata
.하지만 이 방법에는 문제가 하나 있다.일부 프로토콜을 준수하지 않으면 메타데이터를 얻으려는 Thin형을 Existential Metatype container로 압축할 수 없습니다.
Any.Type
그러나 우리는 모든 종류의supertype
struct
을 가지고 있다.게다가 애니는 non-nominal이기 때문에 Thick형으로 사용하고 운행시간 정보를 유지했다.struct Stone {}
let stoneType: Any.Type = Stone.self
let metadataPointer = unsafeBitCast(stoneType, to: UnsafePointer<StructMetadata>.self)
let metadata = metadataPointer.pointee
metadata.kind // 1
이렇게 안전(?)Type metadata
획득 방법 설정총결산
Any
는 실제로Server Side Swift의 프레임 Zewo 등에 사용 Swift 언어 기능을 확장할 수 있는 환상적인 정보원이다.다른 한편, 문서를 만들지 못한 부분이 많아 수정할 수도 있다.사용 시 테스트 등 대책을 꼼꼼히 써야 한다.신나게
Type metadata
놀아라.참고 자료
Reference
이 문제에 관하여(Swift Type metadata), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/kateinoigakukun/items/8718d152c3708a7a314b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)