Browse Source

Merge zend_execute_data->called_scope into zend_execute_data->This.

"called_scope" made sense only for static method calls, for dynamic calls it was always equal to the class of $this.
Now EG(This) may store IS_OBJECT + $this or IS_UNUSED + "called_scope" (of course, "called_scope" may be NULL).
Some code might need to be adopted to support this change.
Checks (Z_OBJ(EX(This))) might need to be converted into (Z_TYPE(EX(This)) == IS_OBJECT).
pull/1846/head
Dmitry Stogov 10 years ago
parent
commit
7abfaac901
  1. 2
      Zend/zend_API.h
  2. 4
      Zend/zend_builtin_functions.c
  3. 5
      Zend/zend_compile.h
  4. 12
      Zend/zend_exceptions.c
  5. 14
      Zend/zend_execute.c
  6. 28
      Zend/zend_execute.h
  7. 24
      Zend/zend_execute_API.c
  8. 8
      Zend/zend_generators.c
  9. 90
      Zend/zend_vm_def.h
  10. 586
      Zend/zend_vm_execute.h
  11. 4
      ext/reflection/php_reflection.c

2
Zend/zend_API.h

@ -358,7 +358,7 @@ ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *na
ZEND_API char *zend_get_type_by_const(int type);
#define getThis() (Z_OBJ(EX(This)) ? &EX(This) : NULL)
#define getThis() ((Z_TYPE(EX(This)) == IS_OBJECT) ? &EX(This) : NULL)
#define ZEND_IS_METHOD_CALL() (EX(func)->common.scope != NULL)
#define WRONG_PARAM_COUNT ZEND_WRONG_PARAM_COUNT()

4
Zend/zend_builtin_functions.c

@ -2433,7 +2433,7 @@ ZEND_FUNCTION(debug_print_backtrace)
}
/* $this may be passed into regular internal functions */
object = Z_OBJ(call->This);
object = (Z_TYPE(call->This) == IS_OBJECT) ? Z_OBJ(call->This) : NULL;
if (call->func) {
func = call->func;
@ -2652,7 +2652,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
}
/* $this may be passed into regular internal functions */
object = call ? Z_OBJ(call->This) : NULL;
object = (call && (Z_TYPE(call->This) == IS_OBJECT)) ? Z_OBJ(call->This) : NULL;
if (call && call->func) {
func = call->func;

5
Zend/zend_compile.h

@ -451,7 +451,6 @@ struct _zend_execute_data {
zval *return_value;
zend_function *func; /* executed funcrion */
zval This; /* this + call_info + num_args */
zend_class_entry *called_scope;
zend_execute_data *prev_execute_data;
zend_array *symbol_table;
#if ZEND_EX_USE_RUN_TIME_CACHE
@ -482,8 +481,8 @@ struct _zend_execute_data {
#define ZEND_CALL_KIND(call) \
ZEND_CALL_KIND_EX(ZEND_CALL_INFO(call))
#define ZEND_SET_CALL_INFO(call, info) do { \
Z_TYPE_INFO((call)->This) = IS_OBJECT_EX | ((info) << 24); \
#define ZEND_SET_CALL_INFO(call, object, info) do { \
Z_TYPE_INFO((call)->This) = ((object) ? IS_OBJECT_EX : IS_UNDEF) | ((info) << 24); \
} while (0)
#define ZEND_ADD_CALL_FLAG_EX(call_info, flag) do { \

12
Zend/zend_exceptions.c

@ -268,8 +268,10 @@ ZEND_METHOD(exception, __construct)
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, zend_ce_throwable) == FAILURE) {
zend_class_entry *ce;
if (execute_data->called_scope) {
ce = execute_data->called_scope;
if (Z_TYPE(EX(This)) == IS_OBJECT) {
ce = Z_OBJCE(EX(This));
} else if (Z_CE(EX(This))) {
ce = Z_CE(EX(This));
} else {
ce = base_ce;
}
@ -330,8 +332,10 @@ ZEND_METHOD(error_exception, __construct)
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, zend_ce_throwable) == FAILURE) {
zend_class_entry *ce;
if (execute_data->called_scope) {
ce = execute_data->called_scope;
if (Z_TYPE(EX(This)) == IS_OBJECT) {
ce = Z_OBJCE(EX(This));
} else if (Z_CE(EX(This))) {
ce = Z_CE(EX(This));
} else {
ce = zend_ce_error_exception;
}

14
Zend/zend_execute.c

@ -2149,7 +2149,7 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
} while (var != end);
}
if (check_this && op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
if (check_this && op_array->this_var != (uint32_t)-1 && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
GC_REFCOUNT(Z_OBJ(EX(This)))++;
}
@ -2174,7 +2174,7 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
EX(call) = NULL;
EX(return_value) = return_value;
if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_OBJ(EX(This)))) {
if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
GC_REFCOUNT(Z_OBJ(EX(This)))++;
if (!zend_hash_str_add(EX(symbol_table), "this", sizeof("this")-1, &EX(This))) {
GC_REFCOUNT(Z_OBJ(EX(This)))--;
@ -2204,7 +2204,7 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
EX(return_value) = return_value;
if (UNEXPECTED(EX(symbol_table) != NULL)) {
if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_OBJ(EX(This)))) {
if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
GC_REFCOUNT(Z_OBJ(EX(This)))++;
if (!zend_hash_str_add(EX(symbol_table), "this", sizeof("this")-1, &EX(This))) {
GC_REFCOUNT(Z_OBJ(EX(This)))--;
@ -2264,7 +2264,7 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
} while (var != end);
}
if (op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
if (op_array->this_var != (uint32_t)-1 && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
GC_REFCOUNT(Z_OBJ(EX(This)))++;
}
@ -2315,8 +2315,8 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
call_info,
(zend_function*)op_array,
num_args,
call->called_scope,
Z_OBJ(call->This));
Z_TYPE(call->This) != IS_OBJECT ? Z_CE(call->This) : NULL,
Z_TYPE(call->This) == IS_OBJECT ? Z_OBJ(call->This) : NULL);
EX(prev_execute_data) = NULL;
EX_NUM_ARGS() = num_args;
@ -2367,7 +2367,7 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call,
/* copy call frame into new stack segment */
new_call = zend_vm_stack_extend(used_stack * sizeof(zval));
*new_call = *call;
ZEND_SET_CALL_INFO(new_call, ZEND_CALL_INFO(new_call) | ZEND_CALL_ALLOCATED);
ZEND_ADD_CALL_FLAG(new_call, ZEND_CALL_ALLOCATED);
if (passed_args) {
zval *src = ZEND_CALL_ARG(call, 1);

28
Zend/zend_execute.h

@ -167,6 +167,19 @@ ZEND_API void zend_vm_stack_init(void);
ZEND_API void zend_vm_stack_destroy(void);
ZEND_API void* zend_vm_stack_extend(size_t size);
static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
{
call->func = func;
if (object) {
Z_OBJ(call->This) = object;
ZEND_SET_CALL_INFO(call, 1, call_info);
} else {
Z_CE(call->This) = called_scope;
ZEND_SET_CALL_INFO(call, 0, call_info);
}
ZEND_CALL_NUM_ARGS(call) = num_args;
}
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
{
zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top);
@ -175,19 +188,14 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(ui
if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) {
call = (zend_execute_data*)zend_vm_stack_extend(used_stack);
ZEND_SET_CALL_INFO(call, call_info | ZEND_CALL_ALLOCATED);
ZEND_ASSERT_VM_STACK_GLOBAL;
zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, called_scope, object);
return call;
} else {
EG(vm_stack_top) = (zval*)((char*)call + used_stack);
ZEND_SET_CALL_INFO(call, call_info);
zend_vm_init_call_frame(call, call_info, func, num_args, called_scope, object);
return call;
}
ZEND_ASSERT_VM_STACK_GLOBAL;
call->func = func;
Z_OBJ(call->This) = object;
ZEND_CALL_NUM_ARGS(call) = num_args;
call->called_scope = called_scope;
return call;
}
static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, zend_function *func)

24
Zend/zend_execute_API.c

@ -769,10 +769,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
}
func = fci_cache->function_handler;
call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION,
func, fci->param_count, fci_cache->called_scope, fci_cache->object);
calling_scope = fci_cache->calling_scope;
fci->object = fci_cache->object;
fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ?
NULL : fci_cache->object;
call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION,
func, fci->param_count, fci_cache->called_scope, fci->object);
if (fci->object &&
(!EG(objects_store).object_buckets ||
!IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) {
@ -839,10 +841,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
}
EG(scope) = calling_scope;
if (func->common.fn_flags & ZEND_ACC_STATIC) {
fci->object = NULL;
}
Z_OBJ(call->This) = fci->object;
if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT);
@ -1064,11 +1062,13 @@ ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
{
while (ex) {
if (ex->called_scope) {
return ex->called_scope;
if (Z_TYPE(ex->This) == IS_OBJECT) {
return Z_OBJCE(ex->This);
} else if (Z_CE(ex->This)) {
return Z_CE(ex->This);
} else if (ex->func) {
if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
return ex->called_scope;
return NULL;
}
}
ex = ex->prev_execute_data;
@ -1080,11 +1080,11 @@ ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ *
ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
{
while (ex) {
if (Z_OBJ(ex->This)) {
if (Z_TYPE(ex->This) == IS_OBJECT) {
return Z_OBJ(ex->This);
} else if (ex->func) {
if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
return Z_OBJ(ex->This);
return NULL;
}
}
ex = ex->prev_execute_data;

8
Zend/zend_generators.c

@ -211,7 +211,7 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */
if (EX_CALL_INFO() & ZEND_CALL_FREE_EXTRA_ARGS) {
size += EX_NUM_ARGS() - op_array->num_args;
}
size += Z_OBJ(execute_data->This) != NULL; /* $this */
size += Z_TYPE(execute_data->This) == IS_OBJECT; /* $this */
size += (EX_CALL_INFO() & ZEND_CALL_CLOSURE) != 0; /* Closure object */
/* Yield from root references */
@ -273,7 +273,7 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {
}
}
if (Z_OBJ(execute_data->This)) {
if (Z_TYPE(execute_data->This) == IS_OBJECT) {
ZVAL_OBJ(gc_buffer++, Z_OBJ(execute_data->This));
}
if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) {
@ -351,7 +351,7 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array
execute_data->return_value = (zval*)generator;
memset(&generator->execute_fake, 0, sizeof(zend_execute_data));
Z_OBJ(generator->execute_fake.This) = (zend_object *) generator;
ZVAL_OBJ(&generator->execute_fake.This, (zend_object *) generator);
}
/* }}} */
@ -365,7 +365,7 @@ static ZEND_COLD zend_function *zend_generator_get_constructor(zend_object *obje
ZEND_API zend_execute_data *zend_generator_check_placeholder_frame(zend_execute_data *ptr)
{
if (!ptr->func && Z_OBJ(ptr->This)) {
if (!ptr->func && Z_TYPE(ptr->This) == IS_OBJECT) {
if (Z_OBJCE(ptr->This) == zend_ce_generator) {
zend_generator *generator = (zend_generator *) Z_OBJ(ptr->This);
zend_generator *root = (generator->node.children < 1 ? generator : generator->node.ptr.leaf)->node.ptr.root;

90
Zend/zend_vm_def.h

@ -711,7 +711,7 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
SAVE_OPLINE();
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
FREE_UNFETCHED_OP2();
@ -771,7 +771,7 @@ ZEND_VM_HELPER(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|UNU
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
FREE_UNFETCHED_OP2();
@ -1101,7 +1101,7 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
SAVE_OPLINE();
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -1180,7 +1180,7 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
SAVE_OPLINE();
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -1813,7 +1813,7 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -1886,7 +1886,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_OP2();
HANDLE_EXCEPTION();
@ -1912,7 +1912,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_OP2();
HANDLE_EXCEPTION();
@ -1937,7 +1937,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -2013,7 +2013,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_OP2();
HANDLE_EXCEPTION();
@ -2045,7 +2045,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -2166,7 +2166,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, SPEC(
SAVE_OPLINE();
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -3095,7 +3095,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, CONST|T
object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_OP2();
HANDLE_EXCEPTION();
@ -3275,7 +3275,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
zend_throw_error(NULL, "Cannot call constructor");
HANDLE_EXCEPTION();
}
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name));
HANDLE_EXCEPTION();
}
@ -3284,7 +3284,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
object = NULL;
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
object = Z_OBJ(EX(This));
ce = object->ce;
} else {
@ -3313,7 +3313,11 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
/* previous opcode is ZEND_FETCH_CLASS */
if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
(opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
if (Z_TYPE(EX(This)) == IS_OBJECT) {
ce = Z_OBJCE(EX(This));
} else {
ce = Z_CE(EX(This));
}
}
}
@ -3989,8 +3993,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
} else { /* ZEND_OVERLOADED_FUNCTION */
zval retval;
/* Not sure what should be done here if it's a static method */
object = Z_OBJ(call->This);
if (UNEXPECTED(object == NULL)) {
if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) {
zend_vm_stack_free_args(call);
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
zend_string_release(fbc->common.function_name);
@ -4002,6 +4005,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
HANDLE_EXCEPTION();
}
object = Z_OBJ(call->This);
EG(scope) = fbc->common.scope;
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
@ -4737,12 +4741,12 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY)
if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
}
if (Z_OBJ(EX(call)->This)) {
if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
OBJ_RELEASE(Z_OBJ(EX(call)->This));
}
EX(call)->func = (zend_function*)&zend_pass_function;
EX(call)->called_scope = NULL;
Z_OBJ(EX(call)->This) = NULL;
ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)));
} else {
uint32_t arg_num;
HashTable *ht;
@ -4784,12 +4788,12 @@ ZEND_VM_C_LABEL(send_array):
if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
}
if (Z_OBJ(EX(call)->This)) {
if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
OBJ_RELEASE(Z_OBJ(EX(call)->This));
}
EX(call)->func = (zend_function*)&zend_pass_function;
EX(call)->called_scope = NULL;
Z_OBJ(EX(call)->This) = NULL;
ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)));
break;
}
@ -4841,13 +4845,13 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, NUM)
if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
}
if (Z_OBJ(EX(call)->This)) {
if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
OBJ_RELEASE(Z_OBJ(EX(call)->This));
}
ZVAL_UNDEF(param);
EX(call)->func = (zend_function*)&zend_pass_function;
EX(call)->called_scope = NULL;
Z_OBJ(EX(call)->This) = NULL;
ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)));
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@ -5144,7 +5148,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
SAVE_OPLINE();
obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(obj) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
HANDLE_EXCEPTION();
}
@ -5658,7 +5662,9 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL)
new_op_array->scope = EG(scope);
call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE,
(zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)));
(zend_function*)new_op_array, 0,
Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL,
Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL);
if (EX(symbol_table)) {
call->symbol_table = EX(symbol_table);
@ -5814,7 +5820,7 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -5906,7 +5912,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -6730,7 +6736,7 @@ ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, CO
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -6869,7 +6875,7 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, C
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) {
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
zend_throw_error(NULL, "Using $this when not in object context");
FREE_UNFETCHED_OP2();
HANDLE_EXCEPTION();
@ -7509,20 +7515,28 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
{
USE_OPLINE
zval *zfunc;
zval *object;
zend_class_entry *called_scope;
SAVE_OPLINE();
zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1)));
ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION);
if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) ||
if (Z_TYPE(EX(This)) == IS_OBJECT) {
called_scope = Z_OBJCE(EX(This));
if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) ||
(EX(func)->common.fn_flags & ZEND_ACC_STATIC))) {
zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc),
EG(scope), EX(called_scope), NULL);
object = NULL;
} else {
object = &EX(This);
}
} else {
zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc),
EG(scope), EX(called_scope), Z_OBJ(EX(This)) ? &EX(This) : NULL);
called_scope = Z_CE(EX(This));
object = NULL;
}
zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc),
EG(scope), called_scope, object);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
@ -8057,6 +8071,7 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY, CLASS_FETCH)
{
uint32_t fetch_type;
zend_class_entry *called_scope;
USE_OPLINE
SAVE_OPLINE();
@ -8082,7 +8097,12 @@ ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY, CLASS_FETCH)
ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->parent->name);
break;
case ZEND_FETCH_CLASS_STATIC:
ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(called_scope)->name);
if (Z_TYPE(EX(This)) == IS_OBJECT) {
called_scope = Z_OBJCE(EX(This));
} else {
called_scope = Z_CE(EX(This));
}
ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}

586
Zend/zend_vm_execute.h
File diff suppressed because it is too large
View File

4
ext/reflection/php_reflection.c

@ -88,7 +88,7 @@ ZEND_DECLARE_MODULE_GLOBALS(reflection)
/* Method macros */
#define METHOD_NOTSTATIC(ce) \
if (!Z_OBJ(EX(This)) || !instanceof_function(Z_OBJCE(EX(This)), ce)) { \
if ((Z_TYPE(EX(This)) != IS_OBJECT) || !instanceof_function(Z_OBJCE(EX(This)), ce)) { \
php_error_docref(NULL, E_ERROR, "%s() cannot be called statically", get_active_function_name()); \
return; \
} \
@ -2316,7 +2316,7 @@ ZEND_METHOD(reflection_generator, getThis)
REFLECTION_CHECK_VALID_GENERATOR(ex)
if (Z_OBJ(ex->This)) {
if (Z_TYPE(ex->This) == IS_OBJECT) {
ZVAL_COPY(return_value, &ex->This);
} else {
ZVAL_NULL(return_value);

Loading…
Cancel
Save