REGISTER_HELPER(zend_jit_find_func_helper);
REGISTER_HELPER(zend_jit_find_ns_func_helper);
REGISTER_HELPER(zend_jit_find_method_helper);
+ REGISTER_HELPER(zend_jit_find_method_tmp_helper);
REGISTER_HELPER(zend_jit_push_static_metod_call_frame);
REGISTER_HELPER(zend_jit_push_static_metod_call_frame_tmp);
REGISTER_HELPER(zend_jit_invalid_method_call);
+ REGISTER_HELPER(zend_jit_invalid_method_call_tmp);
REGISTER_HELPER(zend_jit_unref_helper);
REGISTER_HELPER(zend_jit_extend_stack_helper);
REGISTER_HELPER(zend_jit_int_extend_stack_helper);
}
zend_throw_error(NULL, "Call to a member function %s() on %s",
Z_STRVAL_P(function_name), zend_zval_type_name(object));
- if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
- zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
- }
+}
+
+static ZEND_COLD void ZEND_FASTCALL zend_jit_invalid_method_call_tmp(zval *object)
+{
+ zend_execute_data *execute_data = EG(current_execute_data);
+ const zend_op *opline = EX(opline);
+
+ zend_jit_invalid_method_call(object);
+ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
}
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method)
zend_execute_data *execute_data = EG(current_execute_data);
const zend_op *opline = EX(opline);
zend_class_entry *called_scope = obj->ce;
- zend_object *orig_obj = obj;
zend_function *fbc;
- fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), function_name + 1);
+ fbc = obj->handlers->get_method(obj_ptr, Z_STR_P(function_name), function_name + 1);
if (UNEXPECTED(fbc == NULL)) {
if (EXPECTED(!EG(exception))) {
zend_undefined_method(called_scope, Z_STR_P(function_name));
}
- if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
- zend_objects_store_del(orig_obj);
- }
return NULL;
}
zend_init_func_run_time_cache(&fbc->op_array);
}
- if (UNEXPECTED(obj != orig_obj)) {
- if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
- GC_ADDREF(obj);
- if (GC_DELREF(orig_obj) == 0) {
- zend_objects_store_del(orig_obj);
- }
- }
- *obj_ptr = obj;
+ if (UNEXPECTED(obj != *obj_ptr)) {
return fbc;
}
return fbc;
}
+static zend_function* ZEND_FASTCALL zend_jit_find_method_tmp_helper(zend_object *obj, zval *function_name, zend_object **obj_ptr)
+{
+ zend_function *fbc;
+
+ fbc = zend_jit_find_method_helper(obj, function_name, obj_ptr);
+ if (!fbc) {
+ if (GC_DELREF(obj) == 0) {
+ zend_objects_store_del(obj);
+ }
+ } else if (obj != *obj_ptr) {
+ GC_ADDREF(obj);
+ if (GC_DELREF(obj) == 0) {
+ zend_objects_store_del(obj);
+ }
+ }
+ return fbc;
+}
+
static zend_execute_data* ZEND_FASTCALL zend_jit_push_static_metod_call_frame(zend_object *obj, zend_function *fbc, uint32_t num_args)
{
zend_class_entry *scope = obj->ce;
}
opline = ssa_opcodes[use];
- if (opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) {
+ if (opline->opcode == ZEND_INIT_METHOD_CALL) {
+ return (opline->op2_type == IS_CONST &&
+ Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_STRING);
+ } else if (opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) {
if (!JIT_G(current_frame)
|| !JIT_G(current_frame)->call
|| !JIT_G(current_frame)->call->func
} else if (opline->opcode != ZEND_FETCH_OBJ_R
&& opline->opcode != ZEND_FETCH_OBJ_IS
&& opline->opcode != ZEND_FETCH_OBJ_W
- && opline->opcode != ZEND_ASSIGN_OBJ) {
+ && opline->opcode != ZEND_ASSIGN_OBJ
+ && opline->opcode != ZEND_ASSIGN_OBJ_OP
+ && opline->opcode != ZEND_PRE_INC_OBJ
+ && opline->opcode != ZEND_PRE_DEC_OBJ
+ && opline->opcode != ZEND_POST_INC_OBJ
+ && opline->opcode != ZEND_POST_DEC_OBJ) {
return 0;
}
op1_addr = 0;
} else {
op1_info = OP1_INFO();
- if (!(op1_info & MAY_BE_OBJECT)) {
- goto generic_dynamic_call;
- }
op1_addr = OP1_REG_ADDR();
if (orig_op1_type != IS_UNKNOWN
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
zif_handler orig_internal_handler;
} zend_closure;
-static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, zend_function *func, zend_bool is_closure)
+static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, zend_function *func, zend_bool is_closure, zend_bool use_this)
{
uint32_t used_stack;
| // Z_PTR(call->This) = obj;
| mov r1, aword T1
| mov aword EX:RX->This.value.ptr, r1
- if (opline->op1_type == IS_UNUSED) {
+ if (opline->op1_type == IS_UNUSED || use_this) {
| // call->call_info |= ZEND_CALL_HAS_THIS;
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
| mov dword EX:RX->This.u1.type_info, ZEND_CALL_HAS_THIS
|3:
}
- if (!zend_jit_push_call_frame(Dst, opline, func, 0)) {
+ if (!zend_jit_push_call_frame(Dst, opline, func, 0, 0)) {
return 0;
}
| LOAD_ZVAL_ADDR FCARG1a, op1_addr
}
| SET_EX_OPLINE opline, r0
- | EXT_CALL zend_jit_invalid_method_call, r0
+ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) {
+ | EXT_CALL zend_jit_invalid_method_call_tmp, r0
+ } else {
+ | EXT_CALL zend_jit_invalid_method_call, r0
+ }
| jmp ->exception_handler
|.code
}
| push r0
|.endif
| SET_EX_OPLINE opline, r0
- | EXT_CALL zend_jit_find_method_helper, r0
+ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) {
+ | EXT_CALL zend_jit_find_method_tmp_helper, r0
+ } else {
+ | EXT_CALL zend_jit_find_method_helper, r0
+ }
| test r0, r0
| jz ->exception_handler
|.if not(X64)
| sub r4, 12
| push opline->extended_value
|.endif
- if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
+ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) {
| EXT_CALL zend_jit_push_static_metod_call_frame_tmp, r0
} else {
| EXT_CALL zend_jit_push_static_metod_call_frame, r0
|.if not(X64)
| add r4, 12
|.endif
- if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
+ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR) && !use_this)) {
| test r0, r0
| jz ->exception_handler
}
}
if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) {
- if (!zend_jit_push_call_frame(Dst, opline, func, 0)) {
+ if (!zend_jit_push_call_frame(Dst, opline, func, 0, use_this)) {
return 0;
}
}
}
}
- if (!zend_jit_push_call_frame(Dst, opline, func, 1)) {
+ if (!zend_jit_push_call_frame(Dst, opline, func, 1, 0)) {
return 0;
}