mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Speed up fetching of class entries for self:: parent:: and static::
This is generalized solution for Bob's idea of speed up self::method() calls without ZEND_FETCH_CLASS. At first, it adds few new opcodes to separate class related behaviour: FETCH_STATIC_PROP_R FETCH_STATIC_PROP_W FETCH_STATIC_PROP_RW FETCH_STATIC_PROP_FUNC_ARG FETCH_STATIC_PROP_UNSET FETCH_STATIC_PROP_IS UNSET_STATIC_PROP ISSET_ISEMPTY_STATIC_PROP FETCH_CLASS_CONSTANT At seconds, it enables IS_UNUSED operand to fetch (self, parent or static without separate FETCH_CLASS) for new opcodes and the following ones: INIT_STATIC_METHOD_CALL NEW END_INSTANCEOF Finaly, opcache optimizer had to be fixed to support new opcodes.
This commit is contained in:
parent
ff0ec06562
commit
eb7be5379d
@ -627,7 +627,8 @@ void zend_do_free(znode *op1) /* {{{ */
|
||||
&& opline->result.var == op1->u.op.var) {
|
||||
if (opline->opcode == ZEND_FETCH_R ||
|
||||
opline->opcode == ZEND_FETCH_DIM_R ||
|
||||
opline->opcode == ZEND_FETCH_OBJ_R) {
|
||||
opline->opcode == ZEND_FETCH_OBJ_R ||
|
||||
opline->opcode == ZEND_FETCH_STATIC_PROP_R) {
|
||||
/* It's very rare and useless case. It's better to use
|
||||
additional FREE opcode and simplify the FETCH handlers
|
||||
their selves */
|
||||
@ -1807,25 +1808,27 @@ ZEND_API size_t zend_dirname(char *path, size_t len)
|
||||
|
||||
static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
|
||||
{
|
||||
zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
|
||||
|
||||
switch (type & BP_VAR_MASK) {
|
||||
case BP_VAR_R:
|
||||
return;
|
||||
case BP_VAR_W:
|
||||
case BP_VAR_REF:
|
||||
opline->opcode += 3;
|
||||
opline->opcode += 1 * factor;
|
||||
return;
|
||||
case BP_VAR_RW:
|
||||
opline->opcode += 6;
|
||||
opline->opcode += 2 * factor;
|
||||
return;
|
||||
case BP_VAR_IS:
|
||||
opline->opcode += 9;
|
||||
opline->opcode += 3 * factor;
|
||||
return;
|
||||
case BP_VAR_FUNC_ARG:
|
||||
opline->opcode += 12;
|
||||
opline->opcode += 4 * factor;
|
||||
opline->extended_value |= type >> BP_VAR_SHIFT;
|
||||
return;
|
||||
case BP_VAR_UNSET:
|
||||
opline->opcode += 15;
|
||||
opline->opcode += 5 * factor;
|
||||
return;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
@ -2158,6 +2161,62 @@ static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast, int th
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_compile_class_ref_ex(znode *result, zend_ast *name_ast, uint32_t fetch_flags) /* {{{ */
|
||||
{
|
||||
uint32_t fetch_type;
|
||||
|
||||
if (name_ast->kind != ZEND_AST_ZVAL) {
|
||||
znode name_node;
|
||||
|
||||
zend_compile_expr(&name_node, name_ast);
|
||||
|
||||
if (name_node.op_type == IS_CONST) {
|
||||
zend_string *name;
|
||||
|
||||
if (Z_TYPE(name_node.u.constant) != IS_STRING) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
|
||||
}
|
||||
|
||||
name = Z_STR(name_node.u.constant);
|
||||
fetch_type = zend_get_class_fetch_type(name);
|
||||
|
||||
if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
|
||||
result->op_type = IS_CONST;
|
||||
ZVAL_STR(&result->u.constant, zend_resolve_class_name(name, ZEND_NAME_FQ));
|
||||
} else {
|
||||
zend_ensure_valid_class_fetch_type(fetch_type);
|
||||
result->op_type = IS_UNUSED;
|
||||
result->u.op.num = fetch_type | fetch_flags;
|
||||
}
|
||||
|
||||
zend_string_release(name);
|
||||
} else {
|
||||
zend_op *opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
|
||||
opline->extended_value = ZEND_FETCH_CLASS_DEFAULT | fetch_flags;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fully qualified names are always default refs */
|
||||
if (name_ast->attr == ZEND_NAME_FQ) {
|
||||
result->op_type = IS_CONST;
|
||||
ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
|
||||
return;
|
||||
}
|
||||
|
||||
fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
|
||||
if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
|
||||
result->op_type = IS_CONST;
|
||||
ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
|
||||
} else {
|
||||
zend_ensure_valid_class_fetch_type(fetch_type);
|
||||
result->op_type = IS_UNUSED;
|
||||
result->u.op.num = fetch_type | fetch_flags;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
|
||||
{
|
||||
zend_ast *name_ast = ast->child[0];
|
||||
@ -2364,19 +2423,14 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t
|
||||
znode class_node, prop_node;
|
||||
zend_op *opline;
|
||||
|
||||
if (zend_is_const_default_class_ref(class_ast)) {
|
||||
class_node.op_type = IS_CONST;
|
||||
ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
|
||||
} else {
|
||||
zend_compile_class_ref(&class_node, class_ast, 1);
|
||||
}
|
||||
zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
|
||||
|
||||
zend_compile_expr(&prop_node, prop_ast);
|
||||
|
||||
if (delayed) {
|
||||
opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
|
||||
opline = zend_delayed_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
|
||||
} else {
|
||||
opline = zend_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
|
||||
opline = zend_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
|
||||
}
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zend_alloc_polymorphic_cache_slot(opline->op1.constant);
|
||||
@ -3296,15 +3350,8 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
|
||||
|
||||
znode class_node, method_node;
|
||||
zend_op *opline;
|
||||
zend_ulong extended_value = 0;
|
||||
|
||||
if (zend_is_const_default_class_ref(class_ast)) {
|
||||
class_node.op_type = IS_CONST;
|
||||
ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
|
||||
} else {
|
||||
opline = zend_compile_class_ref(&class_node, class_ast, 1);
|
||||
extended_value = opline->extended_value;
|
||||
}
|
||||
zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
|
||||
|
||||
zend_compile_expr(&method_node, method_ast);
|
||||
if (method_node.op_type == IS_CONST) {
|
||||
@ -3320,7 +3367,6 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
|
||||
|
||||
opline = get_next_op(CG(active_op_array));
|
||||
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
||||
opline->extended_value = extended_value;
|
||||
|
||||
zend_set_class_name_op1(opline, &class_node);
|
||||
|
||||
@ -3352,10 +3398,7 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
|
||||
zend_op *opline;
|
||||
uint32_t opnum;
|
||||
|
||||
if (zend_is_const_default_class_ref(class_ast)) {
|
||||
class_node.op_type = IS_CONST;
|
||||
ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
|
||||
} else if (class_ast->kind == ZEND_AST_CLASS) {
|
||||
if (class_ast->kind == ZEND_AST_CLASS) {
|
||||
uint32_t dcl_opnum = get_next_op_number(CG(active_op_array));
|
||||
zend_compile_class_decl(class_ast);
|
||||
/* jump over anon class declaration */
|
||||
@ -3367,7 +3410,7 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
|
||||
class_node.u.op.var = opline->result.var;
|
||||
opline->op1.opline_num = get_next_op_number(CG(active_op_array));
|
||||
} else {
|
||||
zend_compile_class_ref(&class_node, class_ast, 1);
|
||||
zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
|
||||
}
|
||||
|
||||
opnum = get_next_op_number(CG(active_op_array));
|
||||
@ -3507,7 +3550,7 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
|
||||
return;
|
||||
case ZEND_AST_STATIC_PROP:
|
||||
opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET, 0);
|
||||
opline->opcode = ZEND_UNSET_VAR;
|
||||
opline->opcode = ZEND_UNSET_STATIC_PROP;
|
||||
return;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
@ -6301,13 +6344,7 @@ void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
|
||||
"instanceof expects an object instance, constant given");
|
||||
}
|
||||
|
||||
if (zend_is_const_default_class_ref(class_ast)) {
|
||||
class_node.op_type = IS_CONST;
|
||||
ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
|
||||
} else {
|
||||
opline = zend_compile_class_ref(&class_node, class_ast, 0);
|
||||
opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
|
||||
}
|
||||
zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
||||
|
||||
opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
|
||||
|
||||
@ -6379,7 +6416,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
|
||||
break;
|
||||
case ZEND_AST_STATIC_PROP:
|
||||
opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS, 0);
|
||||
opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
|
||||
opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP;
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
@ -6559,7 +6596,6 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
|
||||
|
||||
znode class_node, const_node;
|
||||
zend_op *opline;
|
||||
zend_string *resolved_name;
|
||||
|
||||
if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, const_ast, 0)) {
|
||||
if (Z_TYPE(result->u.constant) == IS_NULL) {
|
||||
@ -6575,31 +6611,26 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
|
||||
zend_eval_const_expr(&const_ast);
|
||||
|
||||
if (class_ast->kind == ZEND_AST_ZVAL) {
|
||||
zend_string *resolved_name;
|
||||
|
||||
resolved_name = zend_resolve_class_name_ast(class_ast);
|
||||
if (const_ast->kind == ZEND_AST_ZVAL && zend_try_ct_eval_class_const(&result->u.constant, resolved_name, zend_ast_get_str(const_ast))) {
|
||||
result->op_type = IS_CONST;
|
||||
zend_string_release(resolved_name);
|
||||
return;
|
||||
}
|
||||
zend_string_release(resolved_name);
|
||||
}
|
||||
if (const_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(const_ast), "class")) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Dynamic class names are not allowed in compile-time ::class fetch");
|
||||
}
|
||||
|
||||
if (zend_is_const_default_class_ref(class_ast)) {
|
||||
class_node.op_type = IS_CONST;
|
||||
ZVAL_STR(&class_node.u.constant, resolved_name);
|
||||
} else {
|
||||
if (class_ast->kind == ZEND_AST_ZVAL) {
|
||||
zend_string_release(resolved_name);
|
||||
}
|
||||
zend_compile_class_ref(&class_node, class_ast, 1);
|
||||
}
|
||||
zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
|
||||
|
||||
zend_compile_expr(&const_node, const_ast);
|
||||
|
||||
opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, &const_node);
|
||||
opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_CONSTANT, NULL, &const_node);
|
||||
|
||||
zend_set_class_name_op1(opline, &class_node);
|
||||
|
||||
|
@ -1470,7 +1470,7 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
|
||||
ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@ -1494,61 +1494,30 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
|
||||
name = zval_get_string(varname);
|
||||
}
|
||||
|
||||
if (OP2_TYPE != IS_UNUSED) {
|
||||
zend_class_entry *ce;
|
||||
|
||||
if (OP2_TYPE == IS_CONST) {
|
||||
if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
|
||||
retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(fetch_var_return);
|
||||
} else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (OP1_TYPE != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
FREE_OP1();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
||||
}
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
||||
if (OP1_TYPE == IS_CONST &&
|
||||
(retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(fetch_var_return);
|
||||
}
|
||||
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
||||
retval = zend_hash_find(target_symbol_table, name);
|
||||
if (retval == NULL) {
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
case BP_VAR_UNSET:
|
||||
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_IS:
|
||||
retval = &EG(uninitialized_zval);
|
||||
break;
|
||||
case BP_VAR_RW:
|
||||
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
|
||||
retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
|
||||
break;
|
||||
case BP_VAR_W:
|
||||
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (OP1_TYPE == IS_CONST && retval) {
|
||||
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
|
||||
}
|
||||
|
||||
FREE_OP1();
|
||||
} else {
|
||||
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
||||
retval = zend_hash_find(target_symbol_table, name);
|
||||
if (retval == NULL) {
|
||||
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
||||
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
||||
retval = Z_INDIRECT_P(retval);
|
||||
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
case BP_VAR_UNSET:
|
||||
@ -1559,52 +1528,30 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
|
||||
break;
|
||||
case BP_VAR_RW:
|
||||
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
|
||||
retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
|
||||
break;
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_W:
|
||||
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
||||
ZVAL_NULL(retval);
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
||||
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
||||
retval = Z_INDIRECT_P(retval);
|
||||
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
case BP_VAR_UNSET:
|
||||
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_IS:
|
||||
retval = &EG(uninitialized_zval);
|
||||
break;
|
||||
case BP_VAR_RW:
|
||||
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_W:
|
||||
ZVAL_NULL(retval);
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
||||
if (Z_CONSTANT_P(retval)) {
|
||||
if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) {
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
||||
if (Z_CONSTANT_P(retval)) {
|
||||
if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) {
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
||||
FREE_OP1();
|
||||
}
|
||||
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
||||
FREE_OP1();
|
||||
}
|
||||
|
||||
if (OP1_TYPE != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
ZEND_VM_C_LABEL(fetch_var_return):
|
||||
ZEND_ASSERT(retval != NULL);
|
||||
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
||||
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
||||
@ -1617,22 +1564,22 @@ ZEND_VM_C_LABEL(fetch_var_return):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_RW);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
@ -1643,16 +1590,146 @@ ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_IS);
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
zval *varname;
|
||||
zval *retval;
|
||||
zend_string *name;
|
||||
zend_class_entry *ce;
|
||||
|
||||
SAVE_OPLINE();
|
||||
varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
name = Z_STR_P(varname);
|
||||
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
||||
name = Z_STR_P(varname);
|
||||
zend_string_addref(name);
|
||||
} else {
|
||||
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
|
||||
GET_OP1_UNDEF_CV(varname, BP_VAR_R);
|
||||
}
|
||||
name = zval_get_string(varname);
|
||||
}
|
||||
|
||||
if (OP2_TYPE == IS_CONST) {
|
||||
if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
|
||||
retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(fetch_static_prop_return);
|
||||
} else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (OP1_TYPE != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
FREE_OP1();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
||||
}
|
||||
} else {
|
||||
if (OP2_TYPE == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
||||
}
|
||||
if (OP1_TYPE == IS_CONST &&
|
||||
(retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(fetch_static_prop_return);
|
||||
}
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (OP1_TYPE == IS_CONST && retval) {
|
||||
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
|
||||
}
|
||||
|
||||
FREE_OP1();
|
||||
|
||||
if (OP1_TYPE != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
ZEND_VM_C_LABEL(fetch_static_prop_return):
|
||||
ZEND_ASSERT(retval != NULL);
|
||||
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
||||
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
||||
ZVAL_UNREF(retval);
|
||||
}
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
||||
} else {
|
||||
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_R);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_W);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_RW);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_W);
|
||||
} else {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_R);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_UNSET);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_IS);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -3007,7 +3084,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSED|CV)
|
||||
ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CONST|VAR, CONST|TMPVAR|UNUSED|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *function_name;
|
||||
@ -3032,6 +3109,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
||||
}
|
||||
} else if (OP1_TYPE == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
||||
}
|
||||
@ -3125,10 +3204,10 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
|
||||
}
|
||||
}
|
||||
|
||||
if (OP1_TYPE != IS_CONST) {
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
/* previous opcode is ZEND_FETCH_CLASS */
|
||||
if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
|
||||
((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
|
||||
if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
|
||||
(opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
|
||||
ce = EX(called_scope);
|
||||
}
|
||||
}
|
||||
@ -4892,7 +4971,7 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
|
||||
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CONST|VAR, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval object_zval;
|
||||
@ -4909,6 +4988,8 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
||||
}
|
||||
} else if (OP1_TYPE == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
||||
}
|
||||
@ -5025,110 +5106,122 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED, CONST)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_constant *c;
|
||||
|
||||
SAVE_OPLINE();
|
||||
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
|
||||
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
|
||||
char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
|
||||
if (!actual) {
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
|
||||
} else {
|
||||
actual++;
|
||||
ZVAL_STRINGL(EX_VAR(opline->result.var),
|
||||
actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
|
||||
}
|
||||
/* non-qualified constant - allow text substitution */
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
||||
Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
} else {
|
||||
zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
|
||||
}
|
||||
|
||||
#ifdef ZTS
|
||||
if (c->flags & CONST_PERSISTENT) {
|
||||
ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
|
||||
}
|
||||
#else
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
|
||||
#endif
|
||||
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zval *value;
|
||||
USE_OPLINE
|
||||
|
||||
SAVE_OPLINE();
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
zend_constant *c;
|
||||
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
|
||||
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
|
||||
char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
|
||||
if (!actual) {
|
||||
ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
|
||||
} else {
|
||||
actual++;
|
||||
ZVAL_STRINGL(EX_VAR(opline->result.var),
|
||||
actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
|
||||
}
|
||||
/* non-qualified constant - allow text substitution */
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
||||
Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
do {
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_DEREF(value);
|
||||
#ifdef ZTS
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
#endif
|
||||
break;
|
||||
} else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
} else {
|
||||
zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (EXPECTED(!EG(exception))) {
|
||||
zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
||||
}
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
||||
}
|
||||
} else {
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
|
||||
}
|
||||
#ifdef ZTS
|
||||
if (c->flags & CONST_PERSISTENT) {
|
||||
ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
|
||||
}
|
||||
#else
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
|
||||
#endif
|
||||
} else {
|
||||
/* class constant */
|
||||
zend_class_entry *ce;
|
||||
zval *value;
|
||||
|
||||
do {
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_DEREF(value);
|
||||
#ifdef ZTS
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
#endif
|
||||
break;
|
||||
} else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
} else {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (EXPECTED(!EG(exception))) {
|
||||
zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
||||
}
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
||||
}
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
||||
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
||||
ZVAL_DEREF(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
||||
ZVAL_DEREF(value);
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
EG(scope) = ce;
|
||||
zval_update_constant_ex(value, 1, NULL);
|
||||
EG(scope) = EX(func)->op_array.scope;
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
|
||||
} else {
|
||||
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
|
||||
}
|
||||
} else {
|
||||
zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
#ifdef ZTS
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
#else
|
||||
|
||||
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
ZVAL_DEREF(value);
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
EG(scope) = ce;
|
||||
zval_update_constant_ex(value, 1, NULL);
|
||||
EG(scope) = EX(func)->op_array.scope;
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
|
||||
} else {
|
||||
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
|
||||
}
|
||||
} else {
|
||||
zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} while (0);
|
||||
|
||||
#ifdef ZTS
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
#endif
|
||||
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
@ -5493,7 +5586,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval tmp, *varname;
|
||||
@ -5502,7 +5595,6 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
|
||||
SAVE_OPLINE();
|
||||
if (OP1_TYPE == IS_CV &&
|
||||
OP2_TYPE == IS_UNUSED &&
|
||||
(opline->extended_value & ZEND_QUICK_SET)) {
|
||||
zval *var = EX_VAR(opline->op1.var);
|
||||
|
||||
@ -5533,33 +5625,58 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
varname = &tmp;
|
||||
}
|
||||
|
||||
if (OP2_TYPE != IS_UNUSED) {
|
||||
zend_class_entry *ce;
|
||||
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
||||
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
||||
|
||||
if (OP2_TYPE == IS_CONST) {
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (EXPECTED(!EG(exception))) {
|
||||
zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
}
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
||||
}
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
||||
}
|
||||
zend_std_unset_static_property(ce, Z_STR_P(varname));
|
||||
} else {
|
||||
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
||||
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
FREE_OP1();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval tmp, *varname;
|
||||
zend_class_entry *ce;
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
|
||||
varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||
|
||||
ZVAL_UNDEF(&tmp);
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
||||
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
|
||||
varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R);
|
||||
}
|
||||
ZVAL_STR(&tmp, zval_get_string(varname));
|
||||
varname = &tmp;
|
||||
}
|
||||
|
||||
if (OP2_TYPE == IS_CONST) {
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (EXPECTED(!EG(exception))) {
|
||||
zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
}
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
||||
}
|
||||
} else if (OP2_TYPE == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
||||
}
|
||||
zend_std_unset_static_property(ce, Z_STR_P(varname));
|
||||
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
@ -6358,14 +6475,13 @@ ZEND_VM_C_LABEL(fe_fetch_w_exit):
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
int result;
|
||||
|
||||
if (OP1_TYPE == IS_CV &&
|
||||
OP2_TYPE == IS_UNUSED &&
|
||||
(opline->extended_value & ZEND_QUICK_SET)) {
|
||||
value = EX_VAR(opline->op1.var);
|
||||
if (opline->extended_value & ZEND_ISSET) {
|
||||
@ -6386,6 +6502,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
} else {
|
||||
zend_free_op free_op1;
|
||||
zval tmp, *varname;
|
||||
HashTable *target_symbol_table;
|
||||
|
||||
SAVE_OPLINE();
|
||||
varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
|
||||
@ -6395,56 +6512,14 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
varname = &tmp;
|
||||
}
|
||||
|
||||
if (OP2_TYPE != IS_UNUSED) {
|
||||
zend_class_entry *ce;
|
||||
|
||||
if (OP2_TYPE == IS_CONST) {
|
||||
if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(is_var_return);
|
||||
} else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
||||
}
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
||||
if (OP1_TYPE == IS_CONST &&
|
||||
(value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(is_var_return);
|
||||
}
|
||||
}
|
||||
|
||||
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
|
||||
|
||||
if (OP1_TYPE == IS_CONST && value) {
|
||||
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
|
||||
}
|
||||
} else {
|
||||
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
||||
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
||||
}
|
||||
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
||||
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
||||
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
FREE_OP1();
|
||||
|
||||
ZEND_VM_C_LABEL(is_var_return):
|
||||
if (opline->extended_value & ZEND_ISSET) {
|
||||
result = value && Z_TYPE_P(value) > IS_NULL &&
|
||||
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
||||
@ -6458,6 +6533,82 @@ ZEND_VM_C_LABEL(is_var_return):
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
int result;
|
||||
zend_free_op free_op1;
|
||||
zval tmp, *varname;
|
||||
zend_class_entry *ce;
|
||||
|
||||
SAVE_OPLINE();
|
||||
varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
|
||||
ZVAL_UNDEF(&tmp);
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
||||
ZVAL_STR(&tmp, zval_get_string(varname));
|
||||
varname = &tmp;
|
||||
}
|
||||
|
||||
if (OP2_TYPE == IS_CONST) {
|
||||
if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(is_static_prop_return);
|
||||
} else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
||||
}
|
||||
} else {
|
||||
if (OP2_TYPE == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
||||
}
|
||||
if (OP1_TYPE == IS_CONST &&
|
||||
(value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
ZEND_VM_C_GOTO(is_static_prop_return);
|
||||
}
|
||||
}
|
||||
|
||||
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
|
||||
|
||||
if (OP1_TYPE == IS_CONST && value) {
|
||||
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
|
||||
}
|
||||
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
FREE_OP1();
|
||||
|
||||
ZEND_VM_C_LABEL(is_static_prop_return):
|
||||
if (opline->extended_value & ZEND_ISSET) {
|
||||
result = value && Z_TYPE_P(value) > IS_NULL &&
|
||||
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
||||
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
||||
result = !value || !i_zend_is_true(value);
|
||||
}
|
||||
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -6959,7 +7110,7 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, CONST|VAR)
|
||||
ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@ -6984,6 +7135,8 @@ ZEND_VM_C_LABEL(try_instanceof):
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
||||
}
|
||||
} else if (OP2_TYPE == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <zend.h>
|
||||
|
||||
const char *zend_vm_opcodes_map[173] = {
|
||||
const char *zend_vm_opcodes_map[182] = {
|
||||
"ZEND_NOP",
|
||||
"ZEND_ADD",
|
||||
"ZEND_SUB",
|
||||
@ -195,6 +195,15 @@ const char *zend_vm_opcodes_map[173] = {
|
||||
"ZEND_SPACESHIP",
|
||||
"ZEND_DECLARE_ANON_CLASS",
|
||||
"ZEND_DECLARE_ANON_INHERITED_CLASS",
|
||||
"ZEND_FETCH_STATIC_PROP_R",
|
||||
"ZEND_FETCH_STATIC_PROP_W",
|
||||
"ZEND_FETCH_STATIC_PROP_RW",
|
||||
"ZEND_FETCH_STATIC_PROP_IS",
|
||||
"ZEND_FETCH_STATIC_PROP_FUNC_ARG",
|
||||
"ZEND_FETCH_STATIC_PROP_UNSET",
|
||||
"ZEND_UNSET_STATIC_PROP",
|
||||
"ZEND_ISSET_ISEMPTY_STATIC_PROP",
|
||||
"ZEND_FETCH_CLASS_CONSTANT",
|
||||
};
|
||||
|
||||
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
|
||||
|
@ -202,5 +202,14 @@ END_EXTERN_C()
|
||||
#define ZEND_SPACESHIP 170
|
||||
#define ZEND_DECLARE_ANON_CLASS 171
|
||||
#define ZEND_DECLARE_ANON_INHERITED_CLASS 172
|
||||
#define ZEND_FETCH_STATIC_PROP_R 173
|
||||
#define ZEND_FETCH_STATIC_PROP_W 174
|
||||
#define ZEND_FETCH_STATIC_PROP_RW 175
|
||||
#define ZEND_FETCH_STATIC_PROP_IS 176
|
||||
#define ZEND_FETCH_STATIC_PROP_FUNC_ARG 177
|
||||
#define ZEND_FETCH_STATIC_PROP_UNSET 178
|
||||
#define ZEND_UNSET_STATIC_PROP 179
|
||||
#define ZEND_ISSET_ISEMPTY_STATIC_PROP 180
|
||||
#define ZEND_FETCH_CLASS_CONSTANT 181
|
||||
|
||||
#endif
|
||||
|
@ -1091,13 +1091,15 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
|
||||
VAR_SOURCE(opline->op1) &&
|
||||
(VAR_SOURCE(opline->op1)->opcode == ZEND_FAST_CONCAT ||
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_ROPE_END ||
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_FETCH_CONSTANT))) &&
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_FETCH_CONSTANT ||
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_FETCH_CLASS_CONSTANT))) &&
|
||||
(opline->op2_type == IS_CONST ||
|
||||
(opline->op2_type == IS_TMP_VAR &&
|
||||
VAR_SOURCE(opline->op2) &&
|
||||
(VAR_SOURCE(opline->op2)->opcode == ZEND_FAST_CONCAT ||
|
||||
VAR_SOURCE(opline->op2)->opcode == ZEND_ROPE_END ||
|
||||
VAR_SOURCE(opline->op2)->opcode == ZEND_FETCH_CONSTANT)))) {
|
||||
VAR_SOURCE(opline->op2)->opcode == ZEND_FETCH_CONSTANT ||
|
||||
VAR_SOURCE(opline->op2)->opcode == ZEND_FETCH_CLASS_CONSTANT)))) {
|
||||
opline->opcode = ZEND_FAST_CONCAT;
|
||||
}
|
||||
} else if (opline->opcode == ZEND_QM_ASSIGN &&
|
||||
@ -1116,6 +1118,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_IS_IDENTICAL ||
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_IDENTICAL ||
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_VAR ||
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_STATIC_PROP ||
|
||||
VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ) &&
|
||||
!zend_bitset_in(used_ext, VAR_NUM(ZEND_OP1(opline).var))) {
|
||||
/* T = IS_SMALLER(X, Y), T1 = BOOL(T) => T = IS_SMALLER(X, Y), T1 = QM_ASSIGN(T) */
|
||||
@ -1414,6 +1417,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
|
||||
|
||||
if (src &&
|
||||
src->opcode != ZEND_FETCH_R &&
|
||||
src->opcode != ZEND_FETCH_STATIC_PROP_R &&
|
||||
src->opcode != ZEND_FETCH_DIM_R &&
|
||||
src->opcode != ZEND_FETCH_OBJ_R) {
|
||||
ZEND_RESULT_TYPE(src) |= EXT_TYPE_UNUSED;
|
||||
|
@ -177,25 +177,24 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2);
|
||||
break;
|
||||
case ZEND_FETCH_CONSTANT:
|
||||
if (ZEND_OP1_TYPE(opline) == IS_UNUSED) {
|
||||
if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
|
||||
} else {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
|
||||
}
|
||||
if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
|
||||
} else {
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
}
|
||||
optimizer_literal_class_info(
|
||||
info,
|
||||
opline->op1_type,
|
||||
opline->op1,
|
||||
opline->op2.constant,
|
||||
LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
|
||||
op_array);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_CONSTANT:
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
}
|
||||
optimizer_literal_class_info(
|
||||
info,
|
||||
opline->op1_type,
|
||||
opline->op1,
|
||||
opline->op2.constant,
|
||||
LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
|
||||
op_array);
|
||||
break;
|
||||
case ZEND_FETCH_R:
|
||||
case ZEND_FETCH_W:
|
||||
case ZEND_FETCH_RW:
|
||||
@ -204,23 +203,29 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||
case ZEND_FETCH_FUNC_ARG:
|
||||
case ZEND_UNSET_VAR:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
if (ZEND_OP2_TYPE(opline) == IS_UNUSED) {
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
|
||||
}
|
||||
} else {
|
||||
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
}
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
optimizer_literal_class_info(
|
||||
info,
|
||||
opline->op2_type,
|
||||
opline->op2,
|
||||
opline->op1.constant,
|
||||
LITERAL_STATIC_PROPERTY, 2, 1,
|
||||
op_array);
|
||||
}
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_STATIC_PROP_R:
|
||||
case ZEND_FETCH_STATIC_PROP_W:
|
||||
case ZEND_FETCH_STATIC_PROP_RW:
|
||||
case ZEND_FETCH_STATIC_PROP_IS:
|
||||
case ZEND_FETCH_STATIC_PROP_UNSET:
|
||||
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
|
||||
case ZEND_UNSET_STATIC_PROP:
|
||||
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
|
||||
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
}
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
optimizer_literal_class_info(
|
||||
info,
|
||||
opline->op2_type,
|
||||
opline->op2,
|
||||
opline->op1.constant,
|
||||
LITERAL_STATIC_PROPERTY, 2, 1,
|
||||
op_array);
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_CLASS:
|
||||
|
@ -105,15 +105,24 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
call_stack[call].opline = NULL;
|
||||
break;
|
||||
case ZEND_FETCH_FUNC_ARG:
|
||||
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
|
||||
case ZEND_FETCH_OBJ_FUNC_ARG:
|
||||
case ZEND_FETCH_DIM_FUNC_ARG:
|
||||
if (call_stack[call - 1].func) {
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
|
||||
opline->extended_value &= ZEND_FETCH_TYPE_MASK;
|
||||
opline->opcode -= 9;
|
||||
if (opline->opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG) {
|
||||
opline->opcode -= 9;
|
||||
} else {
|
||||
opline->opcode = ZEND_FETCH_STATIC_PROP_W;
|
||||
}
|
||||
} else {
|
||||
opline->extended_value &= ZEND_FETCH_TYPE_MASK;
|
||||
opline->opcode -= 12;
|
||||
if (opline->opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG) {
|
||||
opline->opcode -= 12;
|
||||
} else {
|
||||
opline->opcode = ZEND_FETCH_STATIC_PROP_R;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -238,8 +238,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
#endif
|
||||
|
||||
case ZEND_FETCH_CONSTANT:
|
||||
if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
|
||||
ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
if (ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
|
||||
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 &&
|
||||
memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) {
|
||||
@ -263,8 +262,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
|
||||
ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
if (ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
/* substitute persistent constants */
|
||||
uint32_t tv = ZEND_RESULT(opline).var;
|
||||
@ -283,10 +281,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* class constant */
|
||||
if (ZEND_OP1_TYPE(opline) != IS_UNUSED &&
|
||||
ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
case ZEND_FETCH_CLASS_CONSTANT:
|
||||
if (ZEND_OP2_TYPE(opline) == IS_CONST &&
|
||||
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
|
||||
zend_class_entry *ce = NULL;
|
||||
@ -308,6 +306,11 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (op_array->scope &&
|
||||
ZEND_OP1_TYPE(opline) == IS_UNUSED &&
|
||||
(opline->op1.num & ~ZEND_FETCH_CLASS_NO_AUTOLOAD) == ZEND_FETCH_CLASS_SELF) {
|
||||
/* for self::B */
|
||||
ce = op_array->scope;
|
||||
} else if (op_array->scope &&
|
||||
ZEND_OP1_TYPE(opline) == IS_VAR &&
|
||||
(opline - 1)->opcode == ZEND_FETCH_CLASS &&
|
||||
|
@ -131,6 +131,7 @@ void zend_optimizer_update_op1_const(zend_op_array *op_array,
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_CATCH:
|
||||
case ZEND_FETCH_CONSTANT:
|
||||
case ZEND_FETCH_CLASS_CONSTANT:
|
||||
case ZEND_DEFINED:
|
||||
case ZEND_NEW:
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
@ -179,20 +180,20 @@ void zend_optimizer_update_op2_const(zend_op_array *op_array,
|
||||
if (Z_TYPE_P(val) == IS_STRING) {
|
||||
zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
|
||||
switch (opline->opcode) {
|
||||
case ZEND_FETCH_R:
|
||||
case ZEND_FETCH_W:
|
||||
case ZEND_FETCH_RW:
|
||||
case ZEND_FETCH_IS:
|
||||
case ZEND_FETCH_UNSET:
|
||||
case ZEND_FETCH_FUNC_ARG:
|
||||
case ZEND_FETCH_CLASS:
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
/*case ZEND_INIT_NS_FCALL_BY_NAME:*/
|
||||
case ZEND_UNSET_VAR:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
case ZEND_ADD_INTERFACE:
|
||||
case ZEND_ADD_TRAIT:
|
||||
case ZEND_INSTANCEOF:
|
||||
case ZEND_FETCH_STATIC_PROP_R:
|
||||
case ZEND_FETCH_STATIC_PROP_W:
|
||||
case ZEND_FETCH_STATIC_PROP_RW:
|
||||
case ZEND_FETCH_STATIC_PROP_IS:
|
||||
case ZEND_FETCH_STATIC_PROP_UNSET:
|
||||
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
|
||||
case ZEND_UNSET_STATIC_PROP:
|
||||
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
|
||||
op_array->cache_size += sizeof(void*);
|
||||
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
|
||||
@ -213,7 +214,7 @@ void zend_optimizer_update_op2_const(zend_op_array *op_array,
|
||||
zend_optimizer_add_literal(op_array, val);
|
||||
zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
|
||||
/* break missing intentionally */
|
||||
/*case ZEND_FETCH_CONSTANT:*/
|
||||
/*case ZEND_FETCH_CLASS_CONSTANT:*/
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
case ZEND_FETCH_OBJ_R:
|
||||
case ZEND_FETCH_OBJ_W:
|
||||
|
Loading…
Reference in New Issue
Block a user