Skip to content

Commit fa30e47

Browse files
committed
Slight performance improvement
1 parent 16b1d45 commit fa30e47

File tree

6 files changed

+101
-87
lines changed

6 files changed

+101
-87
lines changed

UPGRADING

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ PHP 5.5 UPGRADE NOTES
5454
stores new offsets in op_array->opcodes[*].op?.num. You can use macros
5555
EX_TMP_VAR() and EX_TMP_VAR_NUM() to access temp_variable by offset or
5656
number. You can convert number to offset using EX_TMP_VAR_NUM(0, num) or
57-
offset to number (EX_TMP_VAR(0,offset)-EX_TMP_VAR_NUM(0,0)).
57+
offset to number (EX_TMP_VAR_NUM(0,0)-EX_TMP_VAR(0,offset)).
5858
- Removed execute_data->CVs field. The VM compiled variables always allocated
5959
immediately after execute_data structure. Now they are accessed by offset
6060
from the execute_data base pointer (instead of execute_data->CVs). You can

Zend/zend_execute.c

+80-63
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
167167
#define DECODE_CTOR(ce) \
168168
((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
169169

170+
#undef EX
171+
#define EX(element) execute_data->element
172+
170173
ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data, zend_uint var)
171174
{
172175
return EX_CV(var);
@@ -1488,62 +1491,6 @@ ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_i
14881491
}
14891492
}
14901493

1491-
#define ZEND_VM_NEXT_OPCODE() \
1492-
CHECK_SYMBOL_TABLES() \
1493-
ZEND_VM_INC_OPCODE(); \
1494-
ZEND_VM_CONTINUE()
1495-
1496-
#define ZEND_VM_SET_OPCODE(new_op) \
1497-
CHECK_SYMBOL_TABLES() \
1498-
OPLINE = new_op
1499-
1500-
#define ZEND_VM_JMP(new_op) \
1501-
if (EXPECTED(!EG(exception))) { \
1502-
ZEND_VM_SET_OPCODE(new_op); \
1503-
} else { \
1504-
LOAD_OPLINE(); \
1505-
} \
1506-
ZEND_VM_CONTINUE()
1507-
1508-
#define ZEND_VM_INC_OPCODE() \
1509-
OPLINE++
1510-
1511-
#ifdef __GNUC__
1512-
# define ZEND_VM_GUARD(name) __asm__("#" #name)
1513-
#else
1514-
# define ZEND_VM_GUARD(name)
1515-
#endif
1516-
1517-
#include "zend_vm_execute.h"
1518-
1519-
ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
1520-
{
1521-
if (opcode != ZEND_USER_OPCODE) {
1522-
if (handler == NULL) {
1523-
/* restore the original handler */
1524-
zend_user_opcodes[opcode] = opcode;
1525-
} else {
1526-
zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
1527-
}
1528-
zend_user_opcode_handlers[opcode] = handler;
1529-
return SUCCESS;
1530-
}
1531-
return FAILURE;
1532-
}
1533-
1534-
ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
1535-
{
1536-
return zend_user_opcode_handlers[opcode];
1537-
}
1538-
1539-
ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
1540-
return get_zval_ptr(op_type, node, execute_data, should_free, type);
1541-
}
1542-
1543-
ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
1544-
return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
1545-
}
1546-
15471494
void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{ */
15481495
{
15491496
if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
@@ -1558,14 +1505,22 @@ void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{
15581505
}
15591506
/* }}} */
15601507

1561-
void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
1508+
static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
15621509
{
1563-
int i;
1564-
for (i = 0; i < EX(op_array)->last_var; ++i) {
1565-
if (EX_CV(i)) {
1566-
zval_ptr_dtor(EX_CV(i));
1510+
zval ***cv = EX_CV_NUM(execute_data, 0);
1511+
zval ***end = cv + EX(op_array)->last_var;
1512+
while (cv != end) {
1513+
if (*cv) {
1514+
zval_ptr_dtor(*cv);
15671515
}
1568-
}
1516+
cv++;
1517+
}
1518+
}
1519+
/* }}} */
1520+
1521+
void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
1522+
{
1523+
i_free_compiled_variables(execute_data);
15691524
}
15701525
/* }}} */
15711526

@@ -1611,7 +1566,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
16111566
* +----------------------------------------+
16121567
*/
16131568

1614-
zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
1569+
static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
16151570
{
16161571
zend_execute_data *execute_data;
16171572

@@ -1720,6 +1675,68 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra
17201675
}
17211676
/* }}} */
17221677

1678+
zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
1679+
{
1680+
return i_create_execute_data_from_op_array(op_array, nested TSRMLS_CC);
1681+
}
1682+
/* }}} */
1683+
1684+
#define ZEND_VM_NEXT_OPCODE() \
1685+
CHECK_SYMBOL_TABLES() \
1686+
ZEND_VM_INC_OPCODE(); \
1687+
ZEND_VM_CONTINUE()
1688+
1689+
#define ZEND_VM_SET_OPCODE(new_op) \
1690+
CHECK_SYMBOL_TABLES() \
1691+
OPLINE = new_op
1692+
1693+
#define ZEND_VM_JMP(new_op) \
1694+
if (EXPECTED(!EG(exception))) { \
1695+
ZEND_VM_SET_OPCODE(new_op); \
1696+
} else { \
1697+
LOAD_OPLINE(); \
1698+
} \
1699+
ZEND_VM_CONTINUE()
1700+
1701+
#define ZEND_VM_INC_OPCODE() \
1702+
OPLINE++
1703+
1704+
#ifdef __GNUC__
1705+
# define ZEND_VM_GUARD(name) __asm__("#" #name)
1706+
#else
1707+
# define ZEND_VM_GUARD(name)
1708+
#endif
1709+
1710+
#include "zend_vm_execute.h"
1711+
1712+
ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
1713+
{
1714+
if (opcode != ZEND_USER_OPCODE) {
1715+
if (handler == NULL) {
1716+
/* restore the original handler */
1717+
zend_user_opcodes[opcode] = opcode;
1718+
} else {
1719+
zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
1720+
}
1721+
zend_user_opcode_handlers[opcode] = handler;
1722+
return SUCCESS;
1723+
}
1724+
return FAILURE;
1725+
}
1726+
1727+
ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
1728+
{
1729+
return zend_user_opcode_handlers[opcode];
1730+
}
1731+
1732+
ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
1733+
return get_zval_ptr(op_type, node, execute_data, should_free, type);
1734+
}
1735+
1736+
ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
1737+
return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
1738+
}
1739+
17231740
/*
17241741
* Local variables:
17251742
* tab-width: 4

Zend/zend_vm_def.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1852,7 +1852,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
18521852
}
18531853

18541854
/* Generators go throw a different cleanup process */
1855-
if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
1855+
if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
18561856
/* The generator object is stored in return_value_ptr_ptr */
18571857
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
18581858

@@ -1866,7 +1866,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
18661866
EG(current_execute_data) = EX(prev_execute_data);
18671867
EG(opline_ptr) = NULL;
18681868
if (!EG(active_symbol_table)) {
1869-
zend_free_compiled_variables(execute_data);
1869+
i_free_compiled_variables(execute_data);
18701870
}
18711871

18721872
if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {

Zend/zend_vm_execute.h

+9-7
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,6 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o
326326
#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
327327

328328
#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC
329-
#undef EX
330-
#define EX(element) execute_data->element
331-
332329

333330
ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)
334331
{
@@ -340,6 +337,11 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)
340337
original_in_execution = EG(in_execution);
341338
EG(in_execution) = 1;
342339

340+
if (0) {
341+
zend_vm_enter:
342+
execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC);
343+
}
344+
343345
LOAD_REGS();
344346
LOAD_OPLINE();
345347

@@ -357,7 +359,7 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)
357359
EG(in_execution) = original_in_execution;
358360
return;
359361
case 2:
360-
execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC);
362+
goto zend_vm_enter;
361363
break;
362364
case 3:
363365
execute_data = EG(current_execute_data);
@@ -376,7 +378,7 @@ ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC)
376378
if (EG(exception)) {
377379
return;
378380
}
379-
zend_execute_ex(zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC);
381+
zend_execute_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC);
380382
}
381383

382384
static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
@@ -391,7 +393,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
391393
}
392394

393395
/* Generators go throw a different cleanup process */
394-
if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
396+
if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
395397
/* The generator object is stored in return_value_ptr_ptr */
396398
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
397399

@@ -405,7 +407,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
405407
EG(current_execute_data) = EX(prev_execute_data);
406408
EG(opline_ptr) = NULL;
407409
if (!EG(active_symbol_table)) {
408-
zend_free_compiled_variables(execute_data);
410+
i_free_compiled_variables(execute_data);
409411
}
410412

411413
if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {

Zend/zend_vm_execute.skl

+6-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
1212
original_in_execution = EG(in_execution);
1313
EG(in_execution) = 1;
1414

15+
if (0) {
16+
zend_vm_enter:
17+
execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC);
18+
}
19+
1520
LOAD_REGS();
1621
LOAD_OPLINE();
1722

@@ -36,7 +41,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC)
3641
if (EG(exception)) {
3742
return;
3843
}
39-
zend_{%EXECUTOR_NAME%}_ex(zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC);
44+
zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC);
4045
}
4146

4247
{%EXTERNAL_EXECUTOR%}

Zend/zend_vm_gen.php

+3-13
Original file line numberDiff line numberDiff line change
@@ -839,8 +839,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
839839
out($f,"#define ZEND_VM_LEAVE() return 3\n");
840840
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n");
841841
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n");
842-
out($f,"#undef EX\n");
843-
out($f,"#define EX(element) execute_data->element\n\n");
844842
break;
845843
case ZEND_VM_KIND_SWITCH:
846844
out($f,"\n");
@@ -863,12 +861,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
863861
out($f,"#define LOAD_REGS()\n");
864862
out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n");
865863
out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n");
866-
out($f,"#define ZEND_VM_ENTER() execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); LOAD_REGS(); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
864+
out($f,"#define ZEND_VM_ENTER() goto zend_vm_enter\n");
867865
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
868866
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n");
869867
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n");
870-
out($f,"#undef EX\n");
871-
out($f,"#define EX(element) execute_data->element\n\n");
872868
break;
873869
case ZEND_VM_KIND_GOTO:
874870
out($f,"\n");
@@ -891,12 +887,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
891887
out($f,"#define LOAD_REGS()\n");
892888
out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
893889
out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n");
894-
out($f,"#define ZEND_VM_ENTER() execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); LOAD_REGS(); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
890+
out($f,"#define ZEND_VM_ENTER() goto zend_vm_enter\n");
895891
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
896892
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n");
897893
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n");
898-
out($f,"#undef EX\n");
899-
out($f,"#define EX(element) execute_data->element\n\n");
900894
break;
901895
}
902896
break;
@@ -965,7 +959,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
965959
$m[1]."\t\tEG(in_execution) = original_in_execution;\n".
966960
$m[1]."\t\treturn;\n".
967961
$m[1]."\tcase 2:\n" .
968-
$m[1]."\t\texecute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC);\n".
962+
$m[1]."\t\tgoto zend_vm_enter;\n".
969963
$m[1]."\t\tbreak;\n" .
970964
$m[1]."\tcase 3:\n" .
971965
$m[1]."\t\texecute_data = EG(current_execute_data);\n".
@@ -1215,8 +1209,6 @@ function gen_vm($def, $skel) {
12151209
// Generate un-specialized executor
12161210
if (ZEND_VM_OLD_EXECUTOR) {
12171211
out($f,"\n/* Old executor */\n\n");
1218-
out($f,"#undef EX\n");
1219-
out($f,"#define EX(element) execute_data.element\n\n");
12201212
out($f,"#undef ZEND_VM_CONTINUE\n\n");
12211213
out($f,"#undef ZEND_VM_RETURN\n\n");
12221214
out($f,"#undef ZEND_VM_ENTER\n\n");
@@ -1289,8 +1281,6 @@ function gen_vm($def, $skel) {
12891281
out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n");
12901282
out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
12911283
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
1292-
out($f,"#undef EX\n");
1293-
out($f,"#define EX(element) execute_data->element\n\n");
12941284
out($f,"#undef ZEND_VM_CONTINUE\n");
12951285
out($f,"#undef ZEND_VM_RETURN\n");
12961286
out($f,"#undef ZEND_VM_ENTER\n");

0 commit comments

Comments
 (0)