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

No.js 中 V8 堆外內存管理和字符編碼解碼的實現

開發 前端
對于基于 V8 的 JS 運行時來說,堆外內存的管理是非常重要的一部分,因為 gc 的原因,V8 自己管理堆內存大小是有限制的,我們不能什么數據都往 V8 的堆里存儲,比如我們想一下讀取一個 1G 的文件,如果存到 V8 的堆,一下子就滿了,所以我們需要定義堆外內存并進行管理。

[[427211]]

對于基于 V8 的 JS 運行時來說,堆外內存的管理是非常重要的一部分,因為 gc 的原因,V8 自己管理堆內存大小是有限制的,我們不能什么數據都往 V8 的堆里存儲,比如我們想一下讀取一個 1G 的文件,如果存到 V8 的堆,一下子就滿了,所以我們需要定義堆外內存并進行管理。本文介紹 No.js 里目前支持的簡單堆內存管理機制和字符編碼解碼的實現。

1 字符串的使用

數據的讀寫,在底層都是一個個字節,那么我們在 JS 層定義的字符串,C++ 層是怎么獲取的呢?比如我們在 JS 里調用自定義 log 函數打印日志。

  1. log("hello"); 

我們來看看 JS 運行時中 log 函數的實現。

  1. void No::Console::log(V8_ARGS) { 
  2.     V8_ISOLATE 
  3.     String::Utf8Value str(isolate, args[0]); 
  4.     Log(*str); 

最終在 C++ 里可以通過 V8 提供的 String::Utf8Value 從 args 中獲得 JS 層的字符串,然后調用系統函數把它打印到屏幕就行。但是這種形式使用的內容是 V8 的堆內存。那么如果我們需要操作一個非常大的字符串,那怎么辦呢?這時候就需要使用 V8 提供的堆外內存機制 ArrayBuffer。

2 ArrayBuffer 的實現

我們看看這個類關于內存申請的一些實現細節。當我們在 JS 里執行以下代碼時

  1. new ArrayBuffer(1) 

來看看 V8 的實現。

  1. BUILTIN(ArrayBufferConstructor) { 
  2.   // [[Construct]]  args 為 JS 層的參數 
  3.   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target()); 
  4.   // JS 層定義的長度,即 ArrayBuffer 的第一個參數 
  5.   Handle<Object> length = args.atOrUndefined(isolate, 1); 
  6.  
  7.   return ConstructBuffer(isolate,  
  8.                          target,  
  9.                          new_target,  
  10.                          number_length, // = length 
  11.                          number_max_length,  // 空 
  12.                          InitializedFlag::kZeroInitialized); 

接著看 ConstructBuffer 。

  1. Object ConstructBuffer(Isolate* isolate, Handle<JSFunction> target, 
  2.                        Handle<JSReceiver> new_target, Handle<Object> length, 
  3.                        Handle<Object> max_length, InitializedFlag initialized) { 
  4.       // resizable = ResizableFlag::kNotResizable 
  5.       ResizableFlag resizable = max_length.is_null() ? ResizableFlag::kNotResizable : ResizableFlag::kResizable; 
  6.       // 申請一個 JSArrayBuffer 對象,不包括存儲數據的內存                                               
  7.       Handle<JSObject> result; 
  8.       ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 
  9.           isolate, result, 
  10.           JSObject::New(target, new_target, Handle<AllocationSite>::null())); 
  11.       auto array_buffer = Handle<JSArrayBuffer>::cast(result); 
  12.      
  13.       size_t byte_length; 
  14.       size_t max_byte_length = 0; 
  15.       // byte_length:需要申請的字節數,由 length Object 解析得到,并且校驗申請的大小是否超過閾值 
  16.       if (!TryNumberToSize(*length, &byte_length) || 
  17.           byte_length > JSArrayBuffer::kMaxByteLength) { 
  18.           // ... 
  19.       } 
  20.       std::unique_ptr<BackingStore> backing_store; 
  21.       // 申請存儲數據的內存 
  22.       backing_store = BackingStore::Allocate(isolate, byte_length, shared, initialized); 
  23.       max_byte_length = byte_length; 
  24.       // 保存ArrayBuffer 存儲數據的內存 
  25.       array_buffer->Attach(std::move(backing_store)); 
  26.       array_buffer->set_max_byte_length(max_byte_length); 

以上代碼首先申請了一個 JSArrayBuffer 對象,但是申請的對象中不包括存儲數據的內存,接著通過 BackingStore::Allocate 申請存儲數據的內存,并且保存到 JSArrayBuffer 中。我們接著看 BackingStore::Allocate 的內存分配邏輯。

  1. std::unique_ptr<BackingStore> BackingStore::Allocate( 
  2.     Isolate* isolate, size_t byte_length, SharedFlag shared, 
  3.     InitializedFlag initialized) { 
  4.   void* buffer_start = nullptr; 
  5.   // ArrayBuffer 的內存分配器,初始化 V8 的時候可以設置 
  6.   auto allocator = isolate->array_buffer_allocator(); 
  7.   if (byte_length != 0) { 
  8.     auto allocate_buffer = [allocator, initialized](size_t byte_length) { 
  9.       void* buffer_start = allocator->Allocate(byte_length); 
  10.       return buffer_start; 
  11.     }; 
  12.     // 執行 allocate_buffer 分配內存 
  13.     buffer_start = isolate->heap()->AllocateExternalBackingStore(allocate_buffer, byte_length); 
  14.   } 
  15.   / 分配一個 BackingStore 對象管理上面申請的內存 
  16.   auto result = new BackingStore(...); 
  17.   return std::unique_ptr<BackingStore>(result); 

我們看到最終通過 allocator->Allocate 分配內存,allocator 是在初始化 V8 的時候設置的,比如 No.js 設置的 ArrayBuffer::Allocator::NewDefaultAllocator()。

  1. v8::ArrayBuffer::Allocator* v8::ArrayBuffer::Allocator::NewDefaultAllocator() { 
  2.   return new ArrayBufferAllocator(); 

我們看看 ArrayBufferAllocator。

  1. class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { 
  2.  public
  3.   void* Allocate(size_t length) override { 
  4.     return page_allocator_->AllocatePages(nullptr, RoundUp(length, page_size_), 
  5.                                           page_size_, 
  6.                                           PageAllocator::kReadWrite); 
  7.   } 
  8.  private: 
  9.   PageAllocator* page_allocator_ = internal::GetPlatformDataCagePageAllocator(); 
  10.   const size_t page_size_ = page_allocator_->AllocatePageSize(); 
  11. }; 

最終調用 page_allocator_ 去分配內存,從 page_allocator_ 的值 GetPlatformDataCagePageAllocator 我們可以看到這里是調用系統相關的函數去申請內存,比如 Linux 下的 mmap。至此我們看到了 ArrayBuffer 的內存由來,

3 ArrayBuffer 應用

有了 ArrayBuffer,我們就可以在 V8 堆之外申請內存了,我們看看 No.js 里怎么使用。

  1. http.createServer({host: '127.0.0.1', port: 8888}, (req, res) => { 
  2.     // HTTP 響應的 body 
  3.     const body  = `...`; 
  4.     // HTTP 響應報文 
  5.     const response = `...`; 
  6.     // 申請堆外內存 
  7.     const responseBuffer = new ArrayBuffer(response.length); 
  8.     // 把響應內容寫入堆外內存 
  9.     const bytes = new Uint8Array(responseBuffer); 
  10.     for (let i = 0; i < response.length; i++) { 
  11.         bytes[i] = response[i].charCodeAt(0); 
  12.     } 
  13.     // 發送給客戶端 
  14.     res.write(responseBuffer); 
  15. }); 

接著我們看看 write 的實現。

  1. // 拿到 JS 的 ArrayBuffer 
  2. Local<ArrayBuffer> arrayBuffer = args[1].As<ArrayBuffer>(); 
  3. std::shared_ptr<BackingStore> backing = arrayBuffer->GetBackingStore();// 申請一個寫請求struct io_request *io_req = (struct io_request *)malloc(sizeof(*io_req));memset(io_req, 0, sizeof(*io_req));// 拿到底層存儲數據的內存,保存到 request 中等待發送 
  4. io_req->buf = backing->Data(); 
  5. io_req->len = backing->ByteLength(); 

JS 層設置數據,然后在 C++ 層拿到存儲數據的內存發送出去,這個看起來可以滿足需求,但是似乎還不夠,首先每次都要自己申請一個 ArrayBuffer 和 Uint8Array 比較麻煩,而且還需要自己設置 Uint8Array 的內容,最重要的是 Uint8Array 只能保存單字節的數據,如果我們要發送非單字節的字符就會出現問題了。比如 “??“ 在 JS 里長度是 2,底層占四個字節。

  1. '𠮷'.length => 2 

所以還需要封裝一個模塊處理這些問題。

4 Buffer

類似 Node.js,No.js 也提供 Buffer 模塊處理 V8 堆外內存,但是 No.js 沒有 Node.js 實現的功能那么多。下面我們看看如何實現。

  1. class Buffer { 
  2.     bytes = null
  3.     memory = null
  4.     constructor({ length }) { 
  5.         this.memory = new ArrayBuffer(length); 
  6.         this.bytes = new Uint8Array(this.memory); 
  7.         this.byteLength = length; 
  8.     } 
  9.  
  10.     static from(str) { 
  11.         const chars = toUTF8(str); 
  12.         const buffer = new Buffer({length: chars.length}); 
  13.         for (let i = 0; i < buffer.byteLength; i++) { 
  14.             buffer.bytes[i] = chars[i]; 
  15.         } 
  16.         return buffer; 
  17.     } 
  18.  
  19.     static toString(bytes) { 
  20.         return fromUTF8(bytes); 
  21.     } 

使用的方式和 Node.js 一樣。

  1. Buffer.from("你好"

字符串通過 Buffer 類實現,Buffer 封裝了 ArrayBuffer 和 Uint8Array,不過更重要的是實現了 UTF-8 編碼和解碼,這樣應用層就可以傳任何字符串,Buffer 會轉成對應的 UTF-8 編碼(一系列二進制數據),處理完后再通過底層傳輸就可以。看一下 UTF-8 編碼解碼的實現。

  1. function toUTF8(str) { 
  2.     // 通過 ... 解決多字節字符問題 
  3.     const chars = [...str]; 
  4.     const bytes = []; 
  5.     for (let i = 0; i < chars.length; i++) { 
  6.         const char = chars[i]; 
  7.         const code = char.codePointAt(0); 
  8.         if (code > 0 && code < 0x7F) { 
  9.             bytes.push(code) 
  10.         } else if (code > 0x80 && code < 0x7FF) { 
  11.             bytes.push((code >> 6) & 0x1f | 0xC0); 
  12.             bytes.push(code & 0x3f | 0x80);   
  13.         } else if ((code > 0x800 && code < 0xFFFF) || (code > 0xE000 && code < 0xFFFF)) { 
  14.             bytes.push((code >> 12) & 0x0f | 0xE0); 
  15.             bytes.push((code >> 6) & 0x3f | 0x80); 
  16.             bytes.push(code & 0x3f | 0x80);  
  17.         } else if (code > 0x10000 && code < 0x10FFFF) { 
  18.             bytes.push((code >> 18) & 0x07 | 0xF0); 
  19.             bytes.push((code >> 12) & 0x3f | 0x80); 
  20.             bytes.push((code >> 6) & 0x3f | 0x80); 
  21.             bytes.push(code & 0x3f | 0x80);  
  22.         }  
  23.     } 
  24.     return bytes; 

toUTF8 把字符的 Unicode 碼變成 UTF-8 編碼,具體實現就是根據 UTF-8 的規則,但是有一個地方需要注意的是,不能簡單遍歷 JS 字符串。比如 “??“ 在遍歷的時候情況如下

  1. '𠮷'[0] => '\uD842''𠮷'[1] => '\uDFB7' 

所以需要處理一下使得每個字符變得一個獨立的元素,再獲得它的 unicode 碼進行處理。

  1. const chars = [...str]; 

接著看看 解碼。

  1. // 計算二進制數最左邊有多少個連續的 1 
  2. function countByte(byte) { 
  3.     let bytelen = 0; 
  4.     while(byte & 0x80) { 
  5.         bytelen++; 
  6.         byte = (byte << 1) & 0xFF; 
  7.     } 
  8.     return bytelen || 1;} 
  9.  
  10. function fromUTF8(bytes) { 
  11.     let i = 0; 
  12.     const chars = []; 
  13.     while(i < bytes.length) { 
  14.         const byteLen = countByte(bytes[i]); 
  15.         switch(byteLen) { 
  16.             case 1: 
  17.                 chars.push(String.fromCodePoint(bytes[i])); 
  18.                 i += 1; 
  19.                 break; 
  20.             case 2: 
  21.                 chars.push(String.fromCodePoint( (bytes[i] & 0x1F) << 6 | (bytes[i + 1] & 0x3F) )); 
  22.                 i += 2; 
  23.                 break; 
  24.             case 3: 
  25.                 chars.push(String.fromCodePoint( (bytes[i] & 0x0F) << 12 | (bytes[i + 1] & 0x3F) << 6| (bytes[i + 2] & 0x3F) )); 
  26.                 i += 3; 
  27.                 break; 
  28.             case 4: 
  29.                 chars.push(String.fromCodePoint( (bytes[i] & 0x07) << 18 | (bytes[i + 1] & 0x3F) << 12 | (bytes[i + 2] & 0x3F) << 6 | (bytes[i + 3] & 0x3F) )); 
  30.                 i += 4; 
  31.                 break; 
  32.             default
  33.                 throw new Error('invalid byte'); 
  34.         } 
  35.     } 
  36.     return chars.join(''); 

解碼的原理是首先計算單字節的最左邊有多少個 1,這個表示后續的多少個字節組成一個字符。計算完后就把一個或多個字節按照 UTF-8 規則拼出 unicode 碼,然后使用 fromCodePoint 轉成對應字符。最后看看使用例子。

  1. http.createServer({host: '127.0.0.1', port: 8888}, (req, res) => { 
  2.     const body  = `<html> 
  3.         <head></head> 
  4.         <body> 
  5.             你好! 
  6.         </body> 
  7.         </html>`; 
  8.     res.setHeaders({ 
  9.         "Content-Type""text/html; charset=UTF-8" 
  10.     }); 
  11.     res.end(body); 
  12. }); 

5 總結

 

 

 

目前初步實現了堆外內存管理和編碼解碼的功能,這樣應用層就不需要面對麻煩的堆外內存管理和數據設置問題。另外 V8 堆外內存我們平時可能關注的不是很多,但是卻是一個重要的部分。

 

責任編輯:武曉燕 來源: 編程雜技
相關推薦

2022-04-29 08:05:06

內存堆外GC

2023-02-28 07:56:07

V8內存管理

2023-10-10 10:23:50

JavaScriptV8

2021-09-05 17:46:21

云計算No.jsio_uringJS

2021-10-16 05:00:32

.js Buffer模塊

2022-04-29 08:00:51

V8垃圾回收

2010-08-31 11:42:03

DB2MDC

2011-10-19 13:47:57

ibmdwRationalWAS

2021-08-29 18:34:44

編譯V8C++

2022-05-06 23:03:48

V8CPUProfiler

2022-08-19 06:40:02

V8GC

2021-05-24 11:25:13

Node.js 16V8前端

2021-07-05 22:13:09

Node內存控制

2025-09-08 01:55:00

2021-10-04 19:49:23

HTTP模塊No.js

2021-07-09 00:24:10

No.jsNode.js原理

2021-09-16 05:32:31

No.js 模塊加載器module1.js

2022-03-26 16:51:27

Node.jstrace架構

2010-07-20 16:35:52

V8JavaScript瀏覽器

2021-10-22 21:39:11

InspectorV8 JS
點贊
收藏

51CTO技術棧公眾號

欧美日韩免费区域视频在线观看| 日本另类视频| 天天揉久久久久亚洲精品| 国产精品无圣光一区二区| 曰本色欧美视频在线| 日韩高清在线播放| 久久综合加勒比| 丝袜美腿一区| 寂寞少妇一区二区三区| 日韩精品资源二区在线| 色哟哟免费网站| 毛片av免费在线观看| 亚洲av无码片一区二区三区| 久久精品66| wwwwww.欧美系列| 亚洲欧美精品中文字幕在线| 美女黄色片视频| 99久久99久久久精品棕色圆| 特黄特色欧美大片| 中文字幕不卡在线观看| 国产精品白嫩初高中害羞小美女| 亚洲精品午夜在线观看| 高潮毛片在线观看| 久久国产日韩| 在线激情影院一区| 人妻换人妻仑乱| 天天射天天色天天干| 玖玖国产精品视频| 欧美成人高清视频| 激情综合丁香五月| 国产欧美88| 久久久无码精品亚洲日韩按摩| 免费不卡在线观看av| 奇米777第四色| caoporn免费在线视频| 国产福利不卡视频| 中文字幕久热精品在线视频 | 亚洲国产精品久久久久久女王| 永久免费看片视频教学| 成人精品毛片| 中文字幕视频一区二区三区久| 日韩高清不卡一区| 亚洲国产一二三| 欧美日韩亚洲综合一区二区三区激情在线| 亚洲无码久久久久| 国产偷自视频区视频一区二区| www.日韩视频| 亚洲不卡视频在线| 国产一二三区在线观看| 日韩av在线发布| 亚洲大尺度美女在线| 久久国产精品国产精品| 午夜伦理福利在线| 亚洲综合成人网| 成人蜜桃视频| 久久久久久久99| h视频久久久| 欧美精品久久一区| av五月天在线| 国产白浆在线免费观看| √…a在线天堂一区| 欧美综合激情| 免费国产在线观看| 噜噜爱69成人精品| 久久久久久久久久亚洲| 免费在线观看a级片| 成人国产一区二区三区精品麻豆| 午夜久久久影院| 一区二区免费在线视频| 97在线观看免费观看高清 | 精品成人国产在线观看男人呻吟| 亚洲v日韩v综合v精品v| 中文字幕在线观看视频一区| 国产精品99一区二区三| 国产一级揄自揄精品视频| 色婷婷免费视频| 欧美调教视频| 91福利视频久久久久| 一区二区日本伦理| 亚洲视频tv| 国产乱子轮精品视频| 99久久精品国产毛片| 欧美激情在线一区| 懂色av蜜臀av粉嫩av永久| 国产成人精品一区二区三区视频| 好吊成人免视频| 国产肥臀一区二区福利视频| 亚洲精品日产| 日本韩国欧美一区二区三区| 激情五月亚洲色图| 成人在线不卡| 欧美日韩国产一区| 手机在线观看日韩av| 精品成人18| 亚洲va天堂va国产va久| 少妇av一区二区三区无码| 日本无删减在线| 亚洲成人在线网站| 热久久精品国产| jizz欧美| 精品毛片乱码1区2区3区| 成人午夜精品无码区| 影视先锋久久| 日韩午夜在线观看| 亚洲少妇18p| 欧美猛男同性videos| 色噜噜国产精品视频一区二区 | 国产亚洲综合在线| 国产男女猛烈无遮挡91| 国产精品视频在线观看免费| 成人激情黄色小说| 日韩.欧美.亚洲| 黄视频网站在线| 精品久久久久久久久久久久久| 国产v亚洲v天堂无码久久久| 成人黄色91| 日韩av在线一区二区| 999精品久久久| 亚洲私人影院| 日韩视频免费在线观看| 免看一级a毛片一片成人不卡| 日韩欧美国产大片| 亚洲性视频网址| 青娱乐国产在线| 日韩专区在线视频| yellow视频在线观看一区二区| 欧美日本网站| 一区二区三区中文字幕精品精品 | 黄色成人小视频| 偷拍一区二区三区四区| jizz欧美激情18| 91蝌蚪精品视频| 中文字幕精品在线| 国产成人精品网| 国产黄色精品视频| 亚洲三区在线观看| 高清不卡亚洲| 精品国产成人在线影院| 欧美老女人性生活视频| 一区二区三区精品视频在线观看| 51国产成人精品午夜福中文下载| av中文字幕一区二区三区| 婷婷六月综合网| 亚洲av无一区二区三区久久| 日本一区免费网站| 亚洲精品大尺度| 波多野结衣视频播放| 婷婷综合在线| 国产精品视频一区国模私拍| 亚洲第一视频在线播放| 国产精品第一页第二页第三页| 成人免费观看视频在线观看| 国产精品男女| 亚洲成人黄色网| 特级片在线观看| 亚洲精品孕妇| 超碰97在线资源| 成全电影播放在线观看国语| 亚洲成人1区2区| 午夜影院福利社| 亚洲理论电影片| 久久免费观看视频| 成人激情四射网| 亚洲乱码精品一二三四区日韩在线| 公共露出暴露狂另类av| 国产极品一区| 中文字幕av一区| 加勒比在线一区| 国产欧美中文在线| 国产视频一区二区视频| 欧洲毛片在线视频免费观看| 日本久久中文字幕| 国产乱视频在线观看| 欧洲国内综合视频| 欧美一区二区三区粗大| 日韩国产在线一| 欧美极品视频一区二区三区| 96av在线| 在线国产电影不卡| 亚洲黄色网址大全| 亚洲乱码精品| 久久国产精品久久精品| 国产精品午夜一区二区| 国产欧美精品一区二区色综合朱莉 | 亚洲最色的网站| aaa一级黄色片| xvideos.蜜桃一区二区| 久久免费观看视频| 欧美伦理影视网| 欧美写真视频网站| 人妻体体内射精一区二区| 精品高清在线| 成人免费黄色网| 爱草tv视频在线观看992| 日韩大片在线观看视频| 无码视频在线观看| 国产精品激情偷乱一区二区∴| 亚洲精品高清无码视频| 97偷自拍亚洲综合二区| 欧美一区二三区| а√天堂中文在线资源bt在线| 欧美日韩高清影院| 天天干天天操天天拍| 国产毛片精品视频| 9久久9毛片又大又硬又粗| 国内精品视频在线观看| 91久久中文字幕| 日韩理论视频| 亚洲欧美国产制服动漫| 影音先锋国产资源| 亚洲高清免费观看高清完整版在线观看 | 97超碰人人看| 99伊人成综合| 亚洲欧美成人一区| 国产一区在线电影| 国产精品美乳一区二区免费| 超碰caoporn久久| 亚洲女人天堂视频| 国产精品日韩无码| 色婷婷精品久久二区二区蜜臂av | 国产99久久| 99re国产| 国产精品亲子伦av一区二区三区| 欧美激情亚洲精品| 午夜激情视频在线| 亚洲精品成人久久电影| 国产三级午夜理伦三级| 色婷婷久久久亚洲一区二区三区 | 自拍偷拍亚洲激情| 中文字幕在线看高清电影| 国产精品1区2区| 欧美日本视频在线观看| 一区二区三区国产精华| 青青影院一区二区三区四区| 国产图片一区| 成人性生交大片免费看小说| 午夜日韩成人影院| 97超碰蝌蚪网人人做人人爽| 超碰在线观看免费版| 亚洲国产一区二区三区在线观看 | 3d蒂法精品啪啪一区二区免费| 日本一区二区三区视频在线| 8050国产精品久久久久久| 色www永久免费视频首页在线| 日韩在线免费观看视频| 久久经典视频| 黑人与娇小精品av专区| 国产性xxxx| 国产精品人成在线观看免费| 国产精品无码久久久久一区二区| 不卡大黄网站免费看| 国产男女无遮挡猛进猛出| 蜜臀av一区二区在线观看| 大肉大捧一进一出好爽视频| 亚洲国产高清视频| 99er在线视频| 高清日韩欧美| 亚洲自拍高清视频网站| 中文幕av一区二区三区佐山爱| 日本三级韩国三级久久| 日本免费一区二区六区| 午夜精品久久久久久久白皮肤 | 国产风韵犹存在线视精品| 制服丝袜中文字幕第一页 | 99国产精品99| 欧美日韩精品欧美日韩精品一综合| 波多野结衣在线观看一区| 色琪琪一区二区三区亚洲区| 亚洲熟妇无码乱子av电影| 欧美天天综合色影久久精品| 爱爱免费小视频| 91免费精品国自产拍在线不卡| 你懂的在线观看网站| 91在线视频观看| 性感美女一区二区三区| 成人av在线影院| 久久人人妻人人人人妻性色av| 99re亚洲国产精品| 四虎永久免费在线观看| 亚洲国产精品高清| 天堂网av2018| 亚洲精品免费视频| 黄色一级片在线免费观看| 一区二区三区四区亚洲| 久久久久久久久久91| 午夜视频在线观看一区二区三区| 六月丁香在线视频| 欧美综合一区二区| 欧美亚洲另类小说| 欧美日韩精品一区二区三区蜜桃| 国产精品怡红院| 亚洲第一区第一页| 加勒比一区二区三区在线| 日韩中文字幕在线| 青草视频在线免费直播 | 色大师av一区二区三区| 久久一本综合| 一区二区三视频| 樱桃成人精品视频在线播放| 精品99在线视频| 亚洲综合色网| 久艹在线免费观看| 日韩成人一级片| 亚洲一区精品视频在线观看| 国产激情视频一区二区三区欧美| 37p粉嫩大胆色噜噜噜| 中文字幕一区二区三区色视频| 日本三级欧美三级| 欧美视频在线观看一区二区| 中国老头性行为xxxx| 日韩欧美黄色影院| 黄色毛片在线观看| 久久国产精品视频| 日韩精品美女| 91在线视频导航| 免费欧美激情| 激情视频小说图片| 日日夜夜精品视频免费| 韩国三级丰满少妇高潮| 国产日韩欧美一区二区三区乱码 | www.涩涩爱| 精品国产精品三级精品av网址| av网站免费大全| 精品国产一区二区三区久久| 成人免费福利| 欧美日韩综合久久| 99精品视频网| 动漫美女无遮挡免费| 亚洲综合自拍偷拍| 国产99久久九九精品无码免费| 综合网中文字幕| 桃子视频成人app| 九色91在线视频| 亚洲精品激情| 香港三日本8a三级少妇三级99| 亚洲曰韩产成在线| 亚洲av无码一区二区三区性色| 另类少妇人与禽zozz0性伦| 日韩成人在线一区| 亚洲资源在线网| 激情欧美一区二区三区在线观看| 91视频免费看片| 欧美日韩亚洲综合| 思思99re6国产在线播放| 国产精品视频在线播放| 日韩欧美午夜| 日本中文字幕影院| ●精品国产综合乱码久久久久| 国产三级漂亮女教师| 欧美麻豆久久久久久中文| 日韩三级网址| 日韩日韩日韩日韩日韩| 99久久99久久精品国产片果冻 | 久久精品成人| av黄色在线免费观看| 欧美午夜一区二区| 青青青青在线| 51国偷自产一区二区三区| 极品裸体白嫩激情啪啪国产精品| 日批在线观看视频| 色婷婷综合中文久久一本| 一本一道波多野毛片中文在线 | 中文字幕在线播放一区二区| 夜夜揉揉日日人人青青一国产精品| 国产77777| 青青久久aⅴ北条麻妃| 日韩国产91| 国产 国语对白 露脸| 成人国产精品视频| 日本天堂网在线| 最近2019年日本中文免费字幕| 国产一精品一av一免费爽爽| 国产精品第157页| 久久综合99re88久久爱| 中文字幕丰满人伦在线| 欧美成人全部免费| 亚洲精品合集| 黄色手机在线视频| 一区二区久久久| 色在线免费视频| 国产日韩专区在线| 成人激情免费视频| 免费不卡av网站| 福利一区福利二区微拍刺激| 视频三区在线| 国产视频一区二区不卡| 日本午夜一区二区| 国产在线视频第一页| 亚洲人成啪啪网站| 日韩一二三区| 熟妇人妻无乱码中文字幕真矢织江| 亚洲美女视频在线观看| 三级视频在线播放| 91传媒在线免费观看| 久久不射中文字幕| 久草免费新视频| 一本久久综合亚洲鲁鲁| 成人在线超碰| 在线黄色免费看| 色香色香欲天天天影视综合网|