]> granicus.if.org Git - php/commitdiff
Implemented builtin instruction for strlen()
authorDmitry Stogov <dmitry@zend.com>
Mon, 14 Jul 2014 11:43:11 +0000 (15:43 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 14 Jul 2014 11:43:11 +0000 (15:43 +0400)
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.c
Zend/zend_vm_opcodes.h
ext/opcache/Optimizer/compact_literals.c
ext/opcache/Optimizer/pass1_5.c
ext/opcache/Optimizer/zend_optimizer.c

index 2350047af543548bb830eec4c9519f804da429ad..dadace094801cb0545e5bedc95d7ef7b8a796e24 100644 (file)
@@ -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) {
index 93c6795fb92b527bd76288cd35ed625f02f8ee8c..b9c45fe0ed9ba1100ecf8b1ca9ae508d30cc8057 100644 (file)
@@ -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)
index dab0fc5e5e587756168edfe9d9bfd1878483d787..950f487c0058e1a30a5b944eab06cc63d4706a4f 100644 (file)
@@ -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,
index f99a34a0216d5dbd18bac17362a16f5594ab4993..729f9229630f606f4a71b048fd9b6e475efdb5f9 100644 (file)
@@ -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,
index c4be566726d136dc7f03af2420ed3b3cceff5865..9274d3e044afab7f3b751a89bb01926ef2f68919 100644 (file)
@@ -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
index 61a50a9bc53848de01d98dafd6b46f994f27c458..b97fda9ab1cc803ef4d21ab65bc45b01e036d7a0 100644 (file)
@@ -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)) {
index c1235b637e0bba1d74e508951a7948422df2f899..b2e5b1cb3c9406a57ac3e1aec28eda0a95e42363 100644 (file)
@@ -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 &&
index 3b6595485b42d74f2ade331c94064d9379c97f1c..e4e1f74acc468440a453473433588802cc8ffdd0 100644 (file)
@@ -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++;