Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Omit FETCH_THIS in closures #14181

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 19 additions & 7 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,11 @@ static bool zend_is_not_imported(zend_string *name) {
return !FC(imports) || zend_hash_find_ptr_lc(FC(imports), name) == NULL;
}

void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_array *op_array) /* {{{ */
{
*prev_context = CG(context);
CG(context).prev = CG(context).op_array ? prev_context : NULL;
CG(context).op_array = op_array;
CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
CG(context).vars_size = 0;
CG(context).literals_size = 0;
Expand Down Expand Up @@ -2920,11 +2922,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 @@ -7869,7 +7881,7 @@ static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel)
op_array->fn_flags |= ZEND_ACC_TOP_LEVEL;
}

zend_oparray_context_begin(&orig_oparray_context);
zend_oparray_context_begin(&orig_oparray_context, op_array);

{
/* Push a separator to the loop variable stack */
Expand Down
4 changes: 3 additions & 1 deletion 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 Expand Up @@ -802,7 +804,7 @@ void init_compiler(void);
void shutdown_compiler(void);
void zend_init_compiler_data_structures(void);

void zend_oparray_context_begin(zend_oparray_context *prev_context);
void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_array *op_array);
void zend_oparray_context_end(zend_oparray_context *prev_context);
void zend_file_context_begin(zend_file_context *prev_context);
void zend_file_context_end(zend_file_context *prev_context);
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_language_scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ static zend_op_array *zend_compile(int type)
}

zend_file_context_begin(&original_file_context);
zend_oparray_context_begin(&original_oparray_context);
zend_oparray_context_begin(&original_oparray_context, op_array);
zend_compile_top_stmt(CG(ast));
CG(zend_lineno) = last_lineno;
zend_emit_final_return(type == ZEND_USER_FUNCTION);
Expand Down
25 changes: 20 additions & 5 deletions ext/opcache/jit/zend_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1742,7 +1742,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down Expand Up @@ -1790,7 +1793,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down Expand Up @@ -1831,7 +1837,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down Expand Up @@ -2305,7 +2314,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
op1_addr = 0;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
on_this = 1;
} else {
op1_info = OP1_INFO();
Expand Down Expand Up @@ -2456,7 +2468,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
op1_addr = 0;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
on_this = 1;
} else {
op1_info = OP1_INFO();
Expand Down
25 changes: 20 additions & 5 deletions ext/opcache/jit/zend_jit_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -4692,7 +4692,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down Expand Up @@ -4783,7 +4786,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down Expand Up @@ -4863,7 +4869,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down Expand Up @@ -5930,7 +5939,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down Expand Up @@ -6209,7 +6221,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
if (opline->op1_type == IS_UNUSED) {
op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
ce = op_array->scope;
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
/* scope is NULL for closures. */
if (ce) {
ce_is_instanceof = (ce->ce_flags & ZEND_ACC_FINAL) != 0;
}
op1_addr = 0;
on_this = 1;
} else {
Expand Down
6 changes: 6 additions & 0 deletions ext/opcache/jit/zend_jit_vm_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,12 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
}
}
op1_type |= flags;
} else if (opline->op1_type == IS_UNUSED && (op_array->fn_flags & ZEND_ACC_CLOSURE)) {
uint32_t op1_flags = ZEND_VM_OP1_FLAGS(zend_get_opcode_flags(opline->opcode));
if ((op1_flags & ZEND_VM_OP_MASK) == ZEND_VM_OP_THIS) {
op1_type = IS_OBJECT;
ce1 = Z_OBJCE(EX(This));
}
}
if (opline->op2_type & (IS_TMP_VAR|IS_VAR|IS_CV)
&& opline->opcode != ZEND_INSTANCEOF
Expand Down