成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一篇可視化的JS引擎執(zhí)行流程

開(kāi)發(fā) 前端
JavaScirpt引擎可以將JS代碼編譯為不同CPU(Intel, ARM以及MIPS等)對(duì)應(yīng)的匯編代碼,這樣我們才不要去翻閱每個(gè)CPU的指令集手冊(cè)。

[[394708]]

前言

這是一篇不錯(cuò)譯文,我強(qiáng)烈推薦的原因在于:

在用動(dòng)圖的形式生動(dòng)形象的講述了JavaScript引擎基本原理。

圖片制作并非本人,如有侵權(quán),會(huì)刪除。

接觸了前端這么久以來(lái),你每天跟JS打交道,你肯定也和我一樣認(rèn)為JavaScript很酷。但機(jī)器怎么能真正理解你寫的代碼呢?

由上面的思考點(diǎn),才引出此文:

帶你了機(jī)一下JavaScript引擎的基本原理,看看它是如何處理我們對(duì)人類友好的JS代碼,并將其轉(zhuǎn)化為機(jī)器所能理解的東西。

作為JavaScript的開(kāi)發(fā)者,清楚明白它的過(guò)程,絕對(duì)是一件好事情。

基本概念

在這之前,我們得了解一些JS引擎的基礎(chǔ)知識(shí)。

什么是JS引擎,它幫我們做了什么事情呢?

我們都知道,我們寫得代碼,經(jīng)過(guò)處理,交給CPU,它是不認(rèn)識(shí)的,無(wú)法去執(zhí)行。而CPU認(rèn)識(shí)的是自己的指令集,指令集對(duì)應(yīng)的是匯編代碼。我們不可能去編寫這些指令集,于是乎,它出現(xiàn)了:

JavaScirpt引擎可以將JS代碼編譯為不同CPU(Intel, ARM以及MIPS等)對(duì)應(yīng)的匯編代碼,這樣我們才不要去翻閱每個(gè)CPU的指令集手冊(cè)。

當(dāng)然了,編譯代碼不是它的唯一功能,比如代碼的執(zhí)行,分配內(nèi)存,垃圾回收機(jī)制都是它工作的。

對(duì)它有了一個(gè)大致的認(rèn)識(shí),那我們常見(jiàn)的JS引擎有哪些呢?我發(fā)現(xiàn),最知名的肯定是V8,至于一些其他的,感興趣的可以去查一查資料,

比如還有:

  • SpiderMonkey (Mozilla)
  • JavaScriptCore (Apple)
  • Chakra (Microsoft)
  • IOT:duktape、JerryScript

V8的內(nèi)容太多了,篇幅有限,后續(xù)再出一篇文章聊一聊。

太出名了,所以這篇文章介紹的知識(shí)主要基于 Node.js 和基于 Chromium 的瀏覽器所用的 V8 引擎。

主要流程圖

細(xì)節(jié)很多,所以主要分析的是主要的流程,如圖:

從圖上,我們可以總結(jié)一下幾個(gè)點(diǎn):

  • 生成抽象語(yǔ)法樹(shù)
    • 詞法分析
    • 語(yǔ)法分析
  • 生成字節(jié)碼
  • 執(zhí)行代碼
    • 即時(shí)編譯
    • 內(nèi)聯(lián)緩存

生成抽象語(yǔ)法樹(shù)

HTML解析器遇到了一個(gè)帶有源的腳本標(biāo)簽。這個(gè)源的代碼會(huì)從網(wǎng)絡(luò)、緩存或已安裝的服務(wù)工作者那里加載。響應(yīng)是請(qǐng)求的腳本作為字節(jié)流,由字節(jié)流解碼器來(lái)處理。字節(jié)流解碼器對(duì)正在下載的字節(jié)流進(jìn)行解碼。

進(jìn)行解碼

詞法分析

生成抽象語(yǔ)法樹(shù)的 第一個(gè)階段是分詞(tokenize),又叫詞法分析。

字節(jié)流解碼器會(huì)先從代碼字節(jié)流中創(chuàng)建 令牌 (token)。

注:令牌可以理解為語(yǔ)法上不可能再分的,最小的單個(gè)字符或字符串)。

例如,0066解碼為f,0075解碼為u,006e解碼為n,0063解碼為c,0074解碼為t,0069解碼為i,006f解碼為o,006e解碼為n,接著后面是一個(gè)空格。然后你會(huì)發(fā)現(xiàn),他們組合起來(lái)就是 function。

這是JavaScript中的一個(gè)保留關(guān)鍵字。

一個(gè)令牌被創(chuàng)建,并被發(fā)送到解析器(parser)。其余的字節(jié)流也是如此,具體如下圖:

詞法分析

語(yǔ)法分析

第二個(gè)階段是解析(parse),也叫語(yǔ)法分析。

該引擎使用兩個(gè)解析器:預(yù)解析器和解析器。為了減少加載網(wǎng)站的時(shí)間,該引擎試圖避免解析那些不需要立即使用的代碼。

預(yù)解析器處理以后可能會(huì)用到的代碼,而解析器則處理立即需要的代碼!

如果某個(gè)函數(shù)只有在用戶點(diǎn)擊某個(gè)按鈕后才會(huì)被調(diào)用,那么就沒(méi)有必要為了加載網(wǎng)站而立即編譯這段代碼了。

如果用戶最終點(diǎn)擊了按鈕,需要那段代碼,它就會(huì)被送到解析器中。

解析器根據(jù)它從字節(jié)流解碼器收到的標(biāo)記創(chuàng)建節(jié)點(diǎn)。通過(guò)這些節(jié)點(diǎn),它創(chuàng)建了一個(gè)抽象語(yǔ)法樹(shù)或AST,如圖:

語(yǔ)法分析

值得思考的是,AST到底是什么呢?(到底是怎么樣的一個(gè)數(shù)據(jù)結(jié)構(gòu)呢,babel里面是不是也有這些概念呢)

接下來(lái),是解釋器的時(shí)間了,解釋器瀏覽AST,并根據(jù)AST包含的信息生成字節(jié)代碼。一旦字節(jié)碼被完全生成,AST就會(huì)被刪除,從而清除內(nèi)存空間。最后,我們有了一個(gè)機(jī)器可以工作的東西。

生成字節(jié)碼

剛剛我們提到,解釋器瀏覽AST,并根據(jù)AST包含的信息生成字節(jié)代碼,那么它的過(guò)程是怎么樣的呢?

大致上,你可以這么理解:

AST交給解釋器(interpreter),遍歷整個(gè)AST,就會(huì)生成字節(jié)碼。當(dāng)字節(jié)碼生成后,AST 便會(huì)被刪除以節(jié)省內(nèi)存空間。最終我們得到了更貼近 機(jī)器碼 的 字節(jié)碼。

這里的 字節(jié)碼 是介于 AST 和 機(jī)器碼 之間的一種代碼,它還是需要通過(guò) 解釋器 將其轉(zhuǎn)換為 機(jī)器碼 后才能執(zhí)行

那我們通過(guò)一個(gè)圖來(lái)看看它的過(guò)程吧:

生成字節(jié)碼

代碼執(zhí)行

我們有了字節(jié)碼后,就可以進(jìn)入執(zhí)行階段了。

即使編譯

雖然字節(jié)碼的速度很快,但它還可以更快。當(dāng)這個(gè)字節(jié)碼運(yùn)行時(shí),信息就會(huì)被生成。

它可以檢測(cè)到某些行為是否經(jīng)常發(fā)生,以及被使用的數(shù)據(jù)類型。也許你一直在調(diào)用一個(gè)函數(shù)幾十次:是時(shí)候優(yōu)化它了,這樣它的運(yùn)行速度會(huì)更快 。字節(jié)代碼,連同生成的類型反饋,被發(fā)送到優(yōu)化編譯器。優(yōu)化編譯器接收字節(jié)碼和類型反饋,并從中生成高度優(yōu)化的機(jī)器代碼。

這種技術(shù)也被稱為 即時(shí)編譯(JIT:Just In Time),而上面所說(shuō)的 優(yōu)化編譯器 也叫 JIT 編譯器。

具體的話,可以參考下面的圖:

及時(shí)編譯

內(nèi)聯(lián)緩存

JavaScript是一種動(dòng)態(tài)類型的語(yǔ)言,這意味著數(shù)據(jù)的類型可以不斷變化。如果JavaScript引擎每次都要檢查某個(gè)值的數(shù)據(jù)類型,那就會(huì)非常慢。

處于上訴所說(shuō),引擎有了一種叫做內(nèi)聯(lián)緩存 (inline caching) 的技術(shù)。

具體流程是這樣子的:

為了減少解釋代碼的時(shí)間,優(yōu)化的機(jī)器代碼只處理引擎在運(yùn)行字節(jié)碼時(shí)曾經(jīng)見(jiàn)過(guò)的情況。如果我們反復(fù)使用某段代碼,反復(fù)返回相同的數(shù)據(jù)類型,那么優(yōu)化后的機(jī)器代碼可以簡(jiǎn)單地重復(fù)使用,以加快速度。

然而,由于JavaScript是動(dòng)態(tài)類型的,可能會(huì)發(fā)生同一段代碼突然返回不同類型的數(shù)據(jù)。如果發(fā)生這種情況,機(jī)器代碼就會(huì)被取消優(yōu)化,引擎就會(huì)退回到解釋生成的字節(jié)碼。假設(shè)某個(gè)函數(shù)被調(diào)用了100次,到目前為止總是返回相同的值。它將假設(shè)在你第101次調(diào)用它時(shí),它也會(huì)返回這個(gè)值。

假設(shè)我們有以下函數(shù)sum,(到目前為止)每次都是以數(shù)值作為參數(shù)來(lái)調(diào)用,如圖:

如果這是真的,就不需要?jiǎng)討B(tài)查找,它可以重新使用優(yōu)化后的機(jī)器代碼。否則,如果假設(shè)不正確,它就會(huì)恢復(fù)到原來(lái)的字節(jié)碼,而不是優(yōu)化后的機(jī)器碼。例如,下一次我們調(diào)用它時(shí),我們傳遞一個(gè)字符串而不是一個(gè)數(shù)字。由于JavaScript是動(dòng)態(tài)類型的,我們可以這樣做而不會(huì)有任何錯(cuò)誤!

如圖:

這意味著數(shù)字2將被強(qiáng)制變成一個(gè)字符串,而函數(shù)將返回字符串 "12"。它回到執(zhí)行解釋的字節(jié)碼并更新類型反饋。

總結(jié)

篇幅不多,但或多或少對(duì)你有幫助,讓你對(duì)JS引擎的執(zhí)行流程有了解。你想了解更多的話,歡迎查原文V8官網(wǎng)的docs:

https://v8.dev/docs

我是TianTian,我們下一期見(jiàn)!!!

參考鏈接

[1] Celebrating 10 years of V8: https://v8.dev/blog/10-years

[2] Launching Ignition and TurboFan: https://v8.dev/blog/launching-ignition-and-turbofan

[3] Understanding V8’s Bytecode: https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775

[4] An Introduction to Speculative Optimization in V8: https://benediktmeurer.de/2017/12/13/an-introduction-to-speculative-optimization-in-v8/

[5] JavaScript Visualized: the JavaScript Engine: https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf

[6] The V8 JavaScript Engine: https://nodejs.dev/learn/the-v8-javascript-engine前言

這是一篇不錯(cuò)譯文,我強(qiáng)烈推薦的原因在于:

在用動(dòng)圖的形式生動(dòng)形象的講述了JavaScript引擎基本原理。

圖片制作并非本人,如有侵權(quán),會(huì)刪除。

接觸了前端這么久以來(lái),你每天跟JS打交道,你肯定也和我一樣認(rèn)為JavaScript很酷。但機(jī)器怎么能真正理解你寫的代碼呢?

由上面的思考點(diǎn),才引出此文:

帶你了機(jī)一下JavaScript引擎的基本原理,看看它是如何處理我們對(duì)人類友好的JS代碼,并將其轉(zhuǎn)化為機(jī)器所能理解的東西。

作為JavaScript的開(kāi)發(fā)者,清楚明白它的過(guò)程,絕對(duì)是一件好事情。

基本概念

在這之前,我們得了解一些JS引擎的基礎(chǔ)知識(shí)。

什么是JS引擎,它幫我們做了什么事情呢?

我們都知道,我們寫得代碼,經(jīng)過(guò)處理,交給CPU,它是不認(rèn)識(shí)的,無(wú)法去執(zhí)行。而CPU認(rèn)識(shí)的是自己的指令集,指令集對(duì)應(yīng)的是匯編代碼。我們不可能去編寫這些指令集,于是乎,它出現(xiàn)了:

JavaScirpt引擎可以將JS代碼編譯為不同CPU(Intel, ARM以及MIPS等)對(duì)應(yīng)的匯編代碼,這樣我們才不要去翻閱每個(gè)CPU的指令集手冊(cè)。

當(dāng)然了,編譯代碼不是它的唯一功能,比如代碼的執(zhí)行,分配內(nèi)存,垃圾回收機(jī)制都是它工作的。

對(duì)它有了一個(gè)大致的認(rèn)識(shí),那我們常見(jiàn)的JS引擎有哪些呢?我發(fā)現(xiàn),最知名的肯定是V8,至于一些其他的,感興趣的可以去查一查資料,

比如還有:

SpiderMonkey (Mozilla)

JavaScriptCore (Apple)

Chakra (Microsoft)

IOT:duktape、JerryScript

V8的內(nèi)容太多了,篇幅有限,后續(xù)再出一篇文章聊一聊。

太出名了,所以這篇文章介紹的知識(shí)主要基于 Node.js 和基于 Chromium 的瀏覽器所用的 V8 引擎。

主要流程圖

細(xì)節(jié)很多,所以主要分析的是主要的流程,如圖:

圖片

從圖上,我們可以總結(jié)一下幾個(gè)點(diǎn):

生成抽象語(yǔ)法樹(shù)

詞法分析

語(yǔ)法分析

生成字節(jié)碼

執(zhí)行代碼

即時(shí)編譯

內(nèi)聯(lián)緩存

生成抽象語(yǔ)法樹(shù)

HTML解析器遇到了一個(gè)帶有源的腳本標(biāo)簽。這個(gè)源的代碼會(huì)從網(wǎng)絡(luò)、緩存或已安裝的服務(wù)工作者那里加載。響應(yīng)是請(qǐng)求的腳本作為字節(jié)流,由字節(jié)流解碼器來(lái)處理。字節(jié)流解碼器對(duì)正在下載的字節(jié)流進(jìn)行解碼。

圖片

進(jìn)行解碼

詞法分析

生成抽象語(yǔ)法樹(shù)的 第一個(gè)階段是分詞(tokenize),又叫詞法分析。

字節(jié)流解碼器會(huì)先從代碼字節(jié)流中創(chuàng)建 令牌 (token)。

注:令牌可以理解為語(yǔ)法上不可能再分的,最小的單個(gè)字符或字符串)。

例如,0066解碼為f,0075解碼為u,006e解碼為n,0063解碼為c,0074解碼為t,0069解碼為i,006f解碼為o,006e解碼為n,接著后面是一個(gè)空格。然后你會(huì)發(fā)現(xiàn),他們組合起來(lái)就是 function。

這是JavaScript中的一個(gè)保留關(guān)鍵字。

一個(gè)令牌被創(chuàng)建,并被發(fā)送到解析器(parser)。其余的字節(jié)流也是如此,具體如下圖:

圖片

詞法分析

語(yǔ)法分析

第二個(gè)階段是解析(parse),也叫語(yǔ)法分析。

該引擎使用兩個(gè)解析器:預(yù)解析器和解析器。為了減少加載網(wǎng)站的時(shí)間,該引擎試圖避免解析那些不需要立即使用的代碼。

預(yù)解析器處理以后可能會(huì)用到的代碼,而解析器則處理立即需要的代碼!

如果某個(gè)函數(shù)只有在用戶點(diǎn)擊某個(gè)按鈕后才會(huì)被調(diào)用,那么就沒(méi)有必要為了加載網(wǎng)站而立即編譯這段代碼了。

如果用戶最終點(diǎn)擊了按鈕,需要那段代碼,它就會(huì)被送到解析器中。

解析器根據(jù)它從字節(jié)流解碼器收到的標(biāo)記創(chuàng)建節(jié)點(diǎn)。通過(guò)這些節(jié)點(diǎn),它創(chuàng)建了一個(gè)抽象語(yǔ)法樹(shù)或AST,如圖:

圖片

語(yǔ)法分析

值得思考的是,AST到底是什么呢?(到底是怎么樣的一個(gè)數(shù)據(jù)結(jié)構(gòu)呢,babel里面是不是也有這些概念呢)

接下來(lái),是解釋器的時(shí)間了,解釋器瀏覽AST,并根據(jù)AST包含的信息生成字節(jié)代碼。一旦字節(jié)碼被完全生成,AST就會(huì)被刪除,從而清除內(nèi)存空間。最后,我們有了一個(gè)機(jī)器可以工作的東西。

生成字節(jié)碼

剛剛我們提到,解釋器瀏覽AST,并根據(jù)AST包含的信息生成字節(jié)代碼,那么它的過(guò)程是怎么樣的呢?

大致上,你可以這么理解:

AST交給解釋器(interpreter),遍歷整個(gè)AST,就會(huì)生成字節(jié)碼。當(dāng)字節(jié)碼生成后,AST 便會(huì)被刪除以節(jié)省內(nèi)存空間。最終我們得到了更貼近 機(jī)器碼 的 字節(jié)碼。

這里的 字節(jié)碼 是介于 AST 和 機(jī)器碼 之間的一種代碼,它還是需要通過(guò) 解釋器 將其轉(zhuǎn)換為 機(jī)器碼 后才能執(zhí)行

那我們通過(guò)一個(gè)圖來(lái)看看它的過(guò)程吧:

圖片

生成字節(jié)碼

代碼執(zhí)行

我們有了字節(jié)碼后,就可以進(jìn)入執(zhí)行階段了。

即使編譯

雖然字節(jié)碼的速度很快,但它還可以更快。當(dāng)這個(gè)字節(jié)碼運(yùn)行時(shí),信息就會(huì)被生成。

它可以檢測(cè)到某些行為是否經(jīng)常發(fā)生,以及被使用的數(shù)據(jù)類型。也許你一直在調(diào)用一個(gè)函數(shù)幾十次:是時(shí)候優(yōu)化它了,這樣它的運(yùn)行速度會(huì)更快 。字節(jié)代碼,連同生成的類型反饋,被發(fā)送到優(yōu)化編譯器。優(yōu)化編譯器接收字節(jié)碼和類型反饋,并從中生成高度優(yōu)化的機(jī)器代碼。

這種技術(shù)也被稱為 即時(shí)編譯(JIT:Just In Time),而上面所說(shuō)的 優(yōu)化編譯器 也叫 JIT 編譯器。

具體的話,可以參考下面的圖:

圖片

及時(shí)編譯

內(nèi)聯(lián)緩存

JavaScript是一種動(dòng)態(tài)類型的語(yǔ)言,這意味著數(shù)據(jù)的類型可以不斷變化。如果JavaScript引擎每次都要檢查某個(gè)值的數(shù)據(jù)類型,那就會(huì)非常慢。

處于上訴所說(shuō),引擎有了一種叫做內(nèi)聯(lián)緩存 (inline caching) 的技術(shù)。

具體流程是這樣子的:

為了減少解釋代碼的時(shí)間,優(yōu)化的機(jī)器代碼只處理引擎在運(yùn)行字節(jié)碼時(shí)曾經(jīng)見(jiàn)過(guò)的情況。如果我們反復(fù)使用某段代碼,反復(fù)返回相同的數(shù)據(jù)類型,那么優(yōu)化后的機(jī)器代碼可以簡(jiǎn)單地重復(fù)使用,以加快速度。

然而,由于JavaScript是動(dòng)態(tài)類型的,可能會(huì)發(fā)生同一段代碼突然返回不同類型的數(shù)據(jù)。如果發(fā)生這種情況,機(jī)器代碼就會(huì)被取消優(yōu)化,引擎就會(huì)退回到解釋生成的字節(jié)碼。假設(shè)某個(gè)函數(shù)被調(diào)用了100次,到目前為止總是返回相同的值。它將假設(shè)在你第101次調(diào)用它時(shí),它也會(huì)返回這個(gè)值。

假設(shè)我們有以下函數(shù)sum,(到目前為止)每次都是以數(shù)值作為參數(shù)來(lái)調(diào)用,如圖:

圖片

如果這是真的,就不需要?jiǎng)討B(tài)查找,它可以重新使用優(yōu)化后的機(jī)器代碼。否則,如果假設(shè)不正確,它就會(huì)恢復(fù)到原來(lái)的字節(jié)碼,而不是優(yōu)化后的機(jī)器碼。例如,下一次我們調(diào)用它時(shí),我們傳遞一個(gè)字符串而不是一個(gè)數(shù)字。由于JavaScript是動(dòng)態(tài)類型的,我們可以這樣做而不會(huì)有任何錯(cuò)誤!

如圖:

圖片

這意味著數(shù)字2將被強(qiáng)制變成一個(gè)字符串,而函數(shù)將返回字符串 "12"。它回到執(zhí)行解釋的字節(jié)碼并更新類型反饋。

總結(jié)

篇幅不多,但或多或少對(duì)你有幫助,讓你對(duì)JS引擎的執(zhí)行流程有了解。你想了解更多的話,歡迎查原文V8官網(wǎng)的docs:

https://v8.dev/docs

我是TianTian,我們下一期見(jiàn)!!!

參考鏈接

[1] Celebrating 10 years of V8: https://v8.dev/blog/10-years

[2] Launching Ignition and TurboFan: https://v8.dev/blog/launching-ignition-and-turbofan

[3] Understanding V8’s Bytecode: https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775

[4] An Introduction to Speculative Optimization in V8: https://benediktmeurer.de/2017/12/13/an-introduction-to-speculative-optimization-in-v8/

[5] JavaScript Visualized: the JavaScript Engine: https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf

[6] The V8 JavaScript Engine: https://nodejs.dev/learn/the-v8-javascript-engine

 

責(zé)任編輯:武曉燕 來(lái)源: TianTianUp
相關(guān)推薦

2021-03-01 07:45:32

kubernetes應(yīng)用程序工具

2017-08-04 15:33:33

大數(shù)據(jù)數(shù)據(jù)可視化方法

2020-08-04 13:40:02

數(shù)據(jù)可視化熱力圖表格

2009-08-03 21:43:03

IT運(yùn)維可視化摩卡

2022-05-05 07:01:09

可視化代碼執(zhí)行工具

2020-03-11 14:39:26

數(shù)據(jù)可視化地圖可視化地理信息

2021-04-27 08:57:58

開(kāi)發(fā)技能代碼

2023-09-15 14:39:09

2015-12-08 11:39:59

JavaScript引擎指南

2022-06-28 09:34:24

可視化Python代碼

2021-07-12 17:23:47

零設(shè)計(jì)可視化引擎

2022-11-08 10:52:25

Flowable節(jié)點(diǎn)表單

2017-10-14 13:54:26

數(shù)據(jù)可視化數(shù)據(jù)信息可視化

2023-05-05 07:41:42

執(zhí)行上下文JavaScript

2021-02-25 21:47:47

開(kāi)源技術(shù) 趨勢(shì)

2009-04-21 14:26:41

可視化監(jiān)控IT管理摩卡

2021-11-24 08:51:32

Node.js監(jiān)聽(tīng)函數(shù)

2022-08-26 09:15:58

Python可視化plotly

2025-02-19 09:55:39

2022-05-30 08:37:34

可視化圖表項(xiàng)目開(kāi)源
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 粉色午夜视频 | 国产免费看 | 91av视频| 99精品一区二区三区 | 久久不卡| 亚洲高清一区二区三区 | 蜜桃视频一区二区三区 | 精品久久久久久亚洲综合网 | 男女国产网站 | 久久久www成人免费精品 | 欧美午夜视频 | 中文字幕一区二区三区在线观看 | 美女视频一区二区三区 | 国产精品一区二区三区久久久 | 欧美日韩一二区 | 99精品久久久久久中文字幕 | 99综合在线 | 日韩精品在线播放 | 女人一区 | 韩日av片| 国产成人综合网 | 日韩激情在线 | 欧美日韩三级 | 91精品国产综合久久久久久丝袜 | 亚洲欧美国产精品一区二区 | 欲色av| 亚洲欧美激情精品一区二区 | 日韩精品a在线观看图片 | 久久人人网 | 国产一级一级国产 | 亚洲欧美一区二区三区视频 | 99精品免费视频 | 日韩a在线| 九九福利| 找个黄色片| 亚洲精品二区 | 亚洲福利| 亚洲欧洲一区二区 | 老司机精品福利视频 | 国产精品久久久久久久久久久久冷 | 亚洲一区二区三区 |