mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
Implemented builtin instruction for strlen()
This commit is contained in:
parent
27f38798a1
commit
6c8db864e0
@ -2703,6 +2703,54 @@ static int zend_do_convert_call_user_func_array(zend_op *init_opline TSRMLS_DC)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_do_convert_strlen(zend_op *init_opline, znode *result TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline = init_opline + 1;
|
||||
zend_op *send = NULL;
|
||||
int level = 0;
|
||||
|
||||
do {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_SEND_VAL:
|
||||
case ZEND_SEND_VAL_EX:
|
||||
case ZEND_SEND_VAR:
|
||||
case ZEND_SEND_VAR_EX:
|
||||
case ZEND_SEND_VAR_NO_REF:
|
||||
case ZEND_SEND_REF:
|
||||
case ZEND_SEND_UNPACK:
|
||||
if (level == 0) {
|
||||
if (opline->opcode == ZEND_SEND_UNPACK) {
|
||||
return 0;
|
||||
}
|
||||
send = opline;
|
||||
}
|
||||
break;
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
case ZEND_INIT_NS_FCALL_BY_NAME:
|
||||
case ZEND_NEW:
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_INIT_FCALL:
|
||||
level++;
|
||||
break;
|
||||
case ZEND_DO_FCALL:
|
||||
level--;
|
||||
break;
|
||||
}
|
||||
opline++;
|
||||
} while (send == NULL);
|
||||
|
||||
MAKE_NOP(init_opline);
|
||||
send->opcode = ZEND_STRLEN;
|
||||
send->extended_value = 0;
|
||||
SET_UNUSED(send->op2);
|
||||
send->result.var = get_temporary_variable(CG(active_op_array));
|
||||
send->result_type = IS_TMP_VAR;
|
||||
GET_NODE(result, send->result);
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
@ -2740,6 +2788,15 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
|
||||
fcall->arg_num = 0;
|
||||
}
|
||||
}
|
||||
} else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 &&
|
||||
func->common.function_name->len == sizeof("strlen")-1 &&
|
||||
memcmp(func->common.function_name->val, "strlen", sizeof("strlen")-1) == 0) {
|
||||
if (fcall->arg_num == 1) {
|
||||
if (zend_do_convert_strlen(opline, result TSRMLS_CC)) {
|
||||
zend_stack_del_top(&CG(function_call_stack));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2776,6 +2833,14 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
|
||||
"Cannot use positional argument after argument unpacking");
|
||||
}
|
||||
|
||||
if (op == ZEND_SEND_VAR && (param->op_type & (IS_CONST|IS_TMP_VAR))) {
|
||||
/* Function call was converted into builtin instruction */
|
||||
zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack));
|
||||
zend_llist_destroy(fetch_list_ptr);
|
||||
zend_stack_del_top(&CG(bp_stack));
|
||||
original_op = op = ZEND_SEND_VAL;
|
||||
}
|
||||
|
||||
if (original_op == ZEND_SEND_REF) {
|
||||
if (function_ptr &&
|
||||
function_ptr->common.function_name &&
|
||||
|
@ -883,6 +883,9 @@ END_EXTERN_C()
|
||||
/* disable constant substitution at compile-time */
|
||||
#define ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION (1<<5)
|
||||
|
||||
/* disable usage of builtin instruction for strlen() */
|
||||
#define ZEND_COMPILE_NO_BUILTIN_STRLEN (1<<6)
|
||||
|
||||
/* The default value for CG(compiler_options) */
|
||||
#define ZEND_COMPILE_DEFAULT ZEND_COMPILE_HANDLE_OP_ARRAY
|
||||
|
||||
|
@ -5846,4 +5846,42 @@ ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMP|VAR|CV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
value = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
|
||||
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
||||
} else {
|
||||
if (Z_TYPE_P(value) < IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
||||
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
||||
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
||||
zend_string *str = zval_get_string(value);
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
||||
zend_string *str;
|
||||
|
||||
if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
|
||||
ZEND_VM_C_GOTO(strlen_error);
|
||||
}
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else {
|
||||
ZEND_VM_C_LABEL(strlen_error):
|
||||
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
}
|
||||
FREE_OP1();
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_EXPORT_HANDLER(zend_do_fcall, ZEND_DO_FCALL)
|
||||
|
@ -3361,6 +3361,44 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
|
||||
|
||||
SAVE_OPLINE();
|
||||
value = opline->op1.zv;
|
||||
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
||||
} else {
|
||||
if (Z_TYPE_P(value) < IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
||||
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
||||
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
||||
zend_string *str = zval_get_string(value);
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
||||
zend_string *str;
|
||||
|
||||
if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
|
||||
goto strlen_error;
|
||||
}
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else {
|
||||
strlen_error:
|
||||
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -8804,6 +8842,44 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_STRLEN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
|
||||
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
||||
} else {
|
||||
if (Z_TYPE_P(value) < IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
||||
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
||||
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
||||
zend_string *str = zval_get_string(value);
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
||||
zend_string *str;
|
||||
|
||||
if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
|
||||
goto strlen_error;
|
||||
}
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else {
|
||||
strlen_error:
|
||||
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
}
|
||||
zval_dtor(free_op1.var);
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -14263,6 +14339,44 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_STRLEN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
|
||||
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
||||
} else {
|
||||
if (Z_TYPE_P(value) < IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
||||
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
||||
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
||||
zend_string *str = zval_get_string(value);
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
||||
zend_string *str;
|
||||
|
||||
if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
|
||||
goto strlen_error;
|
||||
}
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else {
|
||||
strlen_error:
|
||||
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1.var);
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -31336,6 +31450,44 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
|
||||
|
||||
SAVE_OPLINE();
|
||||
value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
|
||||
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
||||
} else {
|
||||
if (Z_TYPE_P(value) < IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
||||
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
||||
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
||||
zend_string *str = zval_get_string(value);
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
||||
zend_string *str;
|
||||
|
||||
if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
|
||||
goto strlen_error;
|
||||
}
|
||||
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
||||
STR_RELEASE(str);
|
||||
} else {
|
||||
strlen_error:
|
||||
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -43619,31 +43771,31 @@ void zend_init_opcodes_handlers(void)
|
||||
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
||||
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
||||
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
||||
ZEND_STRLEN_SPEC_TMP_HANDLER,
|
||||
ZEND_STRLEN_SPEC_TMP_HANDLER,
|
||||
ZEND_STRLEN_SPEC_TMP_HANDLER,
|
||||
ZEND_STRLEN_SPEC_TMP_HANDLER,
|
||||
ZEND_STRLEN_SPEC_TMP_HANDLER,
|
||||
ZEND_STRLEN_SPEC_VAR_HANDLER,
|
||||
ZEND_STRLEN_SPEC_VAR_HANDLER,
|
||||
ZEND_STRLEN_SPEC_VAR_HANDLER,
|
||||
ZEND_STRLEN_SPEC_VAR_HANDLER,
|
||||
ZEND_STRLEN_SPEC_VAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CV_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CV_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CV_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CV_HANDLER,
|
||||
ZEND_STRLEN_SPEC_CV_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
|
@ -143,7 +143,7 @@ const char *zend_vm_opcodes_map[169] = {
|
||||
"ZEND_INIT_USER_CALL",
|
||||
"ZEND_SEND_ARRAY",
|
||||
"ZEND_SEND_USER",
|
||||
NULL,
|
||||
"ZEND_STRLEN",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
@ -144,6 +144,7 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
|
||||
#define ZEND_INIT_USER_CALL 118
|
||||
#define ZEND_SEND_ARRAY 119
|
||||
#define ZEND_SEND_USER 120
|
||||
#define ZEND_STRLEN 121
|
||||
#define ZEND_PRE_INC_OBJ 132
|
||||
#define ZEND_PRE_DEC_OBJ 133
|
||||
#define ZEND_POST_INC_OBJ 134
|
||||
|
@ -1619,6 +1619,7 @@ PHP_RINIT_FUNCTION(mbstring)
|
||||
if (MBSTRG(func_overload)){
|
||||
p = &(mb_ovld[0]);
|
||||
|
||||
CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN;
|
||||
while (p->type > 0) {
|
||||
if ((MBSTRG(func_overload) & p->type) == p->type &&
|
||||
(orig = zend_hash_str_find_ptr(EG(function_table), p->save_func,
|
||||
@ -1687,6 +1688,7 @@ PHP_RSHUTDOWN_FUNCTION(mbstring)
|
||||
}
|
||||
p++;
|
||||
}
|
||||
CG(compiler_options) &= ~ZEND_COMPILE_NO_BUILTIN_STRLEN;
|
||||
}
|
||||
|
||||
#if HAVE_MBREGEX
|
||||
|
@ -440,7 +440,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
|
||||
MAKE_NOP(opline + 2);
|
||||
}
|
||||
}
|
||||
} else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("strlen")-1 &&
|
||||
} else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 &&
|
||||
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("strlen")-1 &&
|
||||
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
|
||||
"strlen", sizeof("strlen")-1)) {
|
||||
zval t;
|
||||
@ -456,6 +457,17 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_STRLEN:
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
|
||||
zval t;
|
||||
|
||||
ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline)));
|
||||
replace_tmp_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC);
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
break;
|
||||
#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
|
||||
case ZEND_DECLARE_CONST:
|
||||
if (collect_constants &&
|
||||
|
Loading…
Reference in New Issue
Block a user