From e499c3d25930ffc16d330b9b28ab2e70863dbce7 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 6 Jun 2014 15:04:30 +0400 Subject: [PATCH] Introduced new BIND_GLOBAL instraction instead of FETCH_W+ASSIGN_REF pair that caused a lot of useles checks --- Zend/zend_compile.c | 36 ++++++++++++++++++--------- Zend/zend_vm_def.h | 30 +++++++++++++++++++++++ Zend/zend_vm_execute.h | 55 ++++++++++++++++++++++++++++++++++++++++++ Zend/zend_vm_opcodes.c | 3 ++- Zend/zend_vm_opcodes.h | 1 + 5 files changed, 112 insertions(+), 13 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c84937b645..de45b5a683 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6257,21 +6257,33 @@ void zend_do_fetch_global_variable(znode *varname, const znode *static_assignmen } opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */ - opline->result_type = IS_VAR; - opline->result.var = get_temporary_variable(CG(active_op_array)); - SET_NODE(opline->op1, varname); - SET_UNUSED(opline->op2); - opline->extended_value = fetch_type; - GET_NODE(&result, opline->result); - if (varname->op_type == IS_CONST) { + if (varname->op_type == IS_CONST && + !zend_is_auto_global(Z_STR(varname->u.constant) TSRMLS_CC) && + !(Z_STRLEN(varname->u.constant) == (sizeof("this")-1) && + !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1))) { + opline->opcode = ZEND_BIND_GLOBAL; + SET_NODE(opline->op2, varname); + opline->op1_type = IS_CV; zval_copy_ctor(&varname->u.constant); - } - fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */ + opline->op1.var = lookup_cv(CG(active_op_array), Z_STR(varname->u.constant) TSRMLS_CC); + } else { + opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */ + opline->result_type = IS_VAR; + opline->result.var = get_temporary_variable(CG(active_op_array)); + SET_NODE(opline->op1, varname); + SET_UNUSED(opline->op2); + opline->extended_value = fetch_type; + GET_NODE(&result, opline->result); - zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC); - CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED; + if (varname->op_type == IS_CONST) { + zval_copy_ctor(&varname->u.constant); + } + fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */ + + zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC); + CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED; + } } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8aa60ce3cd..9542419b39 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5624,4 +5624,34 @@ ZEND_VM_HANDLER(167, ZEND_ASSIGN_POW, VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV) ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op,pow_function); } +ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *varname; + zval *value; + zval *variable_ptr; + zend_string *name; + + SAVE_OPLINE(); + varname = GET_OP2_ZVAL_PTR(BP_VAR_R); + name = Z_STR_P(varname); + value = zend_hash_find(&EG(symbol_table).ht, name); + if (value == NULL) { + value = zend_hash_add_new(&EG(symbol_table).ht, name, &EG(uninitialized_zval)); + /* GLOBAL variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) == IS_UNDEF) { + ZVAL_NULL(value); + } + } + + variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); + zend_assign_to_variable_reference(variable_ptr, value TSRMLS_CC); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1babe8587c..b1198b2c6a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -33168,6 +33168,36 @@ static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND return zend_binary_assign_op_helper_SPEC_CV_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *varname; + zval *value; + zval *variable_ptr; + zend_string *name; + + SAVE_OPLINE(); + varname = opline->op2.zv; + name = Z_STR_P(varname); + value = zend_hash_find(&EG(symbol_table).ht, name); + if (value == NULL) { + value = zend_hash_add_new(&EG(symbol_table).ht, name, &EG(uninitialized_zval)); + /* GLOBAL variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) == IS_UNDEF) { + ZVAL_NULL(value); + } + } + + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + zend_assign_to_variable_reference(variable_ptr, value TSRMLS_CC); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -44468,6 +44498,31 @@ void zend_init_opcodes_handlers(void) ZEND_ASSIGN_POW_SPEC_CV_VAR_HANDLER, ZEND_ASSIGN_POW_SPEC_CV_UNUSED_HANDLER, ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 23edabc47f..df127039c6 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -21,7 +21,7 @@ #include #include -const char *zend_vm_opcodes_map[168] = { +const char *zend_vm_opcodes_map[169] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -190,6 +190,7 @@ const char *zend_vm_opcodes_map[168] = { "ZEND_SEND_UNPACK", "ZEND_POW", "ZEND_ASSIGN_POW", + "ZEND_BIND_GLOBAL", }; ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index f9c30ca126..df499f946b 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -173,5 +173,6 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode); #define ZEND_SEND_UNPACK 165 #define ZEND_POW 166 #define ZEND_ASSIGN_POW 167 +#define ZEND_BIND_GLOBAL 168 #endif -- 2.40.0