Skip to content

Commit 06f372e

Browse files
committed
Don't check $this existence in object opcodes
We are now guaranteed that $this always exists inside methods. Remove checks for $this existence from the individual object opcodes. Instead make use of ZEND_FETCH_THIS in the cases where $this is used but isn't guaranteed to exist, such as closures and pseudo-main scope.
1 parent 81eff22 commit 06f372e

File tree

3 files changed

+25
-861
lines changed

3 files changed

+25
-861
lines changed

Zend/zend_compile.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,6 +2283,19 @@ static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
22832283
}
22842284
/* }}} */
22852285

2286+
static zend_bool this_guaranteed_exists() /* {{{ */
2287+
{
2288+
zend_op_array *op_array = CG(active_op_array);
2289+
/* Scope on closures may be unset. */
2290+
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
2291+
return 0;
2292+
}
2293+
/* Instance methods always have a $this */
2294+
return op_array->scope != NULL
2295+
&& (op_array->fn_flags & ZEND_ACC_STATIC) == 0;
2296+
}
2297+
/* }}} */
2298+
22862299
static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
22872300
{
22882301
if (is_this_fetch(ast)) {
@@ -2380,7 +2393,11 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
23802393
zend_op *opline;
23812394

23822395
if (is_this_fetch(obj_ast)) {
2383-
obj_node.op_type = IS_UNUSED;
2396+
if (this_guaranteed_exists()) {
2397+
obj_node.op_type = IS_UNUSED;
2398+
} else {
2399+
zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
2400+
}
23842401
} else {
23852402
opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
23862403
if (opline && type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) {
@@ -3820,7 +3837,11 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{
38203837
zend_function *fbc = NULL;
38213838

38223839
if (is_this_fetch(obj_ast)) {
3823-
obj_node.op_type = IS_UNUSED;
3840+
if (this_guaranteed_exists()) {
3841+
obj_node.op_type = IS_UNUSED;
3842+
} else {
3843+
zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
3844+
}
38243845
} else {
38253846
zend_compile_expr(&obj_node, obj_ast);
38263847
}

Zend/zend_vm_def.h

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -806,11 +806,6 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
806806

807807
SAVE_OPLINE();
808808
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
809-
810-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
811-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
812-
}
813-
814809
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
815810

816811
do {
@@ -1181,11 +1176,6 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
11811176

11821177
SAVE_OPLINE();
11831178
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
1184-
1185-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
1186-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
1187-
}
1188-
11891179
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
11901180

11911181
do {
@@ -1259,11 +1249,6 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
12591249

12601250
SAVE_OPLINE();
12611251
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
1262-
1263-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
1264-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
1265-
}
1266-
12671252
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
12681253

12691254
do {
@@ -1923,11 +1908,6 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
19231908

19241909
SAVE_OPLINE();
19251910
container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
1926-
1927-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
1928-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
1929-
}
1930-
19311911
offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
19321912

19331913
if (OP1_TYPE == IS_CONST ||
@@ -2031,10 +2011,6 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH
20312011
SAVE_OPLINE();
20322012

20332013
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2034-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2035-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2036-
}
2037-
20382014
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
20392015
result = EX_VAR(opline->result.var);
20402016
zend_fetch_property_address(
@@ -2056,10 +2032,6 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH
20562032

20572033
SAVE_OPLINE();
20582034
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
2059-
2060-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2061-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2062-
}
20632035
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
20642036
result = EX_VAR(opline->result.var);
20652037
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);
@@ -2081,11 +2053,6 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
20812053

20822054
SAVE_OPLINE();
20832055
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
2084-
2085-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2086-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2087-
}
2088-
20892056
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
20902057

20912058
if (OP1_TYPE == IS_CONST ||
@@ -2189,11 +2156,6 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
21892156

21902157
SAVE_OPLINE();
21912158
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
2192-
2193-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2194-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2195-
}
2196-
21972159
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
21982160
result = EX_VAR(opline->result.var);
21992161
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);
@@ -2251,11 +2213,6 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE
22512213

22522214
SAVE_OPLINE();
22532215
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2254-
2255-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
2256-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2257-
}
2258-
22592216
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
22602217
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
22612218

@@ -2620,11 +2577,6 @@ ZEND_VM_HANDLER(200, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
26202577
SAVE_OPLINE();
26212578

26222579
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2623-
2624-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2625-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
2626-
}
2627-
26282580
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
26292581

26302582
cache_addr = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_RETURNS_FUNCTION) : NULL;
@@ -3351,10 +3303,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
33513303

33523304
object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
33533305

3354-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
3355-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
3356-
}
3357-
33583306
if (OP2_TYPE != IS_CONST) {
33593307
function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
33603308
}
@@ -5312,10 +5260,6 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
53125260
SAVE_OPLINE();
53135261
obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
53145262

5315-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
5316-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
5317-
}
5318-
53195263
do {
53205264
if (OP1_TYPE == IS_CONST ||
53215265
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
@@ -5943,9 +5887,6 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S
59435887

59445888
SAVE_OPLINE();
59455889
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
5946-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
5947-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
5948-
}
59495890
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
59505891

59515892
do {
@@ -6642,11 +6583,6 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED
66426583

66436584
SAVE_OPLINE();
66446585
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
6645-
6646-
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
6647-
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
6648-
}
6649-
66506586
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
66516587

66526588
if (OP1_TYPE == IS_CONST ||
@@ -8146,7 +8082,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF)
81468082
ZEND_VM_NEXT_OPCODE();
81478083
}
81488084

8149-
ZEND_VM_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED)
8085+
ZEND_VM_HOT_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED)
81508086
{
81518087
USE_OPLINE
81528088

0 commit comments

Comments
 (0)