Skip to content

Commit 340013a

Browse files
committedMar 19, 2021
Add zend_hash_lookup() and zend_hash_index_lookup() functions.
Thet search for an element with given key/index and add an empty one (NULL), if no found.
1 parent 64e589c commit 340013a

File tree

3 files changed

+96
-44
lines changed

3 files changed

+96
-44
lines changed
 

‎Zend/zend_execute.c

+42-39
Original file line numberDiff line numberDiff line change
@@ -2121,59 +2121,62 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
21212121
if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
21222122
hval = Z_LVAL_P(dim);
21232123
num_index:
2124-
ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
2125-
return retval;
2124+
if (type != BP_VAR_W) {
2125+
ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
2126+
return retval;
21262127
num_undef:
2127-
switch (type) {
2128-
case BP_VAR_R:
2129-
zend_undefined_offset(hval);
2130-
/* break missing intentionally */
2131-
case BP_VAR_UNSET:
2132-
case BP_VAR_IS:
2133-
retval = &EG(uninitialized_zval);
2134-
break;
2135-
case BP_VAR_RW:
2136-
if (UNEXPECTED(zend_undefined_offset_write(ht, hval) == FAILURE)) {
2137-
return NULL;
2138-
}
2139-
/* break missing intentionally */
2140-
case BP_VAR_W:
2141-
retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
2142-
break;
2143-
}
2144-
} else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
2145-
offset_key = Z_STR_P(dim);
2146-
if (ZEND_CONST_COND(dim_type != IS_CONST, 1)) {
2147-
if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
2148-
goto num_index;
2149-
}
2150-
}
2151-
str_index:
2152-
retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0));
2153-
if (!retval) {
21542128
switch (type) {
21552129
case BP_VAR_R:
2156-
zend_undefined_index(offset_key);
2130+
zend_undefined_offset(hval);
21572131
/* break missing intentionally */
21582132
case BP_VAR_UNSET:
21592133
case BP_VAR_IS:
21602134
retval = &EG(uninitialized_zval);
21612135
break;
21622136
case BP_VAR_RW:
2163-
/* Key may be released while throwing the undefined index warning. */
2164-
zend_string_addref(offset_key);
2165-
if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
2166-
zend_string_release(offset_key);
2137+
if (UNEXPECTED(zend_undefined_offset_write(ht, hval) == FAILURE)) {
21672138
return NULL;
21682139
}
2169-
retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
2170-
zend_string_release(offset_key);
2171-
break;
2172-
case BP_VAR_W:
2173-
retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
2140+
retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
21742141
break;
2142+
}
2143+
} else {
2144+
ZEND_HASH_INDEX_LOOKUP(ht, hval, retval);
2145+
}
2146+
} else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
2147+
offset_key = Z_STR_P(dim);
2148+
if (ZEND_CONST_COND(dim_type != IS_CONST, 1)) {
2149+
if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
2150+
goto num_index;
21752151
}
21762152
}
2153+
str_index:
2154+
if (type != BP_VAR_W) {
2155+
retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0));
2156+
if (!retval) {
2157+
switch (type) {
2158+
case BP_VAR_R:
2159+
zend_undefined_index(offset_key);
2160+
/* break missing intentionally */
2161+
case BP_VAR_UNSET:
2162+
case BP_VAR_IS:
2163+
retval = &EG(uninitialized_zval);
2164+
break;
2165+
case BP_VAR_RW:
2166+
/* Key may be released while throwing the undefined index warning. */
2167+
zend_string_addref(offset_key);
2168+
if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
2169+
zend_string_release(offset_key);
2170+
return NULL;
2171+
}
2172+
retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
2173+
zend_string_release(offset_key);
2174+
break;
2175+
}
2176+
}
2177+
} else {
2178+
retval = zend_hash_lookup(ht, offset_key);
2179+
}
21772180
} else if (EXPECTED(Z_TYPE_P(dim) == IS_REFERENCE)) {
21782181
dim = Z_REFVAL_P(dim);
21792182
goto try_again;

‎Zend/zend_hash.c

+37-5
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,9 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
748748
zval *data;
749749

750750
ZEND_ASSERT((flag & HASH_ADD_NEW) == 0);
751-
if (flag & HASH_ADD) {
751+
if (flag & HASH_LOOKUP) {
752+
return &p->val;
753+
} else if (flag & HASH_ADD) {
752754
if (!(flag & HASH_UPDATE_INDIRECT)) {
753755
return NULL;
754756
}
@@ -793,7 +795,11 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
793795
nIndex = h | ht->nTableMask;
794796
Z_NEXT(p->val) = HT_HASH_EX(arData, nIndex);
795797
HT_HASH_EX(arData, nIndex) = HT_IDX_TO_HASH(idx);
796-
ZVAL_COPY_VALUE(&p->val, pData);
798+
if (flag & HASH_LOOKUP) {
799+
ZVAL_NULL(&p->val);
800+
} else {
801+
ZVAL_COPY_VALUE(&p->val, pData);
802+
}
797803

798804
return &p->val;
799805
}
@@ -821,7 +827,9 @@ static zend_always_inline zval *_zend_hash_str_add_or_update_i(HashTable *ht, co
821827
if (p) {
822828
zval *data;
823829

824-
if (flag & HASH_ADD) {
830+
if (flag & HASH_LOOKUP) {
831+
return &p->val;
832+
} else if (flag & HASH_ADD) {
825833
if (!(flag & HASH_UPDATE_INDIRECT)) {
826834
return NULL;
827835
}
@@ -859,7 +867,11 @@ static zend_always_inline zval *_zend_hash_str_add_or_update_i(HashTable *ht, co
859867
p->key = key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
860868
p->h = ZSTR_H(key) = h;
861869
HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
862-
ZVAL_COPY_VALUE(&p->val, pData);
870+
if (flag & HASH_LOOKUP) {
871+
ZVAL_NULL(&p->val);
872+
} else {
873+
ZVAL_COPY_VALUE(&p->val, pData);
874+
}
863875
nIndex = h | ht->nTableMask;
864876
Z_NEXT(p->val) = HT_HASH(ht, nIndex);
865877
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
@@ -901,6 +913,11 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key,
901913
return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW);
902914
}
903915

916+
ZEND_API zval* ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key)
917+
{
918+
return _zend_hash_add_or_update_i(ht, key, NULL, HASH_LOOKUP);
919+
}
920+
904921
ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag)
905922
{
906923
if (flag == HASH_ADD) {
@@ -984,6 +1001,9 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht,
9841001
if (h < ht->nNumUsed) {
9851002
p = ht->arData + h;
9861003
if (Z_TYPE(p->val) != IS_UNDEF) {
1004+
if (flag & HASH_LOOKUP) {
1005+
return &p->val;
1006+
}
9871007
replace:
9881008
if (flag & HASH_ADD) {
9891009
return NULL;
@@ -1032,6 +1052,9 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht,
10321052
if ((flag & HASH_ADD_NEW) == 0 || ZEND_DEBUG) {
10331053
p = zend_hash_index_find_bucket(ht, h);
10341054
if (p) {
1055+
if (flag & HASH_LOOKUP) {
1056+
return &p->val;
1057+
}
10351058
ZEND_ASSERT((flag & HASH_ADD_NEW) == 0);
10361059
goto replace;
10371060
}
@@ -1051,7 +1074,11 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht,
10511074
ht->nNumOfElements++;
10521075
p->h = h;
10531076
p->key = NULL;
1054-
ZVAL_COPY_VALUE(&p->val, pData);
1077+
if (flag & HASH_LOOKUP) {
1078+
ZVAL_NULL(&p->val);
1079+
} else {
1080+
ZVAL_COPY_VALUE(&p->val, pData);
1081+
}
10551082

10561083
return &p->val;
10571084
}
@@ -1099,6 +1126,11 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_next_index_insert_new(HashTable *ht, zval
10991126
return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW | HASH_ADD_NEXT);
11001127
}
11011128

1129+
ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h)
1130+
{
1131+
return _zend_hash_index_add_or_update_i(ht, h, NULL, HASH_LOOKUP);
1132+
}
1133+
11021134
ZEND_API zval* ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, zend_string *key)
11031135
{
11041136
uint32_t nIndex;

‎Zend/zend_hash.h

+17
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#define HASH_UPDATE_INDIRECT (1<<2)
3333
#define HASH_ADD_NEW (1<<3)
3434
#define HASH_ADD_NEXT (1<<4)
35+
#define HASH_LOOKUP (1<<5)
3536

3637
#define HASH_FLAG_CONSISTENCY ((1<<0) | (1<<1))
3738
#define HASH_FLAG_PACKED (1<<2)
@@ -206,6 +207,22 @@ static zend_always_inline zval *zend_hash_find_ex(const HashTable *ht, zend_stri
206207
} while (0)
207208

208209

210+
/* Find or add NULL, if doesn't exist */
211+
ZEND_API zval* ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key);
212+
ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h);
213+
214+
#define ZEND_HASH_INDEX_LOOKUP(_ht, _h, _ret) do { \
215+
if (EXPECTED(HT_FLAGS(_ht) & HASH_FLAG_PACKED)) { \
216+
if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed)) { \
217+
_ret = &_ht->arData[_h].val; \
218+
if (EXPECTED(Z_TYPE_P(_ret) != IS_UNDEF)) { \
219+
break; \
220+
} \
221+
} \
222+
} \
223+
_ret = zend_hash_index_lookup(_ht, _h); \
224+
} while (0)
225+
209226
/* Misc */
210227
static zend_always_inline bool zend_hash_exists(const HashTable *ht, zend_string *key)
211228
{

0 commit comments

Comments
 (0)
Please sign in to comment.