rfc:object_keys_in_arrays

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:object_keys_in_arrays [2021/01/08 14:44] nikicrfc:object_keys_in_arrays [2021/01/11 14:22] (current) nikic
Line 4: Line 4:
   * Status: Draft   * Status: Draft
   * Target Version: PHP 8.1   * Target Version: PHP 8.1
-  * Implementation: TBD+  * Implementation: https://github.com/php/php-src/pull/6588
  
 ===== Introduction ===== ===== Introduction =====
Line 62: Line 62:
   * ''var_dump()'' etc: How should object keys get represented?   * ''var_dump()'' etc: How should object keys get represented?
   * ''serialize()'': The serialization format can easily deal with object keys. However, keys are currently not counted for back references. To preserve proper identity for object keys, while retaining backwards compatibility with the existing format, we need to count object keys only for back references.   * ''serialize()'': The serialization format can easily deal with object keys. However, keys are currently not counted for back references. To preserve proper identity for object keys, while retaining backwards compatibility with the existing format, we need to count object keys only for back references.
 +  * ...
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 103: Line 104:
 The stored hash value is reduced to 32-bits in order to fit into u2 space. As hash indices are already limited to 32-bits, this is not problematic. The stored hash value is reduced to 32-bits in order to fit into u2 space. As hash indices are already limited to 32-bits, this is not problematic.
  
-The key zval may have type ''IS_LONG'', ''IS_STRING'' or ''IS_OBJECT''. During bucket lookups, object keys can be mostly treated the same way as integer keys, because comparison of objects only requires comparison of the object pointers. The hash value for object keys is the object pointer shifted right by the minimum object alignment.+The key zval may have type ''IS_LONG'', ''IS_STRING'' or ''IS_OBJECT''. During bucket lookups, object keys can be mostly treated the same way as integer keys, because comparison of objects only requires comparison of the object pointers. The hash value for object keys is the object pointer shifted right by the minimum object alignment. The hash is computed by ''zend_hash_obj_key()''.
  
-In order to support object keys (and potentially other key types in the future), a new ''zkey'' family of hash functions and macros is added. ''zkey'' functions accept a zval key, which must be of type ''IS_LONG'', ''IS_STRING'' or ''IS_OBJECT''. The u2 value of the zval must already be initialized to contain the key hash. These functions are primarily used when taking a key from an existing array, in which case this initialized is already given.+A number of new hash APIs for working with object keys is added:
  
-A non-exhaustive list of new functions:+<code c> 
 +ZEND_API zval* ZEND_FASTCALL zend_hash_obj_key_add(HashTable *ht, zend_object *obj_key, zval *val); 
 +ZEND_API zval* ZEND_FASTCALL zend_hash_obj_key_add_new(HashTable *ht, zend_object *obj_key, zval *val); 
 +ZEND_API zval* ZEND_FASTCALL zend_hash_obj_key_update(HashTable *ht, zend_object *obj_key, zval *val); 
 +ZEND_API zend_result ZEND_FASTCALL zend_hash_obj_key_del(HashTable *ht, zend_object *obj_key); 
 +ZEND_API zval* ZEND_FASTCALL zend_hash_obj_key_find(const HashTable *ht, zend_object *obj_key); 
 +</code> 
 + 
 +However, the majority of internal code will never use these APIs directly. They only need to be used when working with object keys specifically. 
 + 
 +Instead, a new ''zkey'' family of hash functions and macros is added, which allows working with hash table keys in a more generic manner. ''zkey'' functions accept a zval key, which must be of type ''IS_LONG'', ''IS_STRING'' or ''IS_OBJECT''
 + 
 +The following new functions are added:
  
 <code c> <code c>
-// This omits various _ind, _ptr, etc variants. 
 ZEND_API zval* ZEND_FASTCALL zend_hash_zkey_add_or_update(HashTable *ht, zval *key, zval *val, uint32_t flag); ZEND_API zval* ZEND_FASTCALL zend_hash_zkey_add_or_update(HashTable *ht, zval *key, zval *val, uint32_t flag);
 ZEND_API zval* ZEND_FASTCALL zend_hash_zkey_update(HashTable *ht, zval *key, zval *val); ZEND_API zval* ZEND_FASTCALL zend_hash_zkey_update(HashTable *ht, zval *key, zval *val);
Line 118: Line 130:
 ZEND_API zval* ZEND_FASTCALL zend_hash_zkey_find(const HashTable *ht, zval *key); ZEND_API zval* ZEND_FASTCALL zend_hash_zkey_find(const HashTable *ht, zval *key);
 static zend_always_inline zend_bool zend_hash_zkey_exists(const HashTable *ht, zval *key); static zend_always_inline zend_bool zend_hash_zkey_exists(const HashTable *ht, zval *key);
 +
 +// This is a low-level API that requires the hash value in u2 to be initialized.
 static zend_always_inline zval *_zend_hash_zkey_append(HashTable *ht, zval *key, zval *zv); static zend_always_inline zval *_zend_hash_zkey_append(HashTable *ht, zval *key, zval *zv);
 </code> </code>
- 
-**TODO**: It's not clear yet how to handle the case where now u2 initialization is given. Should there be additional functions for that case, or a function to handle the initialization up-front? 
  
 Similarly, ''ZKEY'' variants of ''ZEND_HASH_FOREACH'' macros are introduced: Similarly, ''ZKEY'' variants of ''ZEND_HASH_FOREACH'' macros are introduced:
Line 178: Line 190:
 ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_zkey(const HashTable *ht, HashPosition *pos);  ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_zkey(const HashTable *ht, HashPosition *pos); 
 </code> </code>
 +
 +The ''zend_hash_get_current_key_type(_ex)'' function and the ''HASH_KEY_IS_LONG'', ''HASH_KEY_IS_STRING'' and ''HASH_KEY_NON_EXISTENT'' constants are also removed, and should be replaced by taking the type of the key zval.
  
 ===== Vote ===== ===== Vote =====
rfc/object_keys_in_arrays.1610117078.txt.gz · Last modified: 2021/01/08 14:44 by nikic