日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

Golang实现JAVA虚拟机-指令集和解释器

發(fā)布時(shí)間:2024/1/11 windows 52 coder
生活随笔 收集整理的這篇文章主要介紹了 Golang实现JAVA虚拟机-指令集和解释器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文鏈接:https://gaoyubo.cn/blogs/f57f32cf.html

前置

Golang實(shí)現(xiàn)JAVA虛擬機(jī)-解析class文件

Golang實(shí)現(xiàn)JAVA虛擬機(jī)-運(yùn)行時(shí)數(shù)據(jù)區(qū)

一、字節(jié)碼、class文件、指令集的關(guān)系

class文件(二進(jìn)制)和字節(jié)碼(十六進(jìn)制)的關(guān)系

class文件

  • 經(jīng)過(guò)編譯器編譯后的文件(如javac),一個(gè)class文件代表一個(gè)類(lèi)或者接口;

  • 是由字節(jié)碼組成的,主要存儲(chǔ)的是字節(jié)碼,字節(jié)碼是訪問(wèn)jvm的重要指令

  • 文件本身是2進(jìn)制,對(duì)應(yīng)的是16進(jìn)制的數(shù)。

字節(jié)碼

  • 包括操作碼(Opcode)操作數(shù):操作碼是一個(gè)字節(jié)

  • 如果方法不是抽象的,也不是本地方法,方法的Java代碼就會(huì)被編譯器編譯成字節(jié)碼,存放在method_info結(jié)構(gòu)的Code屬性中

如圖:操作碼為B2,助記符為助記符是getstatic。它的操作數(shù)是0x0002,代表常量池里的第二個(gè)常量。

操作數(shù)棧和局部變量表只存放數(shù)據(jù)的值, 并不記錄數(shù)據(jù)類(lèi)型。結(jié)果就是:指令必須知道自己在操作什么類(lèi)型的數(shù)據(jù)。

這一點(diǎn)也直接反映在了操作碼的助記符上。

例如,iadd指令:對(duì)int值進(jìn)行加法操作;
dstore指令:把操作數(shù)棧頂?shù)膁ouble值彈出,存儲(chǔ)到局部變量表中;
areturn:從方法中返回引用值。

助記符

如果某類(lèi)指令可以操作不同類(lèi)型的變量,則助記符的第一個(gè)字母表示變量類(lèi)型。助記符首字母和變量類(lèi)型的對(duì)應(yīng)關(guān)系如下:

指令分類(lèi)

Java虛擬機(jī)規(guī)范把已經(jīng)定義的205條指令按用途分成了11類(lèi), 分別是:

  • 常量(constants)指令
  • 加載(loads)指令
  • 存儲(chǔ)(stores)指令
  • 操作數(shù)棧(stack)指令
  • 數(shù)學(xué)(math)指令
  • 轉(zhuǎn)換(conversions)指令
  • 比較(comparisons)指令
  • 控制(control)指令
  • 引用(references)指令
  • 擴(kuò)展(extended)指令
  • 保留(reserved)指令:
    • 操作碼:202(0xCA),助記符:breakpoint,用于調(diào)試器的斷點(diǎn)調(diào)試
    • 254(0xFE),助記符:impdep1
    • 266(0xFF),助記符:impdep2
    • 這三條指令不允許出現(xiàn)在class文件中

本章將要實(shí)現(xiàn)的指令涉及11類(lèi)中的9類(lèi)

二、JVM執(zhí)行引擎

執(zhí)行引擎是Java虛擬機(jī)四大組成部分中一個(gè)核心組成(另外三個(gè)分別是類(lèi)加載器子系統(tǒng)運(yùn)行時(shí)數(shù)據(jù)區(qū)垃圾回收器),

Java虛擬機(jī)的執(zhí)行引擎主要是用來(lái)執(zhí)行Java字節(jié)碼。

它有兩種主要執(zhí)行方式:通過(guò)字節(jié)碼解釋器執(zhí)行,通過(guò)即時(shí)編譯器執(zhí)行

解釋和編譯

在了解字節(jié)碼解釋器和即使編譯器之前,需要先了解解釋編譯

  • 解釋是將代碼逐行或逐條指令地轉(zhuǎn)換為機(jī)器代碼并立即執(zhí)行的方式,適合實(shí)現(xiàn)跨平臺(tái)性。
  • 編譯是將整個(gè)程序或代碼塊翻譯成機(jī)器代碼的方式,生成的機(jī)器代碼可反復(fù)執(zhí)行,通常更快,但不具備跨平臺(tái)性。

字節(jié)碼解釋器

字節(jié)碼解釋器將逐條解釋執(zhí)行Java字節(jié)碼指令。這意味著它會(huì)逐個(gè)讀取字節(jié)碼文件中的指令,并根據(jù)每個(gè)指令執(zhí)行相應(yīng)的操作。雖然解釋執(zhí)行相對(duì)較慢。

逐行解釋和執(zhí)行代碼。它會(huì)逐行讀取源代碼或字節(jié)碼,將每一行翻譯成計(jì)算機(jī)指令,然后立即執(zhí)行該指令。

因此具有平臺(tái)無(wú)關(guān)性,因?yàn)樽止?jié)碼可以在不同的平臺(tái)上運(yùn)行。

即時(shí)編譯器(Just-In-Time Compiler,JIT)

即時(shí)編譯器將字節(jié)碼編譯成本地機(jī)器代碼,然后執(zhí)行本地代碼。

這種方式更快,因?yàn)樗苊饬俗止?jié)碼解釋的過(guò)程,但編譯需要一些時(shí)間。

即時(shí)編譯器通常會(huì)選擇性地編譯某些熱點(diǎn)代碼路徑,以提高性能。

解釋器規(guī)范

Java虛擬機(jī)規(guī)范的2.11節(jié)介紹了Java虛擬機(jī)解釋器的大致邏輯,如下所示:

do {
    atomically calculate pc and fetch opcode at pc;
    if (operands) fetch operands;
    execute the action for the opcode;
} while (there is more to do);
  1. 從當(dāng)前程序計(jì)數(shù)器(Program Counter,通常簡(jiǎn)稱(chēng)為 PC)中獲取當(dāng)前要執(zhí)行的字節(jié)碼指令的地址。
  2. 從該地址獲取字節(jié)碼指令的操作碼(opcode),并執(zhí)行該操作碼對(duì)應(yīng)的操作。
  3. 如果指令需要操作數(shù)(operands),則獲取操作數(shù)。
  4. 執(zhí)行指令對(duì)應(yīng)的操作。
  5. 更新 PC,以便繼續(xù)執(zhí)行下一條字節(jié)碼指令。
  6. 循環(huán)執(zhí)行上述步驟,直到?jīng)]有更多的指令需要執(zhí)行。

每次循環(huán)都包含三個(gè)部分:計(jì)算pc、指令解碼、指令執(zhí)行

可以把這個(gè)邏輯用Go語(yǔ)言寫(xiě)成一個(gè)for循環(huán),里面是個(gè)大大的switch-case語(yǔ)句。但這樣的話,代碼的可讀性將非常差。

所以采用另外一種方式:把指令抽象成接口,解碼和執(zhí)行邏輯寫(xiě)在具體的指令實(shí)現(xiàn)中。

這樣編寫(xiě)出的解釋器就和Java虛擬機(jī)規(guī)范里的偽代碼一樣簡(jiǎn)單,偽代碼如下:

for {
    pc := calculatePC()
    opcode := bytecode[pc]
    inst := createInst(opcode)
    inst.fetchOperands(bytecode)
    inst.execute()
}

三、指令和指令解碼

本節(jié)先定義指令接口,然后定義一個(gè)結(jié)構(gòu)體用來(lái)輔助指令解碼

Instruction接口

為了便于管理,把每種指令的源文件都放在各自的包里,所有指令都共用的代碼則放在base包里。

因此instructions目錄下會(huì)有如下10個(gè)子目錄:

base目錄下創(chuàng)建instruction.go文件,在其中定義Instruction接口,代碼如下:

type Instruction interface {
    FetchOperands(reader *BytecodeReader)
    Execute(frame *rtda.Frame)
}

FetchOperands()方法從字節(jié)碼中提取操作數(shù),Execute()方法執(zhí)行指令邏輯。

有很多指令的操作數(shù)都是類(lèi)似的。為了避免重復(fù)代碼,按照操作數(shù)類(lèi)型定義一些結(jié)構(gòu)體,并實(shí)現(xiàn)FetchOperands()方 法。

無(wú)操作數(shù)指令

instruction.go文件中定義NoOperandsInstruction結(jié)構(gòu)體,代碼如下:

type NoOperandsInstruction struct {}

NoOperandsInstruction表示沒(méi)有操作數(shù)的指令,所以沒(méi)有定義 任何字段。FetchOperands()方法自然也是空空如也,什么也不用 讀,代碼如下:

func (self *NoOperandsInstruction) FetchOperands(reader *BytecodeReader) {
	// nothing to do
}

跳轉(zhuǎn)指令

定義BranchInstruction結(jié)構(gòu)體,代碼如下:

type BranchInstruction struct {
    //偏移量
	Offset int
}

BranchInstruction表示跳轉(zhuǎn)指令,Offset字段存放跳轉(zhuǎn)偏移量。

FetchOperands()方法從字節(jié)碼中讀取一個(gè)uint16整數(shù),轉(zhuǎn)成int后賦給Offset字段。代碼如下:

func (self *BranchInstruction) FetchOperands(reader *BytecodeReader) {
	self.Offset = int(reader.ReadInt16())
}

存儲(chǔ)和加載指令

存儲(chǔ)和加載類(lèi)指令需要根據(jù)索引存取局部變量表,索引由單字節(jié)操作數(shù)給出。把這類(lèi)指令抽象成Index8Instruction結(jié)構(gòu)體,定義Index8Instruction結(jié)構(gòu)體,代碼如下:

type Index8Instruction struct {
    //索引
    Index uint
}

FetchOperands()方法從字節(jié)碼中讀取一個(gè)int8整數(shù),轉(zhuǎn)成uint后賦給Index字段。代碼如下:

func (self *Index8Instruction) FetchOperands(reader *BytecodeReader) {
	self.Index = uint(reader.ReadUint8())
}

訪問(wèn)常量池的指令

有一些指令需要訪問(wèn)運(yùn)行時(shí)常量池,常量池索引由兩字節(jié)操作數(shù)給出,用Index字段表示常量池索引。定義Index16Instruction結(jié)構(gòu)體,代碼如下:

type Index16Instruction struct {
	Index uint
}

FetchOperands()方法從字節(jié)碼中讀取一個(gè) uint16整數(shù),轉(zhuǎn)成uint后賦給Index字段。代碼如下

func (self *Index16Instruction) FetchOperands(reader *BytecodeReader) {
    self.Index = uint(reader.ReadUint16())
}

指令接口和“抽象”指令定義好了,下面來(lái)看BytecodeReader結(jié)構(gòu)體

BytecodeReader結(jié)構(gòu)體

base目錄下創(chuàng)建bytecode_reader.go文件,在 其中定義BytecodeReader結(jié)構(gòu)體

type BytecodeReader struct {
    code []byte // bytecodes
    pc   int
}

code字段存放字節(jié)碼,pc字段記錄讀取到了哪個(gè)字節(jié)。

為了避免每次解碼指令都新創(chuàng)建一個(gè)BytecodeReader實(shí)例,給它定義一個(gè) Reset()方法,代碼如下:

func (self *BytecodeReader) Reset(code []byte, pc int) {
    self.code = code
    self.pc = pc
}

面實(shí)現(xiàn)一系列的Read()方法。首先是最簡(jiǎn)單的ReadUint8()方法,代碼如下:

func (self *BytecodeReader) ReadUint8() uint8 {
    i := self.code[self.pc]
    self.pc++
    return i
}
  • self.code 字節(jié)切片中的 self.pc 位置讀取一個(gè)字節(jié)(8 位)的整數(shù)值。
  • 然后將 self.pc 的值增加1,以便下次讀取下一個(gè)字節(jié)。
  • 最后,返回讀取的字節(jié)作為無(wú)符號(hào) 8 位整數(shù)

ReadInt8()方法調(diào)用ReadUint8(),然后把讀取到的值轉(zhuǎn)成int8 返回,代碼如下:

func (self *BytecodeReader) ReadInt8() int8 {
	return int8(self.ReadUint8())
}

ReadUint16()連續(xù)讀取兩字節(jié)

func (self *BytecodeReader) ReadUint16() uint16 {
    byte1 := uint16(self.ReadUint8())
    byte2 := uint16(self.ReadUint8())
    return (byte1 << 8) | byte2
}

ReadInt16()方法調(diào)用ReadUint16(),然后把讀取到的值轉(zhuǎn)成 int16返回,代碼如下:

func (self *BytecodeReader) ReadInt16() int16 {
	return int16(self.ReadUint16())
}

ReadInt32()方法連續(xù)讀取4字節(jié),代碼如下:

func (self *BytecodeReader) ReadInt32() int32 {
    byte1 := int32(self.ReadUint8())
    byte2 := int32(self.ReadUint8())
    byte3 := int32(self.ReadUint8())
    byte4 := int32(self.ReadUint8())
    return (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4
}

在接下來(lái)的小節(jié)中,將按照分類(lèi)依次實(shí)現(xiàn)約150條指令,占整個(gè)指令集的3/4

四、常量指令

常量指令把常量推入操作數(shù)棧頂。

常量可以來(lái)自三個(gè)地方:隱含在操作碼里操作數(shù)運(yùn)行時(shí)常量池

常量指令共有21條,本節(jié)實(shí)現(xiàn)其中的18條。另外3條是ldc系列指令,用于從運(yùn)行時(shí)常量池中加載常量,將在后續(xù)實(shí)現(xiàn)。

nop指令

nop指令是最簡(jiǎn)單的一條指令,因?yàn)樗裁匆膊蛔觥?br> 在\instructions\constants目錄下創(chuàng)建nop.go文件,在其中實(shí)現(xiàn)nop指令,代碼如下:

type NOP struct{ base.NoOperandsInstruction }

func (self *NOP) Execute(frame *rtda.Frame) {
// 什么也不用做
}

const系列指令

這一系列指令把隱含在操作碼中的常量值推入操作數(shù)棧頂。

constants目錄下創(chuàng)建const.go文件,在其中定義15條指令,代碼如下

type ACONST_NULL struct{ base.NoOperandsInstruction }
type DCONST_0 struct{ base.NoOperandsInstruction }
type DCONST_1 struct{ base.NoOperandsInstruction }
type FCONST_0 struct{ base.NoOperandsInstruction }
type FCONST_1 struct{ base.NoOperandsInstruction }
type FCONST_2 struct{ base.NoOperandsInstruction }
type ICONST_M1 struct{ base.NoOperandsInstruction }
type ICONST_0 struct{ base.NoOperandsInstruction }
type ICONST_1 struct{ base.NoOperandsInstruction }
type ICONST_2 struct{ base.NoOperandsInstruction }
type ICONST_3 struct{ base.NoOperandsInstruction }
type ICONST_4 struct{ base.NoOperandsInstruction }
type ICONST_5 struct{ base.NoOperandsInstruction }
type LCONST_0 struct{ base.NoOperandsInstruction }
type LCONST_1 struct{ base.NoOperandsInstruction }

以3條指令為例進(jìn)行說(shuō)明。aconst_null指令把null引用推入操作 數(shù)棧頂,代碼如下

func (self *ACONST_NULL) Execute(frame *rtda.Frame) {
	frame.OperandStack().PushRef(nil)
}

dconst_0指令把double型0推入操作數(shù)棧頂,代碼如下

func (self *DCONST_0) Execute(frame *rtda.Frame) {
	frame.OperandStack().PushDouble(0.0)
}

iconst_m1指令把int型-1推入操作數(shù)棧頂,代碼如下:

func (self *ICONST_M1) Execute(frame *rtda.Frame) {
	frame.OperandStack().PushInt(-1)
}

bipush和sipush指令

  • bipush指令從操作數(shù)中獲取一個(gè)byte型整數(shù),擴(kuò)展成int型,然后推入棧頂。
  • sipush指令從操作數(shù)中獲取一個(gè)short型整數(shù),擴(kuò)展成int型,然后推入棧頂。

constants目錄下創(chuàng)建 ipush.go文件,在其中定義bipush和sipush指令,代碼如下:

type BIPUSH struct { val int8 } // Push byte
type SIPUSH struct { val int16 } // Push short

BIPUSH結(jié)構(gòu)體實(shí)現(xiàn)方法如下:

type BIPUSH struct {
    val int8
}

func (self *BIPUSH) FetchOperands(reader *base.BytecodeReader) {
    self.val = reader.ReadInt8()
}
func (self *BIPUSH) Execute(frame *rtda.Frame) {
    i := int32(self.val)
    frame.OperandStack().PushInt(i)
}

五、加載指令

加載指令用于從局部變量表獲取變量,并將其推入操作數(shù)棧頂。總共有 33 條加載指令,它們按照所操作的變量類(lèi)型可以分為 6 類(lèi):

  1. aload 系列指令:用于操作引用類(lèi)型變量。
  2. dload 系列指令:用于操作 double 類(lèi)型變量。
  3. fload 系列指令:用于操作 float 變量。
  4. iload 系列指令:用于操作 int 變量。
  5. lload 系列指令:用于操作 long 變量。
  6. xaload 指令:用于操作數(shù)組。

本節(jié)將實(shí)現(xiàn)其中的 25 條加載指令。數(shù)組和xaload系列指令先不實(shí)現(xiàn)。

loads目錄下創(chuàng)建iload.go文件,在其中定義5 條指令,代碼如下:完整代碼移步:jvmgo

// 從局部變量表加載int類(lèi)型
type ILOAD struct{ base.Index8Instruction }
type ILOAD_0 struct{ base.NoOperandsInstruction }
type ILOAD_1 struct{ base.NoOperandsInstruction }
type ILOAD_2 struct{ base.NoOperandsInstruction }
type ILOAD_3 struct{ base.NoOperandsInstruction }

為了避免重復(fù)代碼,定義一個(gè)函數(shù)供iload系列指令使用,代碼如下:

func _iload(frame *rtda.Frame, index uint) {
    val := frame.LocalVars().GetInt(index)
    frame.OperandStack().PushInt(val)
}

iload指令的索引來(lái)自操作數(shù),其Execute()方法如下:

func (self *ILOAD) Execute(frame *rtda.Frame) {
	_iload(frame, uint(self.Index))
}

其余4條指令的索引隱含在操作碼中,以iload_1為例,其 Execute()方法如下:

func (self *ILOAD_1) Execute(frame *rtda.Frame) {
	_iload(frame, 1)
}

六、存儲(chǔ)指令

和加載指令剛好相反,存儲(chǔ)指令把變量從操作數(shù)棧頂彈出,然后存入局部變量表。

和加載指令一樣,存儲(chǔ)指令也可以分為6類(lèi)。以 lstore系列指令為例進(jìn)行介紹。完整代碼移步:jvmgo

instructions\stores目錄下創(chuàng)建 lstore.go文件,在其中定義5條指令,代碼如下:

type LSTORE struct{ base.Index8Instruction }
type LSTORE_0 struct{ base.NoOperandsInstruction }
type LSTORE_1 struct{ base.NoOperandsInstruction }
type LSTORE_2 struct{ base.NoOperandsInstruction }
type LSTORE_3 struct{ base.NoOperandsInstruction }

同樣定義一個(gè)函數(shù)供5條指令使用,代碼如下:

func _lstore(frame *rtda.Frame, index uint) {
    val := frame.OperandStack().PopLong()
    frame.LocalVars().SetLong(index, val)
}

lstore指令的索引來(lái)自操作數(shù),其Execute()方法如下:

func (self *LSTORE) Execute(frame *rtda.Frame) {
	_lstore(frame, uint(self.Index))
}

其余4條指令的索引隱含在操作碼中,以lstore_2為例,其 Execute()方法如下

func (self *LSTORE_2) Execute(frame *rtda.Frame) {
	_lstore(frame, 2)
}

七、棧指令

棧指令直接對(duì)操作數(shù)棧進(jìn)行操作,共9條:

pop和pop2指令將棧頂變量彈出

dup系列指令復(fù)制棧頂變量

swap指令交換棧頂?shù)膬蓚€(gè)變量

和其他類(lèi)型的指令不同,棧指令并不關(guān)心變量類(lèi)型。為了實(shí)現(xiàn)棧指令,需要給OperandStack結(jié)構(gòu)體添加兩個(gè)方法。操作數(shù)棧實(shí)現(xiàn)
rtda\operand_stack.go文件中,在其中定義PushSlot()PopSlot() 方法,代碼如下:

func (self *OperandStack) PushSlot(slot Slot) {
    self.slots[self.size] = slot
    self.size++
}
func (self *OperandStack) PopSlot() Slot {
    self.size--
    return self.slots[self.size]
}

pop和pop2指令

stack目錄下創(chuàng)建pop.go文件,在其中定義 pop和pop2指令,代碼如下:

type POP struct{ base.NoOperandsInstruction }
type POP2 struct{ base.NoOperandsInstruction }

pop指令把棧頂變量彈出,代碼如下:

func (self *POP) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    stack.PopSlot()
}

pop指令只能用于彈出int、float等占用一個(gè)操作數(shù)棧位置的變量。

double和long變量在操作數(shù)棧中占據(jù)兩個(gè)位置,需要使用pop2指令彈出,代碼如下:

func (self *POP2) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    stack.PopSlot()
    stack.PopSlot()
}

dup指令

創(chuàng)建dup.go文件,在其中定義6 條指令,代碼如下:完整代碼移步:jvmgo

type DUP struct{ base.NoOperandsInstruction }
type DUP_X1 struct{ base.NoOperandsInstruction }
type DUP_X2 struct{ base.NoOperandsInstruction }
type DUP2 struct{ base.NoOperandsInstruction }
type DUP2_X1 struct{ base.NoOperandsInstruction }
type DUP2_X2 struct{ base.NoOperandsInstruction }

dup指令復(fù)制棧頂?shù)膯蝹€(gè)變量,代碼如下:

func (self *DUP) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot := stack.PopSlot()
    stack.PushSlot(slot)
    stack.PushSlot(slot)
}

DUP_X1 :復(fù)制棧頂操作數(shù)一份放在第二個(gè)操作數(shù)的下方。Execute代碼如下:

/*
bottom -> top
[...][c][b][a]
          __/
         |
         V
[...][c][a][b][a]
*/
func (self *DUP_X1) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot1 := stack.PopSlot()
    slot2 := stack.PopSlot()
    stack.PushSlot(slot1)
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
}

DUP_X2 :復(fù)制棧頂操作數(shù)棧的一個(gè)或兩個(gè)值,并將它們插入到操作數(shù)棧中的第三個(gè)值的下面。

/*
bottom -> top
[...][c][b][a]
       _____/
      |
      V
[...][a][c][b][a]
*/
func (self *DUP_X2) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot1 := stack.PopSlot()
    slot2 := stack.PopSlot()
    slot3 := stack.PopSlot()
    stack.PushSlot(slot1)
    stack.PushSlot(slot3)
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
}

swap指令

swap指令作用是交換棧頂?shù)膬蓚€(gè)操作數(shù)

下創(chuàng)建swap.go文件,在其中定義swap指令,代碼如下:

type SWAP struct{ base.NoOperandsInstruction }

Execute()方法如下

func (self *SWAP) Execute(frame *rtda.Frame) {
stack := frame.OperandStack()
slot1 := stack.PopSlot()
slot2 := stack.PopSlot()
stack.PushSlot(slot1)
stack.PushSlot(slot2)
}

八、數(shù)學(xué)指令

數(shù)學(xué)指令大致對(duì)應(yīng)Java語(yǔ)言中的加、減、乘、除等數(shù)學(xué)運(yùn)算符。

數(shù)學(xué)指令包括算術(shù)指令、位移指令和布爾運(yùn)算指令等,共37條,將全部在本節(jié)實(shí)現(xiàn)。

算術(shù)指令

算術(shù)指令又可以進(jìn)一步分為:

  • 加法(add)指令
  • 減法(sub)指令
  • 乘法(mul)指令
  • 除法(div)指令
  • 求余(rem)指令
  • 取反(neg)指令

加、減、乘、除和取反指令都比較簡(jiǎn)單,本節(jié)以復(fù)雜的求余指令介紹。

math目錄下創(chuàng)建rem.go文件,在其中定義4條求余指令,代碼如下:

type DREM struct{ base.NoOperandsInstruction }
type FREM struct{ base.NoOperandsInstruction }
type IREM struct{ base.NoOperandsInstruction }
type LREM struct{ base.NoOperandsInstruction }
  • DREM 結(jié)構(gòu)體:表示對(duì)雙精度浮點(diǎn)數(shù) (double) 執(zhí)行取余操作。
  • FREM 結(jié)構(gòu)體:表示對(duì)單精度浮點(diǎn)數(shù) (float) 執(zhí)行取余操作
  • IREM 結(jié)構(gòu)體:表示對(duì)整數(shù) (int) 執(zhí)行取余操作。
  • LREM 結(jié)構(gòu)體:表示對(duì)長(zhǎng)整數(shù) (long) 執(zhí)行取余操作。

iremlrem代碼差不多,以irem為例,其Execute()方法如下:

func (self *IREM) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    v2 := stack.PopInt()
    v1 := stack.PopInt()
    if v2 == 0 {
    	panic("java.lang.ArithmeticException: / by zero")
    }
    result := v1 % v2
    stack.PushInt(result)
}

先從操作數(shù)棧中彈出兩個(gè)int變量,求余,然后把結(jié)果推入操作 數(shù)棧。

注意!對(duì)int或long變量做除法和求余運(yùn)算時(shí),是有可能拋出ArithmeticException異常的。

frem和drem指令差不多,以 drem為例,其Execute()方法如下:

func (self *DREM) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    v2 := stack.PopDouble()
    v1 := stack.PopDouble()
    result := math.Mod(v1, v2)
    stack.PushDouble(result)
}

Go語(yǔ)言沒(méi)有給浮點(diǎn)數(shù)類(lèi)型定義求余操作符,所以需要使用 math包Mod()函數(shù)。

浮點(diǎn)數(shù)類(lèi)型因?yàn)橛蠭nfinity(無(wú)窮大)值,所以即使是除零,也不會(huì)導(dǎo)致ArithmeticException異常拋出

位移指令

分為左移和右移

  • 左移
  • 右移
    • 算術(shù)右移(有符號(hào)右移)
    • 邏輯右移(無(wú)符號(hào)右移)兩種。

算術(shù)右移和邏 輯位移的區(qū)別僅在于符號(hào)位的擴(kuò)展,如下面的Java代碼所示。

int x = -1;
println(Integer.toBinaryString(x)); // 11111111111111111111111111111111
println(Integer.toBinaryString(x >> 8)); // 11111111111111111111111111111111
println(Integer.toBinaryString(x >>> 8)); // 00000000111111111111111111111111

math目錄下創(chuàng)建sh.go文件,在其中定義6條 位移指令,代碼如下

type ISHL struct{ base.NoOperandsInstruction } // int左位移
type ISHR struct{ base.NoOperandsInstruction } // int算術(shù)右位移
type IUSHR struct{ base.NoOperandsInstruction } // int邏輯右位移(無(wú)符號(hào)右移位)
type LSHL struct{ base.NoOperandsInstruction } // long左位移
type LSHR struct{ base.NoOperandsInstruction } // long算術(shù)右位移
type LUSHR struct{ base.NoOperandsInstruction } // long邏輯右移位(無(wú)符號(hào)右移位)

左移

左移指令比較簡(jiǎn)單,以ishl指令為例,其Execute()方法如下:

func (self *ISHL) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    v2 := stack.PopInt()
    v1 := stack.PopInt()
    s := uint32(v2) & 0x1f
    result := v1 << s
    stack.PushInt(result)
}

先從操作數(shù)棧中彈出兩個(gè)int變量v2和v1。v1是要進(jìn)行位移操作的變量,v2指出要移位多少比特。位移之后,把結(jié)果推入操作數(shù)棧。

s := uint32(v2) & 0x1f:這行代碼將被左移的位數(shù) v2 強(qiáng)制轉(zhuǎn)換為 uint32 類(lèi)型,然后執(zhí)行按位與操作(&)與常數(shù) 0x1f
這是為了確保左移的位數(shù)在范圍 0 到 31 內(nèi),因?yàn)樵?Java 中,左移操作最多只能左移 31 位,超出這個(gè)范圍的位數(shù)將被忽略。

這里注意兩點(diǎn):

int變量只有32位,所以只取v2的前5個(gè)比特就 足夠表示位移位數(shù)了

Go語(yǔ)言位移操作符右側(cè)必須是無(wú)符號(hào) 整數(shù),所以需要對(duì)v2進(jìn)行類(lèi)型轉(zhuǎn)換

右移

算數(shù)右移

算術(shù)右移指令需要擴(kuò)展符號(hào)位,代碼和左移指令基本上差不多。以lshr指令為例,其Execute()方法如下:

func (self *LSHR) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    v2 := stack.PopInt()
    //long變量有64位,所以取v2的前6個(gè)比特。
    v1 := stack.PopLong()
    s := uint32(v2) & 0x3f
    result := v1 >> s
    stack.PushLong(result)
}

s := uint32(v2) & 0x1f:

提取 v2 變量的最低的 6 位,將其他位設(shè)置為 0,并將結(jié)果存儲(chǔ)在 s 變量中。這是為了限制右移的位數(shù)在 0 到 63 之間,因?yàn)樵?Java 中,long類(lèi)型右移操作最多只能右移 63 位

邏輯右移

無(wú)符號(hào)右移位,以iushr為例,在移位前,先將v2轉(zhuǎn)化為正數(shù),再進(jìn)行移位,最后轉(zhuǎn)化為int32類(lèi)型,如下代碼所示:

func (self *IUSHR) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    v2 := stack.PopInt()
    v1 := stack.PopInt()
    s := uint32(v2) & 0x1f
    result := int32(uint32(v1) >> s)
    stack.PushInt(result)
}

布爾運(yùn)算指令

布爾運(yùn)算指令只能操作int和long變量,分為:

  • 按位與(and)
  • 按位 或(or)
  • 按位異或(xor)

math目錄下創(chuàng)建and.go文件,在其中定義iand land指令,代碼如下:

type IAND struct{ base.NoOperandsInstruction }
type LAND struct{ base.NoOperandsInstruction }

以iand指令為例,其Execute()方法如下:

func (self *IAND) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    v2 := stack.PopInt()
    v1 := stack.PopInt()
    result := v1 & v2
    stack.PushInt(result)
}

iinc指令

iinc指令給局部變量表中的int變量增加常量值,局部變量表索引和常量值都由指令的操作數(shù)提供。

math目錄下創(chuàng)建iinc.go文件,在其中定義iinc指令,代碼如下:

type IINC struct {
    //索引
	Index uint
    //常量值
	Const int32
}
  • index:一個(gè)字節(jié),表示局部變量表中要增加值的變量的索引。這個(gè)索引指定了要修改的局部變量。
  • const:一個(gè)有符號(hào)字節(jié),表示要增加的常數(shù)值。這個(gè)常數(shù)值將與局部變量的當(dāng)前值相加,并將結(jié)果存儲(chǔ)回同一個(gè)局部變量。

FetchOperands()函數(shù)從字節(jié)碼里讀取操作數(shù),代碼如下:

func (self *IINC) FetchOperands(reader *base.BytecodeReader) {
    self.Index = uint(reader.ReadUint8())
    self.Const = int32(reader.ReadInt8())
}

Execute()方法從局部變量表中讀取變量,給它加上常量值,再把結(jié)果寫(xiě)回局部變量表,代碼如下

func (self *IINC) Execute(frame *rtda.Frame) {
    localVars := frame.LocalVars()
    val := localVars.GetInt(self.Index)
    val += self.Const
    localVars.SetInt(self.Index, val)
}

九、類(lèi)型轉(zhuǎn)換指令

類(lèi)型轉(zhuǎn)換指令大致對(duì)應(yīng)Java語(yǔ)言中的基本類(lèi)型強(qiáng)制轉(zhuǎn)換操作。 類(lèi)型轉(zhuǎn)換指令有共15條,將全部在本節(jié)實(shí)現(xiàn)。

引用類(lèi)型轉(zhuǎn)換對(duì)應(yīng)的是checkcast指令,將在后續(xù)完成。

類(lèi)型轉(zhuǎn)換指令根據(jù)被轉(zhuǎn)換變量的類(lèi)型分為四種系列:

  • i2x 系列指令:這些指令將整數(shù)(int)變量強(qiáng)制轉(zhuǎn)換為其他類(lèi)型。
  • l2x 系列指令:這些指令將長(zhǎng)整數(shù)(long)變量強(qiáng)制轉(zhuǎn)換為其他類(lèi)型。
  • f2x 系列指令:這些指令將浮點(diǎn)數(shù)(float)變量強(qiáng)制轉(zhuǎn)換為其他類(lèi)型。
  • d2x 系列指令:這些指令將雙精度浮點(diǎn)數(shù)(double)變量強(qiáng)制轉(zhuǎn)換為其他類(lèi)型。

這些類(lèi)型轉(zhuǎn)換指令允許將不同類(lèi)型的數(shù)據(jù)進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換,以滿足特定的計(jì)算或操作需求。

d2x系列指令為例進(jìn)行討論。

conversions目錄下創(chuàng)建d2x.go文件,在其中 定義d2f、d2i和d2l指令,代碼如下

type D2F struct{ base.NoOperandsInstruction }
type D2I struct{ base.NoOperandsInstruction }
type D2L struct{ base.NoOperandsInstruction }

d2i指令為例,它的Execute()方法如下:

func (self *D2I) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    d := stack.PopDouble()
    i := int32(d)
    stack.PushInt(i)
}

因?yàn)镚o語(yǔ)言可以很方便地轉(zhuǎn)換各種基本類(lèi)型的變量,所以類(lèi)型轉(zhuǎn)換指令實(shí)現(xiàn)起來(lái)還是比較容易的。

十、比較指令

比較指令可以分為兩類(lèi):

  • 將比較結(jié)果推入操作數(shù)棧頂
  • 根據(jù)比較結(jié)果跳轉(zhuǎn)

比較指令是編譯器實(shí)現(xiàn)if-else、for、while等語(yǔ)句的基石,共有19條

lcmp指令

lcmp指令用于比較long變量。

comparisons目錄下創(chuàng)建lcmp.go文件,在其中定義lcmp指令,代碼如下:

type LCMP struct{ base.NoOperandsInstruction }

Execute()方法把棧頂?shù)膬蓚€(gè)long變量彈出,進(jìn)行比較,然后把比較結(jié)果(int型0、1或-1)推入棧頂,代碼如下:

func (self *LCMP) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	v2 := stack.PopLong()
	v1 := stack.PopLong()
	if v1 > v2 {
		stack.PushInt(1)
	} else if v1 == v2 {
		stack.PushInt(0)
	} else {
		stack.PushInt(-1)
	}
}

fcmp和dcmp指令

fcmpgfcmpl指令用于比較float變量,它們的區(qū)別是對(duì)于非數(shù)字參與,fcmpg會(huì)默認(rèn)為其大于任何非NaN值,fcmpl則相反。

comparisons目錄下創(chuàng)建fcmp.go文件,在其中定義 fcmpgfcmpl指令,代碼如下:

type FCMPG struct{ base.NoOperandsInstruction }
type FCMPL struct{ base.NoOperandsInstruction }

由于浮點(diǎn)數(shù)計(jì)算有可能產(chǎn)生NaN(Not a Number)值,所以比較兩個(gè)浮點(diǎn)數(shù)時(shí),除了大于、等于、小于之外,
還有第4種結(jié)果:無(wú)法比較。

編寫(xiě)一個(gè)函數(shù)來(lái)統(tǒng)一比較float變量,如下:

func _fcmp(frame *rtda.Frame, gFlag bool) {
	stack := frame.OperandStack()
	v2 := stack.PopFloat()
	v1 := stack.PopFloat()
	if v1 > v2 {
		stack.PushInt(1)
	} else if v1 == v2 {
		stack.PushInt(0)
	} else if v1 < v2 {
		stack.PushInt(-1)
	} else if gFlag {
		stack.PushInt(1)
	} else {
		stack.PushInt(-1)
	}
}

Java虛擬機(jī)規(guī)范:浮點(diǎn)數(shù)比較指令 fcmplfcmpg 的規(guī)范要求首先彈出 v2,然后是 v1,以便進(jìn)行浮點(diǎn)數(shù)比較。

Execute()如下:

func (self *FCMPG) Execute(frame *rtda.Frame) {
    _fcmp(frame, true)
}
func (self *FCMPL) Execute(frame *rtda.Frame) {
    _fcmp(frame, false)
}

if<cond>指令

if<cond> 指令是 Java 字節(jié)碼中的條件分支指令,它根據(jù)條件 <cond> 來(lái)執(zhí)行不同的分支。
條件 <cond> 可以是各種比較操作,比如等于、不等于、大于、小于等等。

常見(jiàn)的 if<cond> 指令包括:

  • ifeq: 如果棧頂?shù)闹档扔?,則跳轉(zhuǎn)。
  • ifne: 如果棧頂?shù)闹挡坏扔?,則跳轉(zhuǎn)。
  • iflt: 如果棧頂?shù)闹敌∮?,則跳轉(zhuǎn)。
  • ifge: 如果棧頂?shù)闹荡笥诨虻扔?,則跳轉(zhuǎn)。
  • ifgt: 如果棧頂?shù)闹荡笥?,則跳轉(zhuǎn)。
  • ifle: 如果棧頂?shù)闹敌∮诨虻扔?,則跳轉(zhuǎn)。

創(chuàng)建ifcond.go文件,在其中定義6條if指令,代碼如下:

type IFEQ struct{ base.BranchInstruction }
type IFNE struct{ base.BranchInstruction }
type IFLT struct{ base.BranchInstruction }
type IFLE struct{ base.BranchInstruction }
type IFGT struct{ base.BranchInstruction }
type IFGE struct{ base.BranchInstruction }

ifeq指令為例,其Execute()方法如下:

func (self *IFEQ) Execute(frame *rtda.Frame) {
    val := frame.OperandStack().PopInt()
    if val == 0 {
    	base.Branch(frame, self.Offset)
	}
}

真正的跳轉(zhuǎn)邏輯在Branch()函數(shù)中。因?yàn)檫@個(gè)函數(shù)在很多指令中都會(huì)用到,所以定義在base\branch_logic.go 文件中,代碼如下:

func Branch(frame *rtda.Frame, offset int) {
	pc := frame.Thread().PC()
	nextPC := pc + offset
	frame.SetNextPC(nextPC)
}

if_icmp<cond>指令

if_icmp<cond> 指令是 Java 字節(jié)碼中的一類(lèi)條件分支指令,它用于對(duì)比兩個(gè)整數(shù)值,根據(jù)比較的結(jié)果來(lái)執(zhí)行條件分支。這些指令的操作數(shù)棧上通常有兩個(gè)整數(shù)值,它們分別用于比較。

這類(lèi)指令包括:

  • if_icmpeq: 如果兩個(gè)整數(shù)相等,則跳轉(zhuǎn)。
  • if_icmpne: 如果兩個(gè)整數(shù)不相等,則跳轉(zhuǎn)。
  • if_icmplt: 如果第一個(gè)整數(shù)小于第二個(gè)整數(shù),則跳轉(zhuǎn)。
  • if_icmpge: 如果第一個(gè)整數(shù)大于等于第二個(gè)整數(shù),則跳轉(zhuǎn)。
  • if_icmpgt: 如果第一個(gè)整數(shù)大于第二個(gè)整數(shù),則跳轉(zhuǎn)。
  • if_icmple: 如果第一個(gè)整數(shù)小于等于第二個(gè)整數(shù),則跳轉(zhuǎn)。

創(chuàng)建if_icmp.go文件,在 其中定義6條if_icmp指令,代碼如下:

type IF_ICMPEQ struct{ base.BranchInstruction }
type IF_ICMPNE struct{ base.BranchInstruction }
type IF_ICMPLT struct{ base.BranchInstruction }
type IF_ICMPLE struct{ base.BranchInstruction }
type IF_ICMPGT struct{ base.BranchInstruction }
type IF_ICMPGE struct{ base.BranchInstruction }

以if_icmpne指令 為例,其Execute()方法如下:

func (self *IF_ICMPNE) Execute(frame *rtda.Frame) {
    if val1, val2 := _icmpPop(frame); val1 != val2 {
       base.Branch(frame, self.Offset)
    }
}
func _icmpPop(frame *rtda.Frame) (val1, val2 int32) {
	stack := frame.OperandStack()
	val2 = stack.PopInt()
	val1 = stack.PopInt()
	return
}

if_acmp<cond>指令

if_acmp<cond> 指令是 Java 字節(jié)碼中的一類(lèi)條件分支指令,用于比較兩個(gè)引用類(lèi)型的對(duì)象引用,根據(jù)比較的結(jié)果來(lái)執(zhí)行條件分支。這些指令的操作數(shù)棧上通常有兩個(gè)對(duì)象引用,它們分別用于比較。

這類(lèi)指令包括:

  • if_acmpeq: 如果兩個(gè)引用相等,則跳轉(zhuǎn)。
  • if_acmpne: 如果兩個(gè)引用不相等,則跳轉(zhuǎn)。

創(chuàng)建if_acmp.go文件,在 其中定義兩條if_acmp指令,代碼如下:

type IF_ACMPEQ struct{ base.BranchInstruction }
type IF_ACMPNE struct{ base.BranchInstruction }

以if_acmpeq指令為例,其Execute()方法如下:

func (self *IF_ACMPEQ) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    ref2 := stack.PopRef()
    ref1 := stack.PopRef()
    if ref1 == ref2 {
    	base.Branch(frame, self.Offset)
    }
}

十一、控制指令

  • 控制指令共有 11 條。
  • 在 Java 6 之前,jsrret 指令用于實(shí)現(xiàn) finally 子句。從 Java 6 開(kāi)始,Oracle 的 Java 編譯器不再使用這兩條指令。
  • return 系列指令有 6 條,用于從方法調(diào)用中返回,將在后續(xù)實(shí)現(xiàn)。
  • 本節(jié)將實(shí)現(xiàn)剩下的 3 條指令:gototableswitchlookupswitch

這些指令用于控制程序執(zhí)行流,包括條件分支和無(wú)條件跳轉(zhuǎn)等操作。其中,goto 用于無(wú)條件跳轉(zhuǎn)到指定的目標(biāo)位置,而 tableswitchlookupswitch 用于根據(jù)條件跳轉(zhuǎn)到不同的目標(biāo)位置。

control目錄下創(chuàng)建goto.go文件,在其中定義 goto指令,代碼如下:

總結(jié)

以上是生活随笔為你收集整理的Golang实现JAVA虚拟机-指令集和解释器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

午夜精品一区二区三区免费视频 | 97热在线观看 | 91在线小视频 | 在线观看av免费 | 丁香六月在线观看 | 久久综合久久综合这里只有精品 | 中文字幕综合在线 | 日日摸日日添夜夜爽97 | 狠狠干,狠狠操 | 中文字幕av电影下载 | 国产一区在线观看视频 | 亚洲精品欧洲精品 | 久久国产色 | 久久一区二区三区超碰国产精品 | 国产精品国产三级国产aⅴ入口 | 91传媒视频在线观看 | 婷五月天激情 | 天堂av在线网址 | 亚洲精品国产成人av在线 | 国产精品v a免费视频 | 久久99精品久久久久久久久久久久 | 成人av午夜 | 91女人18片女毛片60分钟 | 亚洲午夜不卡 | 欧美黑人巨大xxxxx | 成人在线观看免费视频 | 亚洲成人av在线 | www.黄色 | 91av成人 | 亚洲国产欧洲综合997久久, | 久久亚洲婷婷 | 夜添久久精品亚洲国产精品 | 一区二区三区免费在线观看视频 | 69热国产视频 | 国产一线二线三线性视频 | 在线蜜桃视频 | 欧美精品亚洲二区 | 国产精品自产拍在线观看网站 | 日本公妇在线观看高清 | 久草资源在线观看 | 日韩欧美亚州 | 999成人网 | 婷婷丁香激情网 | 国产亚洲视频系列 | 久久av在线播放 | 欧美日韩免费观看一区二区三区 | 亚洲综合成人婷婷小说 | 亚洲精品网页 | 97视频在线观看视频免费视频 | 久久久免费观看视频 | 在线观看一区二区精品 | 在线免费观看视频a | 色视频在线观看 | 一区二区视频网站 | 国产精品电影一区二区 | 日本中文一区二区 | 日韩免| 中文字幕日韩电影 | 亚洲精品资源 | 97国产精品久久 | 日韩中文字幕在线不卡 | 最新日韩视频在线观看 | 国产精品毛片久久蜜 | 手机av观看 | 日韩色综合网 | 天天操福利视频 | 亚洲经典视频在线观看 | 日日久视频 | 又色又爽又黄高潮的免费视频 | 在线免费观看黄色小说 | 国产精品一区二区无线 | 久久综合狠狠综合久久激情 | 日韩精品91偷拍在线观看 | 国产黄色片免费观看 | 中文字幕中文中文字幕 | 亚洲精品乱码久久久久久9色 | 黄a网站 | 在线观看免费国产小视频 | 婷婷精品| 久久公开免费视频 | 九色91在线视频 | 丁香五月网久久综合 | 黄色视屏av | 成人a级黄色片 | av手机在线播放 | 国产精品毛片一区二区三区 | 亚洲精品在线资源 | 久久激情视频免费观看 | 黄色免费国产 | 99在线高清视频在线播放 | 亚洲最大av | 亚洲精品国产精品乱码在线观看 | 日韩免费中文 | 国产操在线 | 人人澡人人添人人爽一区二区 | 欧美激情第一页xxx 午夜性福利 | 四虎最新域名 | 日本成人黄色片 | 日韩午夜精品 | 亚洲精品成人 | 国产黄视频在线观看 | 在线视频精品 | 久久精品国产免费 | 日韩极品视频在线观看 | 黄色小说网站在线 | 亚洲精品高清一区二区三区四区 | 91丨九色丨丝袜 | 黄色小说免费在线观看 | 日韩高清免费在线观看 | 国产夫妻自拍av | 五月婷婷导航 | 精品色综合 | 国产成人久久久77777 | 国产无套精品久久久久久 | 色婷婷在线观看视频 | 久久欧美视频 | 国产在线一区二区三区播放 | 最新av在线免费观看 | 欧美视屏一区二区 | 亚洲www天堂com | 四虎天堂 | 成人国产精品一区二区 | 久久精品一二区 | 久久久精品免费观看 | 黄污网站在线 | 最新91在线视频 | 伊人va| 超碰人人国产 | 伊人久久国产 | 久久一精品 | 91精品啪在线观看国产线免费 | 青春草免费视频 | 99热.com | 91综合色 | 美女av免费看 | 欧美一级高清片 | 91免费高清在线观看 | 在线观看视频你懂得 | 国产成人精品av | 自拍超碰在线 | 天天夜操| 久久香蕉电影 | 丁香婷婷色综合亚洲电影 | 国产精品国产三级国产aⅴ入口 | 久久精品之 | 99精品免费网 | 香蕉91视频| 一级a性色生活片久久毛片波多野 | 国产在线高清精品 | 美女免费黄视频网站 | 亚洲成人精品久久 | 干综合网 | 97精品视频在线播放 | 成人一区二区三区中文字幕 | 久久夜av | 精品国产福利在线 | 欧美福利精品 | 亚洲一区二区三区毛片 | 亚洲国产三级在线 | 韩国在线视频一区 | 久久精品免费看 | 中文字幕av免费 | 成年人看片 | 日本中文字幕系列 | bbb搡bbb爽爽爽 | 久久观看免费视频 | 亚洲精品成人 | 看国产黄色片 | 国产黄色视 | 99久久精品免费看国产麻豆 | 国产第一福利 | 欧美日韩二三区 | 爱射综合 | 国产精品久久一区二区三区不卡 | 四虎影视成人永久免费观看视频 | 一区二区三区在线观看免费视频 | 亚洲毛片一区二区三区 | 超碰在线人人97 | 干 操 插 | 夜夜爽88888免费视频4848 | 丝袜精品视频 | 欧美日韩国产高清视频 | 天天艹日日干 | 99麻豆视频 | 精品v亚洲v欧美v高清v | 成人精品在线 | 色综合久久88色综合天天人守婷 | 欧美成天堂网地址 | 日本中文字幕网址 | 色中色资源站 | 国产不卡在线观看 | 九九热在线免费观看 | 91av在线免费播放 | av免费黄色| 成人在线免费视频观看 | 欧美成人视 | 97在线观看 | 久久久久美女 | 午夜久操| 国产网红在线 | 韩日精品在线 | 9在线观看免费高清完整版在线观看明 | 久久久精品影视 | 久久精品99北条麻妃 | 手机在线小视频 | 免费视频成人 | 伊人电影在线观看 | 国产视频综合在线 | 国产伦精品一区二区三区免费 | 91喷水 | 国产高清在线 | 高清一区二区三区 | 九九欧美视频 | 欧美日韩视频在线一区 | 亚洲色图美腿丝袜 | 在线看欧美 | 久久天天操 | 青青河边草免费直播 | 免费在线黄 | 一区二区三区电影 | 亚洲黄色app | 麻豆国产露脸在线观看 | 国产高清视频在线播放一区 | 视频国产精品 | 在线 视频 一区二区 | 天天射天天色天天干 | 国产婷婷色| 97视频精品| 成人国产在线 | 日韩av电影一区 | www亚洲国产 | 看片一区二区三区 | 日韩一区二区在线免费观看 | 中文字幕在线观看完整版电影 | 日韩理论在线视频 | 99久久精品免费看国产 | 成人h在线播放 | 免费高清无人区完整版 | 日本久久免费电影 | 国产专区日韩专区 | 久久久精品网站 | 久色网| 国产精品毛片久久久久久久久久99999999 | 亚洲午夜av电影 | 91视频这里只有精品 | 另类老妇性bbwbbw高清 | 亚洲综合视频在线 | 成人黄色电影免费观看 | 日韩精品免费一区二区三区 | 毛片永久免费 | 国产免费黄视频在线观看 | 麻豆播放 | 精品国产乱码久久 | 天天干天天操天天射 | 99精品国产兔费观看久久99 | 日韩在线观看a | 91在线最新 | 国产91aaa| 国产在线不卡视频 | 亚洲mv大片欧洲mv大片免费 | 久久爱综合 | 最新动作电影 | 精品人妖videos欧美人妖 | 欧美日韩网站 | 日韩精品一区在线观看 | 国产麻豆视频网站 | 天天要夜夜操 | 成人av免费在线播放 | 99久久99久国产黄毛片 | 久久久久久久久久久影院 | 国产美女被啪进深处喷白浆视频 | 日本韩国精品一区二区在线观看 | 国产精品毛片一区二区在线 | 国产精品大片在线观看 | 国产在线观看不卡 | 美女免费网站 | 免费看黄色大全 | 香蕉视频在线免费 | 99 久久久久| 午夜电影久久 | 久久这里只有精品视频首页 | 亚洲三级视频 | 亚洲自拍偷拍色图 | 国产一区二区在线观看视频 | 日韩久久激情 | 91精品一区二区三区蜜臀 | 成x99人av在线www | 国产精品一区二区三区99 | 色网免费观看 | 国内精品久久久 | 国产精品久久影院 | 欧美日本不卡视频 | 五月婷婷综合网 | 开心色激情网 | 久久久久久久久电影 | 婷婷久月 | 国产伦理精品一区二区 | 国产精品美女久久久久久久网站 | 国产视频久久 | 成人a视频片观看免费 | 久草在线资源观看 | 国产精品1区2区 | 中文字幕一区二区三区四区 | 成人黄色电影在线播放 | 国产亚洲字幕 | 91视频 - 114av | 国产精品亚洲a | 欧美日产在线观看 | 免费aa大片 | 婷婷久久网 | 国产精品av在线 | 日本精a在线观看 | 午夜123| 欧美日韩一区久久 | 一级黄视频 | 国产人免费人成免费视频 | 中文字幕在线视频一区 | 久久免费播放视频 | 亚洲激情在线播放 | 久草青青在线观看 | 免费看黄色大全 | 亚洲精品在线观看的 | 五月婷婷激情六月 | a级黄色片视频 | 国产日产精品一区二区三区四区的观看方式 | 最近日本中文字幕 | 91网址在线看 | av黄色影院 | 久久国产二区 | 狠狠操操网 | 日韩免费三级 | 97成人免费视频 | 人人插人人 | 亚洲婷婷免费 | 欧美视频国产视频 | 激情综合啪 | 久久精品国产成人 | 911精品美国片911久久久 | 天天操天 | 五月天色综合 | 欧美精品一区二区性色 | 91重口视频 | 亚洲伊人网在线观看 | 天天综合网 天天 | 狠狠狠狠狠狠操 | 亚洲精品9 | 在线免费观看黄色av | 亚洲人久久久 | 天天操婷婷| 色综合天天干 | 中文字幕高清视频 | 九九九热精品免费视频观看 | 亚洲国产精品电影 | 五月天久久狠狠 | 黄色一级免费网站 | 一级黄色片在线免费看 | 国产在线观看你懂得 | 狠狠久久伊人 | 91试看 | 91在线www| 亚洲另类交 | 成人国产在线 | 99视频+国产日韩欧美 | 色婷婷啪啪免费在线电影观看 | 99re国产视频 | 亚洲撸撸 | 欧美一区二区在线 | 人人擦 | 中文日韩在线视频 | 国产精品成人a免费观看 | 免费男女羞羞的视频网站中文字幕 | 日韩欧美黄色网址 | 免费久草视频 | 亚洲欧美国产精品久久久久 | 国产福利91精品一区 | 亚洲精品综合在线观看 | 区一区二在线 | 热久久精品在线 | 国产 亚洲 欧美 在线 | 日韩中文三级 | 伊人影院在线观看 | 国产高清一 | 精品一区二区6 | 亚洲精品午夜国产va久久成人 | 97国产情侣爱久久免费观看 | 中文字幕一区在线观看视频 | 最近中文字幕大全 | 国产午夜三级一区二区三 | 麻豆视频免费 | 天天爽夜夜爽人人爽一区二区 | 国产精品18久久久久久首页狼 | 亚洲五月婷 | 亚洲一区黄色 | 99视频精品视频高清免费 | 日韩精品视 | 日韩精品免费在线观看视频 | 亚洲精品五月天 | 亚洲精品麻豆 | 日韩伦理一区二区三区av在线 | 亚洲精品综合一二三区在线观看 | 亚州成人av在线 | 91大神精品视频在线观看 | 国产在线视频导航 | 亚洲综合干 | 精品国产1区二区 | 亚洲免费av一区二区 | 天天干天天爽 | 九九热精 | 久久久久久久久久久久av | 亚洲精品无 | av先锋中文字幕 | 在线观看精品黄av片免费 | 久草视频首页 | 91麻豆免费视频 | 亚洲美女在线国产 | 99人久久精品视频最新地址 | 日韩电影精品一区 | 91污视频在线观看 | 五月婷婷黄色网 | 国产九九在线 | 99在线精品视频 | 99久久影院| 天天射天天射天天 | 97人人澡人人爽人人模亚洲 | 久久免费视频在线观看30 | 久久久91精品国产一区二区精品 | 在线观看自拍 | 成年人视频在线免费观看 | 日韩免费一区 | 狠狠干在线播放 | 丁香九月婷婷综合 | 精品国产伦一区二区三区观看说明 | 国产不卡av在线 | av 一区二区三区四区 | aaa免费毛片 | 国产精品久久久久久久久岛 | 91九色老 | 色婷婷婷| 欧美另类v | 国产一区在线视频 | 成人亚洲精品久久久久 | 91xav | 五月婷婷深开心 | 五月开心激情 | 中文字幕成人网 | 一级久久久 | 精品久久久久久综合日本 | 久久电影日韩 | 久久久久网站 | 999久久国精品免费观看网站 | 中文字幕在线观看第一区 | h动漫中文字幕 | 深爱激情站 | 日日日日日 | 亚洲国产资源 | 区一区二区三在线观看 | 毛片3| 精品播放| 久久无码av一区二区三区电影网 | 91高清在线 | 麻豆视频免费网站 | 国产色婷婷精品综合在线手机播放 | 午夜精品视频在线 | 在线不卡a | 精品一区二区三区在线播放 | 婷婷九九 | 91视频啪| 亚洲欧美一区二区三区孕妇写真 | 国产日韩视频在线 | 天天干天天天天 | 日韩欧美大片免费观看 | 黄色一级大片在线免费看产 | 亚洲爱爱视频 | 国产在线自 | 看全黄大色黄大片 | 国产va精品免费观看 | 黄色免费看片网站 | 久久婷婷丁香 | 日韩欧美高清不卡 | 在线a视频免费观看 | 日韩精品免费一区二区在线观看 | 在线观看免费黄视频 | 亚洲最新视频在线播放 | 午夜精品视频免费在线观看 | 久久久久久国产一区二区三区 | 国产在线观看91 | 国产网红在线观看 | 免费看十八岁美女 | 精品久久久久一区二区国产 | 欧美日韩国产一区二 | 国产精品一区二区三区在线播放 | 午夜精品av在线 | 日韩在线视 | 国产高清在线永久 | 国产精品久久9 | 久草免费色站 | 亚洲欧美一区二区三区孕妇写真 | 97在线免费观看 | 久久激情视频网 | 欧美精品亚州精品 | 日韩精品一区二区三区水蜜桃 | 日韩欧美视频免费在线观看 | 黄网站免费看 | 黄色a视频免费 | 色成人亚洲网 | 日韩欧美在线不卡 | 中文字幕在线观看播放 | 免费高清在线观看成人 | 精品一区中文字幕 | 天天玩天天干天天操 | 久免费 | 国产精品你懂的在线观看 | 麻豆视传媒官网免费观看 | 久久视频这里有久久精品视频11 | 亚洲人人爱| 国产精品久久久久久久免费观看 | 九色91在线 | 干av在线 | 成人av中文字幕在线观看 | 亚洲欧洲av | 成人午夜电影网 | 国产一级视屏 | 欧美另类高潮 | 欧美在线一二 | av一区二区三区在线 | 在线视频观看国产 | 久久久久 | 四虎视频 | 青草草在线 | 久久一级电影 | 国产一区麻豆 | 免费在线观看亚洲视频 | 99爱视频在线观看 | 97精品国产97久久久久久粉红 | 91九色成人| 黄色大全免费网站 | 日本mv大片欧洲mv大片 | 亚洲 欧美日韩 国产 中文 | 国产成人精品一区二区在线 | 97超碰人人澡人人爱 | 欧美一级专区免费大片 | 国产视频99| 精品国产综合区久久久久久 | 欧美国产不卡 | 九九热久久久 | 91精品一区二区在线观看 | 人人澡人人爽欧一区 | 亚洲影院一区 | 成人午夜电影在线观看 | 欧美日韩精品在线 | 超碰97国产精品人人cao | av在线亚洲天堂 | 夜夜澡人模人人添人人看 | 99视频精品在线 | 久久久久伊人 | 操操操com | 日韩视频免费 | 国产精品美女久久 | 免费国产一区二区 | 国产精品99久久久久久武松影视 | 91丨九色丨国产丨porny精品 | 国产精品区一区 | 九色91av| 99在线视频精品 | 精品久久久久久久久久国产 | 久久久久综合网 | 日韩69av | 91理论电影 | 午夜精品视频福利 | 视频国产在线观看18 | 国产精品视频线看 | 久久久久蜜桃 | 亚洲美女免费精品视频在线观看 | 久草视频观看 | 91成人免费视频 | 精品亚洲欧美无人区乱码 | av丝袜美腿| 久久99国产精品二区护士 | 麻花豆传媒mv在线观看网站 | 免费在线观看黄网站 | 国产又粗又猛又爽又黄的视频先 | 国产精品久久久久久久午夜 | 特级黄色电影 | 日本性xxx| 黄色免费大全 | 天天玩天天干天天操 | 中文字幕免费高清 | 午夜精品一区二区三区免费视频 | 丁香花五月 | 国产999精品久久久 免费a网站 | 极品久久久 | 国内精品久久久久影院一蜜桃 | 精品久久久久久久久久国产 | 天天干,天天干 | 久久国产热视频 | 开心色激情网 | 狠狠色丁香婷婷综合久小说久 | 久草精品视频 | 国产精品一区在线 | 91xav| 国产不卡网站 | 精品国产一区二区三区久久久 | 久久精品这里热有精品 | 精品国产精品久久一区免费式 | 久久久久久久久久影院 | 久久久久久麻豆 | 久久久久国产精品www | 日韩精品视频在线观看免费 | 日韩欧美区 | 狠狠综合网 | 99c视频在线 | 天天天插 | 青青河边草免费 | 亚洲第一久久久 | 奇米导航| 国产91粉嫩白浆在线观看 | 日韩免费看视频 | 四虎影院在线观看av | 久久电影网站中文字幕 | 久久综合九色综合久久久精品综合 | 日韩mv欧美mv国产精品 | 热久久视久久精品18亚洲精品 | 精品毛片一区二区免费看 | 久久久久北条麻妃免费看 | 久久久综合电影 | 青青河边草免费直播 | 99久久久久久 | 国产一级免费电影 | 97视频在线观看免费 | 深夜免费网站 | 日韩有码在线播放 | 在线 国产 亚洲 欧美 | 99精品黄色片免费大全 | 麻豆系列在线观看 | 欧美一级裸体视频 | 手机av片 | 伊人伊成久久人综合网小说 | 91成人小视频 | 国产伦理一区二区三区 | 成人综合免费 | h网站免费在线观看 | 久草在线免费资源 | 手机在线黄色网址 | 久产久精国产品 | 日日干夜夜爱 | 久久69精品 | 黄色小说18 | 午夜精品99久久免费 | 狠狠操综合 | 成人国产一区 | 日韩高清不卡一区二区三区 | 黄色av一区二区三区 | 色婷婷激婷婷情综天天 | 亚州日韩中文字幕 | 久久免费视频在线观看 | 久久精品视频在线观看 | 91精品一区二区三区蜜桃 | 亚洲精品福利在线 | 麻豆系列在线观看 | 国产精品一区二区在线观看免费 | 天天综合网久久 | 亚洲欧美日韩国产一区二区三区 | 欧美激情精品久久久久久免费印度 | 精品二区久久 | 国产精品免费观看国产网曝瓜 | 九九九热精品免费视频观看 | 亚洲欧美视屏 | 狠狠狠狠狠狠 | 欧美成天堂网地址 | 在线观看一级片 | 精品日韩视频 | 五月婷网站 | 中文字幕韩在线第一页 | 九九热国产视频 | 国产精品va | 亚洲激情一区二区三区 | 日韩av一区在线观看 | 888av| 丁香在线观看完整电影视频 | 亚洲国产成人久久 | 久草视频在线免费播放 | 色综合久久久久久中文网 | 国产欧美精品xxxx另类 | 女人高潮特级毛片 | 午夜视频免费 | 成人精品国产 | 精产嫩模国品一二三区 | av网站免费在线 | 亚洲永久免费av | 狠狠干夜夜操天天爽 | 伊人中文在线 | 亚洲成熟女人毛片在线 | 日本三级吹潮在线 | 久久成电影| 久草电影在线 | 婷婷性综合 | 成人黄色中文字幕 | 在线视频免费观看 | 国产精品久久久久一区二区三区共 | 国精产品一二三线999 | 美女网站在线免费观看 | 超碰97免费| 国产一区二区手机在线观看 | 国产 一区二区三区 在线 | 91精品在线免费观看视频 | 91精品老司机久久一区啪 | 欧美午夜寂寞影院 | 久草网站 | 69亚洲视频 | 久久视频网| 国产色在线视频 | 少妇bbbb搡bbbb桶 | 在线亚洲激情 | 美女免费视频网站 | 欧美性色综合网站 | 成人综合免费 | 91探花国产综合在线精品 | 国产高清日韩欧美 | 日韩中文字幕网站 | 午夜黄色影院 | 欧美地下肉体性派对 | 在线之家免费在线观看电影 | 在线观看视频亚洲 | 午夜国产福利视频 | 精品99在线观看 | 国产在线视频一区二区 | 欧美日韩破处 | 欧美动漫一区二区三区 | 视频国产精品 | 亚洲成人欧美 | 国产剧情在线一区 | 久久午夜色播影院免费高清 | 免费网站黄 | 久综合网 | 97超级碰碰碰碰久久久久 | 欧美激情视频一区二区三区免费 | av在线播放快速免费阴 | 国产精品一区二区三区视频免费 | 久久免费黄色网址 | 亚洲乱码精品 | 天天综合导航 | 国产在线播放观看 | 高清av免费看 | 日韩精品久久一区二区三区 | 欧美色图30p | 色播六月天 | 日韩色一区二区三区 | 国产69精品久久久久久久久久 | 麻豆传媒视频在线播放 | 成人免费观看网站 | 天天综合网在线观看 | 国产精品毛片一区二区 | 国语精品视频 | 超碰国产在线播放 | 午夜精品剧场 | 在线成人观看 | 国产精品美女www爽爽爽视频 | 在线免费观看的av | 97视频在线观看视频免费视频 | 色网av| 黄色免费av | 91精品影视| 在线精品视频免费播放 | 国产免费观看高清完整版 | 国产精品久久久久久久久久久久午 | 久久开心激情 | 天天射一射 | 黄色com | 天天色天天射天天干 | 中文在线中文资源 | 夜夜躁日日躁狠狠久久88av | 中文字幕在线播放一区二区 | 在线观看日本高清mv视频 | 韩国视频一区二区三区 | 四虎影视精品永久在线观看 | 免费色婷婷 | 99精品一区二区三区 | 日本黄区免费视频观看 | 国产精品久久久久久久久岛 | 91精品亚洲影视在线观看 | 色视频在线| 久久极品 | 久久66热这里只有精品 | 激情欧美一区二区三区免费看 | 在线之家免费在线观看电影 | 日韩高清国产精品 | 91大神免费在线观看 | 久久www免费人成看片高清 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 在线观看国产福利片 | 免费看搞黄视频网站 | 日韩二区三区在线观看 | 玖玖爱免费视频 | 香蕉视频在线观看免费 | 高清av免费看 | 国产伦精品一区二区三区照片91 | 色婷婷在线观看视频 | 国产成人精品一区二区三区在线观看 | 色婷婷丁香 | 手机看片国产日韩 | 日韩中文字幕免费电影 | 六月丁香激情网 | 久草久草久草久草 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 特黄特色特刺激视频免费播放 | 久久久久久久久久久久久久av | 国产精品久久久久久久久搜平片 | 黄污污网站 | 视频一区二区国产 | 欧美日韩在线观看一区二区三区 | 在线 你懂 | 天天干天天做天天操 | 午夜久久电影网 | 久久中文字幕在线视频 | 天天插综合 | 午夜视频导航 | 91cn国产在线| 激情五月伊人 | 色吊丝在线永久观看最新版本 | 香蕉视频在线免费 | 最近中文字幕高清字幕在线视频 | 久久久黄色免费网站 | 成人在线视频一区 | 九九精品久久久 | 中文字幕一区在线观看视频 | 久久婷综合 | 在线观看爱爱视频 | 日韩欧美在线观看一区二区 | a在线视频v视频 | av电影 一区二区 | 久久综合五月天婷婷伊人 | 天堂久色| 午夜视频播放 | 婷婷激情av| 久久五月情影视 | 91麻豆精品国产自产在线游戏 | 国产中文字幕视频 | 亚洲春色综合另类校园电影 | 免费在线观看成人 | .国产精品成人自产拍在线观看6 | 国产精品久久久久久久久毛片 | 91久久奴性调教 | 久草免费色站 | 99久久999久久久精玫瑰 | 免费看一及片 | 国产97在线观看 | 欧美 国产 视频 | 九九久| 欧美成人久久 | 中文字幕综合在线 | 91看片在线观看 | 日韩在线精品视频 | 天天操天天干天天操天天干 | 一区二区三区免费看 | av在线中文 | 黄色小网站在线观看 | 中文字幕在线免费观看 | 亚洲人人爱 | 亚洲精品婷婷 | 欧美激情第一区 | 97人人模人人爽人人喊中文字 | 日韩欧美视频免费在线观看 | 91精品啪在线观看国产线免费 | 91免费在线看片 | 2020天天干夜夜爽 | 在线色吧 | 国产视频在线观看免费 | 中文字幕在线看视频 | 99自拍视频在线观看 | 中文字幕在线看视频 | 成人丁香花 | 国产破处精品 | 久久涩视频 | 激情xxxx| 久久美女视频 | 久久99电影 | 国产美腿白丝袜足在线av | 久草在线免费看视频 | 国内久久精品 | 黄色av观看| 麻豆传媒视频在线播放 | 九九在线视频 | 中日韩在线视频 | 免费一区在线 | 国产精彩视频一区二区 | 人人玩人人添人人澡97 | 美国三级黄色大片 | 久久精品国产第一区二区三区 | 国产精品二区三区 | 少妇高潮冒白浆 | 少妇性aaaaaaaaa视频 | 国产一级免费观看 | wwwwww黄| 日韩性久久 | 免费高清在线观看成人 | 中文字幕视频网 | 国产午夜一区二区 | 五月婷婷电影网 | 国内精品久久久久影院日本资源 | 中文字幕一区二区三区四区 | 99热日本| 在线电影日韩 | av高清免费 | 四虎5151久久欧美毛片 | 婷婷在线精品视频 | 国产精品xxxx18a99| 久久网站av| 国产涩涩网站 | 久久这里只有精品久久 | 999久久a精品合区久久久 | 免费人成在线观看网站 | 亚洲视频h | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 日本中文字幕在线观看 | 国产一区二区三区高清播放 | 五月色婷| 国产成人精品综合久久久 | 黄色片视频在线观看 | 成人看片 | 欧美日韩性视频 | 中文不卡视频在线 | 91精品国产三级a在线观看 | 国产91精品久久久久久 | 欧美va天堂va视频va在线 | 狠狠色免费 | 日韩在线三区 | 精品久久久久久亚洲综合网站 | 全久久久久久久久久久电影 | 欧美伦理一区 | 天天干,夜夜操 | 欧美一区,二区 | 天天操操操操操 | 香蕉在线视频观看 | 国产在线2020 | 久久精品国产免费 | 日韩激情片在线观看 | 免费在线91 | 国产精品精 | 九九热精品国产 | 五月综合婷| 免费av高清 | 国产小视频在线 | 日韩免费不卡视频 | 91高清视频免费 | 成年人免费av网站 | 成人黄色毛片视频 | 国产欧美日韩精品一区二区免费 | 久草网视频在线观看 | 欧美日韩在线精品一区二区 | 国产亚洲精品免费 | 九九久久国产 | 国产一级免费观看视频 | 精品uu| 久久综合干 | 免费成人在线观看视频 | 国产精品久久久久久久毛片 | 久草在线资源视频 | a级片韩国 | 丁香婷婷深情五月亚洲 | 叶爱av在线| 欧美日韩性生活 | 99久久国产免费,99久久国产免费大片 | 婷婷成人在线 | 探花视频免费在线观看 | 高清视频一区 | 超级碰99| 免费h在线观看 | 久久成人高清 | 免费久久99精品国产 | 久久视频免费在线 | 亚洲成人av电影 | 久久久高清免费视频 | 成人在线播放免费观看 | 天天艹 | 中文字幕xxxx | 香蕉视频在线免费看 | 国产精品久久99综合免费观看尤物 | 欧美一级电影免费观看 | 日av免费| av一区二区三区在线观看 | 亚洲精品一区二区久 | 亚洲天天 | 99精品免费久久久久久日本 | 久久久受www免费人成 | 日韩资源视频 | 91精品毛片 | 午夜视频在线瓜伦 | 亚洲综合激情网 | 91免费在线视频 | 91精品福利在线 | 国产精品久久久久久久久久免费看 | 久久国产视屏 | 国内精品一区二区 | 狠狠的日| 亚洲性少妇性猛交wwww乱大交 | 奇米影视777四色米奇影院 | 最新免费中文字幕 | 亚洲成a人片在线观看网站口工 |