}
}
- post_incdec_object:
+ pre_incdec_object:
/* here we are sure we are dealing with an object */
+ zobj = Z_OBJ_P(object);
+ if (IS_CONST == IS_CONST) {
+ name = Z_STR_P(property);
+ } else {
+ name = zval_get_tmp_string(property, &tmp_name);
+ }
cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL;
- if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) {
+ if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) {
if (UNEXPECTED(Z_ISERROR_P(zptr))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
} else {
if (IS_CONST == IS_CONST) {
- prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
+ prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
} else {
prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr);
}
-
- zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC);
+ zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC);
}
} else {
- zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC);
- zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC);
++ zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC);
+ }
+ if (IS_CONST != IS_CONST) {
+ zend_tmp_string_release(tmp_name);
}
} while (0);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
- static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_post_incdec_property_helper_SPEC_CV_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_pre_incdec_property_helper_SPEC_CV_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
- static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_post_incdec_property_helper_SPEC_CV_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_pre_incdec_property_helper_SPEC_CV_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
- static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_static_property_helper_SPEC_CV_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
+ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
- zval *prop;
+
+ zval *object;
+ zval *property;
+ zval *zptr;
+ void **cache_slot;
zend_property_info *prop_info;
++ zend_object *zobj;
++ zend_string *name, *tmp_name;
SAVE_OPLINE();
+ object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC);
- if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
+ if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
- zend_pre_incdec_property_zval(prop, prop_info->type ? prop_info : NULL, inc OPLINE_CC EXECUTE_DATA_CC);
+ property = RT_CONSTANT(opline, opline->op2);
+
+ do {
+ if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
+ object = Z_REFVAL_P(object);
+ goto post_incdec_object;
+ }
+ object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC);
+ if (UNEXPECTED(!object)) {
+ break;
+ }
+ }
+
+ post_incdec_object:
+ /* here we are sure we are dealing with an object */
++ zobj = Z_OBJ_P(object);
++ if (IS_CONST == IS_CONST) {
++ name = Z_STR_P(property);
++ } else {
++ name = zval_get_tmp_string(property, &tmp_name);
++ }
+ cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL;
- if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) {
++ if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) {
+ if (UNEXPECTED(Z_ISERROR_P(zptr))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ if (IS_CONST == IS_CONST) {
+ prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
+ } else {
+ prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr);
+ }
+
+ zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC);
+ }
+ } else {
- zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC);
++ zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC);
++ }
++ if (IS_CONST != IS_CONST) {
++ zend_tmp_string_release(tmp_name);
+ }
+ } while (0);
+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
{
USE_OPLINE
- zval *prop, *value;
- zend_property_info *prop_info;
+ zval *object, *property, *value, tmp;
++ zend_object *zobj;
++ zend_string *name, *tmp_name;
SAVE_OPLINE();
+ object = EX_VAR(opline->op1.var);
- if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
-
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
- }
-
- value = RT_CONSTANT((opline+1), (opline+1)->op1);
-
- if (UNEXPECTED(prop_info->type)) {
- value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC);
-
- } else {
- value = zend_assign_to_variable(prop, value, IS_CONST, EX_USES_STRICT_TYPES());
- }
-
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
- /* assign_static_prop has two opcodes! */
- ZEND_VM_NEXT_OPCODE_EX(1, 2);
- }
-
- static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
- {
- USE_OPLINE
- zend_free_op free_op_data;
- zval *prop, *value;
- zend_property_info *prop_info;
+ property = RT_CONSTANT(opline, opline->op2);
+ value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC);
- SAVE_OPLINE();
+ if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
+ object = Z_REFVAL_P(object);
+ goto assign_object;
+ }
+ object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC);
+ if (UNEXPECTED(!object)) {
- if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
- zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
+ goto exit_assign_obj;
+ }
}
- value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC);
+ assign_object:
++ zobj = Z_OBJ_P(object);
+ if (IS_CONST == IS_CONST &&
- EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) {
++ EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) {
+ void **cache_slot = CACHE_ADDR(opline->extended_value);
+ uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
+ zend_object *zobj = Z_OBJ_P(object);
+ zval *property_val;
- if (UNEXPECTED(prop_info->type)) {
- value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC);
- zval_ptr_dtor_nogc(free_op_data);
- } else {
- value = zend_assign_to_variable(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES());
- }
+ if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
+ property_val = OBJ_PROP(zobj, prop_offset);
+ if (Z_TYPE_P(property_val) != IS_UNDEF) {
+ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- }
+ if (UNEXPECTED(prop_info != NULL)) {
+ zend_uchar orig_type = IS_UNDEF;
- /* assign_static_prop has two opcodes! */
- ZEND_VM_NEXT_OPCODE_EX(1, 2);
- }
+ if (IS_CV == IS_CONST) {
+ orig_type = Z_TYPE_P(value);
+ }
- static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
- {
- USE_OPLINE
- zend_free_op free_op_data;
- zval *prop, *value;
- zend_property_info *prop_info;
+ value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC);
- SAVE_OPLINE();
+ /* will remain valid, thus no need to check prop_info in future here */
+ if (IS_CV == IS_CONST && Z_TYPE_P(value) == orig_type) {
+ CACHE_PTR_EX(cache_slot + 2, NULL);
+ }
- if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
- zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
- }
+ } else {
+ fast_assign_obj:
+ value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES());
+ }
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ goto exit_assign_obj;
+ }
+ } else {
+ if (EXPECTED(zobj->properties != NULL)) {
+ if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_DELREF(zobj->properties);
+ }
+ zobj->properties = zend_array_dup(zobj->properties);
+ }
+ property_val = zend_hash_find_ex(zobj->properties, Z_STR_P(property), 1);
+ if (property_val) {
+ goto fast_assign_obj;
+ }
+ }
- value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC);
+ if (!zobj->ce->__set) {
- if (UNEXPECTED(prop_info->type)) {
- value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC);
- zval_ptr_dtor_nogc(free_op_data);
- } else {
- value = zend_assign_to_variable(prop, value, IS_VAR, EX_USES_STRICT_TYPES());
+ if (EXPECTED(zobj->properties == NULL)) {
+ rebuild_object_properties(zobj);
+ }
+ if (IS_CV == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) {
+ Z_ADDREF_P(value);
+ }
+ } else if (IS_CV != IS_TMP_VAR) {
+ if (Z_ISREF_P(value)) {
+ if (IS_CV == IS_VAR) {
+ zend_reference *ref = Z_REF_P(value);
+ if (GC_DELREF(ref) == 0) {
+ ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value));
+ efree_size(ref, sizeof(zend_reference));
+ value = &tmp;
+ } else {
+ value = Z_REFVAL_P(value);
+ Z_TRY_ADDREF_P(value);
+ }
+ } else {
+ value = Z_REFVAL_P(value);
+ Z_TRY_ADDREF_P(value);
+ }
+ } else if (IS_CV == IS_CV) {
+ Z_TRY_ADDREF_P(value);
+ }
+ }
+ zend_hash_add_new(zobj->properties, Z_STR_P(property), value);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ goto exit_assign_obj;
+ }
+ }
}
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(value);
}
- /* assign_static_prop has two opcodes! */
- ZEND_VM_NEXT_OPCODE_EX(1, 2);
- }
-
- static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
- {
- USE_OPLINE
-
- zval *prop, *value;
- zend_property_info *prop_info;
-
- SAVE_OPLINE();
-
- if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
-
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
- property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL);
++ if (IS_CONST == IS_CONST) {
++ name = Z_STR_P(property);
++ } else {
++ name = zval_get_tmp_string(property, &tmp_name);
+ }
+
- value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC);
-
- if (UNEXPECTED(prop_info->type)) {
- value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC);
++ property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL);
+
- } else {
- value = zend_assign_to_variable(prop, value, IS_CV, EX_USES_STRICT_TYPES());
++ if (IS_CONST != IS_CONST) {
++ zend_tmp_string_release(tmp_name);
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ ZVAL_COPY(EX_VAR(opline->result.var), property);
}
- /* assign_static_prop has two opcodes! */
+ exit_assign_obj:
+
+
+ /* assign_obj has two opcodes! */
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}