Zend engine
This presentation is the property of its rightful owner.
Sponsored Links
1 / 31

Zend Engine изнутри PowerPoint PPT Presentation


  • 176 Views
  • Uploaded on
  • Presentation posted in: General

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

Download Presentation

Zend Engine изнутри

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Zend engine

Zend Engine изнутри

Дмитрий Стогов


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

  • 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


Zend engine

Подсистемы ZE

  • Менеджер памяти

  • API для доступа к внутренним структурам данных

  • Компилятор PHP

  • Виртуальная машина PHP

  • API для ресурсов (файлы, DB коннекшены)

  • API для внешних расширений PHP

  • Набор внутренних функций

  • Сборщик мусора (5.3)


Zend engine

Стадии работы PHP


Thread safe resource manager

Thread Safe Resource Manager

  • non-ZTS-build (single-thread)

  • ZTS-build (thread-safe)

    • Каждый thread работает со своими глобальными данными

      • ZE использует compiler_globals (CG) и executor_globals (EG)

      • Любое расширение PHP может определить свои глобальные данные, которые должны быть уникальными для разных thread-ов


Zend engine

TSRM макросы

  • void some_function(void) {process(EG(symbol_table));// compilation error}


Zend engine

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_paremeterTSRMLS_DC) {process(EG(symbol_table));}

    some_function(0TSRMLS_CC);


Zend engine

Менеджер памяти

emalloc()

efree()

erealloc()

estrdup()

estrndup()

ecalloc()

$ USE_ZEND_ALLOC=0 valgrind php test.php


Zend engine

typedef struct _zval_struct {

zend_uchar type;

zvalue_value value;

zend_uchar is_ref;

zebd_uint refcount;

} zval;

Значения (zval-коетейнер)


Zend engine

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

Значения (zval-коетейнер)


Zend engine

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;

Значения (zval-коетейнер)


Zend engine

<?php

$a = 10;

$b =& $b;

Ссылки

EG(symbol_table)

HashTable

$a

zval

type

IS_LONG

$b

value

10

is_ref

1

refcount

2


Zend engine

<?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}

Присваивание и копирование при записи


Zend engine

Компилятор

  • Основан на flex/bison based (основан на re2c/bison начиная с 5.3)

  • Однопроходная компиляция (на самом деле два прохода)

    • AST не создается

    • Прямая компиляция в байт-кодVM

    • Быстрая компиляция

    • Оптимизация практически не выполняется


Zend engine

Глобальные данные компилятора (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)


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;

Функции PHP (op_array)


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;

Инструкции VM (zend_op)


Vm zend op1

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

Инструкции VM (zend_op)


Vm zend op2

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;

Инструкции VM (zend_op)


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

Операнды (znode)


Zend engine

<?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)

Пример компиляции (5.0)


Zend engine

<?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)

Пример компиляции (5.1)


Vm eg

Глобальные данные 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)


Switch threaded executor 4

Switch-threaded Executor (4.*)

void execute(zend_op_array *op_arrayTSRMLS_DC) {

zend_execute_data execute_data;

// initialization

EX(opline) = op_array->opcodes;

while (1) {

switch (EX(opline)->opcode) {

case ZEND_RETURN;

return;

}

}

}


Call threaded executor 5

Call-threaded Executor (5.*)

void execute(zend_op_array *op_arrayTSRMLS_DC) {

zend_execute_data execute_data;

// initialization

EX(opline) = op_array->opcodes;

while (1) {

if (EX(opline)->handler(&execute_dataTSRMLS_CC)) {

return;

}

}

}


Call threaded executor 5 0

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;

}


Vm 5 1

Специализация в 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;

}


Vm 5 11

Специализация в 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;

}


Zend engine

Классы

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;


Zend engine

Объекты

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;


Zend engine

Вопросы?


  • Login