Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Internal Implementation of Variables in PHP 7

Tools May 13 15

In PHP, variables consist of two components: the variable name and variable value. These correspond to zval and zend_value structures respectively. PHP manages variabel memory through reference counting, which in PHP 7 is tracked in zend_value rather than zval.

Variable Definition and Initialization

PHP variables are defined using the $ keyword:

$varName;
$varName = "initial value";

These operations involve two distinct steps: declaration and initialization.

Core Data Structures

zval Structure

typedef struct _zval_struct zval;

typedef union _zend_value {
    int64_t          long_val;     // Integer values
    double           double_val;   // Floating-point values
    zend_refcounted *ref_counted;
    zend_string     *string_ptr;   // String references
    zend_array      *array_ptr;    // Array references
    zend_object     *object_ptr;   // Object references
    zend_resource   *resource_ptr; // Resource handles
    zend_reference  *reference_ptr;// Reference types
    zend_ast_ref    *ast_ref;
    zval            *zval_ptr;
    void            *void_ptr;
    zend_class_entry *class_entry;
    zend_function   *function_ptr;
    struct {
        uint32_t word1;
        uint32_t word2;
    } double_word;
} zend_value;

struct _zval_struct {
    zend_value        stored_value;
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                unsigned char type,
                unsigned char type_flags,
                unsigned char const_flags,
                unsigned char reserved)
        } detail;
        uint32_t type_data;
    } metadata;
    union {
        uint32_t     variable_flags;
        uint32_t     hash_next;
        uint32_t     cached_slot;
        uint32_t     line_number;
        uint32_t     argument_count;
        uint32_t     foreach_position;
        uint32_t     foreach_index;
    } auxiliary;
};

Data Type Constants

#define IS_UNDEFINED          0
#define IS_NULL               1
#define IS_FALSE              2
#define IS_TRUE               3
#define IS_LONG               4
#define IS_DOUBLE             5
#define IS_STRING             6
#define IS_ARRAY              7
#define IS_OBJECT             8
#define IS_RESOURCE           9
#define IS_REFERENCE          10
#define IS_CONSTANT           11
#define IS_CONSTANT_AST       12
#define _IS_BOOL              13
#define IS_CALLABLE           14
#define IS_INDIRECT           15
#define IS_POINTER            17

Scalar Types

Simple types including booleans, integers, doubles, and null values store their data directly within the zend_value union without additional memory allocations.

String Implementation

struct _zend_string {
    zend_refcounted_h refcount_header;
    uint64_t          hash_value;
    size_t            length;
    char              content[1];
};

Strings are categorized into several types based on their allocation method and lifecycle characteristics.

Array Implementation

Arrays are implemented as ordered hash tables:

typedef struct _zend_array HashTable;

struct _zend_array {
    zend_refcounted_h refcount_header;
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                unsigned char flags,
                unsigned char apply_count,
                unsigned char iterator_count,
                unsigned char reserved)
        } detail;
        uint32_t flags;
    } metadata;
    uint32_t          table_mask;
    Bucket           *data_array;
    uint32_t          used_count;
    uint32_t          element_count;
    uint32_t          table_size;
    uint32_t          internal_pointer;
    int64_t           next_free_element;
    dtor_func_t       destructor_func;
};

Reference Implementation

References create a specialized structure:

struct _zend_reference {
    zend_refcounted_h refcount_header;
    zval              referenced_value;
};

Example reference behavior:

$original = "data string";
$reference = &$original;
$copy = $reference;

Memory Management

PHP employs reference counting with copy-on-write semantics for efficient memory management.

Reference Counting Mechanism

typedef struct _zend_refcounted_h {
    uint32_t         reference_count;
    union {
        struct {
            ZEND_ENDIAN_LOHI_3(
                unsigned char type,
                unsigned char flags,
                uint16_t      gc_data)
        } detail;
        uint32_t type_info;
    } metadata;
} zend_refcounted_h;

Not all data types utilize reference counting. Scalar types and interned strings employ direct value copying.

Copy-on-Write Semantics

When multiple variables reference the same value, modifications trigger a copy operation:

$first = [1, 2, 3];
$second = $first;
$second[] = 4; // Triggers copy operation

Garbage Collection

PHP utilizes a tracing garbage collector for circular references:

$circular = [];
$circular[] = &$circular;
unset($circular); // Creates collectable garbage

The garbage collector identifies and cleans up circular references that cannot be freed through simple reference counting.

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.