diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-12-12 10:19:41 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-12-12 10:19:41 +0300 |
commit | 14e29f51460ecd1ec9ae7a26dfb9dcb2c81768d5 (patch) | |
tree | 98658f59f7973c3bcc538ddea39e3a4953fb325c /Zend/zend_opcode.c | |
parent | 9ea35a37b9425fc0dc392a754dac7e53791f5521 (diff) | |
download | php-git-14e29f51460ecd1ec9ae7a26dfb9dcb2c81768d5.tar.gz |
Reduced size of zend_op on 64-bit systems.
the main idea - the smaller the zend_op structure, the lees memory traffic is required to load VM instructions during execution. The patch reduces the size of each opcode from 48 to 32 bytes (saves 16 bytes for each opcode, and applications use thousands of opoceds). This reduced the number of CPU cache misses by 12% and improved performance of real-life apps by 1-2%.
The patch affects how constants and jump targets are represented in VM during execution. Previously they were implemented as absolute 64-bit pointers. Now they are relative 32-bit offsets.
In run-time constant now should be accessed as:
RT_CONSTANT(op_array, opine->op1) instead of opline->op1.zv
EX_CONSTANT(opline->op1) instead of opline->op1.zv
Jump targets:
OP_JMP_ADDR(opline, opline->op2) instead of opline->op2.jmp_addr
The patch doesn't change zend_op representation for 32-bit systems. They still use absolute addresses. The compile-time representation is also kept the same.
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r-- | Zend/zend_opcode.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 0ab110b52c..1bc788a644 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -662,9 +662,10 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) } } case ZEND_GOTO: - if (Z_TYPE(op_array->literals[opline->op2.constant]) != IS_LONG) { + if (Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) != IS_LONG) { uint32_t num = opline->op2.constant; - opline->op2.zv = &op_array->literals[opline->op2.constant]; + + ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2); zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); opline->op2.constant = num; } @@ -717,12 +718,12 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { - opline->op1.zv = &op_array->literals[opline->op1.constant]; + ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1); } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var); } if (opline->op2_type == IS_CONST) { - opline->op2.zv = &op_array->literals[opline->op2.constant]; + ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2); } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) { opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var); } @@ -735,17 +736,17 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value); break; case ZEND_GOTO: - if (Z_TYPE_P(opline->op2.zv) != IS_LONG) { + if (Z_TYPE_P(RT_CONSTANT(op_array, opline->op2)) != IS_LONG) { zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); } /* break omitted intentionally */ case ZEND_JMP: case ZEND_FAST_CALL: - opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); break; case ZEND_JMPZNZ: /* absolute index to relative offset */ - opline->extended_value = (char*)(op_array->opcodes + opline->extended_value) - (char*)opline; + opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: @@ -756,12 +757,12 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) case ZEND_NEW: case ZEND_FE_RESET: case ZEND_FE_FETCH: - opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: if (op_array->fn_flags & ZEND_ACC_GENERATOR) { - if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) { + if (opline->op1_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(op_array, opline->op1)) != IS_NULL) { CG(zend_lineno) = opline->lineno; zend_error_noreturn(E_COMPILE_ERROR, "Generators cannot return values using \"return\""); } |