diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-07-14 15:43:11 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-07-14 15:43:11 +0400 |
commit | af7cb1690781cb05cb25b2a30ee4e6d446d0e660 (patch) | |
tree | b7b5687343a8ba211a70cba1666e8cc0e875244d | |
parent | 42c4bcaed12fcfc2451838e615e584a1d61a5228 (diff) | |
download | php-git-af7cb1690781cb05cb25b2a30ee4e6d446d0e660.tar.gz |
Implemented builtin instruction for strlen()
-rw-r--r-- | Zend/zend_compile.c | 38 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 20 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 30 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.c | 2 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.h | 1 | ||||
-rw-r--r-- | ext/opcache/Optimizer/compact_literals.c | 3 | ||||
-rw-r--r-- | ext/opcache/Optimizer/pass1_5.c | 13 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 1 |
8 files changed, 102 insertions, 6 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2350047af5..dadace0948 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2799,6 +2799,36 @@ static int zend_do_convert_type_check(zend_op *init_opline, znode *result, zend_ } /* }}} */ +static int zend_do_convert_defined(zend_op *init_opline, znode *result TSRMLS_DC) /* {{{ */ +{ + zval c; + zend_string *lc_name; + zend_op *opline = init_opline + 1; + + if (opline->opcode != ZEND_SEND_VAL || + opline->op1_type != IS_CONST || + Z_TYPE(CONSTANT(opline->op1.constant)) != IS_STRING + || zend_memrchr(Z_STRVAL(CONSTANT(opline->op1.constant)), '\\', Z_STRLEN(CONSTANT(opline->op1.constant))) != NULL + || zend_memrchr(Z_STRVAL(CONSTANT(opline->op1.constant)), ':', Z_STRLEN(CONSTANT(opline->op1.constant))) != NULL) { + return 0; + } + + MAKE_NOP(init_opline); + opline->opcode = ZEND_DEFINED; + opline->extended_value = 0; + GET_CACHE_SLOT(opline->op1.constant); + /* lowcase constant name */ + lc_name = STR_ALLOC(Z_STRLEN(CONSTANT(opline->op1.constant)), 0); + zend_str_tolower_copy(lc_name->val, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant))); + ZVAL_NEW_STR(&c, lc_name); + zend_add_literal(CG(active_op_array), &c); + opline->result.var = get_temporary_variable(CG(active_op_array)); + opline->result_type = IS_TMP_VAR; + GET_NODE(result, opline->result); + return 1; +} +/* }}} */ + void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */ { zend_op *opline; @@ -2836,6 +2866,14 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho fcall->arg_num = 0; } } + } else if (func->common.function_name->len == sizeof("defined")-1 && + memcmp(func->common.function_name->val, "defined", sizeof("defined")-1) == 0) { + if (fcall->arg_num == 1) { + if (zend_do_convert_defined(opline, result TSRMLS_CC)) { + zend_stack_del_top(&CG(function_call_stack)); + return; + } + } } else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 && func->common.function_name->len == sizeof("strlen")-1 && memcmp(func->common.function_name->val, "strlen", sizeof("strlen")-1) == 0) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 93c6795fb9..b9c45fe0ed 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5935,4 +5935,24 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY) +{ + USE_OPLINE + zval *name; + zend_constant *c; + + SAVE_OPLINE(); + name = GET_OP1_ZVAL_PTR(BP_VAR_R); + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } else if ((c = zend_quick_get_constant(opline->op1.zv, 0 TSRMLS_CC)) == NULL) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } else { + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), c); + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_EXPORT_HANDLER(zend_do_fcall, ZEND_DO_FCALL) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index dab0fc5e5e..950f487c00 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3450,6 +3450,26 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *name; + zend_constant *c; + + SAVE_OPLINE(); + name = opline->op1.zv; + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } else if ((c = zend_quick_get_constant(opline->op1.zv, 0 TSRMLS_CC)) == NULL) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } else { + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), c); + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -44000,11 +44020,11 @@ void zend_init_opcodes_handlers(void) ZEND_STRLEN_SPEC_CV_HANDLER, ZEND_STRLEN_SPEC_CV_HANDLER, ZEND_STRLEN_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_DEFINED_SPEC_CONST_HANDLER, + ZEND_DEFINED_SPEC_CONST_HANDLER, + ZEND_DEFINED_SPEC_CONST_HANDLER, + ZEND_DEFINED_SPEC_CONST_HANDLER, + ZEND_DEFINED_SPEC_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index f99a34a021..729f922963 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -144,7 +144,7 @@ const char *zend_vm_opcodes_map[169] = { "ZEND_SEND_ARRAY", "ZEND_SEND_USER", "ZEND_STRLEN", - NULL, + "ZEND_DEFINED", "ZEND_TYPE_CHECK", NULL, NULL, diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index c4be566726..9274d3e044 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -145,6 +145,7 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode); #define ZEND_SEND_ARRAY 119 #define ZEND_SEND_USER 120 #define ZEND_STRLEN 121 +#define ZEND_DEFINED 122 #define ZEND_TYPE_CHECK 123 #define ZEND_PRE_INC_OBJ 132 #define ZEND_PRE_DEC_OBJ 133 diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c index 61a50a9bc5..b97fda9ab1 100644 --- a/ext/opcache/Optimizer/compact_literals.c +++ b/ext/opcache/Optimizer/compact_literals.c @@ -147,6 +147,9 @@ static void optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_c case ZEND_CATCH: LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); break; + case ZEND_DEFINED: + 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)) { diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index c1235b637e..b2e5b1cb3c 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -468,6 +468,19 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { MAKE_NOP(opline); } break; + case ZEND_DEFINED: + { + zval c; + zend_uint tv = ZEND_RESULT(opline).var; + if (!zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0 TSRMLS_CC)) { + break; + } + ZVAL_TRUE(&c); + replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC); + literal_dtor(&ZEND_OP1_LITERAL(opline)); + MAKE_NOP(opline); + } + break; #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO case ZEND_DECLARE_CONST: if (collect_constants && diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 3b6595485b..e4e1f74acc 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -171,6 +171,7 @@ static void update_op1_const(zend_op_array *op_array, case ZEND_INIT_STATIC_METHOD_CALL: case ZEND_CATCH: case ZEND_FETCH_CONSTANT: + case ZEND_DEFINED: opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC); STR_HASH_VAL(Z_STR(ZEND_OP1_LITERAL(opline))); Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++; |