Skip to content

Commit aef8836

Browse files
committed
Don't check $this existence in object opcodes
We are now guaranteed that $this always exists inside methods, as well as insides closures (if they use $this at all). This removes checks for $this existence from the individual object opcodes. Instead ZEND_FETCH_THIS is used in the cases where $this is not guaranteed to exist, which is mainly the pseudo-main scope. Closes GH-3822.
1 parent 776f4bc commit aef8836

File tree

5 files changed

+161
-1091
lines changed

5 files changed

+161
-1091
lines changed

Zend/zend_compile.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,16 @@ static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
24292429
}
24302430
/* }}} */
24312431

2432+
static zend_bool this_guaranteed_exists() /* {{{ */
2433+
{
2434+
zend_op_array *op_array = CG(active_op_array);
2435+
/* Instance methods always have a $this.
2436+
* This also includes closures that have a scope and use $this. */
2437+
return op_array->scope != NULL
2438+
&& (op_array->fn_flags & ZEND_ACC_STATIC) == 0;
2439+
}
2440+
/* }}} */
2441+
24322442
static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
24332443
{
24342444
if (is_this_fetch(ast)) {
@@ -2531,7 +2541,11 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
25312541
zend_op *opline;
25322542

25332543
if (is_this_fetch(obj_ast)) {
2534-
obj_node.op_type = IS_UNUSED;
2544+
if (this_guaranteed_exists()) {
2545+
obj_node.op_type = IS_UNUSED;
2546+
} else {
2547+
zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
2548+
}
25352549
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
25362550
} else {
25372551
opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
@@ -3929,7 +3943,11 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{
39293943
zend_function *fbc = NULL;
39303944

39313945
if (is_this_fetch(obj_ast)) {
3932-
obj_node.op_type = IS_UNUSED;
3946+
if (this_guaranteed_exists()) {
3947+
obj_node.op_type = IS_UNUSED;
3948+
} else {
3949+
zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
3950+
}
39333951
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
39343952
} else {
39353953
zend_compile_expr(&obj_node, obj_ast);

Zend/zend_vm_def.h

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -994,11 +994,6 @@ ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP)
994994

995995
SAVE_OPLINE();
996996
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
997-
998-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
999-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
1000-
}
1001-
1002997
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1003998

1004999
do {
@@ -1257,11 +1252,6 @@ ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH
12571252

12581253
SAVE_OPLINE();
12591254
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1260-
1261-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
1262-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
1263-
}
1264-
12651255
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
12661256

12671257
do {
@@ -1335,11 +1325,6 @@ ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CAC
13351325

13361326
SAVE_OPLINE();
13371327
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1338-
1339-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
1340-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
1341-
}
1342-
13431328
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
13441329

13451330
do {
@@ -2007,11 +1992,6 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
20071992

20081993
SAVE_OPLINE();
20091994
container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
2010-
2011-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2012-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2013-
}
2014-
20151995
offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
20161996

20171997
if (OP1_TYPE == IS_CONST ||
@@ -2132,10 +2112,6 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH
21322112
SAVE_OPLINE();
21332113

21342114
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2135-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2136-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2137-
}
2138-
21392115
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
21402116
result = EX_VAR(opline->result.var);
21412117
zend_fetch_property_address(
@@ -2156,10 +2132,6 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH
21562132

21572133
SAVE_OPLINE();
21582134
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
2159-
2160-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2161-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2162-
}
21632135
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
21642136
result = EX_VAR(opline->result.var);
21652137
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
@@ -2179,11 +2151,6 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
21792151

21802152
SAVE_OPLINE();
21812153
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
2182-
2183-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2184-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2185-
}
2186-
21872154
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
21882155

21892156
if (OP1_TYPE == IS_CONST ||
@@ -2310,11 +2277,6 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
23102277

23112278
SAVE_OPLINE();
23122279
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
2313-
2314-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2315-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2316-
}
2317-
23182280
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
23192281
result = EX_VAR(opline->result.var);
23202282
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
@@ -2369,11 +2331,6 @@ ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_
23692331

23702332
SAVE_OPLINE();
23712333
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2372-
2373-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
2374-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2375-
}
2376-
23772334
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
23782335
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
23792336

@@ -2712,11 +2669,6 @@ ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CA
27122669
SAVE_OPLINE();
27132670

27142671
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2715-
2716-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2717-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2718-
}
2719-
27202672
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
27212673

27222674
value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W);
@@ -3403,10 +3355,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
34033355

34043356
object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
34053357

3406-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
3407-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
3408-
}
3409-
34103358
if (OP2_TYPE != IS_CONST) {
34113359
function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
34123360
}
@@ -5342,10 +5290,6 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
53425290
SAVE_OPLINE();
53435291
obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
53445292

5345-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
5346-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
5347-
}
5348-
53495293
do {
53505294
if (OP1_TYPE == IS_CONST ||
53515295
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
@@ -6080,9 +6024,6 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S
60806024

60816025
SAVE_OPLINE();
60826026
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
6083-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
6084-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
6085-
}
60866027
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
60876028

60886029
do {
@@ -6784,11 +6725,6 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED
67846725

67856726
SAVE_OPLINE();
67866727
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
6787-
6788-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
6789-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
6790-
}
6791-
67926728
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
67936729

67946730
if (OP1_TYPE == IS_CONST ||
@@ -8229,7 +8165,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF)
82298165
ZEND_VM_NEXT_OPCODE();
82308166
}
82318167

8232-
ZEND_VM_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED)
8168+
ZEND_VM_HOT_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED)
82338169
{
82348170
USE_OPLINE
82358171

0 commit comments

Comments
 (0)