精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美精品99久久| 国产精品亚洲综合| 男人的午夜天堂| 精品视频在线观看网站| 亚洲一区二区三区小说| 美日韩免费视频| 国产又粗又长又黄| 日韩一级不卡| 色偷偷噜噜噜亚洲男人的天堂| 青青草精品在线| 亚洲淫成人影院| 亚洲视频在线观看三级| 国产手机精品在线| 亚洲天堂网在线观看视频| 黄色亚洲在线| 日韩中文理论片| 亚洲色图14p| 性欧美video另类hd尤物| 亚洲成人激情综合网| 少妇精品久久久久久久久久| 国精产品乱码一区一区三区四区| 日韩在线一区二区| 韩国三级日本三级少妇99| 国产成人在线网址| 日韩美脚连裤袜丝袜在线| 777精品伊人久久久久大香线蕉| 分分操这里只有精品| 麻豆视频免费在线观看| 97久久精品人人做人人爽| 亚洲iv一区二区三区| 欧美一区二区三区久久久| 欧美三级特黄| 日韩视频在线观看免费| 欧美激情aaa| 国产精品网址| 日韩午夜精品电影| 天堂av8在线| 香蕉视频亚洲一级| 精品久久久中文| 国产欧美久久久久| 国产精品一级伦理| 久久日韩粉嫩一区二区三区| 国产精品入口免费| 精品国自产在线观看| 久久国产婷婷国产香蕉| 国产精品高清在线| 国产成人无码av| 在线亚洲免费| 55夜色66夜色国产精品视频 | 亚洲色图图片| 91黄色激情网站| 免费无码国产v片在线观看| 国产深夜视频在线观看| 一区二区视频在线| 无码人妻aⅴ一区二区三区日本| 在线观看免费网站黄| 中文字幕国产精品一区二区| 欧美亚洲免费高清在线观看| 亚洲欧美日本在线观看| 97se亚洲国产综合自在线不卡| 国产高清精品一区二区| 亚洲精品无amm毛片| 国产99精品国产| 不卡一区二区三区四区五区| 国产高清精品软件丝瓜软件| 国产老肥熟一区二区三区| 91天堂在线观看| 国产美女明星三级做爰| 国产精品亚洲一区二区三区在线 | 日韩中文字幕亚洲| 女教师淫辱の教室蜜臀av软件| 成人高清av| 色偷偷av一区二区三区| 黄色a级片在线观看| 午夜久久99| 国内外成人免费激情在线视频| 国产午夜小视频| 香蕉久久夜色精品国产| 国产精品99一区| 国产又大又黑又粗| 成人视屏免费看| 欧美日韩电影一区二区| av影片免费在线观看| 亚洲同性同志一二三专区| 成年在线观看视频| 极品美鲍一区| 欧美午夜电影网| 亚洲一级片免费观看| 久久九九热re6这里有精品 | 成人国产精品一区二区| www日本高清视频| 91美女视频网站| 午夜欧美一区二区三区免费观看| 黄色网在线免费看| 亚洲成人免费在线观看| 日本激情综合网| 精品一区二区三区四区五区| 亚洲精品国产综合区久久久久久久| 午夜理伦三级做爰电影| 小说区亚洲自拍另类图片专区| 久久久之久亚州精品露出| 一级黄色av片| 国产91在线|亚洲| 日本不卡二区| 亚洲男同gay网站| 色综合天天综合在线视频| 亚洲最大天堂网| 亚洲视频分类| 九色91av视频| 欧美男人天堂网| 成人激情小说网站| 亚洲日本精品一区| 国产在线88av| 欧美变态网站| 亚洲一区在线播放| www.天天射.com| 国产成人福利av| 日韩中文字在线| 波多野结衣视频网站| 国产伦精品一区二区三区在线观看| 久久久久久九九九九| 超碰免费公开在线| 欧美性色欧美a在线播放| 国产日韩视频一区| 99久久99久久精品国产片果冰| 91av在线精品| 亚洲精品中文字幕成人片| 国产精品久久久久aaaa| 精品一卡二卡三卡| 免费日韩一区二区三区| 欧美另类极品videosbest最新版本| 成人小视频在线播放| 成人精品视频.| 佐佐木明希av| 激情中国色综合| 国产亚洲欧美aaaa| 久草手机在线视频| 99久久精品费精品国产一区二区| 超级碰在线观看| 韩国一区二区三区视频| 日韩中文字幕亚洲| 91亚洲国产成人精品一区| 亚洲国产精华液网站w| 日本一本二本在线观看| 日本午夜精品| 欧美亚洲国产视频| 四虎在线免费看| 亚洲va中文字幕| 黄色国产在线视频| 亚洲激精日韩激精欧美精品| 99热在线国产| 超碰中文在线| 亚洲精品久久久久久久久久久久| 日韩欧美亚洲视频| 91在线视频观看| 99久久久无码国产精品6| 香蕉久久夜色精品国产使用方法 | 日韩情涩欧美日韩视频| 极品久久久久久| 国产高清在线精品| 999久久欧美人妻一区二区| 五月亚洲婷婷| 欧美精品久久久久久久免费观看| 亚洲欧美高清视频| 偷拍一区二区三区| 久久av无码精品人妻系列试探| 葵司免费一区二区三区四区五区| 日韩wuma| 祥仔av免费一区二区三区四区| 久久亚洲欧美日韩精品专区| 性生活黄色大片| 亚洲mv在线观看| 美女脱光内衣内裤| 蜜桃视频免费观看一区| 黄色影视在线观看| 欧美亚洲tv| 国产精品av在线播放| 日本暖暖在线视频| 精品久久久久久无| 国产三级精品三级在线观看| 国产欧美日韩另类视频免费观看| 色一情一区二区三区| 欧美国产91| 欧美第一黄网| av在线精品| 欧美一区二区三区图| av成人手机在线| 欧美岛国在线观看| 中文字幕视频网站| 中文天堂在线一区| 日本中文字幕有码| 玖玖精品视频| 狠狠干视频网站| 特黄特色欧美大片| 成人国产精品av| 天天综合av| www.欧美免费| 四虎精品在线| 91精品国产欧美一区二区| 日本韩国欧美中文字幕| 亚洲欧洲另类国产综合| 成人精品在线观看视频| 激情欧美一区二区| 日本免费一级视频| 欧美福利电影在线观看| 日韩一区不卡| 欧美人成在线观看ccc36| 国产在线精品自拍| 日韩成人av电影| 久久99国产精品久久久久久久久| 欧美xxx.com| 精品国产欧美一区二区| 亚洲综合免费视频| 日韩欧美在线国产| 波多野结衣亚洲色图| 久久久久久久电影| 无码国产69精品久久久久网站| 免费观看久久久4p| 北条麻妃69av| 激情久久久久久久| 国产三级中文字幕| 日韩欧美大片| 热re99久久精品国产99热| 美女呻吟一区| 国产高清一区二区三区| 日韩国产在线不卡视频| 国产精品久久一区| 黑人巨大精品| 91国内在线视频| 福利成人导航| 欧美精品久久久久a| 成人免费观看视频大全| 日韩在线视频二区| 91在线观看| 一区二区av在线| 国产系列电影在线播放网址| 精品视频—区二区三区免费| 国产 日韩 欧美 综合| 日韩亚洲欧美一区二区三区| 国产精品无码久久久久成人app| 色av成人天堂桃色av| 久久久久女人精品毛片九一| 午夜国产不卡在线观看视频| 日本少妇久久久| 亚洲6080在线| 日本中文字幕免费| 五月综合激情日本mⅴ| 日韩精品久久久久久久| 亚洲国产成人tv| 国产黄色片视频| 亚洲成人免费电影| 午夜毛片在线观看| 一本色道亚洲精品aⅴ| www.久久久久久久| 精品久久久久久亚洲精品| 韩国av中文字幕| 91国偷自产一区二区使用方法| 波多野结衣在线观看视频| 欧美午夜精品一区| 91丨porny丨在线中文 | 91av国产精品| 51精品秘密在线观看| 国产99999| 精品国产一区久久| 头脑特工队2在线播放| 亚洲欧美国内爽妇网| h视频在线观看免费| 精品激情国产视频| 黄色污污视频在线观看| 欧美性受xxx| 台湾成人免费视频| 91麻豆桃色免费看| 亚洲五码在线| 免费一区二区三区在在线视频| 激情婷婷综合| 色哺乳xxxxhd奶水米仓惠香| 亚洲国产婷婷| 精品久久久久久无码国产| 强制捆绑调教一区二区| 一级做a爱视频| 成人a区在线观看| 日韩免费成人av| 亚洲精品美国一| 99久热在线精品996热是什么| 在线免费视频一区二区| 国产美女www爽爽爽视频| 日韩电影中文字幕一区| 91高清在线视频| 久久久在线观看| 欧美91在线|欧美| 国产精品久久久久久久久久直播 | 国产成人av电影在线播放| 国产麻豆天美果冻无码视频| 国产精品丝袜91| 午夜偷拍福利视频| 欧美午夜精品久久久久久超碰| 亚洲免费成人在线| 伊人久久精品视频| www.综合网.com| 国产日韩欧美电影在线观看| 精品在线网站观看| 特级毛片在线免费观看| 国产情侣久久| 性生活一级大片| 欧美激情一区二区三区四区| 国产精品suv一区二区69| 欧美日韩中文字幕一区| 天天干天天舔天天射| 日韩中文字幕在线观看| 伊人久久精品一区二区三区| 91精品国产99久久久久久红楼| 在线一级成人| 蜜臀av色欲a片无码精品一区 | 亚洲第一av色| 亚洲天堂自拍偷拍| 国产视频在线一区二区| 四虎影视国产在线视频| 国产自产女人91一区在线观看| 香蕉人人精品| 国产精品久久中文字幕| 国产一区二区h| 色撸撸在线视频| 欧美性猛交xxxx免费看漫画| 精品女同一区二区三区| 日韩一区二区精品视频| 久久野战av| 你懂的视频在线一区二区| 亚洲无线一线二线三线区别av| 亚洲av无日韩毛片久久| 欧美精彩视频一区二区三区| 你懂的国产视频| 亚洲国产精品久久久久| 天天干在线视频论坛| 亚洲一区二区三| 希岛爱理av一区二区三区| 美女喷白浆视频| 久久久精品综合| 亚洲天堂男人av| 精品无人国产偷自产在线| 大菠萝精品导航| 好吊色欧美一区二区三区| 欧美午夜一区二区福利视频| 亚洲丝袜在线观看| 亚洲激情在线激情| 国产福利视频导航| 欧美极品少妇xxxxⅹ喷水 | 久久精品国产精品青草色艺 | 精品少妇3p| 黄网站欧美内射| 99久精品国产| wwwxxx亚洲| 亚洲免费伊人电影在线观看av| 丝袜诱惑一区二区| 欧美污视频久久久| 日本欧洲一区二区| 开心激情五月网| 欧美一区二区精美| 国产探花在线观看| 精品国产乱码一区二区三区四区| 国产日韩欧美高清免费| 中文字幕高清视频| 欧美天堂亚洲电影院在线播放| 在线观看麻豆| 91gao视频| 亚洲麻豆视频| 免费看黄色的视频| 欧美日韩在线播放三区| 国产超级va在线视频| julia一区二区中文久久94| 亚洲欧洲日本mm| 亚洲永久精品ww.7491进入| 在线观看中文字幕不卡| 欧美尤物美女在线| av一区二区三区四区电影| 亚洲欧洲另类| 国产午夜精品久久久久久久久| 91精品国产免费| 麻豆蜜桃在线观看| 亚洲一区二区不卡视频| 国产精品正在播放| 国产超碰人人爽人人做人人爱| 一本色道久久综合狠狠躁篇的优点 | 国产精品日日摸夜夜摸av| 国产激情久久久久久熟女老人av| 久久琪琪电影院| 日韩成人精品一区二区| 国产精品99久久久精品无码| 色综合久久综合网97色综合| 免费黄网站在线| 国产精品一区二区av| 日本v片在线高清不卡在线观看| 亚洲天堂网av在线| 亚洲精品乱码久久久久久按摩观| a成人v在线| 欧美视频在线免费播放| 中文字幕在线不卡| 手机看片福利在线观看| 91香蕉电影院| 噜噜噜久久亚洲精品国产品小说| 熟女少妇a性色生活片毛片|