Presentation is loading. Please wait.

Presentation is loading. Please wait.

Zend Engine изнутри Дмитрий Стогов. Немного истории Zend Engine была разработана в качестве ядра для PHP 4 Andi Gutmans и Zeev Suraski в 1999 PHP 5.0.

Similar presentations


Presentation on theme: "Zend Engine изнутри Дмитрий Стогов. Немного истории Zend Engine была разработана в качестве ядра для PHP 4 Andi Gutmans и Zeev Suraski в 1999 PHP 5.0."— Presentation transcript:

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 Вопросы?


Download ppt "Zend Engine изнутри Дмитрий Стогов. Немного истории Zend Engine была разработана в качестве ядра для PHP 4 Andi Gutmans и Zeev Suraski в 1999 PHP 5.0."

Similar presentations


Ads by Google