亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

PHP中語言結構echo的深入解析(推薦)

2020-03-22 18:11:20
字體:
來源:轉載
供稿:網友
echo實際上作為一種語言結構,是在php編寫代碼時會經常被使用的,所以,接下來的這篇文章將給大家具體分析一下關于echo這個語言結構的用處,話不多說,直接來看正文吧。

1、文檔(VeVb.com)

1.1 輸出一個或多個字符串

void echo ( string $arg1 [, string $... ] )

1.2 說明

echo 不是一個函數,是一個PHP的語言結構,因此不一定要使用小括號來指明參數,單引號、雙引號都行.
echo 不表現得像一個函數,所以不能總是使用一個函數的上下文。
echo 輸出多個字符串的時候, 不能使用小括號。
echo 在php.ini中啟用 short_open_tag 時,有一個快捷用法(view層) ?= Hello World ?
echo 和 print 最主要的不同之處是, echo 接受參數列表,并且沒有返回值。

1.3 注釋

Note: 因為是一個語言構造器而不是一個函數,不能被 可變函數 調用。

 ?php * Tip * 相對 echo 中拼接字符串而言,傳遞多個參數比較好,考慮到了 PHP 中連接運算符(“.”)的優先級。 傳入多個參數,不需要圓括號保證優先級:echo Sum: , 1 + 2;echo Hello , isset($name) ? $name : John Doe , ! /** Tip * 如果是拼接的,相對于加號和三目元算符,連接運算符(“.”)具有更高優先級。為了正確性,必須使用圓括號:echo Sum: . (1 + 2);echo Hello . (isset($name) ? $name : John Doe ) . ! 

2、應用

2.1 輸出基本數據類型

echo 123, abc , [12, 34]; // 123abcArrayecho Sum: , 1 + 2; // Sum: 3echo Sum: . (1 + 2); // Sum: 3echo Hello , isset($name) ? $name : John Doe , ! // Hello John Doe!echo Hello . (isset($name) ? $name : John Doe ) . ! // Hello John Doe!

2.2 輸出對象類型

 ?php html' target='_blank'>class Customer { public function say() { return Hello World echo (new Customer());

Catchable fatal error: Object of class Customer could not be converted to string in /usercode/file.php on line 8

輸出對象時匯報以上錯誤, 所以如果需要輸出對象, 一定要在其內部實現 __toString()。

 ?php class Customer { public function say() { return Hello World  * __toString() 方法用于一個類被當成字符串時應怎樣回應。例如 echo $obj; 應該顯示些什么。此方法必須返回一個字符串,否則將發出一條 E_RECOVERABLE_ERROR 級別的致命錯誤。 public function __toString(){ return $this- say();echo (new Customer()); // Hello World

2.3 輸出資源類型

echo tmpfile(); // Resource id #1

3、源碼

3.1 源碼概述

php 是一門腳本語言, 所以所有的符號都會先經過詞法解析和語法解析階段, 這兩個階段由lex yacc 完成。

計算機科學里面,lex是一個產生詞法分析器的程序。 Lex常常與yacc 語法分析器產生程序一起使用。Lex是許多UNIX系統的標準詞法分析器產生程序,而且這個工具所作的行為被詳列為POSIX標準的一部分。 Lex讀進一個代表詞法分析器規則的輸入字符串流,然后輸出以C語言實做的詞法分析器源代碼。

對應的文件在 Zend/zend_language_parser.y 和 Zend/zend_language_scanner.l。

3.2 字符轉標記(Zend/zend_language_scanner.l)

 ST_IN_SCRIPTING echo { RETURN_TOKEN(T_ECHO);}

ZEND引擎在讀取一個PHP文件之后會先進行詞法分析,就是用lex掃描,把對應的PHP字符轉換成相應的標記(也叫token),比如 echo $a; 在碰到這句首先會匹配到echo,符合上面的規則,然后就返回一個 T_ECHO 標記,這個在后面的語法分析會用上,也就是在 zend_language_parser.y 文件中

3.3 語法分析(Zend/zend_language_parser.y)

# %token Token就是一個個的“詞塊”%token T_ECHO echo (T_ECHO) # statement T_ECHO echo_expr_liststatement: { inner_statement_list } { $$ = $2; } | if_stmt { $$ = $1; } | alt_if_stmt { $$ = $1; } | T_WHILE ( expr ) while_statement { $$ = zend_ast_create(ZEND_AST_WHILE, $3, $5); } | T_DO statement T_WHILE ( expr )  { $$ = zend_ast_create(ZEND_AST_DO_WHILE, $2, $5); } | T_FOR ( for_exprs for_exprs for_exprs ) for_statement { $$ = zend_ast_create(ZEND_AST_FOR, $3, $5, $7, $9); } | T_SWITCH ( expr ) switch_case_list { $$ = zend_ast_create(ZEND_AST_SWITCH, $3, $5); } | T_BREAK optional_expr { $$ = zend_ast_create(ZEND_AST_BREAK, $2); } | T_CONTINUE optional_expr { $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); } | T_RETURN optional_expr { $$ = zend_ast_create(ZEND_AST_RETURN, $2); } | T_GLOBAL global_var_list { $$ = $2; } | T_STATIC static_var_list { $$ = $2; } | T_ECHO echo_expr_list { $$ = $2; } | T_INLINE_HTML { $$ = zend_ast_create(ZEND_AST_ECHO, $1); } | expr { $$ = $1; } | T_UNSET ( unset_variables ) { $$ = $3; } | T_FOREACH ( expr T_AS foreach_variable ) foreach_statement { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $5, NULL, $7); } | T_FOREACH ( expr T_AS foreach_variable T_DOUBLE_ARROW foreach_variable )  foreach_statement { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $7, $5, $9); } | T_DECLARE ( const_list )  { zend_handle_encoding_declaration($3); } declare_statement { $$ = zend_ast_create(ZEND_AST_DECLARE, $3, $6); } | /* empty statement */ { $$ = NULL; } | T_TRY { inner_statement_list } catch_list finally_statement { $$ = zend_ast_create(ZEND_AST_TRY, $3, $5, $6); } | T_THROW expr { $$ = zend_ast_create(ZEND_AST_THROW, $2); } | T_GOTO T_STRING { $$ = zend_ast_create(ZEND_AST_GOTO, $2); } | T_STRING : { $$ = zend_ast_create(ZEND_AST_LABEL, $1); };

在 statement 看到了 T_ECHO, 后面跟著 echo_expr_list,再搜這個字符串,找到如下代碼:

# echo_expr_listecho_expr_list: echo_expr_list , echo_expr { $$ = zend_ast_list_add($1, $3); } | echo_expr { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }echo_expr: expr { $$ = zend_ast_create(ZEND_AST_ECHO, $1); }expr: variable { $$ = $1; } | expr_without_variable { $$ = $1; };

詞法分析后得到單獨存在的詞塊不能表達完整的語義,還需要借助規則進行組織串聯。語法分析器就是這個組織者。它會檢查語法、匹配Token,對Token進行關聯。PHP7中,組織串聯的產物就是抽象語法樹(Abstract Syntax Tree,AST), 詳情請查看相關源碼: 抽象語法樹(Abstract Syntax Tree,AST)

這么看比較難理解,接下來我們從一個簡單的例子看下最終生成的語法樹。

$a = 123;$b = hi~ echo $a,$b;

具體解析過程這里不再解釋,有興趣的可以翻下zend_language_parse.y中,這個過程不太容易理解,需要多領悟幾遍,最后生成的ast如下圖:

1518340723-5b6066f7a1a5e_articlex.png

4.4 模塊初始化(main/main.c)

通過 write_function 綁定PHP輸出函 數php_output_wrapper 至 zend_utility_functions結構體, 此結構體會在xx被使用

# php_module_startupzend_utility_functions zuf;// ...gc_globals_ctor();zuf.error_function = php_error_cb;zuf.printf_function = php_printf;zuf.write_function = php_output_wrapper;zuf.fopen_function = php_fopen_wrapper_for_zend;zuf.message_handler = php_message_handler_for_zend;zuf.get_configuration_directive = php_get_configuration_directive_for_zend;zuf.ticks_function = php_run_ticks;zuf.on_timeout = php_on_timeout;zuf.stream_open_function = php_stream_open_for_zend;zuf.printf_to_smart_string_function = php_printf_to_smart_string;zuf.printf_to_smart_str_function = php_printf_to_smart_str;zuf.getenv_function = sapi_getenv;zuf.resolve_path_function = php_resolve_path_for_zend;zend_startup( zuf, NULL);

zuf 是一個 zend_utility_functions 結構體,這樣就把php_output_wrapper函數傳給了zuf.write_function,后面還有好幾層包裝,最后的實現也是在main/main.c文件里面實現的,是下面這個函數:

/* {{{ php_output_wrapperstatic size_t php_output_wrapper(const char *str, size_t str_length) return php_output_write(str, str_length);}

在 php_out_wrapper 中調用的 php_output_write 在 main/output.c 中實現, 實現代碼如下:

/* {{{ int php_output_write(const char *str, size_t len) * Buffered write  * #define PHP_OUTPUT_ACTIVATED 0x100000  * 當flags=PHP_OUTPUT_ACTIVATED,會調用sapi_module.ub_write輸出, 每個SAPI都有自已的實現, cli中是調用sapi_cli_single_write() * php_output_write(); //輸出,有buffer, 調用php_output_op() * php_output_write_unbuffered();//輸出,沒有buffer,調用PHP_OUTPUT_ACTIVATED,會調用sapi_module.ub_write * php_output_set_status(); //用于SAPI設置output.flags * php_output_get_status(); //獲取output.flags的值PHPAPI size_t php_output_write(const char *str, size_t len) if (OG(flags) PHP_OUTPUT_ACTIVATED) { php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len); return len; if (OG(flags) PHP_OUTPUT_DISABLED) { return 0; return php_output_direct(str, len);/* }}} */

3.5 輸出的終點(main/output.c fwrite函數)

不調用sapi_module的輸出

static size_t (*php_output_direct)(const char *str, size_t str_len) = php_output_stderr;static size_t php_output_stderr(const char *str, size_t str_len) fwrite(str, 1, str_len, stderr);/* See http://support.microsoft.com/kb/190351 */#ifdef PHP_WIN32 fflush(stderr);#endif return str_len;}

調用sapi_module的輸出

sapi_module.ub_write(context.out.data, context.out.used);if (OG(flags) PHP_OUTPUT_IMPLICITFLUSH) { sapi_flush();}

php_output_op 詳細實現如下:

/* {{{ static void php_output_op(int op, const char *str, size_t len) * Output op dispatcher, passes input and output handlers output through the output handler stack until it gets written to the SAPI static inline void php_output_op(int op, const char *str, size_t len) php_output_context context; php_output_handler **active; int obh_cnt; if (php_output_lock_error(op)) { return; php_output_context_init( context, op); * broken up for better performance: * - apply op to the one active handler; note that OG(active) might be popped off the stack on a flush * - or apply op to the handler stack if (OG(active) (obh_cnt = zend_stack_count( OG(handlers)))) { context.in.data = (char *) str; context.in.used = len; if (obh_cnt 1) { zend_stack_apply_with_argument( OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_op, context); } else if ((active = zend_stack_top( OG(handlers))) (!((*active)- flags PHP_OUTPUT_HANDLER_DISABLED))) { php_output_handler_op(*active, context); } else { php_output_context_pass( context); } else { context.out.data = (char *) str; context.out.used = len; if (context.out.data context.out.used) { php_output_header(); if (!(OG(flags) PHP_OUTPUT_DISABLED)) {#if PHP_OUTPUT_DEBUG fprintf(stderr, ::: sapi_write( %s , %zu)/n , context.out.data, context.out.used);#endif sapi_module.ub_write(context.out.data, context.out.used); if (OG(flags) PHP_OUTPUT_IMPLICITFLUSH) { sapi_flush(); OG(flags) |= PHP_OUTPUT_SENT; php_output_context_dtor( context);}

以上了解了PHP輸出函數的實現, 接下來了解echo實現.

3.6 輸出動作的ZEND引擎實現(Zend/zend_vm_def.h)

ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY) USE_OPLINE zend_free_op free_op1; zval *z; SAVE_OPLINE(); z = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if (Z_TYPE_P(z) == IS_STRING) { zend_string *str = Z_STR_P(z); if (ZSTR_LEN(str) != 0) { zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); } else { zend_string *str = _zval_get_string_func(z); if (ZSTR_LEN(str) != 0) { zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); } else if (OP1_TYPE == IS_CV UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { GET_OP1_UNDEF_CV(z, BP_VAR_R); zend_string_release(str); FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();}

可以看到在 zend vm 中通過調用zend_write來實現輸出,接下來看下zend_write的實現。

3.7 zend_write實現(Zend/zend.c)

# Zend/zend.htypedef int (*zend_write_func_t)(const char *str, size_t str_length);# Zend/zend.cZEND_API zend_write_func_t zend_write;# 如下圖所示, zend_write的初始化是在zend_startup()函數里面,這是zend引擎啟動的時候需要做的一些初始化工作,有下面一句:zend_write = (zend_write_func_t) utility_functions- write_function; // php_output_wrapper

zend_utility_functions *utility_functions 在 main/main.c php_module_startup()的 zuf中被定義:

zuf.write_function = php_output_wrapper;

2969020953-5b6064936cef1_articlex.png

4、php(echo)加速

4.1 PHP echo真的慢么?

echo 輸出大字符串(500K)的時候,執行時間會明顯變長,所以會被認為PHP的echo性能很差, 實際上這并不是語言(PHP)問題, 而是一個IO問題(IO的速度限制了輸出的速度)。

但是在某些時候echo執行時間過長, 會影響其他的服務, 進而影響整個系統。

那么使用 apache 時如何優化使的 echo 變快, 讓PHP的請求處理過程盡快結束?

4.2 還是可以優化的: 打開輸出緩存

echo慢是在等待“寫數據”成功返回, 所以可打開輸出緩存:

# 編輯php.inioutput_buffering = 4096 //bytes# 調用ob_start()ob_start();echo $hugeString;ob_end_flush();

ob_start() 會開辟一塊4096大小的buffer,所以如果 $hugeString 大于 4096,將不會起到加速作用。

echo 會立即執行成功返回, 因為數據暫時寫到了我們的輸出緩存中,如果buffer足夠大,那么內容會等到腳本的最后,才一次性的發送給客戶端(嚴格的說是發給webserver)。

5、輸出時的類型轉換

5.1輸出時的類型轉換規則

inputoutputdesccodeBooleanString1 或 0echo true; // 1IntegerInteger不轉換echo 123; // 123FloatFloat不轉換, 注意精度問題echo 123.234; // 123.234StringString不轉換echo abcd // abcdArrayArray-echo [12, 34]; // ArrayObjectCatchable fatal errorObject of class stdClass could not be converted to string in file.php on line *echo json_decode(json_encode([ a = b ]));ResourceResource id #1-echo tmpfile(); // Resource id #1NULLstring轉為空字符串echo null; // 空字符串

5.2 輸出時的類型轉換源碼(Zend/zend_operators.h Zend/zend_operators.c)

# Zend/zend_operators.hZEND_API zend_string* ZEND_FASTCALL _zval_get_string_func(zval *op);# Zend/zend_operators.cZEND_API zend_string* ZEND_FASTCALL _zval_get_string_func(zval *op) /* {{{ */try_again: switch (Z_TYPE_P(op)) { case IS_UNDEF: case IS_NULL: case IS_FALSE: return ZSTR_EMPTY_ALLOC(); case IS_TRUE: if (CG(one_char_string)[ 1 ]) { return CG(one_char_string)[ 1  } else { return zend_string_init( 1 , 1, 0); case IS_RESOURCE: { char buf[sizeof( Resource id # ) + MAX_LENGTH_OF_LONG]; int len; len = snprintf(buf, sizeof(buf), Resource id # ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op)); return zend_string_init(buf, len, 0); case IS_LONG: { return zend_long_to_str(Z_LVAL_P(op)); case IS_DOUBLE: { return zend_strpprintf(0, %.*G , (int) EG(precision), Z_DVAL_P(op)); case IS_ARRAY: zend_error(E_NOTICE, Array to string conversion  return zend_string_init( Array , sizeof( Array )-1, 0); case IS_OBJECT: { zval tmp; if (Z_OBJ_HT_P(op)- cast_object) { if (Z_OBJ_HT_P(op)- cast_object(op, tmp, IS_STRING) == SUCCESS) { return Z_STR(tmp); } else if (Z_OBJ_HT_P(op)- get) { zval *z = Z_OBJ_HT_P(op)- get(op, tmp); if (Z_TYPE_P(z) != IS_OBJECT) { zend_string *str = zval_get_string(z); zval_ptr_dtor(z); return str; zval_ptr_dtor(z); zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, Object of class %s could not be converted to string , ZSTR_VAL(Z_OBJCE_P(op)- name)); return ZSTR_EMPTY_ALLOC(); case IS_REFERENCE: op = Z_REFVAL_P(op); goto try_again; case IS_STRING: return zend_string_copy(Z_STR_P(op)); EMPTY_SWITCH_DEFAULT_CASE() return NULL;/* }}} */

6、Zend/zend_compile.c對echo的解析

6.1 源碼地址

PHP源碼地址 zend_compile.h

PHP源碼地址 zend_compile.c

6.2 zend_compile_expr 實現

# Zend/zend_compile.hvoid zend_compile_expr(znode *node, zend_ast *ast);# Zend/zend_compile.cvoid zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */ /* CG(zend_lineno) = ast- lineno; */ CG(zend_lineno) = zend_ast_get_lineno(ast); switch (ast- kind) { case ZEND_AST_ZVAL: ZVAL_COPY( result- u.constant, zend_ast_get_zval(ast)); result- op_type = IS_CONST; return; case ZEND_AST_ZNODE: *result = *zend_ast_get_znode(ast); return; case ZEND_AST_VAR: case ZEND_AST_DIM: case ZEND_AST_PROP: case ZEND_AST_STATIC_PROP: case ZEND_AST_CALL: case ZEND_AST_METHOD_CALL: case ZEND_AST_STATIC_CALL: zend_compile_var(result, ast, BP_VAR_R); return; case ZEND_AST_ASSIGN: zend_compile_assign(result, ast); return; case ZEND_AST_ASSIGN_REF: zend_compile_assign_ref(result, ast); return; case ZEND_AST_NEW: zend_compile_new(result, ast); return; case ZEND_AST_CLONE: zend_compile_clone(result, ast); return; case ZEND_AST_ASSIGN_OP: zend_compile_compound_assign(result, ast); return; case ZEND_AST_BINARY_OP: zend_compile_binary_op(result, ast); return; case ZEND_AST_GREATER: case ZEND_AST_GREATER_EQUAL: zend_compile_greater(result, ast); return; case ZEND_AST_UNARY_OP: zend_compile_unary_op(result, ast); return; case ZEND_AST_UNARY_PLUS: case ZEND_AST_UNARY_MINUS: zend_compile_unary_pm(result, ast); return; case ZEND_AST_AND: case ZEND_AST_OR: zend_compile_short_circuiting(result, ast); return; case ZEND_AST_POST_INC: case ZEND_AST_POST_DEC: zend_compile_post_incdec(result, ast); return; case ZEND_AST_PRE_INC: case ZEND_AST_PRE_DEC: zend_compile_pre_incdec(result, ast); return; case ZEND_AST_CAST: zend_compile_cast(result, ast); return; case ZEND_AST_CONDITIONAL: zend_compile_conditional(result, ast); return; case ZEND_AST_COALESCE: zend_compile_coalesce(result, ast); return; case ZEND_AST_PRINT: zend_compile_print(result, ast); return; case ZEND_AST_EXIT: zend_compile_exit(result, ast); return; case ZEND_AST_YIELD: zend_compile_yield(result, ast); return; case ZEND_AST_YIELD_FROM: zend_compile_yield_from(result, ast); return; case ZEND_AST_INSTANCEOF: zend_compile_instanceof(result, ast); return; case ZEND_AST_INCLUDE_OR_EVAL: zend_compile_include_or_eval(result, ast); return; case ZEND_AST_ISSET: case ZEND_AST_EMPTY: zend_compile_isset_or_empty(result, ast); return; case ZEND_AST_SILENCE: zend_compile_silence(result, ast); return; case ZEND_AST_SHELL_EXEC: zend_compile_shell_exec(result, ast); return; case ZEND_AST_ARRAY: zend_compile_array(result, ast); return; case ZEND_AST_CONST: zend_compile_const(result, ast); return; case ZEND_AST_CLASS_CONST: zend_compile_class_const(result, ast); return; case ZEND_AST_ENCAPS_LIST: zend_compile_encaps_list(result, ast); return; case ZEND_AST_MAGIC_CONST: zend_compile_magic_const(result, ast); return; case ZEND_AST_CLOSURE: zend_compile_func_decl(result, ast); return; default: ZEND_ASSERT(0 /* not supported */);/* }}} */

6.3 zend_compile_echo 實現

# Zend/zend_compile.cvoid zend_compile_echo(zend_ast *ast) /* {{{ */ zend_op *opline; zend_ast *expr_ast = ast- child[0]; znode expr_node; zend_compile_expr( expr_node, expr_ast); opline = zend_emit_op(NULL, ZEND_ECHO, expr_node, NULL); opline- extended_value = 0;}

相關文章推薦:

php編程中echo用逗號和用點號連接的區別,echo逗號

php echo 輸出字符串函數詳解

以上就是PHP中語言結構echo的深入解析(推薦)的詳細內容,PHP教程

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美中文字幕在线视频| 欧美精品videofree1080p| 91热福利电影| 欧美电影免费观看高清| 中文字幕亚洲欧美一区二区三区| 精品久久中文字幕| 久久精品人人做人人爽| 国产精品视频在线播放| 日韩精品亚洲元码| 伊人久久男人天堂| 国产精品久久久久久久久久99| 亚洲第一精品久久忘忧草社区| 欧美专区日韩视频| 久久99久久99精品中文字幕| 一区二区中文字幕| 日韩视频免费中文字幕| 中文字幕精品一区久久久久| 国产日韩精品入口| 日韩免费在线视频| 亚洲人成亚洲人成在线观看| 欧美性猛交xxxx| 2019中文字幕免费视频| 欧美日韩中文字幕在线视频| 欧美电影在线观看完整版| 麻豆国产精品va在线观看不卡| 日韩免费视频在线观看| 热草久综合在线| www欧美日韩| 亚洲成人精品av| 欧美尺度大的性做爰视频| 欧美大荫蒂xxx| 91精品国产九九九久久久亚洲| 久久夜精品香蕉| 奇米一区二区三区四区久久| 亚洲欧洲在线视频| 性欧美长视频免费观看不卡| 亚洲成人网久久久| 亚洲美女中文字幕| 国产精品第100页| 91免费国产网站| 亚洲欧美日韩国产中文| 日本三级久久久| 日韩电影在线观看中文字幕| 亚洲欧美中文字幕在线一区| 一个人看的www久久| 国产成人亚洲综合91精品| 国产日韩欧美黄色| 亚洲在线免费视频| 国内精品免费午夜毛片| 亚洲人免费视频| 国内精品久久久久| 91久久久久久久久久久| 91av在线网站| 在线丨暗呦小u女国产精品| 91在线视频九色| 麻豆成人在线看| 日韩免费在线电影| 久久成人精品视频| 一区二区三区动漫| 成人在线中文字幕| 欧美精品久久久久久久| 欧美另类极品videosbest最新版本| 国产欧美精品一区二区三区-老狼| 最近2019中文字幕在线高清| 亚洲第一av网站| 日韩在线高清视频| 精品人伦一区二区三区蜜桃免费| 青草热久免费精品视频| 国产盗摄xxxx视频xxx69| 欧美成人免费va影院高清| 日本精品久久久| 日韩中文字幕网| 精品国产一区二区三区久久狼黑人| 亚洲欧美中文另类| 亚洲最大成人在线| 亚洲欧美视频在线| 日韩欧中文字幕| 欧美成人在线免费视频| 色妞色视频一区二区三区四区| 亚洲国产日韩精品在线| 欧美亚洲国产视频小说| 色狠狠av一区二区三区香蕉蜜桃| 国产精品99久久99久久久二8| 中文字幕无线精品亚洲乱码一区| 久久免费视频在线观看| 91精品久久久久| 欧美疯狂xxxx大交乱88av| 中文字幕日韩电影| 色偷偷偷综合中文字幕;dd| 亚洲国产小视频| 久久亚洲精品一区| 久久国产精品久久精品| 亚洲国产精品专区久久| 成人黄色生活片| 中文字幕欧美专区| 91在线观看免费| 懂色av中文一区二区三区天美| 中国人与牲禽动交精品| 91在线观看免费高清| 亚洲第一级黄色片| 国产精品1区2区在线观看| 久久夜精品香蕉| 亚洲欧洲第一视频| 亚洲精品之草原avav久久| 亚洲精品成a人在线观看| 亚洲大胆美女视频| 成人情趣片在线观看免费| 97在线观看免费| 国产美女91呻吟求| 国模gogo一区二区大胆私拍| 国产精品av在线播放| 国产99久久精品一区二区永久免费| 性夜试看影院91社区| 欧美色另类天堂2015| 夜夜嗨av色综合久久久综合网| 97在线观看免费| 亚洲网站在线看| 欧美成aaa人片免费看| 在线观看欧美视频| 日韩www在线| 国产91精品久久久| 欧美在线视频观看免费网站| 久久免费福利视频| 视频在线一区二区| 国产亚洲精品一区二555| 久色乳综合思思在线视频| 亚洲天堂色网站| 色综合天天综合网国产成人网| 欧美日韩高清在线观看| 中文字幕一区电影| 国产91色在线播放| 色偷偷av亚洲男人的天堂| 成人网欧美在线视频| 宅男66日本亚洲欧美视频| 大量国产精品视频| 久久精品99久久香蕉国产色戒| 亚洲自拍偷拍视频| 欧美日韩999| 57pao成人国产永久免费| 精品久久久av| 亚洲香蕉av在线一区二区三区| 久久久女女女女999久久| 色妞欧美日韩在线| 亚洲欧美国产视频| 在线观看精品国产视频| 久久久久久av| 日韩精品视频在线| 琪琪亚洲精品午夜在线| 亚洲视频电影图片偷拍一区| 国产精品夫妻激情| 久久久久久久久爱| 欧美国产激情18| 国产精品亚洲美女av网站| 中文在线不卡视频| 九九精品在线播放| 国产精品久久久久久久久免费看| 日本国产欧美一区二区三区| 在线免费看av不卡| 一区二区三区在线播放欧美| 狠狠躁夜夜躁久久躁别揉| 国产精品无码专区在线观看| 欧美精品免费看| 永久免费毛片在线播放不卡| 国产成人精品视频在线观看|