精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

字典是怎么擴容的?它會經歷哪些過程?

開發 前端
擴容之后的新哈希表的容量要大于等于 ma_used * 3,注意:是大于等于?ma_used * 3,不是?dk_nentries * 3。因為 dk_nentries 還包含了被刪除的 entry,但哈希表在擴容的時候會將其丟棄,所以擴容之后新哈希表的容量取決于 ma_used。

在介紹字典的底層結構時我們看到,當已使用的 entry 數量達到總容量的 2/3 時,會發生擴容。

而在早期,哈希表只使用一個鍵值對數組,這個鍵值對數組不僅要存儲具體的 entry,還要承載哈希索引數組的功能。本來這個方式很簡單,但是內存浪費嚴重,于是后面 Python 官方就將一個數組拆成兩個數組來實現。

不是說只能用 2/3 嗎?那就只給鍵值對數組申請 2/3 容量的空間,并且只負責存儲鍵值對。至于索引,則由哈希索引數組來體現。通過將 key 映射成索引,找到指定的哈希槽,再根據槽里面存儲的索引,找到鍵值對數組中存儲的 entry。

因此減少內存開銷的核心就在于,避免鍵值對數組的浪費。

所以哈希索引數組的長度就可以看成是哈希表的容量,而鍵值對數組的長度本身就是哈希索引數組的 2/3、或者說容量的 2/3。那么很明顯,當鍵值對數組滿了,就說明當前的哈希表要擴容了。

// Objects/dictobject.c
#define GROWTH_RATE(d) ((d)->ma_used*3)

擴容之后的新哈希表的容量要大于等于 ma_used * 3,注意:是大于等于 ma_used * 3,不是 dk_nentries * 3。因為 dk_nentries 還包含了被刪除的 entry,但哈希表在擴容的時候會將其丟棄,所以擴容之后新哈希表的容量取決于 ma_used。

當然啦,哈希表的容量還要等于 2 的冪次方,所以有兩個條件:

  • 大于等于 ma_used * 3;
  • 等于 2 的冪次方;

基于以上兩個限制條件,取到的最小值便是擴容之后的容量。為此 Python 底層專門提供了一個 calculate_log2_keysize 函數,看一下它的邏輯。

// Objects/dictobject.c
static inline uint8_t
calculate_log2_keysize(Py_ssize_t minsize)
{
    // 參數 minsize 表示字典的 ma_used * 3,即長度 * 3
    // 1 << log2_size 便是擴容之后的字典的容量
    uint8_t log2_size;
    // PyDict_LOG_MINSIZE 是一個宏,值為 3,所以字典的最小容量是 8
    // 如果 (1 << log2_size) < minsize,那么不斷循環
    // 直到條件不滿足時,便找到了大于等于 minsize 的最小 2 的冪次方數
    for (log2_size = PyDict_LOG_MINSIZE;
            (((Py_ssize_t)1) << log2_size) < minsize;
            log2_size++)
        ;
    return log2_size;
}

只不過返回的不是擴容之后的字典的容量,而是以 2 為底、容量的對數。

然后我們來看看擴容對應的具體邏輯。

// Objects/dictobject.c
static int
insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
{
    // 當字典添加 entry 卻發現容量不夠時,會調用 insertion_resize 函數
    // 該函數內部會調用 dictresize 函數,傳遞的參數的含義如下:
    /*
     * 參數一:進程狀態對象
     * 參數二:字典
     * 參數三:擴容之后的字典的容量的對數
     * 參數四:是否是 unicode table,即字典的 key 是否都是字符串
     */
    return dictresize(interp, mp, 
        calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
}

所以核心在于 dictresize 函數,但這個函數比較長,在看它的內部實現之前,先來回顧一下基礎知識。

圖片圖片

以上是字典的底層結構,假設變量 mp 指向了 PyDictObject 實例,那么可以得到如下信息。

  • mp->ma_keys->dk_indices 便是哈希索引數組,它的長度便是哈希表的容量。
  • mp->ma_keys->dk_entries 便是鍵值對數組,里面的一個 entry 就是一個鍵值對。
  • 如果字典使用的是結合表,那么 entry 的 me_key、me_value 字段負責存儲鍵和值,此時 mp->ma_values 為 NULL。
  • 如果字典使用的是分離表,那么 entry 的 me_key 字段負責存儲鍵,me_value 字段則始終為 NULL,此時由 mp->ma_values 負責存儲值,這種做法可以讓多個字典共享一組 key,從而節省內存。

因為分離表是 Python 針對實例對象的屬性字典單獨設計的,我們平時創建的都是結合表,所以一開始并沒有討論分離表。但分離表其實非常簡單,這里來補充一下吧,我們看一下 ma_values 是怎么定義的。

// Include/dictobject.h
typedef struct _dictvalues PyDictValues;
// Include/internal/pycore_dict.h
struct _dictvalues {
    PyObject *values[1];
};

結構非常簡單,就是維護了一個數組,保存所有的 value。另外我們發現字段 values 是一個數組,而不是指向數組首元素的二級指針,這就說明使用分離表的字典的容量是固定的,如果要擴容,那么結構會發生改變,分離表會重構為結合表。

現在假設有一個字典,里面有三個鍵值對 "a": 1, "b": 2, "c": 3,我們看一下分別使用結合表和分離表存儲時,字典的結構是什么樣子。

結合表:

圖片圖片

分離表:

圖片圖片

所以結合表是鍵和值存在一起,分離表是鍵和值分開存儲,非常好理解。我們自己創建的字典,使用的都是結合表,分離表是為了減少對象屬性字典的內存使用而專門引入的。

然后是字典(哈希表)的三種形式:

  • Unicode split table:分離表,key 全部是字符串。
  • Unicode combined table:結合表,key 全部是字符串。
  • Generic combined table:結合表,key 的類型沒有限制。

所以對于一個分離表而言,它的 key 一定都是字符串,否則不可能是分離表。而如果 key 都是字符串,那么既可以是分離表,也可以是結合表。

但如果不滿足 key 都是字符串,或者說 key 沒有類型限制,那么一定是結合表。所以 Generic combined table 里面的 combined 可以省略,因為當 key 的類型是 Generic 時,哈希表一定是 combined。

接著是轉換關系:

  • split 可以轉成 combined,但反過來不行。
  • unicode 可以轉成 generic,但反過來不行。

好,最后我們看一下 dictresize 函數。

// Objects/dictobject.c
static int
dictresize(PyInterpreterState *interp, PyDictObject *mp,
           uint8_t log2_newsize, int unicode)
{   
    // mp->ma_keys
    PyDictKeysObject *oldkeys;
    // mp->ma_values
    PyDictValues *oldvalues;
    
    // log2_newsize 是擴容之后的字典的容量的對數
    // 它是由 insertion_resize 函數傳過來的
    // SIZEOF_SIZE_T 是一個宏,在 64 位機器上等于 8
    // 所以 log2_newsize 不能超過 64,即字典的容量不能達到 2 ** 64
    if (log2_newsize >= SIZEOF_SIZE_T*8) {
        PyErr_NoMemory();  // 否則拋出 MemoryError
        return -1;
    }
    assert(log2_newsize >= PyDict_LOG_MINSIZE);

    oldkeys = mp->ma_keys;
    oldvalues = mp->ma_values;
    // 如果 !(dk->dk_kind != DICT_KEYS_GENERAL),說明字典之前是 Generic table
    // 而一個 Generic table 不可能變成 Unicode table,所以將 unicode 設置為 0
    if (!DK_IS_UNICODE(oldkeys)) {
        unicode = 0;
    }

    // 在介紹字典的創建時,我們說過這個函數,它負責為 PyDictKeysObject 實例申請內存
    mp->ma_keys = new_keys_object(interp, log2_newsize, unicode);
    if (mp->ma_keys == NULL) {
        mp->ma_keys = oldkeys;
        return -1;
    }
    assert(mp->ma_keys->dk_usable >= mp->ma_used);
    // 字典的長度
    Py_ssize_t numentries = mp->ma_used;

    // 如果 oldvalues 不為 NULL,說明字典使用的是分離表
    // 那么當字典發生擴容時,要轉成結合表
    if (oldvalues != NULL) {
        // oldentries,一個 entry 16 字節
        PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
        // split -> Generic combined
        if (mp->ma_keys->dk_kind == DICT_KEYS_GENERAL) {
            // newentries,一個 entry 24 字節
            PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
            for (Py_ssize_t i = 0; i < numentries; i++) {
                int index = get_index_from_order(mp, i);
                PyDictUnicodeEntry *ep = &oldentries[index];
                assert(oldvalues->values[index] != NULL);
                // key 始終存儲在 entry 中
                newentries[i].me_key = Py_NewRef(ep->me_key);
                // 設置哈希值
                newentries[i].me_hash = unicode_get_hash(ep->me_key);
                // 將 mp->ma_values 里面的值,賦值給 entry->me_value
                newentries[i].me_value = oldvalues->values[index];
            }
            // 因為擴容了,所以遍歷鍵值對數組,依次對里面的 key 進行索引映射
            // 找到指定的哈希槽,讓其保存 key 對應的 entry 在鍵值對數組中的索引
            // 因此這一步就是在重新構建哈希索引數組
            build_indices_generic(mp->ma_keys, newentries, numentries);
        }
        // split -> Unicode combined
        else { 
            // 代碼和上面是一樣的,唯一的區別就是這里 entry 的類型和之前是一樣的
            // 因為重構前后都是 Unicode table,所以 entry 的類型不變
            PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys);

            for (Py_ssize_t i = 0; i < numentries; i++) {
                int index = get_index_from_order(mp, i);
                PyDictUnicodeEntry *ep = &oldentries[index];
                assert(oldvalues->values[index] != NULL);
                newentries[i].me_key = Py_NewRef(ep->me_key);
                newentries[i].me_value = oldvalues->values[index];
            }
            build_indices_unicode(mp->ma_keys, newentries, numentries);
        }
        dictkeys_decref(interp, oldkeys);
        // 釋放 ma_values
        mp->ma_values = NULL;
        free_values(oldvalues);
    }
    // 說明字典使用的是結合表,重構的結果依舊是結合表
    else { 
        // Generic -> Generic
        if (oldkeys->dk_kind == DICT_KEYS_GENERAL) {
            
            assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
            PyDictKeyEntry *oldentries = DK_ENTRIES(oldkeys);
            PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
            // 如果 entry 的數量等于字典的長度,說明沒有被刪除的 entry
            // 那么直接 memcpy 過去即可
            if (oldkeys->dk_nentries == numentries) {
                memcpy(newentries, oldentries, 
                       numentries * sizeof(PyDictKeyEntry));
            }
            // 否則要遍歷 oldentries,將 me_value != NULL 的 entry 拷貝過去
            else {
                PyDictKeyEntry *ep = oldentries;
                for (Py_ssize_t i = 0; i < numentries; i++) {
                    while (ep->me_value == NULL)
                        ep++;
                    newentries[i] = *ep++;
                }
            }
            // 重構哈希索引數組
            build_indices_generic(mp->ma_keys, newentries, numentries);
        }
        else {  
            PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
            // Unicode combined -> Unicode combined
            if (unicode) { 
                // 邏輯和上面類似,如果不存在被刪除的 entry,那么直接拷貝
                // 否則的話,依次遍歷,獲取 me_value 不為 NULL 的 entry
                PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys);
                if (oldkeys->dk_nentries == numentries && 
                    mp->ma_keys->dk_kind == DICT_KEYS_UNICODE) {
                    memcpy(newentries, oldentries, 
                           numentries * sizeof(PyDictUnicodeEntry));
                }
                else {
                    PyDictUnicodeEntry *ep = oldentries;
                    for (Py_ssize_t i = 0; i < numentries; i++) {
                        while (ep->me_value == NULL)
                            ep++;
                        newentries[i] = *ep++;
                    }
                }
                build_indices_unicode(mp->ma_keys, newentries, numentries);
            }
            // Unicode combined -> Generic combined
            else {
                // 因為前后 entry 的大小不一樣,一個 16 字節,一個 24 字節
                // 所以只能遍歷,然后重新給字段賦值
                PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
                PyDictUnicodeEntry *ep = oldentries;
                for (Py_ssize_t i = 0; i < numentries; i++) {
                    while (ep->me_value == NULL)
                        ep++;
                    newentries[i].me_key = ep->me_key;
                    newentries[i].me_hash = unicode_get_hash(ep->me_key);
                    newentries[i].me_value = ep->me_value;
                    ep++;
                }
                build_indices_generic(mp->ma_keys, newentries, numentries);
            }
        }

        // Py_EMPTY_KEYS 是靜態定義好的,永遠存在
        // 如果 oldkeys != Py_EMPTY_KEYS,那么要釋放掉
        if (oldkeys != Py_EMPTY_KEYS) {
            assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
            assert(oldkeys->dk_refcnt == 1);
            // 以下是緩存池操作,我們下一篇文章細說
#if PyDict_MAXFREELIST > 0
            struct _Py_dict_state *state = get_dict_state(interp);
            if (DK_LOG_SIZE(oldkeys) == PyDict_LOG_MINSIZE &&
                    DK_IS_UNICODE(oldkeys) &&
                    state->keys_numfree < PyDict_MAXFREELIST)
            {
                state->keys_free_list[state->keys_numfree++] = oldkeys;
                OBJECT_STAT_INC(to_freelist);
            }
            else
#endif
            {
                PyObject_Free(oldkeys);
            }
        }
    }
    // dk_usable 表示還可以容納多少個鍵值對
    // dk_nentries 表示已經容納了多少個鍵值對
    // 而 numentries 表示字典的長度,所以重構之后
    // dk_usable 的大小要減去 numentries,dk_nentries 直接等于 numentries
    mp->ma_keys->dk_usable -= numentries;
    mp->ma_keys->dk_nentries = numentries;
    ASSERT_CONSISTENT(mp);
    return 0;
}

因為要對哈希表的種類分情況討論,所以導致代碼有點長,但邏輯不難理解:

  • 首先確定哈希表的容量,它要滿足 2 的冪次方,并且大于等于 ma_used * 3。
  • 為 ma_keys 重新申請內存。
  • 根據哈希表的種類分情況討論,但核心都是將老的沒有被刪除的 entry 搬過去。
  • 釋放 ma_keys,如果字典之前是分離表,還要釋放 ma_values。

以上就是哈希表的擴容,或者說字典的擴容,我們就介紹到這兒,下一篇文章來介紹字典的緩存池。

責任編輯:武曉燕 來源: 古明地覺的編程教室
相關推薦

2024-11-15 16:27:58

函數結構存儲

2024-10-20 13:28:47

虛擬機字節碼CPU

2010-08-25 15:08:22

經歷

2018-09-28 16:35:31

APP圖標工具

2022-04-13 18:24:22

Nacos客戶端存儲

2015-03-18 10:12:06

物聯網云平臺云架構

2024-08-26 11:13:26

字典entry自定義

2021-06-26 07:29:42

RedisHashtable數據

2023-10-30 23:14:57

瀏覽器URL網頁

2021-03-29 15:59:52

區塊鏈比特幣擴容

2023-04-03 08:02:16

切片擴容GO

2017-03-29 15:50:09

AndroidApp框架

2024-05-21 12:51:06

Python對象PyObject

2024-05-22 13:04:46

Python對象關系

2022-01-21 14:26:05

區塊鏈鏈上鏈下

2024-08-22 10:11:00

字典取值源碼

2020-11-16 11:18:24

5G

2024-08-08 11:05:22

2013-11-06 10:03:44

Windows 8.1Windows 8.1

2009-04-20 17:31:57

互聯網
點贊
收藏

51CTO技術棧公眾號

九一国产精品视频| 国产成人亚洲综合91| 一二三级黄色片| 久久五月精品中文字幕| av成人老司机| 国产精品久久久久久网站| 希岛爱理中文字幕| 日韩av综合| 欧美日韩综合视频网址| 伊人天天久久大香线蕉av色| 蜜臀av午夜精品| 久久亚洲视频| 久久91精品国产91久久跳| 国产传媒第一页| 中文字幕日本一区| 欧美日韩免费看| 午夜啪啪福利视频| 男女视频在线观看| 激情综合色播激情啊| 78色国产精品| 青青青在线视频| 九热爱视频精品视频| 日韩一区二区三区四区| 50路60路老熟妇啪啪| 青草av在线| 欧美激情中文字幕| 久久精品成人一区二区三区蜜臀| 亚洲综合免费视频| 午夜亚洲一区| 欧美精品电影免费在线观看| 18精品爽国产三级网站| 亚洲专区视频| 亚洲国产高清自拍| 久久aaaa片一区二区| 欧美高清xxx| 色系网站成人免费| 日本人体一区二区| 午夜dj在线观看高清视频完整版 | 98精品视频| 亚洲精品理论电影| 日韩av成人网| 欧美一区一区| 在线91免费看| 麻豆三级在线观看| 日韩精品三区| 在线观看一区二区视频| 国产欧美在线一区| 中文字幕影音在线| 午夜久久久影院| 国产黄色片免费在线观看| 视频在线这里都是精品| 亚洲人成网站色在线观看| 一级做a爰片久久| 国产女人在线视频| 国产日韩欧美不卡在线| 日本午夜精品一区二区| 久久久久久女乱国产| 久久伊人中文字幕| 欧美人与物videos另类| 污视频软件在线观看| 99久久99久久综合| 久久久久高清| 久久米奇亚洲| 国产精品成人免费在线| 亚洲一区二区三区精品视频| 天堂资源在线中文| 国产精品久久久久婷婷| 久久久国产精华液999999| 欧美私人网站| 亚洲精品久久久久久国产精华液| 亚洲乱码日产精品bd在线观看| www免费视频观看在线| 一区二区三区在线观看网站| 艳母动漫在线观看| 国产第一页在线| 黑人巨大精品欧美一区二区免费| 无码无遮挡又大又爽又黄的视频| 97精品国产综合久久久动漫日韩| 欧美特级限制片免费在线观看| 丰满少妇在线观看| 国产精品一区二区三区av | 在线一区二区不卡| 99这里只有精品视频| 亚洲精品国产精品国产自| 能免费看av的网站| 小处雏高清一区二区三区| 欧美精品videossex性护士| 精品国产一区二区三区四| 美女久久久精品| 国产精品久久精品国产| 经典三级在线| 夜夜精品浪潮av一区二区三区| 黄色一级片播放| 欧美一级做一级爱a做片性| 欧美一区2区视频在线观看| 国产不卡一二三| 日韩黄色大片| 91精品国产91久久久久福利| 中文字幕免费在线看| 丁香桃色午夜亚洲一区二区三区| 欧美不卡三区| 欧美videossex| 欧美亚洲免费在线一区| 国产精品果冻传媒| 国产精品久久久乱弄| 欧美性在线视频| 一级视频在线播放| 99国产精品国产精品毛片| 亚洲欧美日韩精品久久久| 久草免费在线色站| 婷婷夜色潮精品综合在线| 亚洲精品性视频| 美女视频免费精品| 视频在线一区二区| 国产午夜久久久| 日韩av成人高清| 成人精品一区二区三区电影黑人 | 国产精品一区二区日韩| 欧美日韩在线不卡| 制服丝袜在线第一页| 欧美三级美国一级| 欧美激情在线播放| 中文字幕一区二区三区波野结 | 日韩欧美中文在线| 黄色三级视频在线播放| 亚洲人成精品久久久 | 川上优的av在线一区二区| 亚洲欧美日韩国产一区二区三区| 欧美日韩亚洲一| 精品三级国产| 国产亚洲精品久久久久久牛牛| 日韩中文字幕有码| 一本综合精品| 成人av网站观看| 9色在线视频| 日韩欧美在线观看| 日本国产在线视频| 91tv精品福利国产在线观看| 欧美综合第一页| 视频二区在线| 亚洲国产精品尤物yw在线观看| 亚洲妇熟xx妇色黄蜜桃| 男男gay无套免费视频欧美| 久久久久久久久亚洲| 国产乱色精品成人免费视频 | 久久久久久久久久久久久久一区 | 亚洲激情av在线| 日日干夜夜操s8| 精品一区二区三| 91精品国产精品| 高h放荡受浪受bl| 亚洲免费资源在线播放| 成人性生交免费看| 99久久亚洲精品蜜臀| 国产精品免费视频久久久| 日本一区高清| 欧美视频不卡中文| jlzzjizz在线播放观看| 野花国产精品入口| 好看的日韩精品| 亚洲第一图区| 亚洲成人网av| 久久人人爽人人爽人人| 国产成人免费在线视频| 欧美视频在线第一页| 一区二区三区在线免费看| 欧美夫妻性视频| 午夜美女福利视频| 五月婷婷欧美视频| 久久午夜夜伦鲁鲁片| 国产视频亚洲| 欧美日韩亚洲一区二区三区四区| 一区二区电影免费观看| 精品在线欧美视频| 国产 欧美 日韩 在线| 久久久不卡影院| www欧美激情| 久久久久久久久久久久久久久久久久 | 欧美精品色综合| 国产精品99久久久久久成人| 国产美女主播视频一区| 97超碰国产精品| 欧美电影免费网站| 欧美与欧洲交xxxx免费观看| 97电影在线看视频| 91精品蜜臀在线一区尤物| 国产一区二区视频在线观看免费| 国产成人丝袜美腿| www.浪潮av.com| 欧美色蜜桃97| 91在线看网站| 亚洲精品国产精品国产| 中文字幕亚洲专区| 精品人妻伦一二三区久久| 亚洲国产毛片aaaaa无费看| 97人妻天天摸天天爽天天| 日韩精品一级中文字幕精品视频免费观看 | 黄色亚洲网站| 久久精品视频在线播放| 亚州视频一区二区三区| 欧美日韩久久一区二区| 久久久久成人网站| 欧美极品xxx| 美国黄色一级视频| 日韩高清不卡一区二区三区| 国产成人在线小视频| 欧美日韩爱爱| 666精品在线| 自拍偷拍欧美视频| 久久久91精品国产| 午夜影院免费体验区| 欧美日韩一二三区| 国产免费av一区| 亚洲另类色综合网站| 国产免费看av| 成人的网站免费观看| 九九热免费精品视频| 欧美视频日韩| 亚洲第一精品区| 全国精品免费看| 91在线观看免费高清| 性国裸体高清亚洲| 中文字幕日韩免费视频| 亚洲色图狠狠干| 欧美一级欧美一级在线播放| 中文字幕在线观看视频免费| 亚洲国产视频a| 秋霞欧美一区二区三区视频免费| 亚洲国产高清aⅴ视频| 艳妇乳肉亭妇荡乳av| 国产精品一卡二| 一区二区三区韩国| 亚洲欧美日韩精品一区二区| www.99riav| 欧美在线色图| 日韩精品最新在线观看| 欧美尿孔扩张虐视频| 97久久人人超碰caoprom欧美| 国产福利一区二区三区在线播放| 欧美一区二区色| 三级网站视频在在线播放| 色哟哟入口国产精品| 久久这里精品| 国产视频自拍一区| 欧美一区二区公司| 精品少妇一区二区三区日产乱码 | 成人超碰在线| 欧美精品在线免费观看| 国产黄网站在线观看| 久久精品国产清自在天天线| 在线免费看a| 国产亚洲精品激情久久| 国产视频二区在线观看| 亚洲男人的天堂网站| 黄色在线小视频| 亚洲欧美日韩中文在线| 神马电影在线观看| 精品亚洲aⅴ在线观看| 日本韩国免费观看| 亚洲缚视频在线观看| 日本韩国一区| 亚洲精品在线不卡| 日本中文字幕电影在线观看 | 国产成人精品无码片区在线| 波多野结衣91| 国产色视频一区二区三区qq号| 91视频国产观看| www.av欧美| 国产日韩精品一区二区三区在线| av电影在线不卡| 国产精品福利影院| 国产亚洲精品久久777777| 亚洲观看高清完整版在线观看 | 91插插插影院| 国产成人免费在线视频| 手机免费看av片| 久久精品亚洲一区二区三区浴池 | 99久久夜色精品国产亚洲| 日韩视频一区二区| 天堂av在线免费| 亚洲欧美一区二区三区情侣bbw| 成全电影播放在线观看国语| 色琪琪综合男人的天堂aⅴ视频| 黄色在线论坛| 国内精品久久久久伊人av| 91丝袜在线| 国产精品你懂得| 精品国产鲁一鲁****| 国产在线一区二区三区播放| 免费一区二区| 国产经典久久久| 亚洲综合丁香| 9久久婷婷国产综合精品性色 | 亚洲一区二区在线视频| 伊人手机在线视频| 欧美日韩午夜影院| 性生活视频软件| 亚洲色图av在线| 国产激情小视频在线| 国产成人精品亚洲精品| 国产精品99久久免费| 精品无码久久久久国产| 日韩片欧美片| 欧美精品自拍视频| 人人狠狠综合久久亚洲| 中文字幕免费在线播放| 日本一区二区三区在线不卡| 欧美三级小视频| 色8久久人人97超碰香蕉987| 国产肥老妇视频| 亚洲精品日韩久久久| 国产极品人妖在线观看| 国产精品热视频| 欧美精品国产白浆久久久久| 视频一区视频二区视频三区视频四区国产 | 日韩精品一二区| 少妇搡bbbb搡bbb搡打电话| 国产欧美精品一区二区色综合| 久久久久无码国产精品| 欧美三电影在线| 亚洲a视频在线观看| 中文字幕久热精品在线视频| 98色花堂精品视频在线观看| 国产精品永久免费观看| 西野翔中文久久精品字幕| 国产情侣第一页| 久久精品国产秦先生| 亚洲国产精品成人综合久久久| 亚洲精品国产a久久久久久| 中文字幕在线播放av| 亚洲精品美女免费| 在线观看a级片| 91精品国产综合久久香蕉922| 亚欧洲精品视频在线观看| 一级性生活视频| 国产综合久久久久久久久久久久| aaaaaav| 亚洲成人激情av| 精品人妻av一区二区三区| 久久好看免费视频| 日本综合久久| 久精品国产欧美| 欧美综合二区| 国产精品探花一区二区在线观看| 亚洲在线成人精品| 国产成人三级一区二区在线观看一 | 日本人69视频| 国产人久久人人人人爽| 欧美a视频在线观看| 亚洲视频精品在线| 电影一区二区三| 欧美午夜精品久久久久免费视 | 国产69精品99久久久久久宅男| 国产一区二区三区| 中文字幕久久综合| 久久99久久久久| 丝袜 亚洲 另类 欧美 重口| 91精品国产色综合久久不卡蜜臀 | 伊人久久大香线蕉综合影院首页| 日本一区二区三区视频免费看| 国产毛片久久| 加勒比一区二区| 欧美在线视频不卡| 91精彩在线视频| 成人国产在线视频| 国产精品成人a在线观看| 天天综合成人网| 一区二区激情视频| 人妻精品无码一区二区| 日本一区二区在线免费播放| 免费成人av| 99色精品视频| 国产欧美日韩三级| youjizz在线视频| 在线精品视频视频中文字幕| 婷婷精品久久久久久久久久不卡| 亚洲最大免费| 国产福利视频一区二区三区| 国产大片中文字幕| 亚洲黄色在线看| 在线人成日本视频| 亚洲国产激情一区二区三区| 国产精品性做久久久久久| 日本在线小视频| 亚洲欧美精品中文字幕在线| 成人黄色视屏网站| 色综合久久88色综合天天提莫| 国产乱淫av一区二区三区| 日韩久久久久久久久| 亚洲三级黄色在线观看| 亚洲精品无播放器在线播放| 69sex久久精品国产麻豆| 久久蜜桃av一区精品变态类天堂| 一区二区视频播放| 欧美精品福利在线| 欧美日韩高清| 国产成人精品综合久久久久99| 色婷婷亚洲婷婷| 4438x成人网全国最大| 精品欧美日韩|