Hi Basant,
I've updated you patch for 5.3 (attached, don't forget to regenerate
zend_vm_execute.h). 5.2 is closed for such changes anyway and I don't
think the patch should be applied into 5.3 too, because it is in RC stage.
I got ~10% speed-up on very synthetic benchmarks (b.php attached).
The speed difference on real-life applications without opcode caches is
invisible. I wasn't able to test it with caches.
In general the idea is very interesting, but as I mentioned before I
don't like extension of zend_opcode and tricky usage of object handlers.
It should be done in some more general way.
Anyway, please check if my changes didn't make your patch slower.
May be someone would like to play with patch and make it better...
Thanks. Dmitry.
Basant Kukreja wrote:
Attached is the patch for bug 47815
http://bugs.php.net/bug.php?id=47815
I applied this patch on php-5.2.9 and it applied cleanly.
Thanks for looking into the patch.
Regards,
Basant.
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.12.2.39
diff -u -p -d -r1.316.2.8.2.12.2.39 zend_compile.h
--- Zend/zend_compile.h 26 Jan 2009 22:54:20 -0000 1.316.2.8.2.12.2.39
+++ Zend/zend_compile.h 31 Mar 2009 18:12:53 -0000
@@ -84,6 +84,7 @@ struct _zend_op {
znode op1;
znode op2;
ulong extended_value;
+ ulong hval;
uint lineno;
zend_uchar opcode;
};
Index: Zend/zend_execute.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute.c,v
retrieving revision 1.716.2.12.2.24.2.41
diff -u -p -d -r1.716.2.12.2.24.2.41 zend_execute.c
--- Zend/zend_execute.c 18 Mar 2009 14:15:28 -0000 1.716.2.12.2.24.2.41
+++ Zend/zend_execute.c 31 Mar 2009 18:12:53 -0000
@@ -784,7 +784,7 @@ static inline HashTable *zend_get_target
return NULL;
}
-static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const
zval *dim, int type TSRMLS_DC)
+static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const
zval *dim, int type, zend_ulong hval TSRMLS_DC)
{
zval **retval;
char *offset_key;
@@ -795,6 +795,7 @@ static inline zval **zend_fetch_dimensio
case IS_NULL:
offset_key = "";
offset_key_length = 0;
+ hval = zend_inline_hash_func("", 1);
goto fetch_string_dim;
case IS_STRING:
@@ -803,7 +804,7 @@ static inline zval **zend_fetch_dimensio
offset_key_length = dim->value.str.len;
fetch_string_dim:
- if (zend_symtable_find(ht, offset_key,
offset_key_length+1, (void **) &retval) == FAILURE) {
+ if (zend_symtable_quick_find(ht, offset_key,
offset_key_length+1, hval, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
zend_error(E_NOTICE, "Undefined
index: %s", offset_key);
@@ -819,7 +820,7 @@ fetch_string_dim:
zval *new_zval =
&EG(uninitialized_zval);
Z_ADDREF_P(new_zval);
-
zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval,
sizeof(zval *), (void **) &retval);
+
zend_symtable_quick_update(ht, offset_key, offset_key_length+1, hval,
&new_zval, sizeof(zval *), (void **) &retval);
}
break;
}
@@ -867,7 +868,7 @@ num_index:
return retval;
}
-static void zend_fetch_dimension_address(temp_variable *result, zval
**container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
+static void zend_fetch_dimension_address(temp_variable *result, zval
**container_ptr, zval *dim, int dim_is_tmp_var, int type, zend_ulong hval
TSRMLS_DC)
{
zval *container = *container_ptr;
zval **retval;
@@ -890,7 +891,7 @@ fetch_from_array:
Z_DELREF_P(new_zval);
}
} else {
- retval =
zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
+ retval =
zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type, hval
TSRMLS_CC);
}
result->var.ptr_ptr = retval;
PZVAL_LOCK(*retval);
@@ -1022,7 +1023,7 @@ convert_to_array:
}
}
-static void zend_fetch_dimension_address_read(temp_variable *result, zval
**container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
+static void zend_fetch_dimension_address_read(temp_variable *result, zval
**container_ptr, zval *dim, int dim_is_tmp_var, int type, zend_ulong hval
TSRMLS_DC)
{
zval *container = *container_ptr;
zval **retval;
@@ -1030,7 +1031,7 @@ static void zend_fetch_dimension_address
switch (Z_TYPE_P(container)) {
case IS_ARRAY:
- retval =
zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
+ retval =
zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type, hval
TSRMLS_CC);
if (result) {
AI_SET_PTR(result->var, *retval);
PZVAL_LOCK(*retval);
Index: Zend/zend_hash.h
===================================================================
RCS file: /repository/ZendEngine2/zend_hash.h,v
retrieving revision 1.78.2.2.2.2.2.12
diff -u -p -d -r1.78.2.2.2.2.2.12 zend_hash.h
--- Zend/zend_hash.h 24 Mar 2009 16:02:50 -0000 1.78.2.2.2.2.2.12
+++ Zend/zend_hash.h 31 Mar 2009 18:12:53 -0000
@@ -373,6 +373,30 @@ static inline int zend_symtable_update_c
return zend_hash_update_current_key_ex(ht, HASH_KEY_IS_STRING, arKey,
nKeyLength, 0, mode, NULL);
}
+static inline int zend_symtable_quick_update(HashTable *ht, const char *arKey,
uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest)
+{
+ ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx,
pData, nDataSize, pDest));
+ return zend_hash_quick_update(ht, arKey, nKeyLength, h, pData,
nDataSize, pDest);
+}
+
+static inline int zend_symtable_quick_del(HashTable *ht, const char *arKey,
uint nKeyLength, ulong h)
+{
+ ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx));
+ return zend_hash_quick_del(ht, arKey, nKeyLength, h);
+}
+
+static inline int zend_symtable_quick_find(HashTable *ht, char *arKey, uint
nKeyLength, ulong h, void **pData)
+{
+ ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx,
pData));
+ return zend_hash_quick_find(ht, arKey, nKeyLength, h, pData);
+}
+
+static inline int zend_symtable_quick_exists(HashTable *ht, const char *arKey,
uint nKeyLength, ulong h)
+{
+ ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
+ return zend_hash_quick_exists(ht, arKey, nKeyLength, h);
+}
+
#endif /* ZEND_HASH_H */
/*
Index: Zend/zend_object_handlers.c
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.c,v
retrieving revision 1.135.2.6.2.22.2.26
diff -u -p -d -r1.135.2.6.2.22.2.26 zend_object_handlers.c
--- Zend/zend_object_handlers.c 14 Jan 2009 10:28:22 -0000
1.135.2.6.2.22.2.26
+++ Zend/zend_object_handlers.c 31 Mar 2009 18:12:53 -0000
@@ -190,12 +190,11 @@ static inline zend_bool is_derived_class
}
/* }}} */
-ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry
*ce, zval *member, int silent TSRMLS_DC) /* {{{ */
+ZEND_API struct _zend_property_info
*zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent,
zend_ulong h TSRMLS_DC) /* {{{ */
{
zend_property_info *property_info = NULL;
zend_property_info *scope_property_info;
zend_bool denied_access = 0;
- ulong h;
if (Z_STRVAL_P(member)[0] == '\0') {
if (!silent) {
@@ -207,7 +206,6 @@ ZEND_API struct _zend_property_info *zen
}
return NULL;
}
- h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
if (zend_hash_quick_find(&ce->properties_info, Z_STRVAL_P(member),
Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) {
if(property_info->flags & ZEND_ACC_SHADOW) {
/* if it's a shadow - go to access it's private */
@@ -260,6 +258,14 @@ ZEND_API struct _zend_property_info *zen
}
/* }}} */
+ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry
*ce, zval *member, int silent TSRMLS_DC) /* {{{ */
+{
+ zend_ulong h = zend_get_hash_value(Z_STRVAL_P(member),
Z_STRLEN_P(member) + 1);
+
+ return zend_get_property_info_quick(ce, member, silent, h TSRMLS_CC);
+}
+/* }}} */
+
ZEND_API int zend_check_property_access(zend_object *zobj, char
*prop_info_name, int prop_info_name_len TSRMLS_DC) /* {{{ */
{
zend_property_info *property_info;
@@ -310,10 +316,9 @@ static int zend_get_property_guard(zend_
}
/* }}} */
-zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
/* {{{ */
+zval *zend_std_quick_read_property(zval *object, zval *member, int type,
zend_ulong hval TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
- zval *tmp_member = NULL;
zval **retval;
zval *rv = NULL;
zend_property_info *property_info;
@@ -322,21 +327,12 @@ zval *zend_std_read_property(zval *objec
silent = (type == BP_VAR_IS);
zobj = Z_OBJ_P(object);
- if (Z_TYPE_P(member) != IS_STRING) {
- ALLOC_ZVAL(tmp_member);
- *tmp_member = *member;
- INIT_PZVAL(tmp_member);
- zval_copy_ctor(tmp_member);
- convert_to_string(tmp_member);
- member = tmp_member;
- }
-
#if DEBUG_OBJECT_HANDLERS
fprintf(stderr, "Read object #%d property: %s\n",
Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
#endif
/* make zend_get_property_info silent if we have getter - we may want
to use it */
- property_info = zend_get_property_info(zobj->ce, member,
(zobj->ce->__get != NULL) TSRMLS_CC);
+ property_info = zend_get_property_info_quick(zobj->ce, member,
(zobj->ce->__get != NULL), hval TSRMLS_CC);
if (!property_info || zend_hash_quick_find(zobj->properties,
property_info->name, property_info->name_length+1, property_info->h, (void **)
&retval) == FAILURE) {
zend_guard *guard;
@@ -378,23 +374,15 @@ zval *zend_std_read_property(zval *objec
retval = &EG(uninitialized_zval_ptr);
}
}
- if (tmp_member) {
- Z_ADDREF_PP(retval);
- zval_ptr_dtor(&tmp_member);
- Z_DELREF_PP(retval);
- }
return *retval;
}
/* }}} */
-static void zend_std_write_property(zval *object, zval *member, zval *value
TSRMLS_DC) /* {{{ */
+zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
/* {{{ */
{
- zend_object *zobj;
zval *tmp_member = NULL;
- zval **variable_ptr;
- zend_property_info *property_info;
-
- zobj = Z_OBJ_P(object);
+ zval *retval;
+ zend_ulong hval;
if (Z_TYPE_P(member) != IS_STRING) {
ALLOC_ZVAL(tmp_member);
@@ -404,8 +392,26 @@ static void zend_std_write_property(zval
convert_to_string(tmp_member);
member = tmp_member;
}
+ hval = zend_inline_hash_func(Z_STRVAL_P(member), Z_STRLEN_P(member)+1);
+ retval = zend_std_quick_read_property(object, member, type, hval
TSRMLS_CC);
+ if (tmp_member) {
+ Z_ADDREF_P(retval);
+ zval_ptr_dtor(&tmp_member);
+ Z_DELREF_P(retval);
+ }
+ return retval;
+}
+/* }}} */
- property_info = zend_get_property_info(zobj->ce, member,
(zobj->ce->__set != NULL) TSRMLS_CC);
+void zend_std_quick_write_property(zval *object, zval *member, zval *value,
zend_ulong hval TSRMLS_DC) /* {{{ */
+{
+ zend_object *zobj;
+ zval **variable_ptr;
+ zend_property_info *property_info;
+
+ zobj = Z_OBJ_P(object);
+
+ property_info = zend_get_property_info_quick(zobj->ce, member,
(zobj->ce->__set != NULL), hval TSRMLS_CC);
if (property_info && zend_hash_quick_find(zobj->properties,
property_info->name, property_info->name_length+1, property_info->h, (void **)
&variable_ptr) == SUCCESS) {
/* if we already have this value there, we don't actually need
to do anything */
@@ -461,7 +467,24 @@ static void zend_std_write_property(zval
zend_hash_quick_update(zobj->properties,
property_info->name, property_info->name_length+1, property_info->h, &value,
sizeof(zval *), (void **) &foo);
}
}
+}
+/* }}} */
+void zend_std_write_property(zval *object, zval *member, zval *value
TSRMLS_DC) /* {{{ */
+{
+ zval *tmp_member = NULL;
+ zend_ulong hval;
+
+ if (Z_TYPE_P(member) != IS_STRING) {
+ ALLOC_ZVAL(tmp_member);
+ *tmp_member = *member;
+ INIT_PZVAL(tmp_member);
+ zval_copy_ctor(tmp_member);
+ convert_to_string(tmp_member);
+ member = tmp_member;
+ }
+ hval = zend_inline_hash_func(Z_STRVAL_P(member), Z_STRLEN_P(member)+1);
+ zend_std_quick_write_property(object, member, value, hval TSRMLS_CC);
if (tmp_member) {
zval_ptr_dtor(&tmp_member);
}
@@ -551,27 +574,19 @@ static int zend_std_has_dimension(zval *
}
/* }}} */
-static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member
TSRMLS_DC) /* {{{ */
+zval **zend_std_quick_get_property_ptr_ptr(zval *object, zval *member,
zend_ulong hval TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
- zval tmp_member;
zval **retval;
zend_property_info *property_info;
zobj = Z_OBJ_P(object);
- if (Z_TYPE_P(member) != IS_STRING) {
- tmp_member = *member;
- zval_copy_ctor(&tmp_member);
- convert_to_string(&tmp_member);
- member = &tmp_member;
- }
-
#if DEBUG_OBJECT_HANDLERS
fprintf(stderr, "Ptr object #%d property: %s\n",
Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
#endif
- property_info = zend_get_property_info(zobj->ce, member,
(zobj->ce->__get != NULL) TSRMLS_CC);
+ property_info = zend_get_property_info_quick(zobj->ce, member,
(zobj->ce->__get != NULL), hval TSRMLS_CC);
if (!property_info || zend_hash_quick_find(zobj->properties,
property_info->name, property_info->name_length+1, property_info->h, (void **)
&retval) == FAILURE) {
zval *new_zval;
@@ -591,6 +606,24 @@ static zval **zend_std_get_property_ptr_
retval = NULL;
}
}
+ return retval;
+}
+/* }}} */
+
+zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /*
{{{ */
+{
+ zval tmp_member;
+ zval **retval;
+ zend_ulong hval;
+
+ if (Z_TYPE_P(member) != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ }
+ hval = zend_inline_hash_func(Z_STRVAL_P(member), Z_STRLEN_P(member)+1);
+ retval = zend_std_quick_get_property_ptr_ptr(object, member, hval
TSRMLS_CC);
if (member == &tmp_member) {
zval_dtor(member);
}
Index: Zend/zend_object_handlers.h
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.h,v
retrieving revision 1.47.2.2.2.5.2.7
diff -u -p -d -r1.47.2.2.2.5.2.7 zend_object_handlers.h
--- Zend/zend_object_handlers.h 31 Dec 2008 11:15:32 -0000 1.47.2.2.2.5.2.7
+++ Zend/zend_object_handlers.h 31 Mar 2009 18:12:53 -0000
@@ -163,6 +163,14 @@ ZEND_API int zend_check_protected(zend_c
ZEND_API int zend_check_property_access(zend_object *zobj, char
*prop_info_name, int prop_info_name_len TSRMLS_DC);
ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS);
+
+zval *zend_std_quick_read_property(zval *object, zval *member, int type,
zend_ulong hval TSRMLS_DC);
+zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC);
+void zend_std_quick_write_property(zval *object, zval *member, zval *value,
zend_ulong hval TSRMLS_DC);
+void zend_std_write_property(zval *object, zval *member, zval *value
TSRMLS_DC);
+zval **zend_std_quick_get_property_ptr_ptr(zval *object, zval *member,
zend_ulong hval TSRMLS_DC);
+zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC);
+
END_EXTERN_C()
#endif
Index: Zend/zend_opcode.c
===================================================================
RCS file: /repository/ZendEngine2/zend_opcode.c,v
retrieving revision 1.110.2.6.2.3.2.10
diff -u -p -d -r1.110.2.6.2.3.2.10 zend_opcode.c
--- Zend/zend_opcode.c 31 Dec 2008 11:15:32 -0000 1.110.2.6.2.3.2.10
+++ Zend/zend_opcode.c 31 Mar 2009 18:12:53 -0000
@@ -405,6 +405,49 @@ int pass_two(zend_op_array *op_array TSR
case ZEND_JMP_SET:
opline->op2.u.jmp_addr =
&op_array->opcodes[opline->op2.u.opline_num];
break;
+ case ZEND_FETCH_DIM_R:
+ case ZEND_FETCH_DIM_W:
+ case ZEND_FETCH_DIM_RW:
+ case ZEND_FETCH_DIM_IS:
+ case ZEND_FETCH_DIM_FUNC_ARG:
+ case ZEND_FETCH_DIM_UNSET:
+ case ZEND_FETCH_DIM_TMP_VAR:
+ case ZEND_FETCH_OBJ_R:
+ case ZEND_FETCH_OBJ_IS:
+ case ZEND_FETCH_OBJ_FUNC_ARG:
+ case ZEND_ASSIGN_DIM:
+ case ZEND_ADD_ARRAY_ELEMENT:
+ case ZEND_INIT_ARRAY:
+ case ZEND_UNSET_DIM:
+ case ZEND_PRE_INC_OBJ:
+ case ZEND_PRE_DEC_OBJ:
+ case ZEND_POST_INC_OBJ:
+ case ZEND_POST_DEC_OBJ:
+ if ((opline->op2.op_type == IS_CONST) &&
+ (Z_TYPE(opline->op2.u.constant) ==
IS_STRING)) {
+ opline->hval =
zend_get_hash_value(Z_STRVAL(opline->op2.u.constant),
+
Z_STRLEN(opline->op2.u.constant) +1);
+ }
+ break;
+ case ZEND_ASSIGN_ADD:
+ case ZEND_ASSIGN_SUB:
+ case ZEND_ASSIGN_MUL:
+ case ZEND_ASSIGN_DIV:
+ case ZEND_ASSIGN_MOD:
+ case ZEND_ASSIGN_SL:
+ case ZEND_ASSIGN_SR:
+ case ZEND_ASSIGN_CONCAT:
+ case ZEND_ASSIGN_BW_OR:
+ case ZEND_ASSIGN_BW_AND:
+ case ZEND_ASSIGN_BW_XOR:
+ if ((opline->extended_value == ZEND_ASSIGN_DIM
||
+ opline->extended_value == ZEND_ASSIGN_OBJ)
&&
+ (opline->op2.op_type == IS_CONST) &&
+ (Z_TYPE(opline->op2.u.constant) ==
IS_STRING)) {
+ opline->hval =
zend_get_hash_value(Z_STRVAL(opline->op2.u.constant),
+
Z_STRLEN(opline->op2.u.constant) +1);
+ }
+ break;
}
ZEND_VM_SET_OPCODE_HANDLER(opline);
opline++;
Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.48.2.89
diff -u -p -d -r1.59.2.29.2.48.2.89 zend_vm_def.h
--- Zend/zend_vm_def.h 26 Mar 2009 10:17:27 -0000 1.59.2.29.2.48.2.89
+++ Zend/zend_vm_def.h 31 Mar 2009 18:12:53 -0000
@@ -330,7 +330,14 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr =
Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr;
+
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(property) ==
IS_STRING &&
+ Z_OBJ_HT_P(object)->get_property_ptr_ptr ==
zend_std_get_property_ptr_ptr) {
+ zptr =
zend_std_quick_get_property_ptr_ptr(object, property, opline->hval TSRMLS_CC);
+ } else {
+ zptr =
Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ }
if (zptr != NULL) { /* NULL means
no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
@@ -349,7 +356,12 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z =
Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST &&
Z_TYPE_P(property) == IS_STRING &&
+ Z_OBJ_HT_P(object)->read_property
== zend_std_read_property) {
+ z =
zend_std_quick_read_property(object, property, BP_VAR_R, opline->hval
TSRMLS_CC);
+ } else {
+ z =
Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ }
}
} else /* if (opline->extended_value ==
ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -371,7 +383,12 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
-
Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST &&
Z_TYPE_P(property) == IS_STRING &&
+ Z_OBJ_HT_P(object)->write_property
== zend_std_write_property) {
+
zend_std_quick_write_property(object, property, z, opline->hval TSRMLS_CC);
+ } else {
+
Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ }
} else /* if (opline->extended_value ==
ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
@@ -429,8 +446,14 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_
} else {
zend_op *op_data = opline+1;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zend_ulong hval = 0;
-
zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim,
IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST &&
Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (OP2_TYPE != IS_UNUSED &&
Z_TYPE_P(dim) == IS_STRING) {
+ hval =
zend_inline_hash_func(Z_STRVAL_P(dim), Z_STRLEN_P(dim)+1);
+ }
+
zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim,
IS_OP2_TMP_FREE(), BP_VAR_RW, hval TSRMLS_CC);
value = get_zval_ptr(&op_data->op1,
EX(Ts), &free_op_data1, BP_VAR_R);
var_ptr =
_get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
ZEND_VM_INC_OPCODE();
@@ -576,7 +599,14 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_proper
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object,
property TSRMLS_CC);
+ zval **zptr;
+
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(property) == IS_STRING &&
+ Z_OBJ_HT_P(object)->get_property_ptr_ptr ==
zend_std_get_property_ptr_ptr) {
+ zptr = zend_std_quick_get_property_ptr_ptr(object,
property, opline->hval TSRMLS_CC);
+ } else {
+ zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object,
property TSRMLS_CC);
+ }
if (zptr != NULL) { /* NULL means no
success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
@@ -591,7 +621,14 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_proper
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property &&
Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object,
property, BP_VAR_R TSRMLS_CC);
+ zval *z;
+
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(property) ==
IS_STRING &&
+ Z_OBJ_HT_P(object)->read_property ==
zend_std_read_property) {
+ z = zend_std_quick_read_property(object,
property, BP_VAR_R, opline->hval TSRMLS_CC);
+ } else {
+ z = Z_OBJ_HT_P(object)->read_property(object,
property, BP_VAR_R TSRMLS_CC);
+ }
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
@@ -607,7 +644,12 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_proper
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z
TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(property) ==
IS_STRING &&
+ Z_OBJ_HT_P(object)->write_property ==
zend_std_write_property) {
+ zend_std_quick_write_property(object, property,
z, opline->hval TSRMLS_CC);
+ } else {
+ Z_OBJ_HT_P(object)->write_property(object,
property, z TSRMLS_CC);
+ }
SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
zval_ptr_dtor(&z);
} else {
@@ -670,7 +712,14 @@ ZEND_VM_HELPER_EX(zend_post_incdec_prope
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object,
property TSRMLS_CC);
+ zval **zptr;
+
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(property) == IS_STRING &&
+ Z_OBJ_HT_P(object)->get_property_ptr_ptr ==
zend_std_get_property_ptr_ptr) {
+ zptr = zend_std_quick_get_property_ptr_ptr(object,
property, opline->hval TSRMLS_CC);
+ } else {
+ zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object,
property TSRMLS_CC);
+ }
if (zptr != NULL) { /* NULL means no
success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
@@ -685,9 +734,16 @@ ZEND_VM_HELPER_EX(zend_post_incdec_prope
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property &&
Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object,
property, BP_VAR_R TSRMLS_CC);
+ zval *z;
zval *z_copy;
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(property) ==
IS_STRING &&
+ Z_OBJ_HT_P(object)->read_property ==
zend_std_read_property) {
+ z = zend_std_quick_read_property(object,
property, BP_VAR_R, opline->hval TSRMLS_CC);
+ } else {
+ z = Z_OBJ_HT_P(object)->read_property(object,
property, BP_VAR_R TSRMLS_CC);
+ }
+
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
@@ -706,7 +762,12 @@ ZEND_VM_HELPER_EX(zend_post_incdec_prope
INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property,
z_copy TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(property) ==
IS_STRING &&
+ Z_OBJ_HT_P(object)->write_property ==
zend_std_write_property) {
+ zend_std_quick_write_property(object, property,
z_copy, opline->hval TSRMLS_CC);
+ } else {
+ Z_OBJ_HT_P(object)->write_property(object,
property, z_copy TSRMLS_CC);
+ }
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
@@ -1059,6 +1120,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VA
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **container;
+ zend_ulong hval = 0;
if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
OP1_TYPE != IS_CV &&
@@ -1069,7 +1131,12 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VA
if (OP1_TYPE == IS_VAR && !container) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an
array");
}
-
zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (Z_TYPE_P(dim) == IS_STRING) {
+ hval = zend_inline_hash_func(Z_STRVAL_P(dim),
Z_STRLEN_P(dim)+1);
+ }
+
zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_R, hval TSRMLS_CC);
FREE_OP2();
FREE_OP1_VAR_PTR();
ZEND_VM_NEXT_OPCODE();
@@ -1081,11 +1148,17 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VA
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
+ zend_ulong hval = 0;
if (OP1_TYPE == IS_VAR && !container) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an
array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container,
dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (OP2_TYPE != IS_UNUSED && Z_TYPE_P(dim) == IS_STRING) {
+ hval = zend_inline_hash_func(Z_STRVAL_P(dim),
Z_STRLEN_P(dim)+1);
+ }
+ zend_fetch_dimension_address(&EX_T(opline->result.u.var), container,
dim, IS_OP2_TMP_FREE(), BP_VAR_W, hval TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && OP1_FREE &&
READY_TO_DESTROY(free_op1.var)) {
@@ -1113,11 +1186,17 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, V
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ zend_ulong hval = 0;
if (OP1_TYPE == IS_VAR && !container) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an
array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container,
dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (OP2_TYPE != IS_UNUSED && Z_TYPE_P(dim) == IS_STRING) {
+ hval = zend_inline_hash_func(Z_STRVAL_P(dim),
Z_STRLEN_P(dim)+1);
+ }
+ zend_fetch_dimension_address(&EX_T(opline->result.u.var), container,
dim, IS_OP2_TMP_FREE(), BP_VAR_RW, hval TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && OP1_FREE &&
READY_TO_DESTROY(free_op1.var)) {
@@ -1137,11 +1216,17 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, V
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS);
+ zend_ulong hval = 0;
if (OP1_TYPE == IS_VAR && !container) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an
array");
}
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_IS TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (Z_TYPE_P(dim) == IS_STRING) {
+ hval = zend_inline_hash_func(Z_STRVAL_P(dim),
Z_STRLEN_P(dim)+1);
+ }
+ zend_fetch_dimension_address_read(&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_IS, hval TSRMLS_CC);
FREE_OP2();
FREE_OP1_VAR_PTR();
ZEND_VM_NEXT_OPCODE();
@@ -1153,13 +1238,19 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **container;
+ zend_ulong hval = 0;
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (OP2_TYPE != IS_UNUSED && Z_TYPE_P(dim) == IS_STRING) {
+ hval = zend_inline_hash_func(Z_STRVAL_P(dim),
Z_STRLEN_P(dim)+1);
+ }
if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && !container) {
zend_error_noreturn(E_ERROR, "Cannot use string offset
as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_W, hval TSRMLS_CC);
if (OP1_TYPE == IS_VAR && OP1_FREE &&
READY_TO_DESTROY(free_op1.var)) {
AI_USE_PTR(EX_T(opline->result.u.var).var);
@@ -1176,7 +1267,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_
if (OP1_TYPE == IS_VAR && !container) {
zend_error_noreturn(E_ERROR, "Cannot use string offset
as an array");
}
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_R, hval TSRMLS_CC);
}
FREE_OP2();
FREE_OP1_VAR_PTR();
@@ -1189,6 +1280,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET
zend_free_op free_op1, free_op2;
zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET);
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zend_ulong hval = 0;
/* Not needed in DIM_UNSET
if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
@@ -1203,7 +1295,12 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET
if (OP1_TYPE == IS_VAR && !container) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an
array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container,
dim, IS_OP2_TMP_FREE(), BP_VAR_UNSET TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (Z_TYPE_P(dim) == IS_STRING) {
+ hval = zend_inline_hash_func(Z_STRVAL_P(dim),
Z_STRLEN_P(dim)+1);
+ }
+ zend_fetch_dimension_address(&EX_T(opline->result.u.var), container,
dim, IS_OP2_TMP_FREE(), BP_VAR_UNSET, hval TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && OP1_FREE &&
READY_TO_DESTROY(free_op1.var)) {
@@ -1254,7 +1351,12 @@ ZEND_VM_HELPER_EX(zend_fetch_property_ad
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container,
offset, type TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(offset) == IS_STRING &&
+ Z_OBJ_HT_P(container)->read_property ==
zend_std_read_property) {
+ retval = zend_std_quick_read_property(container,
offset, type, opline->hval TSRMLS_CC);
+ } else {
+ retval =
Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ }
if (RETURN_VALUE_UNUSED(&opline->result)) {
if (Z_REFCOUNT_P(retval) == 0) {
@@ -1458,8 +1560,12 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_DIM_TMP_V
} else {
zend_free_op free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zend_ulong hval = 0;
- AI_SET_PTR(EX_T(opline->result.u.var).var,
*zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R
TSRMLS_CC));
+ if (Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ }
+ AI_SET_PTR(EX_T(opline->result.u.var).var,
*zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R, hval
TSRMLS_CC));
SELECTIVE_PZVAL_LOCK(EX_T(opline->result.u.var).var.ptr,
&opline->result);
FREE_OP2();
}
@@ -1520,8 +1626,14 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VA
zval *value;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **variable_ptr_ptr;
+ zend_ulong hval = 0;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var),
object_ptr, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(dim) == IS_STRING) {
+ hval = opline->hval;
+ } else if (OP2_TYPE != IS_UNUSED && Z_TYPE_P(dim) == IS_STRING)
{
+ hval = zend_inline_hash_func(Z_STRVAL_P(dim),
Z_STRLEN_P(dim)+1);
+ }
+ zend_fetch_dimension_address(&EX_T(op_data->op2.u.var),
object_ptr, dim, IS_OP2_TMP_FREE(), BP_VAR_W, hval TSRMLS_CC);
FREE_OP2();
value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1,
BP_VAR_R);
@@ -3046,6 +3158,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEME
zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
zval *offset=GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zend_ulong hval = 0;
#if !defined(ZEND_VM_SPEC) || OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV
zval **expr_ptr_ptr = NULL;
@@ -3097,7 +3210,12 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEME
zend_hash_index_update(Z_ARRVAL_P(array_ptr),
Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr),
Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(offset) ==
IS_STRING) {
+ hval = opline->hval;
+ } else if (Z_TYPE_P(offset) == IS_STRING) {
+ hval =
zend_inline_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+
zend_symtable_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset),
Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(Z_ARRVAL_P(array_ptr), "",
sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3410,6 +3528,7 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|
zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
long index;
+ zend_ulong hash_value = 0;
if (OP1_TYPE != IS_VAR || container) {
if (OP1_TYPE == IS_CV && container !=
&EG(uninitialized_zval_ptr)) {
@@ -3434,10 +3553,14 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|
if (OP2_TYPE == IS_CV ||
OP2_TYPE == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht,
offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
+ if (OP2_TYPE == IS_CONST) {
+ hash_value =
opline->hval;
+ } else {
+ hash_value =
zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ }
+ if (zend_symtable_quick_del(ht,
offset->value.str.val, offset->value.str.len+1, hash_value) == SUCCESS &&
ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value =
zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
for (ex = EXECUTE_DATA;
ex; ex = ex->prev_execute_data) {
if
(ex->op_array && ex->symbol_table == ht) {
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php