1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        多角度體會 Swift 方法派發(fā)

        共 19145字,需瀏覽 39分鐘

         ·

        2022-05-18 11:25

        ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????


        作者丨鏡畫者

        轉(zhuǎn)自:掘金 

        https://juejin.cn/post/7002201394916622343



        我們知道 Swift 有三種方法派發(fā)方式:靜態(tài)派發(fā)(直接派發(fā))、VTable 派發(fā)(函數(shù)表派發(fā))、消息派發(fā)。下面我們分別從 SIL 中間語言,以及匯編的角度體會 Swift 的方法派發(fā)方式。

        問題引子

        在展開正文之前,我們先來看一個問題:

        有一個 Framework (僅有一個類和一個方法)和一個 Swift App 工程(調(diào)用該方法),代碼如下,將 Framework 編譯后直接集成在 App 工程中:

        // Framework
        public class SwiftMethodDispatchTable {
            public func getMethodName() -> String {
                let name = "SwiftMethodDispatchTable"
                print("Method name: \(name)")
                return name
            }
        }

        // App,ViewController.swift
        class ViewControllerUIViewController {
            override func viewDidLoad() {
                super.viewDidLoad()
                readMethodName()
            }
            func readMethodName() {
                let name = SwiftMethodDispatchTable().getMethodName()
                print("read method name:", name)
            }
        }

        我們?nèi)绻麑?Framework 中的 getMethodName 方法改個名字(getMethodName_new),重新編譯,并將編譯后的二進(jìn)制文件(如下圖所示)覆蓋 App 工程中集成的 Framework 二進(jìn)制文件,且 Headers 與 Modules 目錄保持不變,App 中調(diào)用的方法名稱也保持不變(仍然是 getMethodName)。

        那么問題來了: App 重新編譯后執(zhí)行結(jié)果是什么?

        1. 編譯報錯
        2. 運行時報錯
        3. 正常運行

        下面我們回到正題,最后我們再來回答這個問題。

        SIL

        我們先來看三個相似的類,它們都包含了使用不同派發(fā)方式的 getMethodName 方法,同時我們通過 printMethodName 方法來觀察它們的派發(fā)方式區(qū)別:

        • 靜態(tài)派發(fā)
        final public class SwiftMethodDispatchStatic {
            public init() {}
            
            func printMethodName() -> String {
                let name = getMethodName()
                return name
            }
            
            public func getMethodName() -> String {
                let name = "SwiftMethodDispatchStatic"
                print("Method name: \(name)")
                return name
            }
        }
        • vtable 派發(fā)
        public class SwiftMethodDispatchTable {
            public init() {}
            
            func printMethodName() -> String {
                let name = getMethodName()
                return name
            }
            
            public func getMethodName() -> String {
                let name = "SwiftMethodDispatchTable"
                print("Method name: \(name)")
                return name
            }
        }
        • 消息派發(fā)
        public class SwiftMethodDispatchMessage {
            public init() {}
            
            func printMethodName() -> String {
                let name = getMethodName()
                return name
            }

            @objc dynamic public func getMethodName() -> String {
                let name = "SwiftMethodDispatchMessage"
                print("Method name: \(name)")
                return name
            }
        }

        下面我們分別生成 SIL 對比看看(命令行執(zhí)行 swiftc -emit-silgen -O xxx.swift 生成,以下摘錄關(guān)鍵部分)。

        靜態(tài)派發(fā)

        // SwiftMethodDispatchStatic.printMethodName()
        sil hidden [ossa] @$s25SwiftMethodDispatchStaticAAC05printB4NameSSyF : $@convention(method) (@guaranteed SwiftMethodDispatchStatic) -> @owned String {
        // %0 "self" // users: %3, %1
        bb0(%0 : @guaranteed $SwiftMethodDispatchStatic):
        debug_value %0 : $SwiftMethodDispatchStatic, let, name "self", argno 1 // id: %1
        // function_ref SwiftMethodDispatchStatic.getMethodName()
        %2 = function_ref @$s25SwiftMethodDispatchStaticAAC03getB4NameSSyF : $@convention(method) (@guaranteed SwiftMethodDispatchStatic) -> @owned String // user: %3
        %3 = apply %2(%0) : $@convention(method) (@guaranteed SwiftMethodDispatchStatic) -> @owned String // users: %8, %5, %4
        debug_value %3 : $String, let, name "name" // id: %4
        %5 = begin_borrow %3 : $String // users: %7, %6
        %6 = copy_value %5 : $String // user: %9
        end_borrow %5 : $String // id: %7
        destroy_value %3 : $String // id: %8
        return %6 : $String // id: %9
        } // end sil function '$s25SwiftMethodDispatchStaticAAC05printB4NameSSyF'

        sil_vtable [serialized] SwiftMethodDispatchStatic {
        #SwiftMethodDispatchStatic.init!allocator: (SwiftMethodDispatchStatic.Type) -> () -> SwiftMethodDispatchStatic : @$s25SwiftMethodDispatchStaticAACABycfC // SwiftMethodDispatchStatic.__allocating_init()
        #SwiftMethodDispatchStatic.deinit!deallocator: @$s25SwiftMethodDispatchStaticAACfD // SwiftMethodDispatchStatic.__deallocating_deinit
        }

        在以上的 SIL 中重點看這兩行:

        // function_ref SwiftMethodDispatchStatic.getMethodName()
        %2 = function_ref @$s25SwiftMethodDispatchStaticAAC03getB4NameSSyF : $@convention(method) (@guaranteed SwiftMethodDispatchStatic) -> @owned String // user: %3

        function_ref 關(guān)鍵字表明 getMethodName 方法是通過方法指針來調(diào)用的,并且通過符號 s25SwiftMethodDispatchStaticAAC03getB4NameSSyF 來定位方法地址,同時 sil_vtable 中也未包含該方法。

        vtable 派發(fā)

        // SwiftMethodDispatchTable.printMethodName()
        sil hidden [ossa] @$s24SwiftMethodDispatchTableAAC05printB4NameSSyF : $@convention(method) (@guaranteed SwiftMethodDispatchTable) -> @owned String {
        // %0 "self" // users: %3, %2, %1
        bb0(%0 : @guaranteed $SwiftMethodDispatchTable):
        debug_value %0 : $SwiftMethodDispatchTable, let, name "self", argno 1 // id: %1
        %2 = class_method %0 : $SwiftMethodDispatchTable, #SwiftMethodDispatchTable.getMethodName : (SwiftMethodDispatchTable) -> () -> String, $@convention(method) (@guaranteed SwiftMethodDispatchTable) -> @owned String // user: %3
        %3 = apply %2(%0) : $@convention(method) (@guaranteed SwiftMethodDispatchTable) -> @owned String // users: %8, %5, %4
        debug_value %3 : $String, let, name "name" // id: %4
        %5 = begin_borrow %3 : $String // users: %7, %6
        %6 = copy_value %5 : $String // user: %9
        end_borrow %5 : $String // id: %7
        destroy_value %3 : $String // id: %8
        return %6 : $String // id: %9
        } // end sil function '$s24SwiftMethodDispatchTableAAC05printB4NameSSyF'

        sil_vtable [serialized] SwiftMethodDispatchTable {
        #SwiftMethodDispatchTable.init!allocator: (SwiftMethodDispatchTable.Type) -> () -> SwiftMethodDispatchTable : @$s24SwiftMethodDispatchTableAACABycfC // SwiftMethodDispatchTable.__allocating_init()
        #SwiftMethodDispatchTable.printMethodName: (SwiftMethodDispatchTable) -> () -> String : @$s24SwiftMethodDispatchTableAAC05printB4NameSSyF // SwiftMethodDispatchTable.printMethodName()
        #SwiftMethodDispatchTable.getMethodName: (SwiftMethodDispatchTable) -> () -> String : @$s24SwiftMethodDispatchTableAAC03getB4NameSSyF // SwiftMethodDispatchTable.getMethodName()
        #SwiftMethodDispatchTable.deinit!deallocator: @$s24SwiftMethodDispatchTableAACfD // SwiftMethodDispatchTable.__deallocating_deinit
        }

        在 vtable 的方式中,方法的引用方式就變成了:

        %2 = class_method %0 : $SwiftMethodDispatchTable#SwiftMethodDispatchTable.getMethodName : (SwiftMethodDispatchTable) -> () -> String, $@convention(method) (@guaranteed SwiftMethodDispatchTable) -> @owned String // user: %3

        這里的 class_method 關(guān)鍵字表明 getMethodName 使用類對象方法的方式,即函數(shù)表的方式,通過 sil_vtable 中的信息也能印證這一點,SwiftMethodDispatchTable 類的 vtable 表包含了這個方法。

        消息派發(fā)

        // SwiftMethodDispatchMessage.printMethodName()
        sil hidden [ossa] @$s26SwiftMethodDispatchMessageAAC05printB4NameSSyF : $@convention(method) (@guaranteed SwiftMethodDispatchMessage) -> @owned String {
        // %0 "self" // users: %3, %2, %1
        bb0(%0 : @guaranteed $SwiftMethodDispatchMessage):
        debug_value %0 : $SwiftMethodDispatchMessage, let, name "self", argno 1 // id: %1
        %2 = objc_method %0 : $SwiftMethodDispatchMessage, #SwiftMethodDispatchMessage.getMethodName!foreign : (SwiftMethodDispatchMessage) -> () -> String, $@convention(objc_method) (SwiftMethodDispatchMessage) -> @autoreleased NSString // user: %3
        %3 = apply %2(%0) : $@convention(objc_method) (SwiftMethodDispatchMessage) -> @autoreleased NSString // user: %5
        // function_ref static String._unconditionallyBridgeFromObjectiveC(_:)
        %4 = function_ref @$sSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String // user: %7
        %5 = enum $Optional<NSString>, #Optional.some!enumelt, %3 : $NSString // users: %9, %7
        %6 = metatype $@thin String.Type // user: %7
        %7 = apply %4(%5, %6) : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String // users: %13, %10, %8
        debug_value %7 : $String, let, name "name" // id: %8
        destroy_value %5 : $Optional<NSString> // id: %9
        %10 = begin_borrow %7 : $String // users: %12, %11
        %11 = copy_value %10 : $String // user: %14
        end_borrow %10 : $String // id: %12
        destroy_value %7 : $String // id: %13
        return %11 : $String // id: %14
        } // end sil function '$s26SwiftMethodDispatchMessageAAC05printB4NameSSyF'
        sil_vtable [serialized] SwiftMethodDispatchMessage {
        #SwiftMethodDispatchMessage.init!allocator: (SwiftMethodDispatchMessage.Type) -> () -> SwiftMethodDispatchMessage : @$s26SwiftMethodDispatchMessageAACABycfC // SwiftMethodDispatchMessage.__allocating_init()
        #SwiftMethodDispatchMessage.printMethodName: (SwiftMethodDispatchMessage) -> () -> String : @$s26SwiftMethodDispatchMessageAAC05printB4NameSSyF // SwiftMethodDispatchMessage.printMethodName()
        #SwiftMethodDispatchMessage.deinit!deallocator: @$s26SwiftMethodDispatchMessageAACfD // SwiftMethodDispatchMessage.__deallocating_deinit
        }

        在消息派發(fā)中,引用方式變成了:

        %2 = objc_method %0 : $SwiftMethodDispatchMessage#SwiftMethodDispatchMessage.getMethodName!foreign : (SwiftMethodDispatchMessage) -> () -> String, $@convention(objc_method) (SwiftMethodDispatchMessage) -> @autoreleased NSString // user: %3

        objc_method 關(guān)鍵字表明了方法已經(jīng)轉(zhuǎn)為了使用 OC 中的方法派發(fā)方式,即消息派發(fā),并且方法簽名中,返回類型已經(jīng)變?yōu)榱?NSString,vtable 中也沒有了 getMethodName 方法。

        從 SIL 的角度看 Swift 中的方法派發(fā)方式,是不是很明白。

        匯編

        我們接著再從匯編層面看看以上幾種派發(fā)方式的區(qū)別。

        在開始前我們先準(zhǔn)備點樣例代碼,在最前面的 App 工程中我們增加上面提到的幾個方法:

        @IBAction func StaticDispatch(_ sender: Any) {       
               _ = SwiftMethodDispatchStatic().getMethodName()    
          }        
          
          @IBAction func VTableDispatch(_ sender: Any) {       
              _ = SwiftMethodDispatchTable().getMethodName()   
          }        
          
          @IBAction func MessageDispatch(_ sender: Any) {        
              _ = SwiftMethodDispatchMessage().getMethodName()   
          }

        我們在調(diào)用處打上斷點,并通過匯編模式進(jìn)行調(diào)試觀察(選擇 Debug 菜單中的 Debug Workflow,勾選 Always Show Disassembly):

        下面我們分別看看不同派發(fā)方式中匯編代碼的區(qū)別

        靜態(tài)派發(fā)

        下面是 StaticDispatch 方法對應(yīng)的匯編代碼:

        在第 17 行 bl 0x1047414cc 這條指令后有一個注解:symbol stub for …getMethodName...,可以猜想一定和 getMethodName 方法有關(guān),那么我們看看 0x1047414c 這個地址到底指向什么。

        bl 指令表示跳轉(zhuǎn)到指定的子程序名處執(zhí)行代碼

        symbol stub 表示代碼的符號占位,實際代碼要根據(jù)占位符號進(jìn)行重新定位。

        執(zhí)行以下命令:

        image lookup --address 0x1047414cc

        結(jié)果如下:

        Address: SwiftMethodDispatchAppDemo[0x00000001000054cc] (SwiftMethodDispatchAppDemo.__TEXT.__stubs + 36)
        Summary: SwiftMethodDispatchAppDemo`symbol stub for: SwiftMethodDispatch.SwiftMethodDispatchStatic.getMethodName() -> Swift.String

        這里我們可以看到地址  0x1047414cc 對應(yīng)的偏移地址是 0x00000001000054cc,我們根據(jù)這個地址在 MachO 文件的 __TEXT,__stubs 這個 section 中進(jìn)行查找。

        我們使用 MachOView 這個工具來查看 app 的二進(jìn)制文件信息

        下載這個工程編譯運行即可:

        github.com/emptyglass123/MachOView

        打開 MachOView 后我們在 TEXT 段中找 __TEXT,__stubs 這個 section,查找偏移地址為 000054cc 的記錄:

        對應(yīng)的值是一串符號:_$s19SwiftMethodDispatch0abC6StaticC03getB4NameSSyF,經(jīng)過 demangle 轉(zhuǎn)換后得到的值為:

        SwiftMethodDispatch.SwiftMethodDispatchStatic.getMethodName() -> Swift.String

        這與 image lookup 命令得到的結(jié)果一致,因為 SwiftMethodDispatch 是一個動態(tài)庫,以上符號需要在動態(tài)庫中進(jìn)行重定位,我們在 MachOView 中再打開 SwiftMethodDispatch。

        在 Symbol Table 中搜索符號:_$s19SwiftMethodDispatch0abC6StaticC03getB4NameSSyF,該符號對應(yīng)的代碼段偏移地址是:32F4

        繼續(xù)在 __TEXT,__text section 中查找 32F4 地址對應(yīng)的記錄,從下圖中標(biāo)記的這一行開始即是 getMethodName 這個方法:

        在 Xcode 中調(diào)試 App 的匯編代碼可以對比代碼是一致的:

        從上面的查找過程可以發(fā)現(xiàn) Swift 方法在使用靜態(tài)派發(fā)時,幾乎是直接使用了方法的內(nèi)存地址(因為是外部符號,需要經(jīng)過動態(tài)庫的符號重定位)。如果靜態(tài)派發(fā)的方法存儲在 App 的二進(jìn)制文件中,則調(diào)用的地址即為方法的內(nèi)存入口地址,無需任何轉(zhuǎn)換(可以自行驗證)。

        vtable 派發(fā)

        我們再看看 vtable 派發(fā)的情況,類似地通過斷點查看匯編代碼:

        單步調(diào)試停止到第 16 行處,查看 x8 這個寄存器的值,在 Xcode 的debug 區(qū)執(zhí)行命令:

        register read x8

        結(jié)果如下:

        x8 = 0x0000000100c782a0  type metadata for SwiftMethodDispatch.SwiftMethodDispatchTable

        ldr x8, [x8, #0x60] 這條命令表示把 x8 + 0x60 所在內(nèi)存地址的數(shù)據(jù)(4字節(jié))讀取到 x8 寄存器中。

        我們再看下 x8 + 0x60 的地址(0x0000000100c78300)是什么內(nèi)容:

        image lookup --address 0x0000000100c78300
        Address: SwiftMethodDispatch[0x0000000000008300] (SwiftMethodDispatch.__DATA.__data + 160)
        Summary: type metadata for SwiftMethodDispatch.SwiftMethodDispatchTable + 96

        這里存儲的是 SwiftMethodDispatchTable 這個類的 metadata 信息,內(nèi)部具體結(jié)構(gòu)還有待研究,不過可以知道的是對象定義的方法包含在其中。

        再通過 MachOView 查看 SwiftMethodDispatch 的二進(jìn)制文件信息,定位偏移地址 0x8300 的內(nèi)容:

        可以看到 0x8300 這個地址的值指向了另外一個地址:2CCC(Data LO 中低位地址在前,高位地址在后)

        再重新定位 0x2ccc 這個地址指向的值,這是一個函數(shù)的入口地址:

        我們在 Xcode 中繼續(xù)調(diào)試到 19 行,再進(jìn)入調(diào)用棧,可以看到進(jìn)入了 SwiftMethodDispatchTable.getMethodName() 方法,與上面看到的二進(jìn)制匯編代碼是一致的,通過 image lookup 查找偏移地址也是匹配的:

        image lookup --address 0x100c72ccc
        Address: SwiftMethodDispatch[0x0000000000002ccc] (SwiftMethodDispatch.__TEXT.__text + 152)
        Summary: SwiftMethodDispatch`SwiftMethodDispatch.SwiftMethodDispatchTable.getMethodName() -> Swift.String at SwiftMethodDispatchTable.swift:18

        到這一步已經(jīng)成功調(diào)用到了 getMethodName 方法。

        從上面的過程我們可以看到,基于函數(shù)表派發(fā)的方式,調(diào)用方法時提供的是類的 metadata 數(shù)據(jù)的偏移地址(0x60),基于這個偏移地址可以再次定位到方法的實際入口地址??梢哉J(rèn)為經(jīng)歷了一個查表的過程,不過這張函數(shù)表在編譯時已經(jīng)確定了,Swift 動態(tài)庫提供的 swiftmodule 接口文件已經(jīng)足以在編譯期定位方法在 metadata 中的偏移地址。

        消息派發(fā)

        最后我們再看下消息派發(fā)的匯編代碼:

        這次的代碼較多一點,我們單步調(diào)試停在第 16 行處,查看并計算 x8 + 0xb80 指向的地址:

        (lldb) register read x8
        x8 = 0x0000000100bb0000  (void *)0x00000001020acb98: ObjectiveC._convertBoolToObjCBool(Swift.Bool) -> ObjectiveC.ObjCBool

        (lldb) image lookup --address 100bb0b80
        Address: SwiftMethodDispatchAppDemo[0x000000010000cb80] (SwiftMethodDispatchAppDemo.__DATA.__objc_selrefs + 128)
        Summary: "getMethodName"

        根據(jù) cb80 這個偏移地址在 App 的二進(jìn)制文件中查找:

        可以看到這個地址保存的內(nèi)容是一個指針,地址為 0x5A9C,再看看這個指針的內(nèi)容是什么:

        0x5A9C 指向的內(nèi)容是一個字符串 getMethodName,其實 __TEXT,__objc_methname 這個 section 就是保存的 OC 方法 SEL 名稱。

        在 Xcode 中運行至 17 行,再讀取 x8 寄存器的內(nèi)容,可以看到結(jié)果也是 getMethodName 這個字符串:

        在 Xcode 中可以看到第 19 行調(diào)用了 objc_msgSend 這個方法,我們進(jìn)入方法調(diào)試:

        走到第 16 行時停下,查看 x17 寄存器的值:

        register read x17 
        x17 = 0x0000000100c7387c  SwiftMethodDispatch`@objc SwiftMethodDispatch.SwiftMethodDispatchMessage.getMethodName() -> Swift.String at <compiler-generated>

        這個地址即是 getMethodName 對應(yīng) OC 方法的入口地址:

        image lookup --address 0x0000000100c7387c
        Address: SwiftMethodDispatch[0x000000000000387c] (SwiftMethodDispatch.__TEXT.__text + 3144) Summary: SwiftMethodDispatch`@objc SwiftMethodDispatch.SwiftMethodDispatchMessage.getMethodName() -> Swift.String at

        在動態(tài)庫的 MachO 中可以查看:

        可以看到 getMethodName 其實對應(yīng)有 2 個方法,一個是 OC 版的,一個是 Swift 版的,在內(nèi)存中是 2 個地址:

        @objc SwiftMethodDispatch.SwiftMethodDispatchMessage.getMethodName() -> Swift.String
        SwiftMethodDispatch.SwiftMethodDispatchMessage.getMethodName() -> Swift.String

        在 Xcode 進(jìn)入 16 行的 br x17 指令,可以看到已經(jīng)進(jìn)入了 getMethodName 方法(OC 版):

        這就證實了對 getMethodName 方法的調(diào)用已經(jīng)轉(zhuǎn)換成了對 getMethodName 這個消息的發(fā)送,走的是 OC 的消息發(fā)送邏輯(由 Swift 編譯生成的 OC 兼容版本),有興趣可以看看 objc_msgSend 的匯編解析。

        從上面的過程可以看到,在 Swift 中如果方法被標(biāo)記為需要通過消息發(fā)送的方式執(zhí)行,那么方法的 SEL 就會存儲在二進(jìn)制中的  __TEXT,__objc_methname 這個 section 中,在調(diào)用時通過 SEL 來查找對應(yīng)的方法入口。

        問題回顧

        現(xiàn)在我們再回到最前面的問題,Swift 方法修改名稱后,在不修改接口信息的情況下,還能調(diào)用嗎。

        根據(jù) Swift 方法派發(fā)的特性,問題中 getMethodName 方法使用的是函數(shù)表派發(fā),由于接口未改動,它的偏移地址是不變的,在 App 運行時編譯都是能正常通過的,在運行時通過類的 metadata 的偏移地址直接定位到方法的入口地址,并未涉及到新方法名的重定位,因此改名后的方法可以順利被執(zhí)行。

        但是如果稍作修改,在 getMethodName 源碼的上方添加另一個方法,偏移地址就發(fā)生了改變,運行時就會執(zhí)行新添加的方法,如果方法的參數(shù)類型與返回值不符則會報錯,相符則仍然可以順利執(zhí)行。

        Demo 工程

        本文的 Demo 工程見 Github.
        (github.com/pmtao/SwiftMethodDispatchDemo)

        轉(zhuǎn)自:掘金 鏡畫者 

        https://juejin.cn/post/7002201394916622343

        -End-

        最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

        點擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

        在看點這里好文分享給更多人↓↓

        瀏覽 20
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            乱伦中文| 欧产日产国产swag| 中文免费高清在线观看视频| 成人无码一区二区| 丁香婷婷五月色成人网站| 特级西西444www无码视频免费看 | 色色欧美视频| 特级特黄AAAAAAAA片| 激情五月在线| 91视频你懂的| 地表最强网红八月未央道具大秀| 天天日天天操天天日| 在线观看免费黄色视频| 中文字幕AV在线观看| 日韩aaaaaa| 国产精品高潮呻吟| 亚洲精品aaa| 亚洲人妻电影一区| 国产精品激情| 日韩久久网| 精品国产污污免费网站入口| 久久精品久久久久久久| 欧美69成人| 噜噜色av| 欧美淫秽视频| 伊人网视频在线观看| 欧美激情亚洲| 亚洲无码手机在线观看| 日韩精品丰满无码一级A片∴| xxxx日韩| 中文字幕线观看| 亚洲一级片| 午夜成人精品视频| 国产精品av在线| 手机在线看A片| 欧美成人AA| 蜜桃人妻无码AV天堂二区| 日韩AV无码专区亚洲AV紧身裤| 操你久久| 爽好紧别夹喷水无码| 欧美精品网站| 翔田AV无码秘三区| 精品欧美乱码久久久久久| 久久婷婷在线| 操逼视频在线免费看| 青青操原| 中文字幕永久在线视频v1.0| 三级片韩国AV| 婷婷亚洲综合| 欧美性爱中文字幕| 日韩一级无码视频| av天堂中文字幕| 在线免费观看亚洲| 欧美性爱视频免费观看| 91二区三区| 中文字幕成人在线观看| 色99在线视频| 成人av免费观看| 狠狠干2021| 美女乱伦| 大香蕉中文| 久久香蕉综合在线| 粉嫩99精品99久久久久久特污兔 | 蜜桃视频com.www| 精品一区二区ww| 国产精品无码无套在线照片| 日韩成人在线看| 韩日无码人妻| 亚洲无码在线观看免费| 色AV高清| 先锋影音资源站| www.天天日| 伊人狠狠| 欧美黑吊大战白妞| 操操日| 黄色毛片电影| 欧美成人午夜福利| 激情五月在线| 麻豆三级片在线观看| 日韩欧美成人在线视频| 免费观看高清无码| 日韩免费a| 五月丁香婷婷基地| 97人人干人人| 国产精品久久久久久久9999| 91高清无码视频| 操穴网| 影音先锋久久久久AV综合网成人| 亚洲欧洲久久| 欧美一级成人片| 爆操视频| 五月丁香在线播放| 精品久久久999| 大香蕉伊人网在线| 思思操在线视频| 人人操人人透| 激情乱伦网站| 亚洲精品成人无码熟妇在线| 黄色a片网站| 无码精品人妻一区二区| 成人毛片在线大全免费| 午夜福利视频无码| 8x8拨牐拨牐拨牐永久免费| 免费无遮挡视频网站视频| 色图插插插| 91人妻无码精品| 久久99精品久久久久| 北条麻妃二区三区| 人人操天天干| 欧美在线视频你懂的| 日本白嫩的BBw| 色播网址| 国产又爽又黄视频在线看| 青青草原免费在线视频| 少妇搡BBBB搡BBB搡毛片少妇| 国产在线观看无码| 亚洲日韩黄色| 丰满人妻一区二区三区四区53| 国产人人爱| 性爱日韩| 在线免费观看无码视频| 国产女主播在线观看| 毛片毛片毛片毛片毛片| 色爽AV| 亚洲视频久久| 久久激情视频| 日韩av电影在线观看| 欧美日本在线| 高清无码黄片| 亚洲一区| 懂色一区二区三区免费| 国产小视频免费在线观看| 中文无码网站| 欧美成人在线免费| 国产一区二区在线播放| 国产熟睡乱子伦午夜视频_第1集| 成人福利视频在线观看| 狠狠插狠狠操| 嫩BBB揍BBB揍BBB| 亚洲中文字幕高清| 国产偷拍网站| 天天干天天干天天日| a在线视频| 国产天天操| 青娱乐黄片| 仙踪林777777野大粗| 欧洲成人无码| 人人艹在线观看| 中国熟睡妇BBwBBw| 日本中文字幕精品| 一插菊花网| 河南熟妇搡BBBB搡BBBB| 欧美日韩毛片| 肉乳无码A片av| 天堂中文字幕在线| 亚洲中文无码在线| 韩国精精品视频| 逼逼爱插插网站| 四色五月婷婷| 亚洲高清无码视频在线播放| 少妇A片| 麻豆做爱| 午夜福利10000| 翔田千里AV在线| 日韩性爱网| 一级黄片免费看| 亚洲va综合va国产va中文| 日韩成人在线看| 99热99re6国产线播放| 波多野结衣国产区42部| 99精品全国免费观看| 一级内射视频| 国产精品成人午夜福利| 欧美精品久久久| 欧美性爱操逼视频| 免费观看黄色一级片| 亚洲免费观看高清完| 大香蕉在8线| 精品黄色片| 色九| 黄色视频网站免费| 亚洲s在线| 四川BBB搡BBB爽爽爽欧美| 国产一区二区在线播放| 四虎操逼| 国产精品二区高清在线苍井空| 日韩在线电影| 欧美激情网站| 国产人妻精品一区二区三区不卡| 免费在线观看内射| 国精品无码A区一区二区| 国产精品人妻无码一区牛牛影视| 午夜乱伦福利| 日韩av中文字幕在线| 91操B| 日韩无码久久久| 日韩在线观看网站| 国产乱子伦一区二区三区视频 | 亚洲日韩欧美在线观看| 中文字幕精品在线观看| 亚洲精品秘一区二区三区蜜桃久| 黑人vs亚洲人在线播放| 人妻无码精品蜜桃| 俺来俺去www色官网| 人妻乱码| 69成人精品国产| 中文字幕在线看| 69堂在线观看| 九久热| 婷色五月天| 免费AV大全| 中文字幕无码在线| 国产亚洲无码| 荫蒂添到高潮免费视频| 久热精品免费| 亚洲的天堂的αⅴ| 欧美在线观看一区| 操逼三级片| 97精品一区二区三区A片| 欧美日韩视频在线播放| 日本免费一级片| 久草黄色电影| 国产又粗又大又长| 91精品在线免费观看| 国产成人在线免费视频| 人人摸人人草| 又爽又黄免费网站97双女| av无码精品一区| 国产不卡一区| 欧美成人黄色电影| 国产精品H| 国产乱子伦无码视频免费| 国产色综合视频| 婷婷五月色| 91黄在线观看| 日本黄色免费在线观看| 亚洲精品一级二级三级| 国产偷拍| 精品乱子伦一区二区三区下载 | 国产成人无码免费| 日韩欧美A片| 一级黄片免费看| 久久精品三级视频| a√天堂中文在线8| 亚洲日韩Av无码中文字幕美国 | 亚洲天堂在线免费观看| 91色五月| 色色五月丁香婷婷| 色色a| 亚洲无码A片在线观看APP| 人人操91| 黄色视频在线观看免费网站| 人妻熟女字幕一区二区| 午夜影院操| 91精品婷婷国产综合久久蝌蚪| 熟女久久| 国产操B| 另类老妇奶性生BBwBBw偷拍 | 成人av影院| 欧美日韩一区在线观看| 好吊妞在线| 老女人操逼视频| 99r6热只有精品免费观看| 超碰一区| 99在线免费观看| 熟妇高潮一区二区高潮| AV天堂小说网| 久久婷婷国产综合| 亚洲av中文| 国产Av大全| 抽插影院| 高清无码在线免费| 精品一区二区三区毛片| 亚洲欧美另类色图| 欧美成人三级在线观看| 欧美五月在线网址| 午夜福利区| 成人做爰黄AA片免费看三区| 丝袜制服中文字幕无码专区| 这里精品| 人妻精品一区二区| 中文字字幕中文字幕乱码| 夜夜干天天操| 天天添天天操| 最新国产毛片| 日韩国产| 亚洲欧美国产精品专区久久| 黄色a片在线观看| 久操视频免费在线观看| 天天拍夜夜操| 高清无码网| 四川少妇BBBB| 亚洲无码中文字幕在线观看| 欧美成人A片AAA片在线播放| 欧美一区二区三区精品| 亚洲视频久久| 北条麻妃无码| 一区二区三区在线视频观看| 中文字幕+乱码+中文字幕在线| 亚洲男人综合| 北条麻妃在线一区二区| 影音先锋成人av| 蜜桃视频欧美| 波多无码在线| 精品成人| 国产精品国产三级国产| 91中文字幕+乱码| 日本黄A级A片国产免费| 东京热91| 成人自拍偷拍视频| 99re在线精品| 激情丁香五月天| 免费看a的网站| 囯产精品久久久久久久久免费无码 | 青草网| 国产精品美女在线观看| 日本一区二区三区在线视频| 国精产品一区二区三区在线观看 | 日日搔av一区二区三区| 天天干夜夜骑| 91精品人妻| 91久久久久久久久久| 国产成人亚洲综合A∨婷婷| 在线免费人成视频| 五月婷婷色播| 无码超碰| 国产大屌| 99在线观看免费视频| 亚洲日韩精品欧美一区二区yw| 一级黄色录像带| 91视频在线观看网| 日韩欧美在线中文字幕| 久热在线视频| 在线观看黄色网页| 久久久久无码精品亚洲日韩| 亚洲成人电影天堂| 久久久亚洲无码精品| 91人妻无码一区二区久久| 久久久久97| 色婷婷丁香| 首屈一指视频在线观看| 亚洲资源在线观看| 操屄视频免费观看| 老司机免费福利视频| 人人妻人人玩澡人人爽| 亚洲专区在线| 精品人妻中文字幕视频| 韩国无码观看| 欧美人妻视频在线| 想要xx在线观看| 免费黄色视频在线观看| 亚洲综合网在线| 91.www91成人影视在线观看91成人网址9 | 日韩成人av在线| 热无码| 国精产品一区一区三区有限公司杨 | 高清无码在线免费观看| 欧美日逼片| 亚洲无码视频免费观看| 天天色粽合合合合合合合| 亚洲成人在线免费观看| 亚洲性爱小说网址| 水蜜桃网址| 秋霞午夜福利影院| 婷婷五月综合网| 不卡的AV| 高h视频在线观看| 亚洲AV电影天堂| 国产精品成人免费精品自在线观看 | 大鸡巴视频在线观看| 99在线观看视频在线高清| 俄罗斯熟妇搡BBBB搡BBBB| 国产精品无码成人AV电影| 亚洲精品成人视频| 很很撸在线视频| 日韩成人高清无码| a日韩| 蜜臀av在线免费观看| 91蜜桃视频| 奥门黄片| 国产黄网| 天天干人人干| 天天爱天天操| 97国产精品人人爽人人做| b逼一区| 大香久久| 老司机无码| 99精品视频免费| 超碰91免费在线观看| 国产一级a毛一级a做免费高清视频| 久久yy| 黄色AV天堂| 五月天无码免费视频| 青青草无码成人天堂免费| 荫蒂添的高潮免费视频| 欧美一区二区三区视频| 亚洲成人AAAAA| 欧美成人在线观看| 欧美一级在线免费观看| 黄色视频在线免费观| 免费观看成人| 高清人妻无码| 亚洲无码A片在线观看| 91红桃视频| 天天射日日干| 免费黄片在线| 996热| 青青草手机在线观看| 无码人妻丰满熟妇区毛片蜜桃麻豆| 黄片大全在线免费观看| 欧美成人精品AAA| 欧美日韩一道本| 国产96在线亚洲| 特级艺体西西444WWw| 俺也去com| 日逼A片| 91在线无码精品秘入口电车| 透逼视频| 国产高清久久| 亚洲AV无码一区毛片AV| 黄片亚洲| 日本在线观看www| 闷骚艳岳的婬乱生活视频| 久久精品在线播放| 成人操B视频在线观看| 91网站免费在线观看| 91艹艹| 悠悠色影院| 一区二区三区在线观看免费| 特黄AAAAAAAA片视频| 国产精品成人影视| 苍井空一区二区三区四区| 国产又爽又黄免费网站校园里| 国内精品久久久久久久久98| 中文字幕三级av片| 日本成人久久| 91精品国产91久久久久久吃药| 国产视频中文字幕| 黄色视频网站在线看| 亚洲天堂av在线免费观看| 天天爽天天射| 亚洲午夜无码久久久| 翔田千里无码| 亚洲最新AV在线| 在线天堂视频| 人人爽人人操人人| 亚洲欧美日韩性爱| 你懂的在线观看| 狠狠色噜噜狠狠狠888米奇视频| 国产激情欧洲在线观看一区二区三区 | 2019国产精品| 91免费在线视频观看| 亚洲综合一区二区| 日韩,变态,另类,中文,人妻| 3级片网站| 精品一二三| 日日夜夜精选视频| 中文字幕三级av片| 国产精品无码成人AV在线播放| 一级片AV| yOujiZZ欧美精品| 免费内射视频| 成人免费视频一区二区三区| 日韩综合色视频导航| 亚洲精品无码视频在线观看| 黄色视频免费观看国产| 亚洲国产成人精品女人久久久| 亚洲人妻无码视频| 天天射日| 亚洲视频一区| 亚洲视频中文字幕在线观看| 中文字幕精品1| 97无码免费| 日韩精品久久久| 中文字幕精品在线免费视频观看视频| 四虎精品成人无码A片| 激情小说在线视频| 激情小视频国产在线播放| 婷婷五月天无码| 99久久久无码国产精品性波多 | 黄片网站免费观看| 久久AV秘一区二区三区水生| 精品一区二区三区四区五区| 欧美淫秽视频| 操碰人人| 五月婷婷网| 亚洲成人无码片| 黄色视频网站在线| 四川少妇BBBB| 久久av影院| 韩国精品久久久| 欧美日韩综合| 日韩有码中文字幕在线观看| 在线天堂9| 中文字幕伊人| 黄片在线免费播放| 天天艹av| 人人妻人人澡人人爽久久| 自拍偷拍无码| 人人操人人搞| 亚洲午夜激情| 开心激情网站| A片在线观看视频| 国产无遮挡又黄又爽又色| 久久国产高清视频| 亚洲AV日韩AV永久无码网站| 人妻精品一区二区| 三浦恵子一级婬片A片| 综合+++夜夜| 91丝袜一区在线观看| 日日夜夜综合| 久久久XXX| 911亚洲精品| 天天色天天色天天色| 在线观看中文字幕一区| 伊人天天色| www香蕉成人片com| 日韩av中文字幕在线| 真人一级毛毛片| 大香蕉免费中文| 91视频一区二区| 可以在线观看的av| 九一国产在线| 天天综合网站| 亚洲色欲色欲www在线成人网| 中文字幕乱码中文乱码91| 免费视频一二区| 无码秘蜜桃一区二区| 亚洲无码自拍偷拍| 操日本少妇| 青青草原免费在线视频| 天堂vs亚洲| 日韩av在线免费观看| www.A片| 黄色免费一级片| 在线观看不卡av| 国产十欧洲十美国+亚洲一二三区在线午夜 | 天天操天天操天天操| 久久99久久99久久99人受| 欧美高潮视频| 在线免费观看av网站| 91羞羞网站| 热99精品| 无码一二三四| 欧美麻豆| 99热在线免费观看| 一本道在线无码| 91精品国产乱码香蕉黄瓜草莓| 91久久久久久久久久| 欧美日本色| 国产v片| 久久男人网| 国产最新地址| 人人干视频| 污污污污污www在线观看优势 | 亚洲日韩在线a成| 日韩午夜欧美精品一二三区| 蜜臀久久99精品久久久老牛影视| JiZZjiZZ亚洲成熟熟妇| av婷婷五月天| 97资源在线视频| 苍井空中文字幕在线观看| 五月婷婷丁香| 99视频在线播放| 1插菊花综合| 亚洲色,天堂网| 夜夜爽7777精品国产三级| 苏妲己一级婬片A片| avcom无码| 国产av激情| 亚洲有码在线| 日韩大屌| 波多野结衣一级| 99久久久精品久久久久久| 亚洲区综合| 日韩无码一区二区三区| 欧美艹逼| 91日逼视频| 91久久精品一区二区三| 尿在小sao货里面好不好| 啪啪网站免费看| 国产成人毛片18女人18精品| 一欧美日韩免费/看| 翔田千里無碼破解| 午夜视频网站| 特黄视频在线观看| 国产毛片欧美毛片高潮| 亚洲免费网站| 丁香五月在线视频| 无码高清免费| 日本在线精品视频| 亚洲欧美日韩激情| 国产欧美日韩视频| 偷拍一区二区三区| 成人一区二区三区四区五区| 仙踪林777777野大粗| 亚洲免费网站| 日韩无码电影网| 91人妻精| 四川少妇BBBB槡BBBB槡| 永久免费一区二区| 一区二区三区四区五区无码 | 婷婷五月综合激情| 91人妻无码精品| 欧美黄片免费视频| 天天爽夜夜爽| 在线不欧美| 五月天激情电影| 三级片无码视频| A片免费在线| 精品无码一区二区三区免费| 大香蕉黄色片| 激情视频综合网| 91久久久久久久久久| 苍井空精毛片精品久久久| 欧美精品在线免费| 中文字字幕中文字幕乱码| 操久久| 成人超碰在线| 激情欧美| 国内自拍视频在线观看| 狠狠草视频| 色哟哟无码精品一区二区三区| 日本性欧美| 在线操B视频| 色伊人久操视频| np高辣调教视频| 亚洲一区二区在线| 色妹子综合| 国产高清无码视频在线观看| 无码人妻一区二区三区线花季传件| 午夜激情视频网站| 久久99久久99精品免视看婷婷| 青青操在线| 日韩亚洲欧美在线| 免费在线观看无码视频| 黑人AV在线观看| 中文字幕AV第一页| av六月天| 国产一区二区三区免费观看| 天天色操| 日韩av免费在线| 国产精品香蕉国产| 国产真人无码| 色婷婷在线视频播放| 99热在线中文字幕| 国产寡妇亲子伦一区二区三区四区| 天天天做夜夜夜夜爽无码| 安徽少妇搡bbw搡bbbb| 一级黄色蜜芽视频| 土耳其电影《爱与罚》| 99热最新| 日韩视频在线播放| 黄色成人网站在线观看| 51黄片| 久草中文在线| 国产精品123区| 免费在线观看AV| 久久精品99| 久久三级| 欧美mv日韩mv国产网站| 亚洲无码成人电影| 日韩A| 97精品人妻| 日韩群交| 91熟女丰满原味| 亚洲视频日韩在线观看| 99热精品免费在线观看| www.青青草视频| 永久免费看片视频5355| 操操小骚逼| 五月激情婷婷基地| 国产香蕉视频免费| 亚洲AV色香蕉一区二区三区| 国产免费成人在线观看| 爱爱视频无码| 大香蕉尹人在线视频| 日本天堂网站| 波多野结衣福利视频| 人妻丰满熟妇av无码| 国产在线精品自拍| 激情久久综合| 欧美操逼电影| 国产亚洲精品久久久久久桃色| 国产成人TV| 色操网| 国产午夜视频在线| 亚洲精品中文字幕乱码三区91 | 人人射人人| 黄色在线免费观看| 日本免费一区二区三区| 黄色日本视频| 一区二区三区四区五区六区高清无吗视频 | 国产视频在线免费观看| 午夜69成人做爱视频网站| 亚洲日韩欧美一区二区天天天| 美女操逼网站| 琪琪色在线视频| 国产黄色在线免费观看| 色色视频网站| 亚洲a视频| 国产视频导航| 影音先锋成人| 精品免费囯产| 欧美成人精品A片免费一区99| 五月婷婷俺也去| 国产精品久久7777777精品无码 | 人人爱人人爽| a片在线免费看| 亲子乱一区二区三区视频| 国产爱搞| 黄色大片免费看| 人妻少妇av中文字幕乱码牛牛 | 五月激情天| 日韩欧美中文字幕公布| 蜜桃性爱视频| 欧美精品一级片| 欧美日本在线观看| 国产一级a毛一级做a爱| 国产AA| 亚洲操逼网| 影音先锋中文字幕资源| 亚洲色情在线播放| 久久久久久久久久久久成人| 91.n| 中文字幕高清无码在线| 91精品在线免费观看| 亚洲AV秘无码苍井空| 色久在线| 天堂精品| 开心四房播播第四婷婷| 四季AV一区二区凹凸懂色桃花| 日本色中文字幕| 亚洲AV成人片色在线观看高潮| 欧美噜噜| 高清无码视频18| 亚洲熟妇无码| 成年人网站在线免费观看| 影音先锋亚洲无码| 欧美国产综合在线| 美女中文字幕| 精品国产AV无码一区二区三区| xxxxxbbbbb| 久久久久久久久久成人永久免费视频| 性饥渴熟妇乱子伦| 爱看福利视频| 麻豆乱伦| 一品国精和二品国精的文化意义 | 久草综合在线| 亚洲不卡视频| 久久精彩| 玖玖国产精品| 欧美特级视频| 色色热热| 操小骚逼视频| 影音先锋亚洲无码| 精品人妻一区二区三区四区| 永久免费黄色视频网站| 99在线精品视频观看| 狠狠躁日日躁夜夜躁A片小说免费 色综合久久久无码中文字幕999 | 制服丝袜在线视频| 一区二区三区四区精品视频| 久久这里都是精品| 久久思思热| 色婷婷一区二区三区四区五区精品视| 无码视频免费播放| 人操人碰| 翔田千里50岁无码| 亚洲性爱无码| 一区二区无码视频| 北条麻妃无码在线视频| 大香蕉久久精品| 安徽妇搡BBBB搡BBBB按摩| 97福利在线| 操逼一区二区| 美妇肥臀一区二区三区-久久99精品国 | 免费黄色视频网站大全| 久久久人妻| 天天撸在线视频| 亚洲精品视频在线观看网站| 亚洲色人妻| 337P粉嫩大胆噜噜噜55569 | 西西特级无码444www| 欧美视频一区| 一级a一级a爰片免费免免在线 | 亚洲欧美在线视频免费| av东方在线| 搡BBBB| 69无码| 成年人毛片视频| 国产h在线播放| 国产尤物视频| 精品无码秘人妻一区二区三区| 欧美日逼视频| 国产SUV精品一区二区| 日韩欧美中文字幕公布| 国产一级A片免费视频| 国产av一级| 久久人妻无码| 久综合网| 亚洲女人在线| 亚洲精品一区二三区不卡| 搡BBBB推BBBB推BBBB| 久久久久久黄片| 国产主播第一页| 逼特逼视频在线观看| 成人自拍偷拍视频| 日韩丰满人妻| www,色婷婷| 2018人人操| 毛片在线视频| 亚洲啊v| 玖玖综合网| 亚洲乱码精品久久久久..| www.大鸡巴| 99九九99九九九99九他書對| 91在线一区| 成年人黄色电影| 欧美成人高清| 黄色一级aa片| 色老板网址| 丰满人妻精品一区二区在线| 无码精品ThePorn| 欧美在线观看一区二区| 99久久99久久兔费精桃| 国产精品夜夜爽7777777| 韩国AV在线| 日韩黄色视频在线观看| 国产精彩无码视频| 欧美动态视频| 99色色| 中文字幕东京热| 特级西西444www大精品| 7799精品视频| 久久久久久久久久免费视频| 黄色一级片免费| 黄片日逼| 婷婷久久综合| 激情婷婷丁香| 午夜久久电影| 91成人精品| 日韩一区二区AV| 国产精品无码激情| 一卡二卡无码| 国产顶级理伦| 日韩中文字幕专区| 一级一级一级做a免费一级做a| 亚洲第一视频| 视频一区在线播放| 熟妇槡BBBB槡BBBB图| 91精品视频在线播放| 亚洲性夜夜天天天天天天| 日本免费黄色小视频| 国产三级国产三级国产| 中文字幕av在线播放| 操B视频在线播放| 亚洲午夜精品久久久| 日韩成人无码AV| 欧美色图网址| 亚洲免费视频网| 欧美操操| 久久久人妻无码精品蜜桃| 亚洲免费黄| 国产又大又粗又长| 偷拍九九热| 黄网站在线免费| 日日摸日日碰| 黄色毛片av| 午夜av在线免费观看| 亚洲一区二区在线免费观看| 欧洲三级片网站| 久久无码在线观看| 黄页网站免费观看| 久久免费看视频| 国产噜噜噜噜久久久久久久久| 免费毛片+一区二区三区| 久久精品视频久久| 五月婷婷精品| 国产福利精品视频| 国产成人精品无码片区在线观91 | 国产亚洲视频完整在线观看 | 黄色在线网站| 人人摸人人操人人爱| 能看的av| 中文字幕++中文字幕明步| 五月激情天| 欧美一道本| 欧美狼友| 一级性爱毛片| 911亚洲精品| 日本绿色精品视频| 日日干日日干| 九九毛片| 国产精品同| 老司机AV| 国产精品毛片一区视频播| 亚洲精品午夜| 无码三级片在线观看| 黑人无码AV| 色综合综合色|