Metadata.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * Copyright 1999-2101 Alibaba Group.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. //
  17. // Created by zhouzhuo on 07/01/2017.
  18. //
  19. struct _class_rw_t {
  20. var flags: Int32
  21. var version: Int32
  22. var ro: UInt
  23. // other fields we don't care
  24. // reference: include/swift/Remote/MetadataReader.h/readObjcRODataPtr
  25. func class_ro_t() -> UnsafePointer<_class_ro_t>? {
  26. var addr: UInt = self.ro
  27. if (self.ro & UInt(1)) != 0 {
  28. if let ptr = UnsafePointer<UInt>(bitPattern: self.ro ^ 1) {
  29. addr = ptr.pointee
  30. }
  31. }
  32. return UnsafePointer<_class_ro_t>(bitPattern: addr)
  33. }
  34. }
  35. struct _class_ro_t {
  36. var flags: Int32
  37. var instanceStart: Int32
  38. var instanceSize: Int32
  39. // other fields we don't care
  40. }
  41. // MARK: MetadataType
  42. protocol MetadataType : PointerType {
  43. static var kind: Metadata.Kind? { get }
  44. }
  45. extension MetadataType {
  46. var kind: Metadata.Kind {
  47. return Metadata.Kind(flag: UnsafePointer<Int>(pointer).pointee)
  48. }
  49. init?(anyType: Any.Type) {
  50. self.init(pointer: unsafeBitCast(anyType, to: UnsafePointer<Int>.self))
  51. if let kind = type(of: self).kind, kind != self.kind {
  52. return nil
  53. }
  54. }
  55. }
  56. // MARK: Metadata
  57. struct Metadata : MetadataType {
  58. var pointer: UnsafePointer<Int>
  59. init(type: Any.Type) {
  60. self.init(pointer: unsafeBitCast(type, to: UnsafePointer<Int>.self))
  61. }
  62. }
  63. struct _Metadata {}
  64. var is64BitPlatform: Bool {
  65. return MemoryLayout<Int>.size == MemoryLayout<Int64>.size
  66. }
  67. // MARK: Metadata + Kind
  68. // include/swift/ABI/MetadataKind.def
  69. let MetadataKindIsNonHeap = 0x200
  70. let MetadataKindIsRuntimePrivate = 0x100
  71. let MetadataKindIsNonType = 0x400
  72. extension Metadata {
  73. static let kind: Kind? = nil
  74. enum Kind {
  75. case `struct`
  76. case `enum`
  77. case optional
  78. case opaque
  79. case foreignClass
  80. case tuple
  81. case function
  82. case existential
  83. case metatype
  84. case objCClassWrapper
  85. case existentialMetatype
  86. case heapLocalVariable
  87. case heapGenericLocalVariable
  88. case errorObject
  89. case `class` // The kind only valid for non-class metadata
  90. init(flag: Int) {
  91. switch flag {
  92. case (0 | MetadataKindIsNonHeap): self = .struct
  93. case (1 | MetadataKindIsNonHeap): self = .enum
  94. case (2 | MetadataKindIsNonHeap): self = .optional
  95. case (3 | MetadataKindIsNonHeap): self = .foreignClass
  96. case (0 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .opaque
  97. case (1 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .tuple
  98. case (2 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .function
  99. case (3 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .existential
  100. case (4 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .metatype
  101. case (5 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .objCClassWrapper
  102. case (6 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .existentialMetatype
  103. case (0 | MetadataKindIsNonType): self = .heapLocalVariable
  104. case (0 | MetadataKindIsNonType | MetadataKindIsRuntimePrivate): self = .heapGenericLocalVariable
  105. case (1 | MetadataKindIsNonType | MetadataKindIsRuntimePrivate): self = .errorObject
  106. default: self = .class
  107. }
  108. }
  109. }
  110. }
  111. // MARK: Metadata + Class
  112. extension Metadata {
  113. struct Class : ContextDescriptorType {
  114. static let kind: Kind? = .class
  115. var pointer: UnsafePointer<_Metadata._Class>
  116. var isSwiftClass: Bool {
  117. get {
  118. // see include/swift/Runtime/Config.h macro SWIFT_CLASS_IS_SWIFT_MASK
  119. // it can be 1 or 2 depending on environment
  120. let lowbit = self.pointer.pointee.rodataPointer & 3
  121. return lowbit != 0
  122. }
  123. }
  124. var contextDescriptorOffsetLocation: Int {
  125. return is64BitPlatform ? 8 : 11
  126. }
  127. var superclass: Class? {
  128. guard let superclass = pointer.pointee.superclass else {
  129. return nil
  130. }
  131. // If the superclass doesn't conform to handyjson/handyjsonenum protocol,
  132. // we should ignore the properties inside
  133. if !(superclass is HandyJSON.Type) && !(superclass is HandyJSONEnum.Type) {
  134. return nil
  135. }
  136. // ignore objc-runtime layer
  137. guard let metaclass = Metadata.Class(anyType: superclass) else {
  138. return nil
  139. }
  140. return metaclass
  141. }
  142. var vTableSize: Int {
  143. // memory size after ivar destroyer
  144. return Int(pointer.pointee.classObjectSize - pointer.pointee.classObjectAddressPoint) - (contextDescriptorOffsetLocation + 2) * MemoryLayout<Int>.size
  145. }
  146. // reference: https://github.com/apple/swift/blob/master/docs/ABI/TypeMetadata.rst#generic-argument-vector
  147. var genericArgumentVector: UnsafeRawPointer? {
  148. let pointer = UnsafePointer<Int>(self.pointer)
  149. var superVTableSize = 0
  150. if let _superclass = self.superclass {
  151. superVTableSize = _superclass.vTableSize / MemoryLayout<Int>.size
  152. }
  153. let base = pointer.advanced(by: contextDescriptorOffsetLocation + 2 + superVTableSize)
  154. if base.pointee == 0 {
  155. return nil
  156. }
  157. return UnsafeRawPointer(base)
  158. }
  159. func _propertyDescriptionsAndStartPoint() -> ([Property.Description], Int32?)? {
  160. let instanceStart = pointer.pointee.class_rw_t()?.pointee.class_ro_t()?.pointee.instanceStart
  161. var result: [Property.Description] = []
  162. if let fieldOffsets = self.fieldOffsets, let fieldRecords = self.reflectionFieldDescriptor?.fieldRecords {
  163. class NameAndType {
  164. var name: String?
  165. var type: Any.Type?
  166. }
  167. for i in 0..<self.numberOfFields {
  168. let name = fieldRecords[i].fieldName
  169. if let cMangledTypeName = fieldRecords[i].mangledTypeName,
  170. let fieldType = _getTypeByMangledNameInContext(cMangledTypeName, getMangledTypeNameSize(cMangledTypeName), genericContext: self.contextDescriptorPointer, genericArguments: self.genericArgumentVector) {
  171. result.append(Property.Description(key: name, type: fieldType, offset: fieldOffsets[i]))
  172. }
  173. }
  174. }
  175. if let superclass = superclass,
  176. String(describing: unsafeBitCast(superclass.pointer, to: Any.Type.self)) != "SwiftObject", // ignore the root swift object
  177. let superclassProperties = superclass._propertyDescriptionsAndStartPoint(),
  178. superclassProperties.0.count > 0 {
  179. return (superclassProperties.0 + result, superclassProperties.1)
  180. }
  181. return (result, instanceStart)
  182. }
  183. func propertyDescriptions() -> [Property.Description]? {
  184. let propsAndStp = _propertyDescriptionsAndStartPoint()
  185. if let firstInstanceStart = propsAndStp?.1,
  186. let firstProperty = propsAndStp?.0.first?.offset {
  187. return propsAndStp?.0.map({ (propertyDesc) -> Property.Description in
  188. let offset = propertyDesc.offset - firstProperty + Int(firstInstanceStart)
  189. return Property.Description(key: propertyDesc.key, type: propertyDesc.type, offset: offset)
  190. })
  191. } else {
  192. return propsAndStp?.0
  193. }
  194. }
  195. }
  196. }
  197. extension _Metadata {
  198. struct _Class {
  199. var kind: Int
  200. var superclass: Any.Type?
  201. var reserveword1: Int
  202. var reserveword2: Int
  203. var rodataPointer: UInt
  204. var classFlags: UInt32
  205. var instanceAddressPoint: UInt32
  206. var instanceSize: UInt32
  207. var instanceAlignmentMask: UInt16
  208. var runtimeReservedField: UInt16
  209. var classObjectSize: UInt32
  210. var classObjectAddressPoint: UInt32
  211. var nominalTypeDescriptor: Int
  212. var ivarDestroyer: Int
  213. // other fields we don't care
  214. func class_rw_t() -> UnsafePointer<_class_rw_t>? {
  215. if MemoryLayout<Int>.size == MemoryLayout<Int64>.size {
  216. let fast_data_mask: UInt64 = 0x00007ffffffffff8
  217. let databits_t: UInt64 = UInt64(self.rodataPointer)
  218. return UnsafePointer<_class_rw_t>(bitPattern: UInt(databits_t & fast_data_mask))
  219. } else {
  220. return UnsafePointer<_class_rw_t>(bitPattern: self.rodataPointer & 0xfffffffc)
  221. }
  222. }
  223. }
  224. }
  225. // MARK: Metadata + Struct
  226. extension Metadata {
  227. struct Struct : ContextDescriptorType {
  228. static let kind: Kind? = .struct
  229. var pointer: UnsafePointer<_Metadata._Struct>
  230. var contextDescriptorOffsetLocation: Int {
  231. return 1
  232. }
  233. var genericArgumentOffsetLocation: Int {
  234. return 2
  235. }
  236. var genericArgumentVector: UnsafeRawPointer? {
  237. let pointer = UnsafePointer<Int>(self.pointer)
  238. let base = pointer.advanced(by: genericArgumentOffsetLocation)
  239. if base.pointee == 0 {
  240. return nil
  241. }
  242. return UnsafeRawPointer(base)
  243. }
  244. func propertyDescriptions() -> [Property.Description]? {
  245. guard let fieldOffsets = self.fieldOffsets, let fieldRecords = self.reflectionFieldDescriptor?.fieldRecords else {
  246. return []
  247. }
  248. var result: [Property.Description] = []
  249. class NameAndType {
  250. var name: String?
  251. var type: Any.Type?
  252. }
  253. for i in 0..<self.numberOfFields {
  254. let name = fieldRecords[i].fieldName
  255. if let cMangledTypeName = fieldRecords[i].mangledTypeName,
  256. let fieldType = _getTypeByMangledNameInContext(cMangledTypeName, getMangledTypeNameSize(cMangledTypeName), genericContext: self.contextDescriptorPointer, genericArguments: self.genericArgumentVector) {
  257. result.append(Property.Description(key: name, type: fieldType, offset: fieldOffsets[i]))
  258. }
  259. }
  260. return result
  261. }
  262. }
  263. }
  264. extension _Metadata {
  265. struct _Struct {
  266. var kind: Int
  267. var contextDescriptorOffset: Int
  268. var parent: Metadata?
  269. }
  270. }
  271. // MARK: Metadata + ObjcClassWrapper
  272. extension Metadata {
  273. struct ObjcClassWrapper: ContextDescriptorType {
  274. static let kind: Kind? = .objCClassWrapper
  275. var pointer: UnsafePointer<_Metadata._ObjcClassWrapper>
  276. var contextDescriptorOffsetLocation: Int {
  277. return is64BitPlatform ? 8 : 11
  278. }
  279. var targetType: Any.Type? {
  280. get {
  281. return pointer.pointee.targetType
  282. }
  283. }
  284. }
  285. }
  286. extension _Metadata {
  287. struct _ObjcClassWrapper {
  288. var kind: Int
  289. var targetType: Any.Type?
  290. }
  291. }