From 6a911e833f6b6dcac669a60808e96dc2c4f391d3 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 30 Apr 2014 11:23:19 +0400 Subject: [PATCH] Optimized JMPZNZ to avoid multiplication at runtime (may be it makes sense to use relative addresses everywere it'll lead to Position Independent Code) --- Zend/zend_execute.c | 4 ++++ Zend/zend_execute_API.c | 4 ++++ Zend/zend_opcode.c | 4 ++++ Zend/zend_vm_def.h | 4 ++-- Zend/zend_vm_execute.h | 16 ++++++++-------- ext/opcache/Optimizer/zend_optimizer.c | 8 ++++++++ ext/opcache/zend_persist.c | 7 ++++++- 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 22acd4e9609..8b3ea40eb6d 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1731,6 +1731,10 @@ static zend_always_inline zval *zend_vm_stack_push_args(int count TSRMLS_DC) /* CHECK_SYMBOL_TABLES() \ OPLINE = new_op +#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \ + CHECK_SYMBOL_TABLES() \ + OPLINE = ((zend_op*)(((char*)opline)+(offset))) + #define ZEND_VM_JMP(new_op) \ if (EXPECTED(!EG(exception))) { \ ZEND_VM_SET_OPCODE(new_op); \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 03f763ea216..a7d7a948a51 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1301,6 +1301,10 @@ void execute_new_code(TSRMLS_D) /* {{{ */ case ZEND_JMP: opline->op1.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.opline_num]; break; + case ZEND_JMPZNZ: + /* absolute index to relative offset */ + opline->extended_value = (char*)(CG(active_op_array)->opcodes + opline->extended_value) - (char*)opline; + /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index e38a32a851e..d1c4e681e14 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -683,6 +683,10 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) case ZEND_FAST_CALL: opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; break; + case ZEND_JMPZNZ: + /* absolute index to relative offset */ + opline->extended_value = (char*)(op_array->opcodes + opline->extended_value) - (char*)opline; + /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1cfd7650c82..4c4115b7616 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2180,13 +2180,13 @@ ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMP|VAR|CV, ANY) #if DEBUG_ZEND>=2 printf("Conditional jmp on true to %d\n", opline->extended_value); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); /* CHECK_ME */ } else { #if DEBUG_ZEND>=2 printf("Conditional jmp on false to %d\n", opline->op2.opline_num); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); ZEND_VM_CONTINUE(); /* CHECK_ME */ } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4e109707981..41b907e8028 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2464,13 +2464,13 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG #if DEBUG_ZEND>=2 printf("Conditional jmp on true to %d\n", opline->extended_value); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); /* CHECK_ME */ } else { #if DEBUG_ZEND>=2 printf("Conditional jmp on false to %d\n", opline->op2.opline_num); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); ZEND_VM_CONTINUE(); /* CHECK_ME */ } } @@ -7564,13 +7564,13 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) #if DEBUG_ZEND>=2 printf("Conditional jmp on true to %d\n", opline->extended_value); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); /* CHECK_ME */ } else { #if DEBUG_ZEND>=2 printf("Conditional jmp on false to %d\n", opline->op2.opline_num); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); ZEND_VM_CONTINUE(); /* CHECK_ME */ } } @@ -12603,13 +12603,13 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) #if DEBUG_ZEND>=2 printf("Conditional jmp on true to %d\n", opline->extended_value); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); /* CHECK_ME */ } else { #if DEBUG_ZEND>=2 printf("Conditional jmp on false to %d\n", opline->op2.opline_num); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); ZEND_VM_CONTINUE(); /* CHECK_ME */ } } @@ -29533,13 +29533,13 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) #if DEBUG_ZEND>=2 printf("Conditional jmp on true to %d\n", opline->extended_value); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); /* CHECK_ME */ } else { #if DEBUG_ZEND>=2 printf("Conditional jmp on false to %d\n", opline->op2.opline_num); #endif - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_SET_OPCODE(opline->op2.jmp_addr); ZEND_VM_CONTINUE(); /* CHECK_ME */ } } diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 39f7b01eead..2b6b07ca82a 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -497,6 +497,10 @@ static void zend_accel_optimize(zend_op_array *op_array, #endif ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes; break; + case ZEND_JMPZNZ: + /* relative offset into absolute index */ + opline->extended_value = (zend_op*)(((char*)opline) + opline->extended_value) - op_array->opcodes; + /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: @@ -538,6 +542,10 @@ static void zend_accel_optimize(zend_op_array *op_array, #endif ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num]; break; + case ZEND_JMPZNZ: + /* absolute index to relative offset */ + opline->extended_value = (char*)(op_array->opcodes + opline->extended_value) - (char*)opline; + /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 0130e12d075..601849b0123 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -275,6 +275,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes]; } break; + case ZEND_JMPZNZ: + /* relative extended_value don't have to be changed */ + /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: @@ -284,7 +287,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes]; } break; - case ZEND_JMPZNZ: case ZEND_BRK: case ZEND_CONT: has_jmp = 1; @@ -323,6 +325,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc #endif ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes]; break; + case ZEND_JMPZNZ: + /* relative extended_value don't have to be changed */ + /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: