Swift源码分析Metadata(二)

Swift 5 ABI 稳定了,Swift的class和struct实际是个HeapObjectSwift源码分析类的初始化(零)

struct InProcess;
template <typename Target> struct TargetHeapMetadata;
using HeapMetadata = TargetHeapMetadata<InProcess>;

struct HeapObject {
  /// This is always a valid pointer to a metadata object.
  HeapMetadata const *__ptrauth_objc_isa_pointer metadata;

  SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;//uint64 refCount;
  ...
}
// 对应Swift的Int类型,如果32位为Int32,64位为Int64
StoredPointer = typename Runtime::StoredPointer
class RelativeDirectPointerImpl { 
  Offset RelativeOffset; 
}
class RelativeDirectPointer<T, Nullable, Offset,typename std::enable_if<!std::is_function<T>::value>::type>
 : private RelativeDirectPointerImpl<T, Nullable, Offset> {   }

template <typename Runtime, typename Pointee, bool Nullable = true>
using TargetRelativeDirectPointer = typename Runtime::template RelativeDirectPointer<Pointee, Nullable>;

enum class FieldDescriptorKind : uint16_t {   Struct, Class,  Enum,  MultiPayloadEnum,  Protocol,  ClassProtocol,  ObjCProtocol,  ObjCClass };
class FieldRecord {
      const FieldRecordFlags Flags;
      const RelativeDirectPointer<const char> MangledTypeName;
      const RelativeDirectPointer<const char> FieldName;
}
// FieldDescriptor的getFields返回类型
class LLVM_GSL_POINTER LLVM_NODISCARD ArrayRef 
{
   const T *Data = nullptr;/// The start of the array, in an external buffer.
   size_type Length = 0; /// The number of elements.
}
class FieldDescriptor {
  const RelativeDirectPointer<const char> MangledTypeName;
  const RelativeDirectPointer<const char> Superclass;
  const FieldDescriptorKind Kind;
  const uint16_t FieldRecordSize;
  const uint32_t NumFields;
  // 属性地址
  llvm::ArrayRef<FieldRecord> getFields() const {
    return {getFieldRecordBuffer(), NumFields};
  }
}
struct TargetMetadata {
  StoredPointer Kind;
}
struct TargetValueMetadata : public TargetMetadata<Runtime> {
  TargetSignedPointer<Runtime, const TargetValueTypeDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;
}

template <typename Target> struct TargetHeapMetadata;
using HeapMetadata = TargetHeapMetadata<InProcess>;

struct TargetHeapMetadata : TargetMetadata<Runtime> { }
struct TargetAnyClassMetadata : public TargetHeapMetadata<Runtime> {
   constexpr TargetAnyClassMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa,TargetClassMetadata *superclass) : TargetHeapMetadata<Runtime>(isa), Superclass(superclass) {   }
  TargetSignedPointer<Runtime, const TargetClassMetadata *__ptrauth_swift_objc_superclass> Superclass;
}
struct TargetAnyClassMetadataObjCInterop: public TargetAnyClassMetadata<Runtime> {
  TargetPointer<Runtime, void> CacheData[2];
  StoredSize Data;
}

If the Runtime supports Objective-C interoperability, this class inherits from TargetAnyClassMetadataObjCInterop, otherwise it inherits from TargetAnyClassMetadata.

struct TargetClassMetadata : public TargetAnyClassMetadataVariant {
  ClassFlags Flags; //特有标志
  uint32_t InstanceAddressPoint; //实例内存首地址
  uint32_t InstanceSize; //实例内存大小
  uint16_t InstanceAlignMask; //实例内存对齐方式
  uint16_t Reserved; //保留字段
  uint32_t ClassSize; //类内存大小
  uint32_t ClassAddressPoint; //类内存首地址
  TargetSignedPointer<Runtime, const TargetClassDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description; //类描述器
  TargetSignedPointer<Runtime, ClassIVarDestroyer * __ptrauth_swift_heap_object_destructor> IVarDestroyer; //实例销毁器
}
struct TargetStructMetadata : public TargetValueMetadata<Runtime> { }

using TargetRelativeContextPointer = RelativeIndirectablePointer<const Context<Runtime>,/nullable/ true, int32_t,TargetSignedContextPointer<Runtime, Context>>;
using RelativeIndirectablePointer = RelativeIndirectablePointer<T, Nullable>;

class RelativeIndirectablePointer {
  Offset RelativeOffsetPlusIndirect;
}
struct TargetContextDescriptor {
  ContextDescriptorFlags Flags;
  TargetRelativeContextPointer<Runtime> Parent;
}
class TargetTypeContextDescriptor: public TargetContextDescriptor<Runtime> {
  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;
  TargetCompactFunctionPointer<Runtime, MetadataResponse(...),true> AccessFunctionPtr;
  TargetRelativeDirectPointer<Runtime, const reflection::FieldDescriptor,true> Fields;
}
class TargetValueTypeDescriptor: public TargetTypeContextDescriptor<Runtime> { }
class TargetStructDescriptor final: public TargetValueTypeDescriptor<Runtime>,
                            public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>, 
                            TargetTypeGenericContextDescriptorHeader,/*additional trailing objects*/
                            TargetForeignMetadataInitialization<Runtime>,
                            TargetSingletonMetadataInitialization<Runtime>,
                            TargetCanonicalSpecializedMetadatasListCount<Runtime>,
                            TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
                            TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>>  {
  uint32_t NumFields;
  uint32_t FieldOffsetVectorOffset;
}
struct TargetVTableDescriptorHeader {
  uint32_t VTableOffset;
  uint32_t VTableSize;
}
class TargetClassDescriptor final: public TargetTypeContextDescriptor<Runtime>,
                              public TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
                              TargetTypeGenericContextDescriptorHeader,/*additional trailing objects:*/
                              TargetResilientSuperclass<Runtime>,
                              TargetForeignMetadataInitialization<Runtime>,
                              TargetSingletonMetadataInitialization<Runtime>,
                              TargetVTableDescriptorHeader<Runtime>,
                              TargetMethodDescriptor<Runtime>,
                              TargetOverrideTableHeader<Runtime>,
                              TargetMethodOverrideDescriptor<Runtime>,
                              TargetObjCResilientClassStubInfo<Runtime>,
                              TargetCanonicalSpecializedMetadatasListCount<Runtime>,
                              TargetCanonicalSpecializedMetadatasListEntry<Runtime>,
                              TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>,
                              TargetCanonicalSpecializedMetadatasCachingOnceToken<Runtime>> {
  TargetRelativeDirectPointer<Runtime, const char> SuperclassType;
  uint32_t MetadataNegativeSizeInWords;
  uint32_t MetadataPositiveSizeInWords;
  uint32_t NumImmediateMembers;
  uint32_t NumFields;
  uint32_t FieldOffsetVectorOffset;
}
const TypeContextDescriptor *swift::swift_getTypeContextDescriptor(const Metadata *type) {
    return type->getTypeContextDescriptor();
}
getTypeContextDescriptor() const {
    switch (getKind()) {
      case MetadataKind::Class: {
        const auto cls = static_cast<const TargetClassMetadataType<Runtime> *>(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 TargetValueMetadata<Runtime> *>(this)->Description;
     case MetadataKind::ForeignClass:
       return static_cast<const TargetForeignClassMetadata<Runtime> *>(this)->Description;
     default return nullptr;
    }
  }
const StoredPointer *getFieldOffsets() const {
  assert(isTypeMetadata());
  auto offset = getDescription()->getFieldOffsetVectorOffset();
  if (offset == 0) return nullptr;
  auto asWords = reinterpret_cast<const void * const*>(this);
  return reinterpret_cast<const StoredPointer *>(asWords + offset);
}

const uint32_t *getFieldOffsets() const {
      auto offset = getDescription()->FieldOffsetVectorOffset;
      if (offset == 0) return nullptr;
      auto asWords = reinterpret_cast<const void * const*>(this);
      return reinterpret_cast<const uint32_t *>(asWords + offset);
}

2、Swift映射

Metadata关系

Descriptor关系
struct TargetMetadata {
    var kind: Int
}
struct TargetValueMetadata {//:TargetMetadata
    var kind: Int
    var typeDescriptor: UnsafeMutablePointer<BaseContextDescriptor>
}
struct TargetHeapMetadata {//:TargetMetadata
    var kind: Int
}

struct TargetAnyClassMetadata {//:TargetHeapMatadata
    var superclass: Any.Type
}

struct TargetAnyClassMetadataObjCInterop {//:TargetAnyClassMetadata
    var superclass: Any.Type
    var reserveword1: Int
    var reserveword2: Int
    var data: UInt
}

enum FieldDescriptorKind : UInt16 {
  case Struct,Class,Enum,MultiPayloadEnum,`Protocol`,ClassProtocol,ObjCProtocol,ObjCClass
}

struct BaseRelativePoiner<Pointee> {
    var offset: Int32
    mutating func relativeOffset() -> UnsafeMutablePointer<Pointee> {
        let offset = self.offset
        return withUnsafePointer(to: &self) { p in
            UnsafeMutablePointer(mutating: UnsafeRawPointer(p)
                .advanced(by: numericCast(offset))
                .assumingMemoryBound(to: Pointee.self))
        }
    }
}

struct FieldRecord {
    var flags: Int32
    var mangledTypeName: BaseRelativePoiner<UInt8>
    var fieldName: BaseRelativePoiner<CChar>
}

struct FieldRecordBuffer<T> {
    var element: T
    var lenght: UInt32
    mutating func index(of i: Int) -> UnsafeMutablePointer<T> {
        return withUnsafePointer(to: &self) {
            UnsafeMutablePointer(mutating: UnsafeRawPointer($0)
                .assumingMemoryBound(to: T.self)
                .advanced(by: i))
        }
    }
}

struct FieldDescriptor {
    var mangledTypeName: BaseRelativePoiner<CChar>
    var superclass: BaseRelativePoiner<CChar>
    var kind: FieldDescriptorKind
    var fieldRecordSize: UInt16
    var numFields: UInt32
    var fields: FieldRecordBuffer<FieldRecord> // 属性列表提取的
}

struct BaseContextDescriptor {
    var flags: Int32
    var parent: Int32
    var name: BaseRelativePoiner<CChar>
    var accessFunctionPtr: Int32
    var fieldDescriptor: BaseRelativePoiner<FieldDescriptor>
}

struct TargetStructMetadata {//:TargetValueMetadata
    var kind: Int
    var typeDescriptor: UnsafeMutablePointer<StructContextDescriptor>
}

struct TargetClassMetadata {//:TargetAnyClassMetadata
    var kind: Int
    var superclass: Any.Type
    var reserveword1: Int
    var reserveword2: Int
    var data: UInt
    var flags: UInt32
    var instanceAddressPoint: UInt32
    var instanceSize: UInt32
    var instanceAlignMask: UInt16
    var reserved: UInt16
    var classSize: UInt32
    var classAddressPoint: UInt32
    var descriptor:  Int
    var ivarDestroyer: Int
}

struct StructContextDescriptor {
    var flags: Int32
    var parent: Int32
    var mangledName: BaseRelativePoiner<CChar>
    var accessFunctionPtr: BaseRelativePoiner<UnsafeRawPointer>
    var fieldDescriptor: BaseRelativePoiner<FieldDescriptor>
    var numberOfFields: UInt32
    var fieldOffsetVector: UInt32
    
    func fieldOffsets(_ metadata: UnsafeRawPointer) -> [Int] {
        (0..<numberOfFields).map {
            Int(metadata.assumingMemoryBound(to: Int32.self)[Int(fieldOffsetVector * 2 + $0)])
        }
    }
}

struct ClassContextDescriptor {
    var flags: Int32
    var parent: Int32
    var mangledName: BaseRelativePoiner<CChar>
    var accessFunctionPtr: BaseRelativePoiner<UnsafeRawPointer>
    var fieldDescriptor: BaseRelativePoiner<FieldDescriptor>
    var superclassType: BaseRelativePoiner<CChar>
    var metadataNegativeSizeInWords: UInt32
    var metadataPositiveSizeInWords: UInt32
    var numImmediateMembers: UInt32
    var numberOfFields: UInt32
    var fieldOffsetVector: UInt32  // 每一个属性值距离当前实例对象地址的偏移量
    var vTableOffset: UInt32
    var vTableSize: UInt32
    // ......... VTable部分
    
    func fieldOffsets(_ metadata: UnsafeRawPointer) -> [Int] {
        (0..<numberOfFields).map {
            Int(metadata.assumingMemoryBound(to: Int.self)[Int(fieldOffsetVector + $0)])
        }
    }
}
// include/swift/ABI/MetadataValues.h
let MetadataKindIsNonHeap = 0x200
let MetadataKindIsRuntimePrivate = 0x100
let MetadataKindIsNonType = 0x400
// 根据include/swift/ABI/MetadataKind.def翻译成Swift,下面在源码中也有Swift结构
struct _MetadataKind {
    static let kind: Kind? = nil
    enum Kind {
        case `struct`
        case `enum`
        case optional
        case opaque
        case foreignClass
        case tuple
        case function
        case existential
        case metatype
        case objCClassWrapper
        case existentialMetatype
        case heapLocalVariable
        case heapGenericLocalVariable
        case errorObject
        case `class` // The kind only valid for non-class metadata
        init(flag: Int) {
            switch flag {
            case (0 | MetadataKindIsNonHeap): self = .struct
            case (1 | MetadataKindIsNonHeap): self = .enum
            case (2 | MetadataKindIsNonHeap): self = .optional
            case (3 | MetadataKindIsNonHeap): self = .foreignClass
            case (0 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .opaque
            case (1 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .tuple
            case (2 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .function
            case (3 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .existential
            case (4 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .metatype
            case (5 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .objCClassWrapper
            case (6 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap): self = .existentialMetatype
            case (0 | MetadataKindIsNonType): self = .heapLocalVariable
            case (0 | MetadataKindIsNonType | MetadataKindIsRuntimePrivate): self = .heapGenericLocalVariable
            case (1 | MetadataKindIsNonType | MetadataKindIsRuntimePrivate): self = .errorObject
            default: self = .class
            }
        }
    }
}
// stdlib/public/core/ReflectionMirror.swift
@available(SwiftStdlib 5.2, *)
@_spi(Reflection)
public enum _MetadataKind: UInt {
  // With "flags":
  // runtimePrivate = 0x100
  // nonHeap = 0x200
  // nonType = 0x400
  
  case `class` = 0
  case `struct` = 0x200     // 0 | nonHeap
  case `enum` = 0x201       // 1 | nonHeap
  case optional = 0x202     // 2 | nonHeap
  case foreignClass = 0x203 // 3 | nonHeap
  case opaque = 0x300       // 0 | runtimePrivate | nonHeap
  case tuple = 0x301        // 1 | runtimePrivate | nonHeap
  case function = 0x302     // 2 | runtimePrivate | nonHeap
  case existential = 0x303  // 3 | runtimePrivate | nonHeap
  case metatype = 0x304     // 4 | runtimePrivate | nonHeap
  case objcClassWrapper = 0x305     // 5 | runtimePrivate | nonHeap
  case existentialMetatype = 0x306  // 6 | runtimePrivate | nonHeap
  case heapLocalVariable = 0x400    // 0 | nonType
  case heapGenericLocalVariable = 0x500 // 0 | nonType | runtimePrivate
  case errorObject = 0x501  // 1 | nonType | runtimePrivate
  case unknown = 0xffff
  
  init(_ type: Any.Type) {
    let v = _metadataKind(type)
    if let result = _MetadataKind(rawValue: v) {
      self = result
    } else {
      self = .unknown
    }
  }
}
  • 桥接元数据

typealias AnyObject = protocol<class>
typealias Any = protocol<>
public typealias AnyClass = AnyObject.Type
Swift 中的元类型用 .Type 表示。比如 Int.Type 就是 Int 的元类型
.Type 是类型,类型的 .self 是值

protocol AnyExtensions {}
extension AnyExtensions {

    public static func write(_ value: Any, to storage: UnsafeMutableRawPointer) {
        guard let this = value as? Self else { return }
        storage.assumingMemoryBound(to: self).pointee = this
    }
    
    public static func value(storage: UnsafeMutableRawPointer) -> Any {
        storage.assumingMemoryBound(to: self).pointee
    }
    
    mutating func storage() -> UnsafeRawPointer {
        if type(of: self) is AnyClass {
            let opaquePointer = Unmanaged.passUnretained(self as AnyObject).toOpaque()
            return UnsafeRawPointer(opaquePointer)
        } else {
            return withUnsafePointer(to: &self) { pointer in
                return UnsafeRawPointer(pointer)
            }
        }
    }
}

func extensions(of type: Any.Type) -> AnyExtensions.Type {
    struct Extensions : AnyExtensions {}
    var extensions: AnyExtensions.Type = Extensions.self
    /// Any.Type.self == Any.Type.Protocol
    withUnsafePointer(to: &extensions) { pointer in
        UnsafeMutableRawPointer(mutating: pointer).assumingMemoryBound(to: Any.Type.self).pointee = type
    }
    return extensions
}

func extensions(of value: Any) -> AnyExtensions {
    struct Extensions : AnyExtensions {}
    var extensions: AnyExtensions = Extensions()
    withUnsafePointer(to: &extensions) { pointer in
        UnsafeMutableRawPointer(mutating: pointer).assumingMemoryBound(to: Any.self).pointee = value
    }
    return extensions
}

  • Swift映射对c++方法
// 根据swift混淆类型名、长度、属性描述、属性入参得到Swift类型元数据
@_silgen_name("swift_getTypeByMangledNameInContext")
public func _getTypeByMangledNameInContext(
    _ name: UnsafePointer<CChar>,
    _ nameLength: Int,
    genericContext: UnsafeRawPointer?,
    genericArguments: UnsafeRawPointer?)
    -> Any.Type?

// 根据元数据提取类型描述
@_silgen_name("swift_getTypeContextDescriptor")
public func _swift_getTypeContextDescriptor(_ metadata: UnsafeRawPointer?) -> UnsafeRawPointer?

// 获取元数据类型
@_silgen_name("swift_getMetadataKind")
internal func _swift_getMetadataKind(_: Any.Type) -> UInt

// 获取元数据类型
@_silgen_name("getMetadataKindOf")
private func _metadataKind<T>(of value: T) -> UnsafePointer<CChar>

// 获取元数据
@_silgen_name("swift_reflectionMirror_normalizedType")
internal func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type

// 获取当前元数据属性个数
@_silgen_name("swift_reflectionMirror_count")
internal func _getChildCount<T>(_: T, type: Any.Type) -> Int

// 递归元数据属性个数
@_silgen_name("swift_reflectionMirror_recursiveCount")
internal func _getRecursiveChildCount(_: Any.Type) -> Int

internal typealias NameFreeFunc = @convention(c) (UnsafePointer<CChar>?) -> Void
//typedef void (*NameFreeFunc)(const char*);
struct _FieldReflectionMetadata {
    var name: UnsafePointer<CChar>?
    var freeFunc: NameFreeFunc?
    var isStrong: Bool?
    var isVar: Bool?
}

// 递归属性
@_silgen_name("swift_reflectionMirror_recursiveChildMetadata")
internal func _getRecursiveChildMetadata(
  _: Any.Type,
  index: Int,
  fieldMetadata: UnsafeMutablePointer<_FieldReflectionMetadata>
) -> Any.Type

// 递归元数据属性偏移量
@_silgen_name("swift_reflectionMirror_recursiveChildOffset")
internal func _getRecursiveChildOffset(
  _: Any.Type,
  index: Int
) -> Int

// 获取属性
@_silgen_name("swift_reflectionMirror_subscript")
internal func _getChild<T>(
  of: T,
  type: Any.Type,
  index: Int,
  outName: UnsafeMutablePointer<UnsafePointer<CChar>?>,
  outFreeFunc: UnsafeMutablePointer<NameFreeFunc?>
) -> Any

// Returns 'c' (class), 'e' (enum), 's' (struct), 't' (tuple), or '\0' (none)
@_silgen_name("swift_reflectionMirror_displayStyle")
internal func _getDisplayStyle<T>(_: T) -> CChar
  • 例子
protocol SwiftRuntime {
    mutating func resolve(isUpdate:Bool);
}

extension SwiftRuntime {
    
    mutating func resolve(isUpdate:Bool = true) {
        let type = type(of: self)
        // 对象首地址
        let basePtr:UnsafeMutableRawPointer? 
        // class 和 strutc获取地址方式有区别
        if type is AnyClass {
            basePtr = UnsafeMutableRawPointer(mutating: Unmanaged.passUnretained(self as AnyObject).toOpaque())
        } else {
            basePtr = withUnsafePointer(to: &self, { UnsafeMutableRawPointer(mutating: $0) })
        }
        guard let basePtr = basePtr else { return }
        let numFields = _getRecursiveChildCount(type)
        for i in 0..<Int(numFields) {
            // 属性地址偏移量
            let offset = _getRecursiveChildOffset(type, index: i)
            // 属性元数据
            var field = _FieldReflectionMetadata()
            // 属性类型
            let fieldType  = _getRecursiveChildMetadata(type, index: i, fieldMetadata: &field)
            // 属性地址
            let pptr = basePtr.advanced(by: offset)
            // 桥接属性,因为不知道fieldType的实际类型
            let anex = extensions(of: fieldType)
            print("  \(String(cString: field.name!)): \(fieldType) = \(anex.value(storage: pptr))")
            // 测试
            if isUpdate {
                if fieldType == Int.self {
                    anex.write(123, to: pptr)
                } else {
                    anex.write("hello world!", to: pptr)
                }
            }
        }
    }
}

class MZBase {
    var kind: String = "parent"
}

class MZPerson:MZBase, SwiftRuntime  {
    var age: Int = 18
    var name: String = "LL"
    var nameTwo: String = "LLLL"
}

输入结果:

================== 修改前 ==================
kind: String = parent
age: Int = 18
name: String = LL
nameTwo: String = LLLL
================== 修改后 ==================
kind: String = hello world!
age: Int = 123
name: String = hello world!
nameTwo: String = hello world!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容