PHP kernel research: HASH tables and variables

Source: Internet
Author: User
In PHP, all data, regardless of variables, constants, classes, and attributes, are implemented using the Hash table. first, let's talk about the HASH table typedefstructbucket {ulongh;/* Usedfornum... "/> In PHP, the Synt php hash table is used for all data regardless of variables, constants, classes, and attributes. first, let's talk about the HASH table typedef struct bucket {ulong h;/* Used for numeric indexing */uint nKeyLength; // key length void * pData; // point to the data pointer void * pDataPtr saved by Bucke; // pointer data struct bucket * pListNext; // The next element pointer struct bucket * pListLast; // the previous element pointer struct bucket * pNext; stru Ct bucket * pLast; char arKey [1];/* Must be last element */} Bucket; typedef struct _ hashtable {uint nTableSize; // size of HashTable uint nTableMask; // equal to nTableSize-1 uint nNumOfElements; // number of objects ulong nNextFreeElement; // point to the next null element location nTableSize + 1 Bucket * pInternalPointer; /* Used for element traversal * // Save the currently traversed pointer Bucket * pListHead; // The header element pointer Bucket * pListTail; // The tail element pointer Bucket ** arBuckets; // store the hash array data dtor_fun C_t pDestructor; // similar to the destructor zend_bool persistent; // which method is used to allocate the memory space? PHP manages the memory in a unified manner or uses the common malloc unsigned char nApplyCount; // The number of times the current hash bucket is accessed, and whether the data has been traversed to prevent infinite recursive loops zend_bool bApplyProtection; # if ZEND_DEBUG int inconsistent; # endif} HashTable; combined with the HASH table initialization function, ZEND_API int _ zend_hash_init (HashTable * ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent listener) {uin T I = 3; Bucket ** tmp; SET_INCONSISTENT (HT_ OK); if (nSize> = 0x80000000) {// HASH table size greater than 0x8/* prevent overflow */ht-> nTableSize = 0x80000000;} else {while (1U <I) <nSize) {// change to the n I ++ of 2;} ht-> nTableSize = 1 <I; // HASH bucket size of 2 to the power I = 3, the minimum nTableSize value is 8} // to improve the computing efficiency, the system automatically adjusts nTableSize to the minimum integer power of 2 not less than nTableSize. That is to say, if you specify a nTableSize not the integer power of 2 when initializing HashTable, the system will automatically adjust the value of nTableSize. Ht-> nTableMask = ht-> nTableSize-1; ht-> pDestructor = pDestructor; // A function pointer. when HashTable is added, delete it, call ht-> arBuckets = NULL; ht-> pListHead = NULL; ht-> pListTail = NULL; ht-> nNumOfElements = 0; ht-> nNextFreeElement = 0; ht-> pInternalPointer = NULL; ht-> persistent = persistent; // If persisient is TRUE, use the memory allocation function of the operating system to allocate memory to the Bucket, otherwise, use the PHP memory allocation function ht-> nApplyCount = 0; ht-> bApplyProtection = 1;/* Uses ecalloc () so That Bucket * = NULL */if (persistent) {// memory allocation mode of the operating system itself. the memory is automatically initialized to 0 tmp = (Bucket **) after calloc allocates the memory **) calloc (ht-> nTableSize, sizeof (Bucket *); if (! Tmp) {return FAILURE;} ht-> arBuckets = tmp;} else {// use the PHP memory management mechanism to allocate the memory tmp = (Bucket **) ecalloc_rel (ht-> nTableSize, sizeof (Bucket *); if (tmp) {ht-> arBuckets = tmp ;}// automatically apply for a piece of memory for arBuckets, the memory size is equal to nTableSize return SUCCESS;} when reading the source code, we often see EG, PG, macro CG such as CG is compile_global short for EG is excutor_global short for G is global variable meaning we take EG macro as an example # ifdef ZTS # define EG (v) TSRMG (executor_globals_id, zend_executor_globals *, v) # else # define EG (v) (executor_globals.v) extern ZEND_API zend_executor_globals executor_globals; # endif is just a macro for obtaining global variables. let's look at the zend_executor_globals struct in/Zend/zend. h defines typedef struct _ zend_executor_globals. it is an alias of _ zend_executor_globals and finds all the local variables, global variables, and functions of PHP in the same file, the Hash table of the class defines struct _ detail {zval ** values; zval uninitialized_zval; zval * values; zval error_zval; zval * error_zval_ptr; zend_ptr_stack arg_types_stack; /* symbol table cache */HashTable * symtable_cache [sequence]; HashTable ** sequence; zend_op ** opline_ptr; HashTable * active_symbol_table; // The local variable HashTable symbol_table; /* main symbol table * // global variable HashTable included_files;/* files already included * // include file JMP_BUF * inclulout; int error_reporting; int orig_error_reporting; int exit_status; zend_op_array * active_op_array; HashTable * function_table;/* function symbol table * // function table HashTable * class_table;/* class table * // class table HashTable * zend_constants; /* constants table * // constant table zend_class_entry * scope; zend_class_entry * called_scope;/* Scope of the calling class */zval * This; long precision; int ticks_count; zend_bool in_execution; hashTable * in_autoload; zend_function * functions; zookeeper;/* for extended information support */incluno_extensions; # ifdef ZEND_WIN32 extends timed_out; OSVERSIONINFOEX extends; # endif HashTable regular_list; HashTable extends; zend_vm_stack argument_stack; int worker; zval * worker; zend_stack worker; zookeeper; assumerror_handling; zend_class_entry * exception_class;/* timeout support */int timeout_seconds; int lambda_count; HashTable * handle; incluobjects_store; zval * exception, * prev_exception; zend_op * handle; zend_op prediction_op [3]; struct _ expect * current_execute_data; struct _ zend_module_entry * current_module; zend_property_info std_property_info; zend_bool active; void * response; void * reserved [response];}; let's take a look at it briefly, the most basic unit variable in PHP: Defining a variable in PHP is much simpler. However, in the kernel, it is implemented using a zval struct. for example, the above defined variables execute the following code in the kernel: zval * val; MAKE_STD_ZVAL (val ); // apply for a piece of memory ZVAL_STRING (val, "hello", 1); // use ZVAL_STRING to set its value to "hello" ZEND_SET_SYMBOL (EG (active_symbol_table), "", val); // add the val pointer to the symbol table. the macro MAKE_STD_ZVAL is defined as follows # define MAKE_STD_ZVAL (zv) \ ALLOC_ZVAL (zv ); \ // It is equivalent to (p) = (type *) emalloc (sizeof (type) INIT_PZVAL (zv); INIT_PZVAL is defined in # define INIT_PZVAL (z) \ it can be seen that it is the initialization parameter (z)-> refcount _ gc = 1; \ (z)-> is_ref _ gc = 0; so what is zval in zend/zend. in h, typedef struct _ zval_struct zval; // The original alias _ zval_struct defines the following typedef union _ zvalue_value {long lval; // double dval that stores long data; // Save the double type data struct {char * val; // The true value int len; // return the length} str; HashTable * ht; zend_object_value obj; // This is an object} zvalue_value; struct _ zval_struct {zvalue_value value; // the stored value zend_uint refcount _ gc; // if the number of times referenced is 1, it will only be used by itself. if it is greater than 1, it will be referenced by other variables in the form. zend_uchar type; // data type. this is also the reason why PHP is weak. zend_uchar is_ref _ gc; // indicates whether it is referenced .. so let's take a look .. using C to create a PHP variable requires an extension. If PHP uses the C extension module, the key code PHP_FUNCTION (test_siren) {zval * value is not mentioned here; char * s = "create a php variable"; value = (zval *) malloc (sizeof (zval); memset (value, 0, sizeof (value )); value-> is_ref _ gc = 0; // The value of the non-reference variable-> refcount _ gc = 1; // The number of times the reference is only the value of the variable itself-> type = IS_STRING; // The type is string value-> value. str. val = s; // value-> value. str. len = strlen (s); // length ZEND_SET_SYMBOL (EG (active_symbol_table), "a", value);} the role of row 3 and row 4 is the same as that of MAKE_STD_ZVAL, row 5-9 of the memory space allocated to the value serves the same purpose as ZVAL_STRING. the last row creates a variable named $ a in PHP .. and add it to the local Hash table .. in this way, in PHP The "create a php variable" OK will be output. I am trying to show you how to create variables in PHP in the form of C, we do not recommend this. you must use the internal memory management mechanism of PHP to allocate and process the memory.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.