mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Moved "zval.u2.cache_slot" into free room of "zend_op"
This commit is contained in:
parent
070a0091b3
commit
ca035f26aa
23 changed files with 2805 additions and 1875 deletions
|
@ -64,18 +64,20 @@ typedef struct _zend_loop_var {
|
|||
} u;
|
||||
} zend_loop_var;
|
||||
|
||||
static inline void zend_alloc_cache_slot(uint32_t literal) {
|
||||
static inline uint32_t zend_alloc_cache_slot(void) {
|
||||
zend_op_array *op_array = CG(active_op_array);
|
||||
Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
|
||||
uint32_t ret = op_array->cache_size;
|
||||
op_array->cache_size += sizeof(void*);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define POLYMORPHIC_CACHE_SLOT_SIZE 2
|
||||
|
||||
static inline void zend_alloc_polymorphic_cache_slot(uint32_t literal) {
|
||||
static inline uint32_t zend_alloc_polymorphic_cache_slot(void) {
|
||||
zend_op_array *op_array = CG(active_op_array);
|
||||
Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
|
||||
uint32_t ret = op_array->cache_size;
|
||||
op_array->cache_size += POLYMORPHIC_CACHE_SLOT_SIZE * sizeof(void*);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
|
||||
|
@ -453,7 +455,6 @@ static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int li
|
|||
zval_make_interned_string(zv);
|
||||
}
|
||||
ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv);
|
||||
Z_CACHE_SLOT(op_array->literals[literal_position]) = -1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -531,8 +532,6 @@ static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *nam
|
|||
zend_string *lc_name = zend_string_tolower(name);
|
||||
zend_add_literal_string(op_array, &lc_name);
|
||||
|
||||
zend_alloc_cache_slot(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -2026,7 +2025,34 @@ static void zend_find_live_range(zend_op *opline, zend_uchar type, uint32_t var)
|
|||
} else if (def->opcode == ZEND_NEW) {
|
||||
/* Objects created via ZEND_NEW are only fully initialized
|
||||
* after the DO_FCALL (constructor call) */
|
||||
def = CG(active_op_array)->opcodes + def->op2.opline_num - 1;
|
||||
int level = 0;
|
||||
while (def + 1 != opline) {
|
||||
def++;
|
||||
if (def->opcode == ZEND_DO_FCALL) {
|
||||
if (level == 0) {
|
||||
break;
|
||||
}
|
||||
level--;
|
||||
} else {
|
||||
switch(def->opcode) {
|
||||
case ZEND_INIT_FCALL:
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
case ZEND_INIT_NS_FCALL_BY_NAME:
|
||||
case ZEND_INIT_DYNAMIC_CALL:
|
||||
case ZEND_INIT_USER_CALL:
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_NEW:
|
||||
level++;
|
||||
break;
|
||||
case ZEND_DO_ICALL:
|
||||
case ZEND_DO_UCALL:
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
level--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (def + 1 == opline) {
|
||||
break;
|
||||
}
|
||||
|
@ -2507,6 +2533,7 @@ static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast, int th
|
|||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
|
||||
zend_resolve_class_name(name, type));
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
} else {
|
||||
zend_ensure_valid_class_fetch_type(fetch_type);
|
||||
}
|
||||
|
@ -2742,7 +2769,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
|
|||
opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node);
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
convert_to_string(CT_CONSTANT(opline->op2));
|
||||
zend_alloc_polymorphic_cache_slot(opline->op2.constant);
|
||||
opline->extended_value = zend_alloc_polymorphic_cache_slot();
|
||||
}
|
||||
|
||||
zend_adjust_for_fetch_type(opline, type);
|
||||
|
@ -2777,12 +2804,15 @@ zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, i
|
|||
}
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
convert_to_string(CT_CONSTANT(opline->op1));
|
||||
zend_alloc_polymorphic_cache_slot(opline->op1.constant);
|
||||
opline->extended_value = zend_alloc_polymorphic_cache_slot();
|
||||
}
|
||||
if (class_node.op_type == IS_CONST) {
|
||||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_class_name_literal(
|
||||
CG(active_op_array), Z_STR(class_node.u.constant));
|
||||
if (opline->op1_type != IS_CONST) {
|
||||
opline->extended_value = zend_alloc_polymorphic_cache_slot();
|
||||
}
|
||||
} else {
|
||||
SET_NODE(opline->op2, &class_node);
|
||||
}
|
||||
|
@ -3148,7 +3178,7 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
|||
|
||||
znode var_node, expr_node;
|
||||
zend_op *opline;
|
||||
uint32_t offset;
|
||||
uint32_t offset, cache_slot;
|
||||
|
||||
zend_ensure_writable_variable(var_ast);
|
||||
|
||||
|
@ -3178,10 +3208,12 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
|||
zend_compile_expr(&expr_node, expr_ast);
|
||||
|
||||
opline = zend_delayed_compile_end(offset);
|
||||
cache_slot = opline->extended_value;
|
||||
opline->opcode = opcode;
|
||||
opline->extended_value = ZEND_ASSIGN_OBJ;
|
||||
|
||||
zend_emit_op_data(&expr_node);
|
||||
opline = zend_emit_op_data(&expr_node);
|
||||
opline->extended_value = cache_slot;
|
||||
return;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
|
@ -3385,7 +3417,7 @@ void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /
|
|||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_ns_func_name_literal(
|
||||
CG(active_op_array), Z_STR(name_node->u.constant));
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
opline->result.num = zend_alloc_cache_slot();
|
||||
|
||||
zend_compile_call_common(result, args_ast, NULL);
|
||||
}
|
||||
|
@ -3406,7 +3438,8 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
|
|||
opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), class);
|
||||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), method);
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
/* 2 slots, for class and method */
|
||||
opline->result.num = zend_alloc_polymorphic_cache_slot();
|
||||
zval_ptr_dtor(&name_node->u.constant);
|
||||
} else {
|
||||
zend_op *opline = get_next_op(CG(active_op_array));
|
||||
|
@ -3415,7 +3448,7 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
|
|||
SET_UNUSED(opline->op1);
|
||||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), str);
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
opline->result.num = zend_alloc_cache_slot();
|
||||
}
|
||||
} else {
|
||||
zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
|
||||
|
@ -3521,7 +3554,7 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
|
|||
opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
|
||||
opline->op1_type = IS_CONST;
|
||||
LITERAL_STR(opline->op1, name);
|
||||
zend_alloc_cache_slot(opline->op1.constant);
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
|
||||
/* Lowercase constant name in a separate literal */
|
||||
{
|
||||
|
@ -3595,7 +3628,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t
|
|||
opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
|
||||
opline->op2_type = IS_CONST;
|
||||
LITERAL_STR(opline->op2, lcname);
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
opline->result.num = zend_alloc_cache_slot();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
@ -3715,7 +3748,7 @@ static int zend_compile_assert(znode *result, zend_ast_list *args, zend_string *
|
|||
opline->op2.constant = zend_add_ns_func_name_literal(
|
||||
CG(active_op_array), name);
|
||||
}
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
opline->result.num = zend_alloc_cache_slot();
|
||||
|
||||
if (args->children == 1 &&
|
||||
(args->child[0]->kind != ZEND_AST_ZVAL ||
|
||||
|
@ -4075,7 +4108,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
|
|||
ZVAL_NEW_STR(&name_node.u.constant, lcname);
|
||||
|
||||
opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
opline->result.num = zend_alloc_cache_slot();
|
||||
|
||||
zend_compile_call_common(result, args_ast, fbc);
|
||||
}
|
||||
|
@ -4109,7 +4142,7 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{
|
|||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
|
||||
Z_STR(method_node.u.constant));
|
||||
zend_alloc_polymorphic_cache_slot(opline->op2.constant);
|
||||
opline->result.num = zend_alloc_polymorphic_cache_slot();
|
||||
} else {
|
||||
SET_NODE(opline->op2, &method_node);
|
||||
}
|
||||
|
@ -4170,12 +4203,11 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
|
|||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
|
||||
Z_STR(method_node.u.constant));
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
} else {
|
||||
zend_alloc_polymorphic_cache_slot(opline->op2.constant);
|
||||
}
|
||||
opline->result.num = zend_alloc_polymorphic_cache_slot();
|
||||
} else {
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
opline->result.num = zend_alloc_cache_slot();
|
||||
}
|
||||
SET_NODE(opline->op2, &method_node);
|
||||
}
|
||||
zend_check_live_ranges(opline);
|
||||
|
@ -4238,17 +4270,13 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
|
|||
opline->op1_type = IS_CONST;
|
||||
opline->op1.constant = zend_add_class_name_literal(
|
||||
CG(active_op_array), Z_STR(class_node.u.constant));
|
||||
opline->op2.num = zend_alloc_cache_slot();
|
||||
} else {
|
||||
SET_NODE(opline->op1, &class_node);
|
||||
}
|
||||
|
||||
zend_compile_call_common(&ctor_result, args_ast, NULL);
|
||||
zend_do_free(&ctor_result);
|
||||
|
||||
/* We save the position of DO_FCALL for convenience in find_live_range().
|
||||
* This info is not preserved for runtime. */
|
||||
opline = &CG(active_op_array)->opcodes[opnum];
|
||||
opline->op2.opline_num = get_next_op_number(CG(active_op_array));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -4279,7 +4307,7 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
|
|||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable");
|
||||
} else if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
|
||||
zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
} else {
|
||||
/* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
|
||||
* to not free the name_node operand, so it can be reused in the following
|
||||
|
@ -5209,6 +5237,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
|
|||
opline->op1_type = IS_CONST;
|
||||
opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
|
||||
zend_resolve_class_name_ast(class_ast));
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
|
||||
if (zend_string_equals_literal(var_name, "this")) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
|
||||
|
@ -5218,7 +5247,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
|
|||
opline->result.var = lookup_cv(CG(active_op_array), var_name);
|
||||
|
||||
if (is_last_catch && is_last_class) {
|
||||
opline->extended_value = ZEND_LAST_CATCH;
|
||||
opline->extended_value |= ZEND_LAST_CATCH;
|
||||
}
|
||||
|
||||
if (!is_last_class) {
|
||||
|
@ -5675,9 +5704,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
|
|||
/* Allocate cache slot to speed-up run-time class resolution */
|
||||
if (opline->opcode == ZEND_RECV_INIT) {
|
||||
if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
} else {
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
}
|
||||
} else {
|
||||
if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
|
||||
|
@ -5688,9 +5715,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (opline->opcode == ZEND_RECV_INIT) {
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
|
||||
} else {
|
||||
if (opline->opcode != ZEND_RECV_INIT) {
|
||||
opline->op2.num = -1;
|
||||
}
|
||||
}
|
||||
|
@ -6272,6 +6297,7 @@ void zend_compile_use_trait(zend_ast *ast) /* {{{ */
|
|||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
|
||||
zend_resolve_class_name_ast(trait_ast));
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
|
||||
ce->num_traits++;
|
||||
}
|
||||
|
@ -6314,6 +6340,7 @@ void zend_compile_implements(znode *class_node, zend_ast *ast) /* {{{ */
|
|||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
|
||||
zend_resolve_class_name_ast(class_ast));
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
|
||||
CG(active_class_entry)->num_interfaces++;
|
||||
}
|
||||
|
@ -7515,6 +7542,7 @@ void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
|
|||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_class_name_literal(
|
||||
CG(active_op_array), Z_STR(class_node.u.constant));
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
} else {
|
||||
SET_NODE(opline->op2, &class_node);
|
||||
}
|
||||
|
@ -7586,7 +7614,9 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
|
|||
}
|
||||
|
||||
result->op_type = opline->result_type = IS_TMP_VAR;
|
||||
opline->extended_value |= ast->kind == ZEND_AST_ISSET ? ZEND_ISSET : 0;
|
||||
if (ast->kind == ZEND_AST_ISSET) {
|
||||
opline->extended_value |= ZEND_ISSET;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -7749,7 +7779,7 @@ void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
|
|||
CG(active_op_array), resolved_name, 0);
|
||||
}
|
||||
}
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
opline->extended_value = zend_alloc_cache_slot();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -7801,11 +7831,7 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
|
|||
|
||||
zend_set_class_name_op1(opline, &class_node);
|
||||
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
} else {
|
||||
zend_alloc_polymorphic_cache_slot(opline->op2.constant);
|
||||
}
|
||||
opline->extended_value = zend_alloc_polymorphic_cache_slot();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -2000,96 +2000,6 @@ use_read_property:
|
|||
}
|
||||
}
|
||||
|
||||
static zend_always_inline zval* zend_fetch_static_property_address(zval *varname, zend_uchar varname_type, znode_op op2, zend_uchar op2_type, int type EXECUTE_DATA_DC OPLINE_DC)
|
||||
{
|
||||
zval *retval;
|
||||
zend_string *name, *tmp_name;
|
||||
zend_class_entry *ce;
|
||||
|
||||
if (varname_type == IS_CONST) {
|
||||
name = Z_STR_P(varname);
|
||||
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
||||
name = Z_STR_P(varname);
|
||||
tmp_name = NULL;
|
||||
} else {
|
||||
if (varname_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
|
||||
zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
|
||||
}
|
||||
name = zval_get_tmp_string(varname, &tmp_name);
|
||||
}
|
||||
|
||||
if (op2_type == IS_CONST) {
|
||||
if (varname_type == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(varname))) != NULL)) {
|
||||
retval = CACHED_PTR(Z_CACHE_SLOT_P(varname) + sizeof(void*));
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
if (type != BP_VAR_IS) {
|
||||
zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
} else {
|
||||
zval *class_name = RT_CONSTANT(opline, op2);
|
||||
|
||||
if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(class_name))) == NULL)) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(class_name), class_name + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (varname_type != IS_CONST) {
|
||||
zend_tmp_string_release(tmp_name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(class_name), ce);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (op2_type == IS_UNUSED) {
|
||||
ce = zend_fetch_class(NULL, op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
if (varname_type != IS_CONST) {
|
||||
zend_tmp_string_release(tmp_name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
ce = Z_CE_P(EX_VAR(op2.var));
|
||||
}
|
||||
if (varname_type == IS_CONST &&
|
||||
EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(varname)) == ce)) {
|
||||
retval = CACHED_PTR(Z_CACHE_SLOT_P(varname) + sizeof(void*));
|
||||
|
||||
/* check if static properties were destoyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
if (type != BP_VAR_IS) {
|
||||
zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
retval = zend_std_get_static_property(ce, name, type == BP_VAR_IS);
|
||||
|
||||
if (varname_type != IS_CONST) {
|
||||
zend_tmp_string_release(tmp_name);
|
||||
}
|
||||
|
||||
if (UNEXPECTED(retval == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (varname_type == IS_CONST) {
|
||||
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(varname), ce, retval);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if ZEND_INTENSIVE_DEBUGGING
|
||||
|
||||
#define CHECK_SYMBOL_TABLES() \
|
||||
|
|
|
@ -663,7 +663,7 @@ ZEND_API int pass_two(zend_op_array *op_array)
|
|||
opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -192,7 +192,6 @@ struct _zval_struct {
|
|||
} u1;
|
||||
union {
|
||||
uint32_t next; /* hash collision chain */
|
||||
uint32_t cache_slot; /* literal cache slot */
|
||||
uint32_t opline_num; /* opline number (for FAST_CALL) */
|
||||
uint32_t lineno; /* line number (for ast nodes) */
|
||||
uint32_t num_args; /* arguments number for EX(This) */
|
||||
|
@ -411,9 +410,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
|
|||
#define Z_NEXT(zval) (zval).u2.next
|
||||
#define Z_NEXT_P(zval_p) Z_NEXT(*(zval_p))
|
||||
|
||||
#define Z_CACHE_SLOT(zval) (zval).u2.cache_slot
|
||||
#define Z_CACHE_SLOT_P(zval_p) Z_CACHE_SLOT(*(zval_p))
|
||||
|
||||
#define Z_LINENO(zval) (zval).u2.lineno
|
||||
#define Z_LINENO_P(zval_p) Z_LINENO(*(zval_p))
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -70,9 +70,11 @@ $vm_op_flags = array(
|
|||
"ZEND_VM_OP_CLASS_FETCH" => 0x70,
|
||||
"ZEND_VM_OP_CONSTRUCTOR" => 0x80,
|
||||
"ZEND_VM_OP_CONST_FETCH" => 0x90,
|
||||
"ZEND_VM_OP_CACHE_SLOT" => 0xa0,
|
||||
|
||||
"ZEND_VM_EXT_VAR_FETCH" => 1<<16,
|
||||
"ZEND_VM_EXT_ISSET" => 1<<17,
|
||||
"ZEND_VM_EXT_CACHE_SLOT" => 1<<18,
|
||||
"ZEND_VM_EXT_ARRAY_INIT" => 1<<19,
|
||||
"ZEND_VM_EXT_REF" => 1<<20,
|
||||
"ZEND_VM_EXT_MASK" => 0x0f000000,
|
||||
|
@ -114,6 +116,7 @@ $vm_op_decode = array(
|
|||
"CLASS_FETCH" => ZEND_VM_OP_CLASS_FETCH,
|
||||
"CONSTRUCTOR" => ZEND_VM_OP_CONSTRUCTOR,
|
||||
"CONST_FETCH" => ZEND_VM_OP_CONST_FETCH,
|
||||
"CACHE_SLOT" => ZEND_VM_OP_CACHE_SLOT,
|
||||
);
|
||||
|
||||
$vm_ext_decode = array(
|
||||
|
@ -129,6 +132,7 @@ $vm_ext_decode = array(
|
|||
"ISSET" => ZEND_VM_EXT_ISSET,
|
||||
"REF" => ZEND_VM_EXT_REF,
|
||||
"SRC" => ZEND_VM_EXT_SRC,
|
||||
"CACHE_SLOT" => ZEND_VM_EXT_CACHE_SLOT,
|
||||
);
|
||||
|
||||
$vm_kind_name = array(
|
||||
|
|
|
@ -247,17 +247,17 @@ static uint32_t zend_vm_opcodes_flags[199] = {
|
|||
0x00000707,
|
||||
0x07000003,
|
||||
0x00000003,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x04046751,
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
|
@ -283,47 +283,47 @@ static uint32_t zend_vm_opcodes_flags[199] = {
|
|||
0x01000701,
|
||||
0x00000000,
|
||||
0x00000001,
|
||||
0x01000300,
|
||||
0x01040300,
|
||||
0x00000000,
|
||||
0x01000310,
|
||||
0x01040310,
|
||||
0x00000003,
|
||||
0x00000010,
|
||||
0x00000310,
|
||||
0x0000a110,
|
||||
0x00040310,
|
||||
0x00001007,
|
||||
0x00001001,
|
||||
0x00001001,
|
||||
0x01000073,
|
||||
0x01000300,
|
||||
0x0100a173,
|
||||
0x01040300,
|
||||
0x00004005,
|
||||
0x00186703,
|
||||
0x00106703,
|
||||
0x08000007,
|
||||
0x00010107,
|
||||
0x00000701,
|
||||
0x00000751,
|
||||
0x00040751,
|
||||
0x00002003,
|
||||
0x03000001,
|
||||
0x00000007,
|
||||
0x00010107,
|
||||
0x00000707,
|
||||
0x00000757,
|
||||
0x00040757,
|
||||
0x00010107,
|
||||
0x00006701,
|
||||
0x00000751,
|
||||
0x00040751,
|
||||
0x00010107,
|
||||
0x00006701,
|
||||
0x00000751,
|
||||
0x00040751,
|
||||
0x00010107,
|
||||
0x00000707,
|
||||
0x00000757,
|
||||
0x00040757,
|
||||
0x00010107,
|
||||
0x00006703,
|
||||
0x00000753,
|
||||
0x00040753,
|
||||
0x00010107,
|
||||
0x00000701,
|
||||
0x00000751,
|
||||
0x00040751,
|
||||
0x0000070b,
|
||||
0x00000391,
|
||||
0x00040391,
|
||||
0x00001001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
|
@ -331,13 +331,13 @@ static uint32_t zend_vm_opcodes_flags[199] = {
|
|||
0x00000000,
|
||||
0x01000000,
|
||||
0x00001001,
|
||||
0x02002003,
|
||||
0x02042003,
|
||||
0x00000003,
|
||||
0x00000771,
|
||||
0x00040771,
|
||||
0x00000057,
|
||||
0x0b000003,
|
||||
0x01000757,
|
||||
0x01008773,
|
||||
0x01040757,
|
||||
0x01048773,
|
||||
0x00030107,
|
||||
0x00020707,
|
||||
0x00001003,
|
||||
|
@ -346,9 +346,9 @@ static uint32_t zend_vm_opcodes_flags[199] = {
|
|||
0x01000000,
|
||||
0x00001003,
|
||||
0x00000007,
|
||||
0x00000003,
|
||||
0x00040003,
|
||||
0x09000003,
|
||||
0x00000103,
|
||||
0x0000a103,
|
||||
0x00002003,
|
||||
0x03000001,
|
||||
0x00004005,
|
||||
|
@ -356,29 +356,29 @@ static uint32_t zend_vm_opcodes_flags[199] = {
|
|||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00040751,
|
||||
0x00040751,
|
||||
0x00040751,
|
||||
0x00040751,
|
||||
0x00040751,
|
||||
0x00000000,
|
||||
0x00007305,
|
||||
0x00047305,
|
||||
0x00000000,
|
||||
0x00000100,
|
||||
0x00000000,
|
||||
0x00000003,
|
||||
0x00000303,
|
||||
0x00000300,
|
||||
0x00040300,
|
||||
0x00000100,
|
||||
0x00000000,
|
||||
0x00006701,
|
||||
0x00020757,
|
||||
0x00060757,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00002000,
|
||||
0x00002003,
|
||||
0x00000103,
|
||||
0x00000000,
|
||||
0x00040000,
|
||||
0x00000000,
|
||||
0x00000101,
|
||||
0x00000071,
|
||||
|
@ -388,24 +388,24 @@ static uint32_t zend_vm_opcodes_flags[199] = {
|
|||
0x00000003,
|
||||
0x00000020,
|
||||
0x00003000,
|
||||
0x00000010,
|
||||
0x0000a110,
|
||||
0x00000000,
|
||||
0x00000707,
|
||||
0x04006751,
|
||||
0x00000301,
|
||||
0x04046751,
|
||||
0x00040301,
|
||||
0x00002003,
|
||||
0x00000707,
|
||||
0x03000000,
|
||||
0x03000100,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00027307,
|
||||
0x00000373,
|
||||
0x00047307,
|
||||
0x00047307,
|
||||
0x00047307,
|
||||
0x00047307,
|
||||
0x00047307,
|
||||
0x00047307,
|
||||
0x00047307,
|
||||
0x00067307,
|
||||
0x00040373,
|
||||
0x00100101,
|
||||
0x00100301,
|
||||
0x00000101,
|
||||
|
|
|
@ -48,8 +48,10 @@
|
|||
#define ZEND_VM_OP_CLASS_FETCH 0x00000070
|
||||
#define ZEND_VM_OP_CONSTRUCTOR 0x00000080
|
||||
#define ZEND_VM_OP_CONST_FETCH 0x00000090
|
||||
#define ZEND_VM_OP_CACHE_SLOT 0x000000a0
|
||||
#define ZEND_VM_EXT_VAR_FETCH 0x00010000
|
||||
#define ZEND_VM_EXT_ISSET 0x00020000
|
||||
#define ZEND_VM_EXT_CACHE_SLOT 0x00040000
|
||||
#define ZEND_VM_EXT_ARRAY_INIT 0x00080000
|
||||
#define ZEND_VM_EXT_REF 0x00100000
|
||||
#define ZEND_VM_EXT_MASK 0x0f000000
|
||||
|
|
|
@ -965,7 +965,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op
|
|||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start);
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -42,76 +42,77 @@
|
|||
#define LITERAL_PROPERTY 0x0900
|
||||
#define LITERAL_GLOBAL 0x0A00
|
||||
|
||||
#define LITERAL_EX_CLASS 0x4000
|
||||
#define LITERAL_EX_OBJ 0x2000
|
||||
#define LITERAL_MAY_MERGE 0x1000
|
||||
#define LITERAL_KIND_MASK 0x0f00
|
||||
#define LITERAL_NUM_RELATED_MASK 0x000f
|
||||
#define LITERAL_NUM_SLOTS_MASK 0x00f0
|
||||
#define LITERAL_NUM_SLOTS_SHIFT 4
|
||||
|
||||
#define LITERAL_NUM_RELATED(info) (info & LITERAL_NUM_RELATED_MASK)
|
||||
#define LITERAL_NUM_SLOTS(info) ((info & LITERAL_NUM_SLOTS_MASK) >> LITERAL_NUM_SLOTS_SHIFT)
|
||||
|
||||
typedef struct _literal_info {
|
||||
uint32_t flags; /* bitmask (see defines above) */
|
||||
union {
|
||||
int num; /* variable number or class name literal number */
|
||||
} u;
|
||||
} literal_info;
|
||||
|
||||
#define LITERAL_FLAGS(kind, slots, related) \
|
||||
((kind) | ((slots) << LITERAL_NUM_SLOTS_SHIFT) | (related))
|
||||
|
||||
#define LITERAL_INFO(n, kind, merge, slots, related) do { \
|
||||
info[n].flags = (((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
|
||||
#define LITERAL_INFO(n, kind, related) do { \
|
||||
info[n].flags = ((kind) | (related)); \
|
||||
} while (0)
|
||||
|
||||
#define LITERAL_INFO_CLASS(n, kind, merge, slots, related, _num) do { \
|
||||
info[n].flags = (LITERAL_EX_CLASS | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
|
||||
info[n].u.num = (_num); \
|
||||
} while (0)
|
||||
|
||||
#define LITERAL_INFO_OBJ(n, kind, merge, slots, related) do { \
|
||||
info[n].flags = (LITERAL_EX_OBJ | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
|
||||
info[n].u.num = (uint32_t)-1; \
|
||||
} while (0)
|
||||
|
||||
static void optimizer_literal_obj_info(literal_info *info,
|
||||
zend_uchar op_type,
|
||||
znode_op op,
|
||||
int constant,
|
||||
uint32_t kind,
|
||||
uint32_t slots,
|
||||
uint32_t related,
|
||||
zend_op_array *op_array)
|
||||
static zend_bool class_name_type_hint(const zend_op_array *op_array, uint32_t arg_num)
|
||||
{
|
||||
/* For now we merge only $this object properties and methods.
|
||||
* In general it's also possible to do it for any CV variable as well,
|
||||
* but it would require complex dataflow and/or type analysis.
|
||||
*/
|
||||
if (Z_TYPE(op_array->literals[constant]) == IS_STRING &&
|
||||
op_type == IS_UNUSED) {
|
||||
LITERAL_INFO_OBJ(constant, kind, 1, slots, related);
|
||||
zend_arg_info *arg_info;
|
||||
|
||||
if (arg_num > 0) {
|
||||
if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
|
||||
if (EXPECTED(arg_num <= op_array->num_args)) {
|
||||
arg_info = &op_array->arg_info[arg_num-1];
|
||||
} else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) {
|
||||
arg_info = &op_array->arg_info[op_array->num_args];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return ZEND_TYPE_IS_CLASS(arg_info->type);
|
||||
}
|
||||
} else {
|
||||
LITERAL_INFO(constant, kind, 0, slots, related);
|
||||
arg_info = op_array->arg_info - 1;
|
||||
return ZEND_TYPE_IS_CLASS(arg_info->type);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void optimizer_literal_class_info(literal_info *info,
|
||||
zend_uchar op_type,
|
||||
znode_op op,
|
||||
int constant,
|
||||
uint32_t kind,
|
||||
uint32_t slots,
|
||||
uint32_t related,
|
||||
zend_op_array *op_array)
|
||||
static uint32_t add_static_slot(HashTable *hash,
|
||||
zend_op_array *op_array,
|
||||
uint32_t op1,
|
||||
uint32_t op2,
|
||||
uint32_t kind,
|
||||
int *cache_size)
|
||||
{
|
||||
if (op_type == IS_CONST) {
|
||||
LITERAL_INFO_CLASS(constant, kind, 1, slots, related, op.constant);
|
||||
uint32_t ret;
|
||||
zend_string *key;
|
||||
size_t key_len;
|
||||
zval *class_name = &op_array->literals[op1];
|
||||
zval *prop_name = &op_array->literals[op2];
|
||||
zval *pos, tmp;
|
||||
|
||||
key_len = Z_STRLEN_P(class_name) + sizeof("::") - 1 + Z_STRLEN_P(prop_name);
|
||||
key = zend_string_alloc(key_len, 0);
|
||||
memcpy(ZSTR_VAL(key), Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
|
||||
memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
|
||||
memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name) + sizeof("::") - 1,
|
||||
Z_STRVAL_P(prop_name),
|
||||
Z_STRLEN_P(prop_name) + 1);
|
||||
|
||||
ZSTR_H(key) = zend_hash_func(ZSTR_VAL(key), ZSTR_LEN(key));
|
||||
ZSTR_H(key) += kind;
|
||||
|
||||
pos = zend_hash_find(hash, key);
|
||||
if (pos) {
|
||||
ret = Z_LVAL_P(pos);
|
||||
} else {
|
||||
LITERAL_INFO(constant, kind, 0, slots, related);
|
||||
ret = *cache_size;
|
||||
*cache_size += 2 * sizeof(void *);
|
||||
ZVAL_LONG(&tmp, ret);
|
||||
zend_hash_add(hash, key, &tmp);
|
||||
}
|
||||
zend_string_release(key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
|
@ -127,9 +128,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
HashTable hash;
|
||||
zend_string *key = NULL;
|
||||
void *checkpoint = zend_arena_checkpoint(ctx->arena);
|
||||
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot;
|
||||
|
||||
if (op_array->last_literal) {
|
||||
cache_size = 0;
|
||||
info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info));
|
||||
|
||||
/* Mark literals of specific types */
|
||||
|
@ -138,66 +139,48 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
while (opline < end) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_INIT_FCALL:
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1);
|
||||
break;
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 2);
|
||||
break;
|
||||
case ZEND_INIT_NS_FCALL_BY_NAME:
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 3);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 3);
|
||||
break;
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1);
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
optimizer_literal_obj_info(
|
||||
info,
|
||||
opline->op1_type,
|
||||
opline->op1,
|
||||
opline->op2.constant,
|
||||
LITERAL_METHOD, 2, 2,
|
||||
op_array);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_METHOD, 2);
|
||||
}
|
||||
break;
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2);
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
optimizer_literal_class_info(
|
||||
info,
|
||||
opline->op1_type,
|
||||
opline->op1,
|
||||
opline->op2.constant,
|
||||
LITERAL_STATIC_METHOD, (opline->op1_type == IS_CONST) ? 1 : 2, 2,
|
||||
op_array);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_STATIC_METHOD, 2);
|
||||
}
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2);
|
||||
break;
|
||||
case ZEND_DEFINED:
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 2);
|
||||
break;
|
||||
case ZEND_FETCH_CONSTANT:
|
||||
if ((opline->op1.num & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 5);
|
||||
} else {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 3);
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_CONSTANT:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2);
|
||||
}
|
||||
optimizer_literal_class_info(
|
||||
info,
|
||||
opline->op1_type,
|
||||
opline->op1,
|
||||
opline->op2.constant,
|
||||
LITERAL_CLASS_CONST, (opline->op1_type == IS_CONST) ? 1 : 2, 1,
|
||||
op_array);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS_CONST, 1);
|
||||
break;
|
||||
case ZEND_FETCH_STATIC_PROP_R:
|
||||
case ZEND_FETCH_STATIC_PROP_W:
|
||||
|
@ -208,16 +191,10 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
case ZEND_UNSET_STATIC_PROP:
|
||||
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2);
|
||||
}
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
optimizer_literal_class_info(
|
||||
info,
|
||||
opline->op2_type,
|
||||
opline->op2,
|
||||
opline->op1.constant,
|
||||
LITERAL_STATIC_PROPERTY, 2, 1,
|
||||
op_array);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_STATIC_PROPERTY, 1);
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_CLASS:
|
||||
|
@ -225,12 +202,12 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
case ZEND_ADD_TRAIT:
|
||||
case ZEND_INSTANCEOF:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2);
|
||||
}
|
||||
break;
|
||||
case ZEND_NEW:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2);
|
||||
}
|
||||
break;
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
|
@ -247,13 +224,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
case ZEND_POST_DEC_OBJ:
|
||||
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
optimizer_literal_obj_info(
|
||||
info,
|
||||
opline->op1_type,
|
||||
opline->op1,
|
||||
opline->op2.constant,
|
||||
LITERAL_PROPERTY, 2, 1,
|
||||
op_array);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1);
|
||||
}
|
||||
break;
|
||||
case ZEND_ASSIGN_ADD:
|
||||
|
@ -270,47 +241,30 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
case ZEND_ASSIGN_BW_XOR:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
|
||||
optimizer_literal_obj_info(
|
||||
info,
|
||||
opline->op1_type,
|
||||
opline->op1,
|
||||
opline->op2.constant,
|
||||
LITERAL_PROPERTY, 2, 1,
|
||||
op_array);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1);
|
||||
} else {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_BIND_GLOBAL:
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 1);
|
||||
break;
|
||||
case ZEND_RECV_INIT:
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 0, 0, 1);
|
||||
if (Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) != (uint32_t)-1) {
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
}
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1);
|
||||
break;
|
||||
case ZEND_DECLARE_FUNCTION:
|
||||
case ZEND_DECLARE_CLASS:
|
||||
case ZEND_DECLARE_INHERITED_CLASS:
|
||||
case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 0, 0, 2);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2);
|
||||
break;
|
||||
case ZEND_RECV:
|
||||
case ZEND_RECV_VARIADIC:
|
||||
case ZEND_VERIFY_RETURN_TYPE:
|
||||
if (opline->op2.num != (uint32_t)-1) {
|
||||
opline->op2.num = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
}
|
||||
default:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
|
||||
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1);
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
|
||||
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -350,26 +304,15 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
}
|
||||
switch (Z_TYPE(op_array->literals[i])) {
|
||||
case IS_NULL:
|
||||
/* Only checking MAY_MERGE for IS_NULL here
|
||||
* is because only IS_NULL can be default value for class type hinting(RECV_INIT). */
|
||||
if ((info[i].flags & LITERAL_MAY_MERGE)) {
|
||||
if (l_null < 0) {
|
||||
l_null = j;
|
||||
if (i != j) {
|
||||
op_array->literals[j] = op_array->literals[i];
|
||||
info[j] = info[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
map[i] = l_null;
|
||||
} else {
|
||||
map[i] = j;
|
||||
if (l_null < 0) {
|
||||
l_null = j;
|
||||
if (i != j) {
|
||||
op_array->literals[j] = op_array->literals[i];
|
||||
info[j] = info[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
map[i] = l_null;
|
||||
break;
|
||||
case IS_FALSE:
|
||||
if (l_false < 0) {
|
||||
|
@ -422,34 +365,20 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
}
|
||||
break;
|
||||
case IS_STRING:
|
||||
if (info[i].flags & LITERAL_MAY_MERGE) {
|
||||
if (info[i].flags & LITERAL_EX_OBJ) {
|
||||
int key_len = sizeof("$this->") - 1 + Z_STRLEN(op_array->literals[i]);
|
||||
key = zend_string_alloc(key_len, 0);
|
||||
memcpy(ZSTR_VAL(key), "$this->", sizeof("$this->") - 1);
|
||||
memcpy(ZSTR_VAL(key) + sizeof("$this->") - 1, Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]) + 1);
|
||||
ZSTR_LEN(key) = key_len;
|
||||
} else if (info[i].flags & LITERAL_EX_CLASS) {
|
||||
int key_len;
|
||||
zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num];
|
||||
key_len = Z_STRLEN_P(class_name) + sizeof("::") - 1 + Z_STRLEN(op_array->literals[i]);
|
||||
key = zend_string_alloc(key_len, 0);
|
||||
memcpy(ZSTR_VAL(key), Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
|
||||
memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
|
||||
memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name) + sizeof("::") - 1,
|
||||
Z_STRVAL(op_array->literals[i]),
|
||||
Z_STRLEN(op_array->literals[i]) + 1);
|
||||
} else {
|
||||
key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0);
|
||||
}
|
||||
ZSTR_H(key) = zend_hash_func(ZSTR_VAL(key), ZSTR_LEN(key));
|
||||
ZSTR_H(key) += info[i].flags;
|
||||
if (LITERAL_NUM_RELATED(info[i].flags) == 1) {
|
||||
key = zend_string_copy(Z_STR(op_array->literals[i]));
|
||||
} else {
|
||||
key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0);
|
||||
ZSTR_H(key) = ZSTR_HASH(Z_STR(op_array->literals[i])) +
|
||||
LITERAL_NUM_RELATED(info[i].flags) - 1;
|
||||
}
|
||||
if ((info[i].flags & LITERAL_MAY_MERGE) &&
|
||||
(pos = zend_hash_find(&hash, key)) != NULL &&
|
||||
Z_TYPE(op_array->literals[i]) == Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) &&
|
||||
info[i].flags == info[Z_LVAL_P(pos)].flags) {
|
||||
|
||||
pos = zend_hash_find(&hash, key);
|
||||
if (pos != NULL &&
|
||||
Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) == IS_STRING &&
|
||||
LITERAL_NUM_RELATED(info[i].flags) == LITERAL_NUM_RELATED(info[Z_LVAL_P(pos)].flags) &&
|
||||
(LITERAL_NUM_RELATED(info[i].flags) != 2 ||
|
||||
((info[i].flags & LITERAL_KIND_MASK) != LITERAL_VALUE &&
|
||||
(info[Z_LVAL_P(pos)].flags & LITERAL_KIND_MASK) != LITERAL_VALUE))) {
|
||||
zend_string_release(key);
|
||||
map[i] = Z_LVAL_P(pos);
|
||||
zval_ptr_dtor_nogc(&op_array->literals[i]);
|
||||
|
@ -461,19 +390,13 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
}
|
||||
} else {
|
||||
map[i] = j;
|
||||
if (info[i].flags & LITERAL_MAY_MERGE) {
|
||||
ZVAL_LONG(&zv, j);
|
||||
zend_hash_add_new(&hash, key, &zv);
|
||||
zend_string_release(key);
|
||||
}
|
||||
ZVAL_LONG(&zv, j);
|
||||
zend_hash_add_new(&hash, key, &zv);
|
||||
zend_string_release(key);
|
||||
if (i != j) {
|
||||
op_array->literals[j] = op_array->literals[i];
|
||||
info[j] = info[i];
|
||||
}
|
||||
if (LITERAL_NUM_SLOTS(info[i].flags)) {
|
||||
Z_CACHE_SLOT(op_array->literals[j]) = cache_size;
|
||||
cache_size += LITERAL_NUM_SLOTS(info[i].flags) * sizeof(void*);
|
||||
}
|
||||
j++;
|
||||
n = LITERAL_NUM_RELATED(info[i].flags);
|
||||
while (n > 1) {
|
||||
|
@ -511,11 +434,19 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
break;
|
||||
}
|
||||
}
|
||||
zend_hash_destroy(&hash);
|
||||
zend_hash_clean(&hash);
|
||||
op_array->last_literal = j;
|
||||
op_array->cache_size = cache_size;
|
||||
|
||||
/* Update opcodes to use new literals table */
|
||||
const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int));
|
||||
memset(const_slot, -1, j * 6 * sizeof(int));
|
||||
class_slot = const_slot + j;
|
||||
func_slot = class_slot + j;
|
||||
bind_var_slot = func_slot + j;
|
||||
property_slot = bind_var_slot + j;
|
||||
method_slot = property_slot + j;
|
||||
|
||||
/* Update opcodes to use new literals table */
|
||||
cache_size = 0;
|
||||
opline = op_array->opcodes;
|
||||
end = opline + op_array->last;
|
||||
while (opline < end) {
|
||||
|
@ -525,8 +456,288 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
|||
if (opline->op2_type == IS_CONST) {
|
||||
opline->op2.constant = map[opline->op2.constant];
|
||||
}
|
||||
switch (opline->opcode) {
|
||||
case ZEND_RECV_INIT:
|
||||
if (class_name_type_hint(op_array, opline->op1.num)) {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
}
|
||||
break;
|
||||
case ZEND_RECV:
|
||||
case ZEND_RECV_VARIADIC:
|
||||
if (class_name_type_hint(op_array, opline->op1.num)) {
|
||||
opline->op2.num = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
}
|
||||
break;
|
||||
case ZEND_VERIFY_RETURN_TYPE:
|
||||
if (class_name_type_hint(op_array, 0)) {
|
||||
opline->op2.num = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
}
|
||||
break;
|
||||
case ZEND_ASSIGN_ADD:
|
||||
case ZEND_ASSIGN_SUB:
|
||||
case ZEND_ASSIGN_MUL:
|
||||
case ZEND_ASSIGN_DIV:
|
||||
case ZEND_ASSIGN_POW:
|
||||
case ZEND_ASSIGN_MOD:
|
||||
case ZEND_ASSIGN_SL:
|
||||
case ZEND_ASSIGN_SR:
|
||||
case ZEND_ASSIGN_CONCAT:
|
||||
case ZEND_ASSIGN_BW_OR:
|
||||
case ZEND_ASSIGN_BW_AND:
|
||||
case ZEND_ASSIGN_BW_XOR:
|
||||
if (opline->extended_value != ZEND_ASSIGN_OBJ) {
|
||||
break;
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
// op2 property
|
||||
if (opline->op1_type == IS_UNUSED &&
|
||||
property_slot[opline->op2.constant] >= 0) {
|
||||
(opline+1)->extended_value = property_slot[opline->op2.constant];
|
||||
} else {
|
||||
(opline+1)->extended_value = cache_size;
|
||||
cache_size += 2 * sizeof(void *);
|
||||
if (opline->op1_type == IS_UNUSED) {
|
||||
property_slot[opline->op2.constant] = (opline+1)->extended_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
case ZEND_FETCH_OBJ_R:
|
||||
case ZEND_FETCH_OBJ_W:
|
||||
case ZEND_FETCH_OBJ_RW:
|
||||
case ZEND_FETCH_OBJ_IS:
|
||||
case ZEND_FETCH_OBJ_UNSET:
|
||||
case ZEND_FETCH_OBJ_FUNC_ARG:
|
||||
case ZEND_UNSET_OBJ:
|
||||
case ZEND_PRE_INC_OBJ:
|
||||
case ZEND_PRE_DEC_OBJ:
|
||||
case ZEND_POST_INC_OBJ:
|
||||
case ZEND_POST_DEC_OBJ:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
// op2 property
|
||||
if (opline->op1_type == IS_UNUSED &&
|
||||
property_slot[opline->op2.constant] >= 0) {
|
||||
opline->extended_value = property_slot[opline->op2.constant];
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += 2 * sizeof(void *);
|
||||
if (opline->op1_type == IS_UNUSED) {
|
||||
property_slot[opline->op2.constant] = opline->extended_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
// op2 property
|
||||
if (opline->op1_type == IS_UNUSED &&
|
||||
property_slot[opline->op2.constant] >= 0) {
|
||||
opline->extended_value = property_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISSET);
|
||||
} else {
|
||||
opline->extended_value = cache_size | (opline->extended_value & ZEND_ISSET);
|
||||
cache_size += 2 * sizeof(void *);
|
||||
if (opline->op1_type == IS_UNUSED) {
|
||||
property_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISSET;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_INIT_FCALL:
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
case ZEND_INIT_NS_FCALL_BY_NAME:
|
||||
// op2 func
|
||||
if (func_slot[opline->op2.constant] >= 0) {
|
||||
opline->result.num = func_slot[opline->op2.constant];
|
||||
} else {
|
||||
opline->result.num = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
func_slot[opline->op2.constant] = opline->result.num;
|
||||
}
|
||||
break;
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
// op2 method
|
||||
if (opline->op1_type == IS_UNUSED &&
|
||||
method_slot[opline->op2.constant] >= 0) {
|
||||
opline->result.num = method_slot[opline->op2.constant];
|
||||
} else {
|
||||
opline->result.num = cache_size;
|
||||
cache_size += 2 * sizeof(void *);
|
||||
if (opline->op1_type == IS_UNUSED) {
|
||||
method_slot[opline->op2.constant] = opline->result.num;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
// op2 static method
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
opline->result.num = add_static_slot(&hash, op_array,
|
||||
opline->op1.constant,
|
||||
opline->op2.constant,
|
||||
LITERAL_STATIC_METHOD,
|
||||
&cache_size);
|
||||
} else {
|
||||
opline->result.num = cache_size;
|
||||
cache_size += 2 * sizeof(void *);
|
||||
}
|
||||
} else if (opline->op1_type == IS_CONST) {
|
||||
// op1 class
|
||||
if (class_slot[opline->op1.constant] >= 0) {
|
||||
opline->result.num = class_slot[opline->op1.constant];
|
||||
} else {
|
||||
opline->result.num = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
class_slot[opline->op1.constant] = opline->result.num;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_DEFINED:
|
||||
// op1 const
|
||||
if (const_slot[opline->op1.constant] >= 0) {
|
||||
opline->extended_value = const_slot[opline->op1.constant];
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
const_slot[opline->op1.constant] = opline->extended_value;
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_CONSTANT:
|
||||
// op2 const
|
||||
if (const_slot[opline->op2.constant] >= 0) {
|
||||
opline->extended_value = const_slot[opline->op2.constant];
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
const_slot[opline->op2.constant] = opline->extended_value;
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_CONSTANT:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
// op1/op2 class_const
|
||||
opline->extended_value = add_static_slot(&hash, op_array,
|
||||
opline->op1.constant,
|
||||
opline->op2.constant,
|
||||
LITERAL_CLASS_CONST,
|
||||
&cache_size);
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += 2 * sizeof(void *);
|
||||
}
|
||||
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:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
// op1 static property
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
opline->extended_value = add_static_slot(&hash, op_array,
|
||||
opline->op2.constant,
|
||||
opline->op1.constant,
|
||||
LITERAL_STATIC_PROPERTY,
|
||||
&cache_size);
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += 2 * sizeof(void *);
|
||||
}
|
||||
} else if (opline->op2_type == IS_CONST) {
|
||||
// op2 class
|
||||
if (class_slot[opline->op2.constant] >= 0) {
|
||||
opline->extended_value = class_slot[opline->op2.constant];
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
class_slot[opline->op2.constant] = opline->extended_value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
// op1 static property
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
opline->extended_value = add_static_slot(&hash, op_array,
|
||||
opline->op2.constant,
|
||||
opline->op1.constant,
|
||||
LITERAL_STATIC_PROPERTY,
|
||||
&cache_size) | (opline->extended_value & ZEND_ISSET);
|
||||
} else {
|
||||
opline->extended_value = cache_size | (opline->extended_value & ZEND_ISSET);
|
||||
cache_size += 2 * sizeof(void *);
|
||||
}
|
||||
} else if (opline->op2_type == IS_CONST) {
|
||||
// op2 class
|
||||
if (class_slot[opline->op2.constant] >= 0) {
|
||||
opline->extended_value = class_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISSET);
|
||||
} else {
|
||||
opline->extended_value = cache_size | (opline->extended_value & ZEND_ISSET);
|
||||
cache_size += sizeof(void *);
|
||||
class_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISSET;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_FETCH_CLASS:
|
||||
case ZEND_ADD_INTERFACE:
|
||||
case ZEND_ADD_TRAIT:
|
||||
case ZEND_INSTANCEOF:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
// op2 class
|
||||
if (class_slot[opline->op2.constant] >= 0) {
|
||||
opline->extended_value = class_slot[opline->op2.constant];
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
class_slot[opline->op2.constant] = opline->extended_value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_NEW:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
// op1 class
|
||||
if (class_slot[opline->op1.constant] >= 0) {
|
||||
opline->op2.num = class_slot[opline->op1.constant];
|
||||
} else {
|
||||
opline->op2.num = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
class_slot[opline->op1.constant] = opline->op2.num;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
// op1 class
|
||||
if (class_slot[opline->op1.constant] >= 0) {
|
||||
opline->extended_value = class_slot[opline->op1.constant] | (opline->extended_value & ZEND_LAST_CATCH);
|
||||
} else {
|
||||
opline->extended_value = cache_size | (opline->extended_value & ZEND_LAST_CATCH);
|
||||
cache_size += sizeof(void *);
|
||||
class_slot[opline->op1.constant] = opline->extended_value & ~ZEND_LAST_CATCH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_BIND_GLOBAL:
|
||||
// op2 bind var
|
||||
if (bind_var_slot[opline->op2.constant] >= 0) {
|
||||
opline->extended_value = bind_var_slot[opline->op2.constant];
|
||||
} else {
|
||||
opline->extended_value = cache_size;
|
||||
cache_size += sizeof(void *);
|
||||
bind_var_slot[opline->op2.constant] = opline->extended_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
opline++;
|
||||
}
|
||||
op_array->cache_size = cache_size;
|
||||
zend_hash_destroy(&hash);
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
|
||||
#if DEBUG_COMPACT_LITERALS
|
||||
|
|
|
@ -552,7 +552,7 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa
|
|||
}
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
if (ZEND_OP2_JMP_ADDR(opline) == op_array->opcodes + old->start) {
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, op_array->opcodes + dst->start);
|
||||
}
|
||||
|
|
|
@ -193,14 +193,12 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
|||
} else if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) {
|
||||
fcall->opcode = ZEND_INIT_FCALL;
|
||||
fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
|
||||
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
|
||||
literal_dtor(&ZEND_OP2_LITERAL(fcall));
|
||||
fcall->op2.constant = fcall->op2.constant + 1;
|
||||
opline->opcode = zend_get_call_op(fcall, call_stack[call].func);
|
||||
} else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
|
||||
fcall->opcode = ZEND_INIT_FCALL;
|
||||
fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
|
||||
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
|
||||
literal_dtor(&op_array->literals[fcall->op2.constant]);
|
||||
literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
|
||||
fcall->op2.constant = fcall->op2.constant + 1;
|
||||
|
|
|
@ -438,7 +438,7 @@ static inline int ct_eval_isset_dim(zval *result, uint32_t extended_value, zval
|
|||
// TODO
|
||||
return FAILURE;
|
||||
} else {
|
||||
ZVAL_BOOL(result, extended_value != ZEND_ISSET);
|
||||
ZVAL_BOOL(result, !(extended_value & ZEND_ISSET));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -592,7 +592,7 @@ static inline int ct_eval_isset_obj(zval *result, uint32_t extended_value, zval
|
|||
}
|
||||
return SUCCESS;
|
||||
} else {
|
||||
ZVAL_BOOL(result, extended_value != ZEND_ISSET);
|
||||
ZVAL_BOOL(result, !(extended_value & ZEND_ISSET));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -385,7 +385,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
|||
BB_START(i + 1);
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes);
|
||||
}
|
||||
BB_START(i + 1);
|
||||
|
@ -546,7 +546,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
|||
block->successors[1] = j + 1;
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
block->successors_count = 2;
|
||||
block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes];
|
||||
block->successors[1] = j + 1;
|
||||
|
|
|
@ -674,7 +674,7 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
|
|||
} else {
|
||||
uint32_t op2_flags = ZEND_VM_OP2_FLAGS(flags);
|
||||
if (ZEND_VM_OP_JMP_ADDR == (op2_flags & ZEND_VM_OP_MASK)) {
|
||||
if (opline->opcode != ZEND_CATCH || opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (opline->opcode != ZEND_CATCH || !(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
if (b) {
|
||||
fprintf(stderr, " BB%d", b->successors[n++]);
|
||||
} else {
|
||||
|
|
|
@ -206,7 +206,6 @@ int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv)
|
|||
op_array->last_literal++;
|
||||
op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval));
|
||||
ZVAL_COPY_VALUE(&op_array->literals[i], zv);
|
||||
Z_CACHE_SLOT(op_array->literals[i]) = -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -232,13 +231,10 @@ static inline void drop_leading_backslash(zval *val) {
|
|||
}
|
||||
}
|
||||
|
||||
static inline void alloc_cache_slots_op1(zend_op_array *op_array, zend_op *opline, uint32_t num) {
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size;
|
||||
op_array->cache_size += num * sizeof(void *);
|
||||
}
|
||||
static inline void alloc_cache_slots_op2(zend_op_array *op_array, zend_op *opline, uint32_t num) {
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
|
||||
static inline uint32_t alloc_cache_slots(zend_op_array *op_array, uint32_t num) {
|
||||
uint32_t ret = op_array->cache_size;
|
||||
op_array->cache_size += num * sizeof(void *);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define REQUIRES_STRING(val) do { \
|
||||
|
@ -275,15 +271,43 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
|||
case ZEND_RETURN_BY_REF:
|
||||
case ZEND_INSTANCEOF:
|
||||
return 0;
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_CATCH:
|
||||
case ZEND_FETCH_CLASS_CONSTANT:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
opline->extended_value = alloc_cache_slots(op_array, 1) | (opline->extended_value & ZEND_LAST_CATCH);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
break;
|
||||
case ZEND_DEFINED:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
opline->extended_value = alloc_cache_slots(op_array, 1);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
break;
|
||||
case ZEND_NEW:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
alloc_cache_slots_op1(op_array, opline, 1);
|
||||
opline->op2.num = alloc_cache_slots(op_array, 1);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
break;
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
if (opline->op2_type != IS_CONST) {
|
||||
opline->result.num = alloc_cache_slots(op_array, 1);
|
||||
}
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
break;
|
||||
case ZEND_FETCH_CLASS_CONSTANT:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
if (opline->op2_type != IS_CONST) {
|
||||
opline->extended_value = alloc_cache_slots(op_array, 1);
|
||||
}
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
break;
|
||||
case ZEND_FETCH_STATIC_PROP_R:
|
||||
|
@ -292,9 +316,23 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
|||
case ZEND_FETCH_STATIC_PROP_IS:
|
||||
case ZEND_FETCH_STATIC_PROP_UNSET:
|
||||
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
|
||||
case ZEND_UNSET_STATIC_PROP:
|
||||
TO_STRING_NOWARN(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
alloc_cache_slots_op1(op_array, opline, 2);
|
||||
if (opline->op2_type == IS_CONST && opline->extended_value + sizeof(void*) == op_array->cache_size) {
|
||||
op_array->cache_size += sizeof(void *);
|
||||
} else {
|
||||
opline->extended_value = alloc_cache_slots(op_array, 2);
|
||||
}
|
||||
break;
|
||||
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
|
||||
TO_STRING_NOWARN(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
if (opline->op2_type == IS_CONST && (opline->extended_value & ~ZEND_ISSET) + sizeof(void*) == op_array->cache_size) {
|
||||
op_array->cache_size += sizeof(void *);
|
||||
} else {
|
||||
opline->extended_value = alloc_cache_slots(op_array, 2) | (opline->extended_value & ZEND_ISSET);
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_VAR:
|
||||
opline->opcode = ZEND_SEND_VAL;
|
||||
|
@ -351,11 +389,22 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
|||
(opline + 1)->op2.var == opline->result.var) {
|
||||
return 0;
|
||||
}
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
/*case ZEND_INIT_NS_FCALL_BY_NAME:*/
|
||||
case ZEND_ADD_INTERFACE:
|
||||
case ZEND_ADD_TRAIT:
|
||||
case ZEND_INSTANCEOF:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
opline->extended_value = alloc_cache_slots(op_array, 1);
|
||||
break;
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
opline->result.num = alloc_cache_slots(op_array, 1);
|
||||
break;
|
||||
case ZEND_FETCH_STATIC_PROP_R:
|
||||
case ZEND_FETCH_STATIC_PROP_W:
|
||||
case ZEND_FETCH_STATIC_PROP_RW:
|
||||
|
@ -363,12 +412,22 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
|||
case ZEND_FETCH_STATIC_PROP_UNSET:
|
||||
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
|
||||
case ZEND_UNSET_STATIC_PROP:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
if (opline->op1_type != IS_CONST) {
|
||||
opline->extended_value = alloc_cache_slots(op_array, 1);
|
||||
}
|
||||
break;
|
||||
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
|
||||
REQUIRES_STRING(val);
|
||||
drop_leading_backslash(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
alloc_cache_slots_op2(op_array, opline, 1);
|
||||
if (opline->op1_type != IS_CONST) {
|
||||
opline->extended_value = alloc_cache_slots(op_array, 1) | (opline->extended_value & ZEND_ISSET);
|
||||
}
|
||||
break;
|
||||
case ZEND_INIT_FCALL:
|
||||
REQUIRES_STRING(val);
|
||||
|
@ -380,7 +439,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
|||
val = &tmp;
|
||||
}
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
alloc_cache_slots_op2(op_array, opline, 1);
|
||||
opline->result.num = alloc_cache_slots(op_array, 1);
|
||||
break;
|
||||
case ZEND_INIT_DYNAMIC_CALL:
|
||||
if (Z_TYPE_P(val) == IS_STRING) {
|
||||
|
@ -398,19 +457,25 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
|||
drop_leading_backslash(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
alloc_cache_slots_op2(op_array, opline, 1);
|
||||
opline->result.num = alloc_cache_slots(op_array, 1);
|
||||
} else {
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
}
|
||||
break;
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
REQUIRES_STRING(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
opline->result.num = alloc_cache_slots(op_array, 2);
|
||||
break;
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
REQUIRES_STRING(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
alloc_cache_slots_op2(op_array, opline, 2);
|
||||
if (opline->op1_type != IS_CONST) {
|
||||
opline->result.num = alloc_cache_slots(op_array, 2);
|
||||
}
|
||||
break;
|
||||
/*case ZEND_FETCH_CLASS_CONSTANT:*/
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
case ZEND_FETCH_OBJ_R:
|
||||
case ZEND_FETCH_OBJ_W:
|
||||
|
@ -423,10 +488,14 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
|||
case ZEND_PRE_DEC_OBJ:
|
||||
case ZEND_POST_INC_OBJ:
|
||||
case ZEND_POST_DEC_OBJ:
|
||||
TO_STRING_NOWARN(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
opline->extended_value = alloc_cache_slots(op_array, 2);
|
||||
break;
|
||||
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
|
||||
TO_STRING_NOWARN(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
alloc_cache_slots_op2(op_array, opline, 2);
|
||||
opline->extended_value = alloc_cache_slots(op_array, 2) | (opline->extended_value & ZEND_ISSET);
|
||||
break;
|
||||
case ZEND_ASSIGN_ADD:
|
||||
case ZEND_ASSIGN_SUB:
|
||||
|
@ -443,7 +512,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
|
|||
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
|
||||
TO_STRING_NOWARN(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
alloc_cache_slots_op2(op_array, opline, 2);
|
||||
(opline+1)->extended_value = alloc_cache_slots(op_array, 2);
|
||||
} else {
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
}
|
||||
|
@ -766,7 +835,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z
|
|||
new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline));
|
||||
}
|
||||
break;
|
||||
|
@ -806,7 +875,7 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_
|
|||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]);
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]);
|
||||
}
|
||||
break;
|
||||
|
@ -1174,7 +1243,7 @@ static void zend_redo_pass_two(zend_op_array *op_array)
|
|||
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes];
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes];
|
||||
}
|
||||
break;
|
||||
|
@ -1260,7 +1329,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
|
|||
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes];
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes];
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -447,7 +447,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
|
|||
SERIALIZE_PTR(opline->op2.jmp_addr);
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
SERIALIZE_PTR(opline->op2.jmp_addr);
|
||||
}
|
||||
break;
|
||||
|
@ -1053,7 +1053,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
|
|||
UNSERIALIZE_PTR(opline->op2.jmp_addr);
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
UNSERIALIZE_PTR(opline->op2.jmp_addr);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -453,7 +453,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
|||
opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
|
||||
break;
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value != ZEND_LAST_CATCH) {
|
||||
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
||||
opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -115,7 +115,7 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *opline) /*{{{ */
|
|||
/* RESULT */
|
||||
switch (opline->opcode) {
|
||||
case ZEND_CATCH:
|
||||
if (opline->extended_value == ZEND_LAST_CATCH) {
|
||||
if (opline->extended_value & ZEND_LAST_CATCH) {
|
||||
if (decode[2]) {
|
||||
efree(decode[2]);
|
||||
decode[2] = NULL;
|
||||
|
|
|
@ -764,16 +764,16 @@ PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zen
|
|||
while (1) {
|
||||
zend_class_entry *ce;
|
||||
|
||||
if (!(ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(cur, cur->op1))))) {
|
||||
if (!(ce = CACHED_PTR(cur->extended_value & ~ZEND_LAST_CATCH))) {
|
||||
ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(cur, cur->op1)), RT_CONSTANT(cur, cur->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(cur, cur->op1)), ce);
|
||||
CACHE_PTR(cur->extended_value & ~ZEND_LAST_CATCH, ce);
|
||||
}
|
||||
|
||||
if (ce == exception->ce || (ce && instanceof_function(exception->ce, ce))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cur->extended_value == ZEND_LAST_CATCH) {
|
||||
if (cur->extended_value & ZEND_LAST_CATCH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ prompt> [L7 %s ECHO<1> "ok\n"
|
|||
00009: } catch (Error $e) {
|
||||
prompt> ok
|
||||
[L7 %s FAST_RET ~%d try-catch(0) %s]
|
||||
[L9 %s CATCH<1> "Error" $e %s]
|
||||
[L9 %s CATCH<%d> "Error" $e %s]
|
||||
>00005: x();
|
||||
00006: } finally {
|
||||
00007: print "ok\n";
|
||||
|
|
|
@ -25,7 +25,7 @@ prompt> [L0 %s HANDLE_EXCEPTION
|
|||
00005: }
|
||||
00006:
|
||||
prompt> [L0 %s HANDLE_EXCEPTION %s]
|
||||
[L9 %s CATCH<1> "Exception" $e %s]
|
||||
[L9 %s CATCH<%d> "Exception" $e %s]
|
||||
>00008: foo();
|
||||
00009: } catch (Exception $e) {
|
||||
00010: echo "ok";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue