summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2021-03-19 22:36:24 +0300
committerDmitry Stogov <dmitry@zend.com>2021-03-19 22:36:24 +0300
commit340013ad01aa6bda92c6c71080f315fc63c9841c (patch)
treebecd88732b78b9f0d76cd5fe175b59d954e4d05b /Zend
parent64e589cab6fcc953f111d6da2a4c137f6f97d5f3 (diff)
downloadphp-git-340013ad01aa6bda92c6c71080f315fc63c9841c.tar.gz
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.
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_execute.c81
-rw-r--r--Zend/zend_hash.c42
-rw-r--r--Zend/zend_hash.h17
3 files changed, 96 insertions, 44 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 39862a2425..f34e1930e2 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -2121,59 +2121,62 @@ try_again:
if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
hval = Z_LVAL_P(dim);
num_index:
- ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
- return retval;
+ if (type != BP_VAR_W) {
+ ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
+ return retval;
num_undef:
- switch (type) {
- case BP_VAR_R:
- zend_undefined_offset(hval);
- /* break missing intentionally */
- case BP_VAR_UNSET:
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- if (UNEXPECTED(zend_undefined_offset_write(ht, hval) == FAILURE)) {
- return NULL;
- }
- /* break missing intentionally */
- case BP_VAR_W:
- retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
- break;
- }
- } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
- offset_key = Z_STR_P(dim);
- if (ZEND_CONST_COND(dim_type != IS_CONST, 1)) {
- if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
- goto num_index;
- }
- }
-str_index:
- retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0));
- if (!retval) {
switch (type) {
case BP_VAR_R:
- zend_undefined_index(offset_key);
+ zend_undefined_offset(hval);
/* break missing intentionally */
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- /* Key may be released while throwing the undefined index warning. */
- zend_string_addref(offset_key);
- if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
- zend_string_release(offset_key);
+ if (UNEXPECTED(zend_undefined_offset_write(ht, hval) == FAILURE)) {
return NULL;
}
- retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
- zend_string_release(offset_key);
- break;
- case BP_VAR_W:
- retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
+ retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
break;
+ }
+ } else {
+ ZEND_HASH_INDEX_LOOKUP(ht, hval, retval);
+ }
+ } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
+ offset_key = Z_STR_P(dim);
+ if (ZEND_CONST_COND(dim_type != IS_CONST, 1)) {
+ if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
+ goto num_index;
}
}
+str_index:
+ if (type != BP_VAR_W) {
+ retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0));
+ if (!retval) {
+ switch (type) {
+ case BP_VAR_R:
+ zend_undefined_index(offset_key);
+ /* break missing intentionally */
+ case BP_VAR_UNSET:
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval);
+ break;
+ case BP_VAR_RW:
+ /* Key may be released while throwing the undefined index warning. */
+ zend_string_addref(offset_key);
+ if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
+ zend_string_release(offset_key);
+ return NULL;
+ }
+ retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
+ zend_string_release(offset_key);
+ break;
+ }
+ }
+ } else {
+ retval = zend_hash_lookup(ht, offset_key);
+ }
} else if (EXPECTED(Z_TYPE_P(dim) == IS_REFERENCE)) {
dim = Z_REFVAL_P(dim);
goto try_again;
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 8d3c7640bf..e52939b1eb 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -748,7 +748,9 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
zval *data;
ZEND_ASSERT((flag & HASH_ADD_NEW) == 0);
- if (flag & HASH_ADD) {
+ if (flag & HASH_LOOKUP) {
+ return &p->val;
+ } else if (flag & HASH_ADD) {
if (!(flag & HASH_UPDATE_INDIRECT)) {
return NULL;
}
@@ -793,7 +795,11 @@ add_to_hash:
nIndex = h | ht->nTableMask;
Z_NEXT(p->val) = HT_HASH_EX(arData, nIndex);
HT_HASH_EX(arData, nIndex) = HT_IDX_TO_HASH(idx);
- ZVAL_COPY_VALUE(&p->val, pData);
+ if (flag & HASH_LOOKUP) {
+ ZVAL_NULL(&p->val);
+ } else {
+ ZVAL_COPY_VALUE(&p->val, pData);
+ }
return &p->val;
}
@@ -821,7 +827,9 @@ static zend_always_inline zval *_zend_hash_str_add_or_update_i(HashTable *ht, co
if (p) {
zval *data;
- if (flag & HASH_ADD) {
+ if (flag & HASH_LOOKUP) {
+ return &p->val;
+ } else if (flag & HASH_ADD) {
if (!(flag & HASH_UPDATE_INDIRECT)) {
return NULL;
}
@@ -859,7 +867,11 @@ add_to_hash:
p->key = key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
p->h = ZSTR_H(key) = h;
HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
- ZVAL_COPY_VALUE(&p->val, pData);
+ if (flag & HASH_LOOKUP) {
+ ZVAL_NULL(&p->val);
+ } else {
+ ZVAL_COPY_VALUE(&p->val, pData);
+ }
nIndex = h | ht->nTableMask;
Z_NEXT(p->val) = HT_HASH(ht, nIndex);
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,
return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW);
}
+ZEND_API zval* ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key)
+{
+ return _zend_hash_add_or_update_i(ht, key, NULL, HASH_LOOKUP);
+}
+
ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag)
{
if (flag == HASH_ADD) {
@@ -984,6 +1001,9 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht,
if (h < ht->nNumUsed) {
p = ht->arData + h;
if (Z_TYPE(p->val) != IS_UNDEF) {
+ if (flag & HASH_LOOKUP) {
+ return &p->val;
+ }
replace:
if (flag & HASH_ADD) {
return NULL;
@@ -1032,6 +1052,9 @@ convert_to_hash:
if ((flag & HASH_ADD_NEW) == 0 || ZEND_DEBUG) {
p = zend_hash_index_find_bucket(ht, h);
if (p) {
+ if (flag & HASH_LOOKUP) {
+ return &p->val;
+ }
ZEND_ASSERT((flag & HASH_ADD_NEW) == 0);
goto replace;
}
@@ -1051,7 +1074,11 @@ add:
ht->nNumOfElements++;
p->h = h;
p->key = NULL;
- ZVAL_COPY_VALUE(&p->val, pData);
+ if (flag & HASH_LOOKUP) {
+ ZVAL_NULL(&p->val);
+ } else {
+ ZVAL_COPY_VALUE(&p->val, pData);
+ }
return &p->val;
}
@@ -1099,6 +1126,11 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_next_index_insert_new(HashTable *ht, zval
return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW | HASH_ADD_NEXT);
}
+ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h)
+{
+ return _zend_hash_index_add_or_update_i(ht, h, NULL, HASH_LOOKUP);
+}
+
ZEND_API zval* ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, zend_string *key)
{
uint32_t nIndex;
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 64a9220573..25d48f6237 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -32,6 +32,7 @@
#define HASH_UPDATE_INDIRECT (1<<2)
#define HASH_ADD_NEW (1<<3)
#define HASH_ADD_NEXT (1<<4)
+#define HASH_LOOKUP (1<<5)
#define HASH_FLAG_CONSISTENCY ((1<<0) | (1<<1))
#define HASH_FLAG_PACKED (1<<2)
@@ -206,6 +207,22 @@ static zend_always_inline zval *zend_hash_find_ex(const HashTable *ht, zend_stri
} while (0)
+/* Find or add NULL, if doesn't exist */
+ZEND_API zval* ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key);
+ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h);
+
+#define ZEND_HASH_INDEX_LOOKUP(_ht, _h, _ret) do { \
+ if (EXPECTED(HT_FLAGS(_ht) & HASH_FLAG_PACKED)) { \
+ if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed)) { \
+ _ret = &_ht->arData[_h].val; \
+ if (EXPECTED(Z_TYPE_P(_ret) != IS_UNDEF)) { \
+ break; \
+ } \
+ } \
+ } \
+ _ret = zend_hash_index_lookup(_ht, _h); \
+ } while (0)
+
/* Misc */
static zend_always_inline bool zend_hash_exists(const HashTable *ht, zend_string *key)
{