Skip to content

Commit 745753e

Browse files
committed
Prevent double load on fast path (manual common subexpression elimination)
1 parent 6b9f31a commit 745753e

File tree

2 files changed

+204
-314
lines changed

2 files changed

+204
-314
lines changed

Zend/zend_vm_def.h

+51-66
Original file line numberDiff line numberDiff line change
@@ -1469,9 +1469,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
14691469
zend_class_entry *ce;
14701470

14711471
if (OP2_TYPE == IS_CONST) {
1472-
if (OP1_TYPE == IS_CONST && EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
1473-
1474-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
1472+
if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
14751473
retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
14761474

14771475
/* check if static properties were destoyed */
@@ -1482,9 +1480,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
14821480
}
14831481

14841482
ZEND_VM_C_GOTO(fetch_var_return);
1485-
} else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
1486-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
1487-
} else {
1483+
} else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
14881484
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
14891485
if (UNEXPECTED(ce == NULL)) {
14901486
if (OP1_TYPE != IS_CONST) {
@@ -2830,12 +2826,13 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV)
28302826

28312827
ZEND_VM_C_LABEL(try_class_name):
28322828
if (OP2_TYPE == IS_CONST) {
2833-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(class_name)))) {
2834-
Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
2835-
} else {
2836-
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value);
2837-
CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var)));
2829+
zend_class_entry *ce = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
2830+
2831+
if (UNEXPECTED(ce == NULL)) {
2832+
ce = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value);
2833+
CACHE_PTR(Z_CACHE_SLOT_P(class_name), ce);
28382834
}
2835+
Z_CE_P(EX_VAR(opline->result.var)) = ce;
28392836
} else if (Z_TYPE_P(class_name) == IS_OBJECT) {
28402837
Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name);
28412838
} else if (Z_TYPE_P(class_name) == IS_STRING) {
@@ -2992,9 +2989,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
29922989

29932990
if (OP1_TYPE == IS_CONST) {
29942991
/* no function found. try a static method in class */
2995-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
2996-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
2997-
} else {
2992+
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
2993+
if (UNEXPECTED(ce == NULL)) {
29982994
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
29992995
if (UNEXPECTED(EG(exception) != NULL)) {
30002996
HANDLE_EXCEPTION();
@@ -3011,8 +3007,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
30113007

30123008
if (OP1_TYPE == IS_CONST &&
30133009
OP2_TYPE == IS_CONST &&
3014-
EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
3015-
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
3010+
EXPECTED((fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) != NULL)) {
3011+
/* nothing to do */
30163012
} else if (OP1_TYPE != IS_CONST &&
30173013
OP2_TYPE == IS_CONST &&
30183014
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
@@ -3121,18 +3117,17 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST)
31213117
zval *function_name, *func;
31223118
zend_execute_data *call;
31233119

3124-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
3125-
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
3126-
} else {
3120+
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
3121+
if (UNEXPECTED(fbc == NULL)) {
31273122
function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
3128-
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
3123+
func = zend_hash_find(EG(function_table), Z_STR_P(function_name));
3124+
if (UNEXPECTED(func == NULL)) {
31293125
SAVE_OPLINE();
31303126
zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
31313127
HANDLE_EXCEPTION();
3132-
} else {
3133-
fbc = Z_FUNC_P(func);
3134-
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
31353128
}
3129+
fbc = Z_FUNC_P(func);
3130+
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
31363131
}
31373132
call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
31383133
fbc, opline->extended_value, NULL, NULL);
@@ -3423,19 +3418,18 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
34233418
zend_execute_data *call;
34243419

34253420
func_name = EX_CONSTANT(opline->op2) + 1;
3426-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
3427-
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
3428-
} else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
3429-
func_name++;
3430-
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
3431-
SAVE_OPLINE();
3432-
zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
3433-
HANDLE_EXCEPTION();
3434-
} else {
3435-
fbc = Z_FUNC_P(func);
3436-
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
3421+
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
3422+
if (UNEXPECTED(fbc == NULL)) {
3423+
func = zend_hash_find(EG(function_table), Z_STR_P(func_name));
3424+
if (func == NULL) {
3425+
func_name++;
3426+
func = zend_hash_find(EG(function_table), Z_STR_P(func_name));
3427+
if (UNEXPECTED(func == NULL)) {
3428+
SAVE_OPLINE();
3429+
zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
3430+
HANDLE_EXCEPTION();
3431+
}
34373432
}
3438-
} else {
34393433
fbc = Z_FUNC_P(func);
34403434
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
34413435
}
@@ -3457,13 +3451,14 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
34573451
zend_function *fbc;
34583452
zend_execute_data *call;
34593453

3460-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(fname)))) {
3461-
fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
3462-
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
3463-
SAVE_OPLINE();
3464-
zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(fname));
3465-
HANDLE_EXCEPTION();
3466-
} else {
3454+
fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
3455+
if (UNEXPECTED(fbc == NULL)) {
3456+
func = zend_hash_find(EG(function_table), Z_STR_P(fname));
3457+
if (UNEXPECTED(func == NULL)) {
3458+
SAVE_OPLINE();
3459+
zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(fname));
3460+
HANDLE_EXCEPTION();
3461+
}
34673462
fbc = Z_FUNC_P(func);
34683463
CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
34693464
}
@@ -4115,9 +4110,8 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
41154110
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
41164111
ZEND_VM_CONTINUE(); /* CHECK_ME */
41174112
}
4118-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
4119-
catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
4120-
} else {
4113+
catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
4114+
if (UNEXPECTED(catch_ce == NULL)) {
41214115
catch_ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
41224116

41234117
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), catch_ce);
@@ -4877,9 +4871,8 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
48774871

48784872
SAVE_OPLINE();
48794873
if (OP1_TYPE == IS_CONST) {
4880-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
4881-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
4882-
} else {
4874+
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
4875+
if (UNEXPECTED(ce == NULL)) {
48834876
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
48844877
if (UNEXPECTED(ce == NULL)) {
48854878
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -5515,9 +5508,8 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
55155508
zend_class_entry *ce;
55165509

55175510
if (OP2_TYPE == IS_CONST) {
5518-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
5519-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
5520-
} else {
5511+
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
5512+
if (UNEXPECTED(ce == NULL)) {
55215513
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
55225514
if (UNEXPECTED(EG(exception) != NULL)) {
55235515
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
@@ -6380,9 +6372,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
63806372
zend_class_entry *ce;
63816373

63826374
if (OP2_TYPE == IS_CONST) {
6383-
if (OP1_TYPE == IS_CONST && EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
6384-
6385-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
6375+
if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
63866376
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
63876377

63886378
/* check if static properties were destoyed */
@@ -6391,9 +6381,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
63916381
}
63926382

63936383
ZEND_VM_C_GOTO(is_var_return);
6394-
} else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
6395-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
6396-
} else {
6384+
} else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
63976385
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
63986386
if (UNEXPECTED(ce == NULL)) {
63996387
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -6959,9 +6947,8 @@ ZEND_VM_C_LABEL(try_instanceof):
69596947
zend_class_entry *ce;
69606948

69616949
if (OP2_TYPE == IS_CONST) {
6962-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
6963-
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
6964-
} else {
6950+
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
6951+
if (UNEXPECTED(ce == NULL)) {
69656952
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
69666953
if (UNEXPECTED(ce == NULL)) {
69676954
ZVAL_FALSE(EX_VAR(opline->result.var));
@@ -7010,9 +6997,8 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST)
70106997
zend_class_entry *iface;
70116998

70126999
SAVE_OPLINE();
7013-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
7014-
iface = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
7015-
} else {
7000+
iface = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
7001+
if (UNEXPECTED(iface == NULL)) {
70167002
iface = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE);
70177003
if (UNEXPECTED(iface == NULL)) {
70187004
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -7035,9 +7021,8 @@ ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY)
70357021
zend_class_entry *trait;
70367022

70377023
SAVE_OPLINE();
7038-
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
7039-
trait = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
7040-
} else {
7024+
trait = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
7025+
if (UNEXPECTED(trait == NULL)) {
70417026
trait = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)),
70427027
EX_CONSTANT(opline->op2) + 1,
70437028
ZEND_FETCH_CLASS_TRAIT);

0 commit comments

Comments
 (0)