summaryrefslogtreecommitdiff
path: root/Zend/zend_types.h
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-09-20 17:01:19 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-11-08 15:15:48 +0100
commitac4e0f0852ce780e143013ceff45067a172e8a83 (patch)
treef39eebeb379b6f75e95a333ccec37c4af264d8ee /Zend/zend_types.h
parenta555cc0b3d4f745e6d0bb8c595de400a0c728827 (diff)
downloadphp-git-ac4e0f0852ce780e143013ceff45067a172e8a83.tar.gz
Make zend_type a 2-field struct
We now store the pointer payload and the type mask separately. This is in preparation for union types, where we will be using both at the same time. To avoid increasing the size of arginfo structures, the pass_by_reference and is_variadic fields are now stored as part of the type_mask (8-bit are reserved for custom use). Different types of pointer payloads are distinguished based on bits in the type_mask.
Diffstat (limited to 'Zend/zend_types.h')
-rw-r--r--Zend/zend_types.h111
1 files changed, 65 insertions, 46 deletions
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index b381eeff14..d77fbc68a3 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -106,87 +106,106 @@ typedef void (*copy_ctor_func_t)(zval *pElement);
* It shouldn't be used directly. Only through ZEND_TYPE_* macros.
*
* ZEND_TYPE_IS_SET() - checks if type-hint exists
- * ZEND_TYPE_IS_MASK() - checks if type-hint refer to standard type
+ * ZEND_TYPE_IS_ONLY_MASK() - checks if type-hint refer to standard type
* ZEND_TYPE_IS_CLASS() - checks if type-hint refer to some class
* ZEND_TYPE_IS_CE() - checks if type-hint refer to some class by zend_class_entry *
* ZEND_TYPE_IS_NAME() - checks if type-hint refer to some class by zend_string *
*
* ZEND_TYPE_NAME() - returns referenced class name
* ZEND_TYPE_CE() - returns referenced class entry
- * ZEND_TYPE_MASK() - returns MAY_BE_* type mask
+ * ZEND_TYPE_PURE_MASK() - returns MAY_BE_* type mask
+ * ZEND_TYPE_FULL_MASK() - returns MAY_BE_* type mask together with other flags
*
* ZEND_TYPE_ALLOW_NULL() - checks if NULL is allowed
*
- * ZEND_TYPE_ENCODE_*() should be used for construction.
+ * ZEND_TYPE_INIT_*() should be used for construction.
*/
-typedef uintptr_t zend_type;
-
-#define _ZEND_TYPE_CODE_MAX ((Z_L(1)<<(IS_VOID+1))-1)
-#define _ZEND_TYPE_FLAG_MASK Z_L(0x3)
-#define _ZEND_TYPE_CE_BIT Z_L(0x1)
+typedef struct {
+ /* Not using a union here, because there's no good way to initialize them
+ * in a way that is supported in both C and C++ (designated initializers
+ * are only supported since C++20). */
+ void *ptr;
+ uint32_t type_mask;
+ /* TODO: We could use the extra 32-bit of padding on 64-bit systems. */
+} zend_type;
+
+#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 24
+#define _ZEND_TYPE_MASK ((1u << 24) - 1)
+#define _ZEND_TYPE_MAY_BE_MASK ((1u << (IS_VOID+1)) - 1)
+#define _ZEND_TYPE_CE_BIT (1u << 22)
+#define _ZEND_TYPE_NAME_BIT (1u << 23)
/* Must have same value as MAY_BE_NULL */
-#define _ZEND_TYPE_NULLABLE_BIT Z_L(0x2)
+#define _ZEND_TYPE_NULLABLE_BIT 0x2
#define ZEND_TYPE_IS_SET(t) \
- ((t) != 0)
-
-#define ZEND_TYPE_IS_MASK(t) \
- ((t) != 0 && (t) <= _ZEND_TYPE_CODE_MAX)
+ (((t).type_mask & _ZEND_TYPE_MASK) != 0)
#define ZEND_TYPE_IS_CLASS(t) \
- ((t) > _ZEND_TYPE_CODE_MAX)
+ (((t.type_mask) & (_ZEND_TYPE_NAME_BIT|_ZEND_TYPE_CE_BIT)) != 0)
#define ZEND_TYPE_IS_CE(t) \
- (((t) & _ZEND_TYPE_CE_BIT) != 0)
+ (((t.type_mask) & _ZEND_TYPE_CE_BIT) != 0)
#define ZEND_TYPE_IS_NAME(t) \
- (ZEND_TYPE_IS_CLASS(t) && !ZEND_TYPE_IS_CE(t))
+ (((t.type_mask) & _ZEND_TYPE_NAME_BIT) != 0)
+
+#define ZEND_TYPE_IS_ONLY_MASK(t) \
+ (ZEND_TYPE_IS_SET(t) && (t).ptr == NULL)
#define ZEND_TYPE_NAME(t) \
- ((zend_string*)((t) & ~_ZEND_TYPE_FLAG_MASK))
+ ((zend_string *) (t).ptr)
+
+#define ZEND_TYPE_LITERAL_NAME(t) \
+ ((const char *) (t).ptr)
#define ZEND_TYPE_CE(t) \
- ((zend_class_entry*)((t) & ~_ZEND_TYPE_FLAG_MASK))
+ ((zend_class_entry *) (t).ptr)
-#define ZEND_TYPE_MASK(t) \
- (t)
+#define ZEND_TYPE_SET_PTR(t, _ptr) \
+ ((t).ptr = (_ptr))
+
+/* FULL_MASK() includes the MAY_BE_* type mask, the CE/NAME bits, as well as extra reserved bits.
+ * The PURE_MASK() only includes the MAY_BE_* type mask. */
+#define ZEND_TYPE_FULL_MASK(t) \
+ ((t).type_mask)
+
+#define ZEND_TYPE_PURE_MASK(t) \
+ ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK)
+
+#define ZEND_TYPE_FULL_MASK_WITHOUT_NULL(t) \
+ ((t).type_mask & ~_ZEND_TYPE_NULLABLE_BIT)
+
+#define ZEND_TYPE_PURE_MASK_WITHOUT_NULL(t) \
+ ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK & ~_ZEND_TYPE_NULLABLE_BIT)
#define ZEND_TYPE_CONTAINS_CODE(t, code) \
- (((t) & (1 << (code))) != 0)
+ (((t).type_mask & (1u << (code))) != 0)
#define ZEND_TYPE_ALLOW_NULL(t) \
- (((t) & _ZEND_TYPE_NULLABLE_BIT) != 0)
-
-#define ZEND_TYPE_WITHOUT_NULL(t) \
- ((t) & ~_ZEND_TYPE_NULLABLE_BIT)
+ (((t).type_mask & _ZEND_TYPE_NULLABLE_BIT) != 0)
-#define ZEND_TYPE_ENCODE_NONE() \
- (0)
+#define ZEND_TYPE_INIT_NONE(extra_flags) \
+ { NULL, (extra_flags) }
-#define ZEND_TYPE_ENCODE_MASK(maybe_code) \
- (maybe_code)
+#define ZEND_TYPE_INIT_MASK(_type_mask) \
+ { NULL, (_type_mask) }
-#define ZEND_TYPE_ENCODE_CODE(code, allow_null) \
- (((code) == _IS_BOOL ? (MAY_BE_FALSE|MAY_BE_TRUE) : (1 << (code))) \
- | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0)))
+#define ZEND_TYPE_INIT_CODE(code, allow_null, extra_flags) \
+ ZEND_TYPE_INIT_MASK(((code) == _IS_BOOL ? (MAY_BE_FALSE|MAY_BE_TRUE) : (1 << (code))) \
+ | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags))
-#define ZEND_TYPE_ENCODE_CE(ce, allow_null) \
- (((uintptr_t)(ce)) | _ZEND_TYPE_CE_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0)))
+#define ZEND_TYPE_INIT_CE(_ce, allow_null, extra_flags) \
+ { (void *) (_ce), \
+ _ZEND_TYPE_CE_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) }
-#define ZEND_TYPE_ENCODE_CLASS(class_name, allow_null) \
- (((uintptr_t)(class_name)) | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0)))
+#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \
+ { (void *) (class_name), \
+ _ZEND_TYPE_NAME_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) }
-#define ZEND_TYPE_ENCODE_CLASS_CONST_0(class_name) \
- ((zend_type) class_name)
-#define ZEND_TYPE_ENCODE_CLASS_CONST_1(class_name) \
- ((zend_type) "?" class_name)
-#define ZEND_TYPE_ENCODE_CLASS_CONST_Q2(macro, class_name) \
- macro(class_name)
-#define ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) \
- ZEND_TYPE_ENCODE_CLASS_CONST_Q2(ZEND_TYPE_ENCODE_CLASS_CONST_ ##allow_null, class_name)
-#define ZEND_TYPE_ENCODE_CLASS_CONST(class_name, allow_null) \
- ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name)
+#define ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, extra_flags) \
+ { (void *) (class_name), \
+ _ZEND_TYPE_NAME_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) }
typedef union _zend_value {
zend_long lval; /* long value */