Skip to content

Instantly share code, notes, and snippets.

@laruence
Created July 13, 2014 02:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laruence/10a37813fcb5938ea1f9 to your computer and use it in GitHub Desktop.
Save laruence/10a37813fcb5938ea1f9 to your computer and use it in GitHub Desktop.
defined handler
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 56d0d97..5331b4b 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2751,6 +2751,27 @@ static int zend_do_convert_strlen(zend_op *init_opline, znode *result TSRMLS_DC)
}
/* }}} */
+static int zend_do_convert_defined(zend_op *init_opline, znode *result TSRMLS_DC) /* {{{ */
+{
+ 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) {
+ return 0;
+ }
+
+ MAKE_NOP(init_opline);
+ opline->opcode = ZEND_DEFINED;
+ opline->extended_value = 0;
+ GET_CACHE_SLOT(opline->op1.constant);
+ 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;
@@ -2788,6 +2809,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 dfe6651..e8d3aa4 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -5884,4 +5884,23 @@ ZEND_VM_C_LABEL(strlen_error):
ZEND_VM_NEXT_OPCODE();
}
+ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY)
+{
+ USE_OPLINE
+ zval *name, *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_get_constant_ex(Z_STR_P(name), NULL, ZEND_FETCH_CLASS_SILENT 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 ecd15ff..a883a29 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3399,6 +3399,25 @@ strlen_error:
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *name, *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_get_constant_ex(Z_STR_P(name), NULL, ZEND_FETCH_CLASS_SILENT 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
@@ -43796,11 +43815,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 7ae371e..6bb6d78 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",
NULL,
NULL,
NULL,
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index 1c20fc6..51516c1 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_PRE_INC_OBJ 132
#define ZEND_PRE_DEC_OBJ 133
#define ZEND_POST_INC_OBJ 134
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index 61a50a9..7790afb 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, 1);
+ 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 c1235b6..b2e5b1c 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 &&
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment