diff options
| -rw-r--r-- | Zend/zend_execute.c | 33 | ||||
| -rw-r--r-- | Zend/zend_vm_def.h | 26 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.h | 234 | 
3 files changed, 260 insertions, 33 deletions
| diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0da6b32ef9..5fb0003986 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1812,19 +1812,21 @@ static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, z  	zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET);  } -static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, int support_strings) +static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, int support_strings, int slow)  {  	zval *retval; -	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -try_array: -		retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type); -		ZVAL_COPY(result, retval); -		return; -	} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { -		container = Z_REFVAL_P(container); +	if (!slow) {  		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { -			goto try_array; +try_array: +			retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type); +			ZVAL_COPY(result, retval); +			return; +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto try_array; +			}  		}  	}  	if (support_strings && EXPECTED(Z_TYPE_P(container) == IS_STRING)) { @@ -1921,17 +1923,22 @@ try_string_offset:  static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type)  { -	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1); +	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1, 0); +} + +static zend_never_inline void zend_fetch_dimension_address_read_R_slow(zval *result, zval *container, zval *dim) +{ +	zend_fetch_dimension_address_read(result, container, dim, IS_CV, BP_VAR_R, 1, 1);  }  static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type)  { -	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1); +	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0);  }  static zend_never_inline void zend_fetch_dimension_address_read_LIST(zval *result, zval *container, zval *dim)  { -	zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, BP_VAR_R, 0); +	zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, BP_VAR_R, 0, 0);  }  ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim) @@ -1941,7 +1948,7 @@ ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *  ZEND_API void zend_fetch_dimension_by_zval_is(zval *result, zval *container, zval *dim, int dim_type)  { -	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1); +	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0);  } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c4a97ab056..0ad1f57845 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1734,11 +1734,33 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)  {  	USE_OPLINE  	zend_free_op free_op1, free_op2; -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE); +	dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); +	if (OP1_TYPE != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +ZEND_VM_C_LABEL(fetch_dim_r_array): +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, OP2_TYPE, BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				ZEND_VM_C_GOTO(fetch_dim_r_array); +			} else { +				ZEND_VM_C_GOTO(fetch_dim_r_slow); +			} +		} else { +ZEND_VM_C_LABEL(fetch_dim_r_slow): +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, OP2_TYPE); +	}  	FREE_OP2();  	FREE_OP1();  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fc6f02a055..eff4305dec 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4831,11 +4831,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_H  {  	USE_OPLINE -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = EX_CONSTANT(opline->op1); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); +	dim = EX_CONSTANT(opline->op2); +	if (IS_CONST != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, IS_CONST); +	}  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -8580,11 +8602,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HAND  {  	USE_OPLINE -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = EX_CONSTANT(opline->op1); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_undef(execute_data, opline->op2.var), IS_CV); +	dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); +	if (IS_CONST != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, IS_CV); +	}  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -10415,11 +10459,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_  {  	USE_OPLINE  	zend_free_op free_op2; -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = EX_CONSTANT(opline->op1); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); +	dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); +	if (IS_CONST != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, (IS_TMP_VAR|IS_VAR)); +	}  	zval_ptr_dtor_nogc(free_op2);  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -40065,11 +40131,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HAND  {  	USE_OPLINE -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); +	dim = EX_CONSTANT(opline->op2); +	if (IS_CV != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, IS_CONST); +	}  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -47056,11 +47144,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER  {  	USE_OPLINE -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_undef(execute_data, opline->op2.var), IS_CV); +	dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); +	if (IS_CV != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, IS_CV); +	}  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -51176,11 +51286,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HAN  {  	USE_OPLINE  	zend_free_op free_op2; -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); +	dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); +	if (IS_CV != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, (IS_TMP_VAR|IS_VAR)); +	}  	zval_ptr_dtor_nogc(free_op2);  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -54643,11 +54775,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_  {  	USE_OPLINE  	zend_free_op free_op1; -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); +	dim = EX_CONSTANT(opline->op2); +	if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, IS_CONST); +	}  	zval_ptr_dtor_nogc(free_op1);  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -56904,11 +57058,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HAN  {  	USE_OPLINE  	zend_free_op free_op1; -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_undef(execute_data, opline->op2.var), IS_CV); +	dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); +	if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, IS_CV); +	}  	zval_ptr_dtor_nogc(free_op1);  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -58068,11 +58244,33 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR  {  	USE_OPLINE  	zend_free_op free_op1, free_op2; -	zval *container; +	zval *container, *dim, *value, *result;  	SAVE_OPLINE();  	container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); -	zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); +	dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); +	if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { +		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: +			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R); +			result = EX_VAR(opline->result.var); +			ZVAL_COPY(result, value); +		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { +			container = Z_REFVAL_P(container); +			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +				goto fetch_dim_r_array; +			} else { +				goto fetch_dim_r_slow; +			} +		} else { +fetch_dim_r_slow: +			result = EX_VAR(opline->result.var); +			zend_fetch_dimension_address_read_R_slow(result, container, dim); +		} +	} else { +		result = EX_VAR(opline->result.var); +		zend_fetch_dimension_address_read_R(result, container, dim, (IS_TMP_VAR|IS_VAR)); +	}  	zval_ptr_dtor_nogc(free_op2);  	zval_ptr_dtor_nogc(free_op1);  	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | 
