summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2010-08-11 15:34:06 +0000
committerDmitry Stogov <dmitry@php.net>2010-08-11 15:34:06 +0000
commitf48999ca3b9d6dd8f432e2b95c1a78c577e01ce7 (patch)
tree0bb98c68e01467bea64828feda9026cf90cbba45
parent931c2d104df3cf7f94a425ee287519365d28c420 (diff)
downloadphp-git-f48999ca3b9d6dd8f432e2b95c1a78c577e01ce7.tar.gz
Optimization of ASSIGN instruction
-rw-r--r--Zend/zend_execute.c99
-rw-r--r--Zend/zend_vm_def.h8
-rw-r--r--Zend/zend_vm_execute.h72
3 files changed, 130 insertions, 49 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 92f2231a55..0a22ffa0dd 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -819,6 +819,7 @@ static inline int zend_assign_to_string_offset(const temp_variable *T, const zva
static inline zval* zend_assign_tmp_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
{
zval *variable_ptr = *variable_ptr_ptr;
+ zval garbage;
if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
@@ -826,26 +827,63 @@ static inline zval* zend_assign_tmp_to_variable(zval **variable_ptr_ptr, zval *v
return variable_ptr;
}
- if (EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
- if (Z_REFCOUNT_P(variable_ptr)==1) {
- zendi_zval_dtor(*variable_ptr);
+ if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
+ EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
+ /* we need to split */
+ Z_DELREF_P(variable_ptr);
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ ALLOC_ZVAL(variable_ptr);
+ INIT_PZVAL_COPY(variable_ptr, value);
+ *variable_ptr_ptr = variable_ptr;
+ return variable_ptr;
+ } else {
+ if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
+ /* nothing to destroy */
ZVAL_COPY_VALUE(variable_ptr, value);
- return variable_ptr;
- } else { /* we need to split */
- Z_DELREF_P(variable_ptr);
- GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
- ALLOC_ZVAL(variable_ptr);
- INIT_PZVAL_COPY(variable_ptr, value);
- *variable_ptr_ptr = variable_ptr;
- return variable_ptr;
+ } else {
+ ZVAL_COPY_VALUE(&garbage, variable_ptr);
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
}
- } else {
- zendi_zval_dtor(*variable_ptr);
- ZVAL_COPY_VALUE(variable_ptr, value);
return variable_ptr;
}
}
+static inline zval* zend_assign_const_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
+{
+ zval *variable_ptr = *variable_ptr_ptr;
+ zval garbage;
+
+ if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
+ UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
+ Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
+ return variable_ptr;
+ }
+
+ if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
+ EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
+ /* we need to split */
+ Z_DELREF_P(variable_ptr);
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ ALLOC_ZVAL(variable_ptr);
+ INIT_PZVAL_COPY(variable_ptr, value);
+ zval_copy_ctor(variable_ptr);
+ *variable_ptr_ptr = variable_ptr;
+ return variable_ptr;
+ } else {
+ if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
+ /* nothing to destroy */
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ } else {
+ ZVAL_COPY_VALUE(&garbage, variable_ptr);
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
+ }
+ return variable_ptr;
+ }
+}
static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
{
@@ -860,24 +898,21 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value
if (EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
if (Z_REFCOUNT_P(variable_ptr)==1) {
- if (variable_ptr==value) {
- return variable_ptr;
- } else if (PZVAL_IS_REF(value)) {
- ZVAL_COPY_VALUE(&garbage, variable_ptr);
- ZVAL_COPY_VALUE(variable_ptr, value);
- zval_copy_ctor(variable_ptr);
- zendi_zval_dtor(garbage);
+ if (UNEXPECTED(variable_ptr == value)) {
return variable_ptr;
- } else {
- Z_DELREF_P(variable_ptr);
+ } else if (EXPECTED(!PZVAL_IS_REF(value))) {
Z_ADDREF_P(value);
*variable_ptr_ptr = value;
- if (variable_ptr != &EG(uninitialized_zval)) {
+ if (EXPECTED(variable_ptr != &EG(uninitialized_zval))) {
GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
zval_dtor(variable_ptr);
efree(variable_ptr);
+ } else {
+ Z_DELREF_P(variable_ptr);
}
return value;
+ } else {
+ goto copy_value;
}
} else { /* we need to split */
Z_DELREF_P(variable_ptr);
@@ -897,16 +932,22 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value
}
} else {
if (EXPECTED(variable_ptr != value)) {
- ZVAL_COPY_VALUE(&garbage, variable_ptr);
- ZVAL_COPY_VALUE(variable_ptr, value);
- zendi_zval_copy_ctor(*variable_ptr);
- zendi_zval_dtor(garbage);
+copy_value:
+ if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
+ /* nothing to destroy */
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ } else {
+ ZVAL_COPY_VALUE(&garbage, variable_ptr);
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
+ }
}
return variable_ptr;
}
}
-
/* Utility Functions for Extensions */
static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
{
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index bd326022d6..f25599f5bc 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1685,8 +1685,10 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -1739,8 +1741,10 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_OP2_TMP_FREE()) {
+ if (OP2_TYPE == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (OP2_TYPE == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index f4669f9019..87cbfbc5f2 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -12782,8 +12782,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -12836,8 +12838,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (0) {
+ if (IS_CONST == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CONST == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -14917,8 +14921,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -14971,8 +14977,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (1) {
+ if (IS_TMP_VAR == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_TMP_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -16970,8 +16978,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -17024,8 +17034,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (0) {
+ if (IS_VAR == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -18383,8 +18395,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -20001,8 +20015,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -20055,8 +20071,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (0) {
+ if (IS_CV == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CV == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -28290,8 +28308,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -28344,8 +28364,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (0) {
+ if (IS_CONST == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CONST == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -30208,8 +30230,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -30262,8 +30286,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (1) {
+ if (IS_TMP_VAR == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_TMP_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -32135,8 +32161,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -32189,8 +32217,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (0) {
+ if (IS_VAR == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -33425,8 +33455,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -34924,8 +34956,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (IS_TMP_FREE(free_op_data1)) {
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}
@@ -34978,8 +35012,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- if (0) {
+ if (IS_CV == IS_TMP_VAR) {
value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CV == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
} else {
value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
}