From 14e6ee7f42723c2e47bb0dd60ab0993ad3fcdd2a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 11 Jun 2014 11:39:42 +0400 Subject: [PATCH] Use absolute addresses as branch targets for NEW, FE_RESET and FE_FETCH --- Zend/zend_execute_API.c | 3 +++ Zend/zend_opcode.c | 3 +++ Zend/zend_vm_def.h | 16 +++++++-------- Zend/zend_vm_execute.h | 28 +++++++++++++------------- ext/opcache/Optimizer/zend_optimizer.c | 6 ++++++ ext/opcache/zend_persist.c | 3 +++ 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 9a74a0d3fb..c95986b7b0 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1192,6 +1192,9 @@ void execute_new_code(TSRMLS_D) /* {{{ */ case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_JMP_SET_VAR: + case ZEND_NEW: + case ZEND_FE_RESET: + case ZEND_FE_FETCH: opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num]; break; } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 37875dca57..2cd0a1bf7d 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -693,6 +693,9 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_JMP_SET_VAR: + case ZEND_NEW: + case ZEND_FE_RESET: + case ZEND_FE_FETCH: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; break; case ZEND_RETURN: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6bf4c7c629..86fcb44c34 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3523,7 +3523,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY) } else { zval_ptr_dtor(&object_zval); } - ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } else { call_slot *call = EX(call_slots) + opline->extended_value; @@ -4290,7 +4290,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } ce = Z_OBJCE_P(array_ptr); @@ -4430,7 +4430,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) FREE_OP1_VAR_PTR(); } if (is_empty) { - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } else { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4465,7 +4465,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) default: case ZEND_ITER_INVALID: zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); case ZEND_ITER_PLAIN_OBJECT: { zend_object *zobj = Z_OBJ_P(array); @@ -4478,7 +4478,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) while (1) { if ((value = zend_hash_get_current_data(fe_ht)) == NULL) { /* reached end of iteration */ - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } if (Z_TYPE_P(value) == IS_INDIRECT) { @@ -4520,7 +4520,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var)); if ((value = zend_hash_get_current_data(fe_ht)) == NULL) { /* reached end of iteration */ - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } if (key) { zend_hash_get_current_key_zval(fe_ht, key); @@ -4547,7 +4547,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) zval_ptr_dtor(array_ref); HANDLE_EXCEPTION(); } - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } value = iter->funcs->get_current_data(iter TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { @@ -4556,7 +4556,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) } if (!value) { /* failure in get_current_data */ - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } if (key) { if (iter->funcs->get_current_key) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d979ce4d81..7961f10adf 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -988,7 +988,7 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval_ptr_dtor(&object_zval); } - ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } else { call_slot *call = EX(call_slots) + opline->extended_value; @@ -3061,7 +3061,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } ce = Z_OBJCE_P(array_ptr); @@ -3201,7 +3201,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } if (is_empty) { - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } else { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -8251,7 +8251,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } ce = Z_OBJCE_P(array_ptr); @@ -8391,7 +8391,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (is_empty) { - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } else { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -13502,7 +13502,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } ce = Z_OBJCE_P(array_ptr); @@ -13642,7 +13642,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; } if (is_empty) { - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } else { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -13677,7 +13677,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG default: case ZEND_ITER_INVALID: zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); case ZEND_ITER_PLAIN_OBJECT: { zend_object *zobj = Z_OBJ_P(array); @@ -13690,7 +13690,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG while (1) { if ((value = zend_hash_get_current_data(fe_ht)) == NULL) { /* reached end of iteration */ - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } if (Z_TYPE_P(value) == IS_INDIRECT) { @@ -13732,7 +13732,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var)); if ((value = zend_hash_get_current_data(fe_ht)) == NULL) { /* reached end of iteration */ - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } if (key) { zend_hash_get_current_key_zval(fe_ht, key); @@ -13759,7 +13759,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval_ptr_dtor(array_ref); HANDLE_EXCEPTION(); } - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } value = iter->funcs->get_current_data(iter TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { @@ -13768,7 +13768,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (!value) { /* failure in get_current_data */ - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } if (key) { if (iter->funcs->get_current_key) { @@ -30723,7 +30723,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } ce = Z_OBJCE_P(array_ptr); @@ -30863,7 +30863,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } if (is_empty) { - ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); + ZEND_VM_JMP(opline->op2.jmp_addr); } else { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 657a3f4b52..029f0846dd 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -533,6 +533,9 @@ static void zend_accel_optimize(zend_op_array *op_array, #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO case ZEND_JMP_SET_VAR: #endif + case ZEND_NEW: + case ZEND_FE_RESET: + case ZEND_FE_FETCH: ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes; break; } @@ -578,6 +581,9 @@ static void zend_accel_optimize(zend_op_array *op_array, #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO case ZEND_JMP_SET_VAR: #endif + case ZEND_NEW: + case ZEND_FE_RESET: + case ZEND_FE_FETCH: ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num]; break; } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index ccdde640e1..bc88df69cf 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -437,6 +437,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO case ZEND_JMP_SET_VAR: #endif + case ZEND_NEW: + case ZEND_FE_RESET: + case ZEND_FE_FETCH: ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes]; break; } -- 2.40.0