Skip to content

Commit

Permalink
Omit FETCH_THIS in closures
Browse files Browse the repository at this point in the history
Non-static closures are guaranteed to have $this. The existing comment
highlights this, but fails to handle it correctly.
  • Loading branch information
iluuu1994 committed May 8, 2024
1 parent d2a9edf commit 024095f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
22 changes: 17 additions & 5 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ static bool zend_is_not_imported(zend_string *name) {
void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
{
*prev_context = CG(context);
CG(context).prev = CG(context).op_array ? prev_context : NULL;
CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
CG(context).vars_size = 0;
CG(context).literals_size = 0;
Expand Down Expand Up @@ -2920,11 +2921,21 @@ static bool is_global_var_fetch(zend_ast *ast)

static bool this_guaranteed_exists(void) /* {{{ */
{
zend_op_array *op_array = CG(active_op_array);
/* Instance methods always have a $this.
* This also includes closures that have a scope and use $this. */
return op_array->scope != NULL
&& (op_array->fn_flags & ZEND_ACC_STATIC) == 0;
zend_oparray_context *ctx = &CG(context);
while (ctx) {
/* Instance methods always have a $this.
* This also includes closures that have a scope and use $this. */
zend_op_array *op_array = ctx->op_array;
if (op_array->fn_flags & ZEND_ACC_STATIC) {
return false;
} else if (op_array->scope) {
return true;
} else if (!(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
return false;
}
ctx = ctx->prev;
}
return false;
}
/* }}} */

Expand Down Expand Up @@ -7870,6 +7881,7 @@ static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel)
}

zend_oparray_context_begin(&orig_oparray_context);
CG(context).op_array = op_array;

{
/* Push a separator to the loop variable stack */
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ typedef struct _zend_live_range {

/* Compilation context that is different for each op array. */
typedef struct _zend_oparray_context {
struct _zend_oparray_context *prev;
zend_op_array *op_array;
uint32_t opcodes_size;
int vars_size;
int literals_size;
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_language_scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ static zend_op_array *zend_compile(int type)

zend_file_context_begin(&original_file_context);
zend_oparray_context_begin(&original_oparray_context);
CG(context).op_array = op_array;
zend_compile_top_stmt(CG(ast));
CG(zend_lineno) = last_lineno;
zend_emit_final_return(type == ZEND_USER_FUNCTION);
Expand Down

0 comments on commit 024095f

Please sign in to comment.