Download presentation
Presentation is loading. Please wait.
Published byPoppy Bryan Modified over 9 years ago
1
Zend Engine изнутри Дмитрий Стогов
2
Немного истории Zend Engine была разработана в качестве ядра для PHP 4 Andi Gutmans и Zeev Suraski в 1999 PHP 5.0 основан на Zend Engine 2 с новой объектной моделью PHP 5.1 основан на Zend Engine 2.1 со специализированной VM PHP 5.2 основан на Zend Engine 2.2 с новым менеджером памяти PHP 5.3 основан на Zend Engine 2.3 которая включает большинство улучшений и нововведений из PHP6, за исключением Unicode, (namespace-ы, сборщик мусора, LSB, оператор goto, ленивая инициализация таблиц символов, новый сканнер основанный на re2c) PHP 6 основан на Zend Engine 3 с поддержкой Unicode
3
Подсистемы ZE Менеджер памяти API для доступа к внутренним структурам данных Компилятор PHP Виртуальная машина PHP API для ресурсов (файлы, DB коннекшены) API для внешних расширений PHP Набор внутренних функций Сборщик мусора (5.3)
4
Стадии работы PHP
5
Thread Safe Resource Manager non-ZTS-build (single-thread) ZTS-build (thread-safe) Каждый thread работает со своими глобальными данными ZE использует compiler_globals (CG) и executor_globals (EG) Любое расширение PHP может определить свои глобальные данные, которые должны быть уникальными для разных thread-ов
6
TSRM макросы void some_function(void) { process(EG(symbol_table)); // compilation error }
7
TSRM макросы void some_function(void) { int some_local_variable; TSRMLS_FETCH(); process(EG(symbol_table)); } void some_function(TSRMLS_D) { process(EG(symbol_table)); } some_function(TSRMLS_C); void some_function(int some_paremeter TSRMLS_DC) { process(EG(symbol_table)); } some_function(0 TSRMLS_CC);
8
Менеджер памяти emalloc() efree() erealloc() estrdup() estrndup() ecalloc() $ USE_ZEND_ALLOC=0 valgrind php test.php
9
Значения (zval-коетейнер) typedef struct _zval_struct { zend_uchar type; zvalue_value value; zend_uchar is_ref; zebd_uint refcount; } zval;
10
Значения (zval-коетейнер) typedef struct _zval_struct { zend_uchar type; zvalue_value value; zend_uchar is_ref; zebd_uint refcount; } zval; IS_NULL IS_LONG IS_DOUBLE IS_BOOL IS_ARRAY IS_OBJECT IS_STRING IS_RESOURCE IS_CONSTANT IS_CONSTANT_ARRAY
11
Значения (zval-коетейнер) typedef struct _zval_struct { zend_uchar type; zvalue_value value; zend_uchar is_ref; zebd_uint refcount; } zval; typedef union _zvalue_value { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; zend_object_value obj; } zvalue_value;
12
Ссылки <?php $a = 10; $b =& $b; $a $b … EG(symbol_table) type value is_ref refcount IS_LONG 10 1 2 zval HashTable
13
Присваивание и копирование при записи <?php $a = 1; $b = $a; $b = 2; $b =& $a; $b = 3; $b =& $c; // $a = {1, refcount=1, is_ref=0} // $a = {1, refcount=2, is_ref=0} // $b = {1, refcount=2, is_ref=0} // $a = {1, refcount=1, is_ref=0} // $b = {2, refcount=1, is_ref=0} // $a = {1, refcount=2, is_ref=1} // $b = {1, refcount=2, is_ref=1} // $a = {3, refcount=2, is_ref=1} // $b = {3, refcount=2, is_ref=1} // $a = {3, refcount=1, is_ref=0} // $b = {?, refcount=?, is_ref=1}
14
Компилятор Основан на flex/bison based (основан на re2c/bison начиная с 5.3) Однопроходная компиляция (на самом деле два прохода) – AST не создается – Прямая компиляция в байт-кодVM – Быстрая компиляция – Оптимизация практически не выполняется
15
Глобальные данные компилятора (CG) struct _zend_compiler_globals { … HashTable *function_table; HashTable *class_table; zend_class_entry *active_class_entry; zend_op_array *active_op_array; … }; CG(function_table)
16
Функции PHP (op_array) typedef struct _zend_op_array { zend_uchar type; char *function_name; zend_class_entry *scope; zend_uint fn_flags; zend_op *opcodes; zend_compiled_variables *vars; zend_uint last, lat_var, T; HashTable *static_variables; … } zend_op_array;
17
Инструкции VM (zend_op) typedef struct _zend_op { zend_uchar opcode; ulong extended_value; znode op1; znode op2; znode result; uint lineno; opcode_handler_t handler; } zend_op;
18
Инструкции VM (zend_op) typedef struct _zend_op { zend_uchar opcode; ulong extended_value; znode op1; znode op2; znode result; uint lineno; opcode_handler_t handler; } zend_op; ZEND_NOP ZEND_ADD ZEND_SUB ZEND_IS_EQUAL ZEND_JMP ZEND_JMPZ ZEND_ASSIGN ZEND_DO_FCALL ZEND_RETURN ~150 opcodes in zend_vm_opcodes.h
19
Инструкции VM (zend_op) typedef struct _zend_op { zend_uchar opcode; ulong extended_value; znode op1; znode op2; znode result; uint lineno; opcode_handler_t handler; } zend_op; typedef struct _znode { int op_type; union { zval constant; zend_uint var; zend_uint opline_num; zend_op *jmp_addr; struct { zend_uint var; zend_uint type; } EA; } u; } znode;
20
Операнды (znode) typedef struct _znode { int op_type; union { zval constant; zend_uint var; zend_uint opline_num; zend_op *jmp_addr; struct { zend_uint var; zend_uint type; } EA; } u; } znode; IS_CONST IS_CV IS_TMP_VAR IS_VAR IS_UNUSED
21
Пример компиляции (5.0) <?php $a = “Hello”; $b = “World”; echo $a.” “. $b; ?> // FETCH_WC(“a”)-> V(0) // ASSIGNV(0), C(“Hello”) // FETCH_WC(“b”)-> V(1) // ASSIGNV(1), C(“World”) // FETCH_RC(“a”)-> V(2) // CONCATV(2), C(“ “)-> T(3) // FETCH_RC(“b”)-> V(4) // CONCATT(3), V(4)-> T(5) // ECHOT(5) // RETURNC(NULL)
22
Пример компиляции (5.1) <?php $a = “Hello”; $b = “World”; echo $a.” “. $b; ?> // // ASSIGNCV(0)[“a”], C(“Hello”) // // ASSIGNCV(1)[“b”], C(“World”) // // CONCATCV(0)[“a”], C(“ “)-> T(0) // CONCATT(0), CV(1)[“b”]-> T(1) // ECHOT(1) // // RETURNC(NULL)
23
Глобальные данные VM (EG) struct _zend_executor_globals { … HashTable *active_symbol_table; HashTable symbol_table;// $GLOBALS[] HashTable *function_table; HashTable *class_table; HashTable *zend_constants; zval *This; zend_class_entry *scope; zend_op_array *active_op_array; zend_op **opline_ptr; struct _zend_execute_data *current_execute_data; … }; EG(symbol_table)
24
Switch-threaded Executor (4.*) void execute(zend_op_array *op_array TSRMLS_DC) { zend_execute_data execute_data; // initialization EX(opline) = op_array->opcodes; while (1) { switch (EX(opline)->opcode) { … case ZEND_RETURN; … return; }
25
Call-threaded Executor (5.*) void execute(zend_op_array *op_array TSRMLS_DC) { zend_execute_data execute_data; // initialization EX(opline) = op_array->opcodes; while (1) { if (EX(opline)->handler(&execute_data TSRMLS_CC)) { return; }
26
Call-threaded Executor (5.0) int zend_concat_handler(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); concat_function(&EX_T(opline->result.u.var).tmp_var, get_zval_ptr(&opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R), get_zval_ptr(&opline->op2, EX(Ts), &EG(free_op2), BP_VAR_R)); FREE_OP1(EX(Ts), &opline->op1, EG(free_op1)); FREE_OP2(EX(Ts), &opline->op2, EG(free_op2)); EX(opline)++; return 0; }
27
Специализация в VM (5.1) ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) { zend_op *opline = EX(opline); zend_free_op free_op1, free_op2; concat_function(&EX_T(opline->result.u.var).tmp_var, GET_OP1_ZVAL_PTR(BP_VAR_R), GET_OP2_ZVAL_PTR(BP_VAR_R)); FREE_OP1(); FREE_OP2(); EX(opline)++; return 0; }
28
Специализация в VM (5.1) int ZEND_CONCAT_SPEC_CV_CONST_HANDLER( ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); concat_function(&EX_T(opline->result.u.var).tmp_var, _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R), &opline->op2.u.constant); EX(opline)++; return 0; }
29
Классы typrdef struct _zend_class_entry { char type; char *name; zend_class_entry *parent; zend_uint ce_flags; HashTable function_table; HashTable default_properties; HashTable properties_info; HashTable *static_members; HashTable constants_table; zend_class_entry **interfaces; … } zend_class_entry;
30
Объекты typedef struct _zend_object_value { zend_uint handle;//Z_OBJ_HANDLE(zval) zend_object_handlers *handlers;//Z_OBJ_HT(zval) } zend_object_value; typedef struct _zend_object { zend_class_entry *ce;//Z_OBJCE(zval) HashTable *properties;//Z_OBJPROP(zval) } zend_object;
31
Вопросы?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.