zend engine изнутри
DESCRIPTION
Zend Engine изнутри. Дмитрий Стогов. Немного истории. Zend Engine была разработана в качестве ядра для PHP 4 Andi Gutmans и Zeev Suraski в 1999 PHP 5.0 основан на Zend Engine 2 с новой объектной моделью PHP 5.1 основан на Zend Engine 2.1 со специализированной VM - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/1.jpg)
Zend Engine изнутри
Дмитрий Стогов
![Page 2: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/2.jpg)
Немного истории
• 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
![Page 3: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/3.jpg)
Подсистемы ZE
• Менеджер памяти • API для доступа к внутренним структурам данных• Компилятор PHP• Виртуальная машина PHP• API для ресурсов (файлы, DB коннекшены)• API для внешних расширений PHP• Набор внутренних функций• Сборщик мусора (5.3)
![Page 4: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/4.jpg)
Стадии работы PHP
![Page 5: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/5.jpg)
Thread Safe Resource Manager
• non-ZTS-build (single-thread)• ZTS-build (thread-safe)
• Каждый thread работает со своими глобальными данными
• ZE использует compiler_globals (CG) и executor_globals (EG)
• Любое расширение PHP может определить свои глобальные данные, которые должны быть уникальными для разных thread-ов
![Page 6: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/6.jpg)
TSRM макросы
• void some_function(void) {process(EG(symbol_table)); // compilation error
}
![Page 7: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/7.jpg)
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);
![Page 8: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/8.jpg)
Менеджер памяти
emalloc()efree()erealloc()estrdup()estrndup()ecalloc()
$ USE_ZEND_ALLOC=0 valgrind php test.php
![Page 9: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/9.jpg)
Значения (zval-коетейнер)
typedef struct _zval_struct {zend_uchar type;zvalue_value value;zend_uchar is_ref;zebd_uint refcount;
} zval;
![Page 10: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/10.jpg)
Значения (zval-коетейнер)
typedef struct _zval_struct {zend_uchar type;zvalue_value value;zend_uchar is_ref;zebd_uint refcount;
} zval;
IS_NULLIS_LONGIS_DOUBLEIS_BOOLIS_ARRAYIS_OBJECTIS_STRINGIS_RESOURCEIS_CONSTANTIS_CONSTANT_ARRAY
![Page 11: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/11.jpg)
Значения (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;
![Page 12: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/12.jpg)
Ссылки
<?php
$a = 10;
$b =& $b;$a
$b
…
EG(symbol_table)
type
value
is_ref
refcount
IS_LONG
10
1
2
zval
HashTable
![Page 13: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/13.jpg)
Присваивание и копирование при записи
<?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}
![Page 14: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/14.jpg)
Компилятор
• Основан на flex/bison based (основан на re2c/bison начиная с 5.3)
• Однопроходная компиляция (на самом деле два прохода)– AST не создается– Прямая компиляция в байт-кодVM– Быстрая компиляция– Оптимизация практически не выполняется
![Page 15: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/15.jpg)
Глобальные данные компилятора (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)
![Page 16: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/16.jpg)
Функции 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;
![Page 17: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/17.jpg)
Инструкции 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;
![Page 18: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/18.jpg)
Инструкции 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_NOPZEND_ADDZEND_SUBZEND_IS_EQUALZEND_JMPZEND_JMPZZEND_ASSIGNZEND_DO_FCALLZEND_RETURN
~150 opcodes in zend_vm_opcodes.h
![Page 19: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/19.jpg)
Инструкции 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;
![Page 20: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/20.jpg)
Операнды (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_CONSTIS_CVIS_TMP_VARIS_VARIS_UNUSED
![Page 21: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/21.jpg)
Пример компиляции (5.0)
<?php$a = “Hello”;
$b = “World”;
echo $a .” “. $b;
?>
// FETCH_W C(“a”) -> V(0)// ASSIGN V(0), C(“Hello”)// FETCH_W C(“b”) -> V(1)// ASSIGN V(1), C(“World”)// FETCH_R C(“a”) -> V(2)// CONCAT V(2), C(“ “) -> T(3)// FETCH_R C(“b”) -> V(4)// CONCAT T(3), V(4) -> T(5)// ECHO T(5)// RETURN C(NULL)
![Page 22: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/22.jpg)
Пример компиляции (5.1)
<?php
$a = “Hello”;
$b = “World”;
echo $a .” “. $b;
?>
// // ASSIGN CV(0)[“a”], C(“Hello”)// // ASSIGN CV(1)[“b”], C(“World”)// // CONCAT CV(0)[“a”], C(“ “) -> T(0)// CONCAT T(0), CV(1)[“b”] -> T(1)// ECHO T(1)////// RETURN C(NULL)
![Page 23: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/23.jpg)
Глобальные данные 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)
![Page 24: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/24.jpg)
Switch-threaded Executor (4.*)
void execute(zend_op_array *op_array TSRMLS_DC) {zend_execute_data execute_data;
// initializationEX(opline) = op_array->opcodes;while (1) {
switch (EX(opline)->opcode) {…case ZEND_RETURN;
…return;
}}
}
![Page 25: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/25.jpg)
Call-threaded Executor (5.*)
void execute(zend_op_array *op_array TSRMLS_DC) {zend_execute_data execute_data;
// initializationEX(opline) = op_array->opcodes;while (1) {
if (EX(opline)->handler(&execute_data TSRMLS_CC)) {return;
}}
}
![Page 26: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/26.jpg)
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;
}
![Page 27: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/27.jpg)
Специализация в 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;
}
![Page 28: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/28.jpg)
Специализация в 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;
}
![Page 29: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/29.jpg)
Классы
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;
![Page 30: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/30.jpg)
Объекты
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;
![Page 31: Zend Engine изнутри](https://reader035.vdocuments.site/reader035/viewer/2022062305/56814a46550346895db76266/html5/thumbnails/31.jpg)
Вопросы?