diff options
Diffstat (limited to 'Zend/zend_vm_def.h')
-rw-r--r-- | Zend/zend_vm_def.h | 171 |
1 files changed, 131 insertions, 40 deletions
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 745d4a5a64..0079ddce29 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -801,6 +801,8 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -827,8 +829,14 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(assign_op_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->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, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL))) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -865,7 +873,10 @@ ZEND_VM_C_LABEL(assign_op_object): } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1165,6 +1176,8 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -1189,8 +1202,14 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(pre_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == 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, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL))) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1204,7 +1223,10 @@ ZEND_VM_C_LABEL(pre_incdec_object): zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - 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 (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1232,6 +1254,8 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -1256,8 +1280,14 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(post_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == 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 { @@ -1270,7 +1300,10 @@ ZEND_VM_C_LABEL(post_incdec_object): 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 (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1921,9 +1954,11 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -1942,17 +1977,17 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; ZEND_VM_C_GOTO(fetch_obj_r_copy); } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -1960,11 +1995,18 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST } } } - } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_r_copy): @@ -2063,9 +2105,11 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -2084,17 +2128,17 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; ZEND_VM_C_GOTO(fetch_obj_is_copy); } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -2102,9 +2146,15 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_is_copy): @@ -2196,6 +2246,8 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE USE_OPLINE zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); @@ -2220,8 +2272,9 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE } ZEND_VM_C_LABEL(assign_object): + zobj = Z_OBJ_P(object); if (OP2_TYPE == 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); @@ -2311,7 +2364,17 @@ ZEND_VM_C_LABEL(fast_assign_obj): ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -3595,7 +3658,7 @@ ZEND_VM_C_LABEL(try_function_name): if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -5258,6 +5321,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) USE_OPLINE zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -5291,9 +5355,10 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); FREE_OP1(); @@ -5314,7 +5379,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -5874,7 +5939,7 @@ ZEND_VM_C_LABEL(num_index_dim): if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -5891,6 +5956,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); @@ -5910,7 +5976,15 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); FREE_OP2(); @@ -5938,20 +6012,24 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE(); } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (OP1_TYPE != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + if (zobj->properties) { + 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); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + zobj->properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(zobj->properties, 0); FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -6574,6 +6652,7 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS); @@ -6598,9 +6677,19 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED } } + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } ZEND_VM_C_LABEL(isset_object_finish): FREE_OP2(); @@ -8257,18 +8346,20 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED) count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; |