1: ZEND_VM
2: =======
3:
4: ZEND_VM architecture allows specializing opcode handlers according to op_type
5: fields and using different execution methods (call threading, switch threading
6: and direct threading). As a result ZE2 got more than 20% speedup on raw PHP
7: code execution (with specialized executor and direct threading execution
8: method). As in most PHP applications raw execution speed isn't the limiting
9: factor but system calls and database calls are, your mileage with this patch
10: will vary.
11:
12: Most parts of the old zend_execute.c go into zend_vm_def.h. Here you can
13: find opcode handlers and helpers. The typical opcode handler template looks
14: like this:
15:
16: ZEND_VM_HANDLER(<OPCODE-NUMBER>, <OPCODE>, <OP1_TYPES>, <OP2_TYPES>)
17: {
18: <HANDLER'S CODE>
19: }
20:
21: <OPCODE-NUMBER> is a opcode number (0, 1, ...)
22: <OPCODE> is an opcode name (ZEN_NOP, ZEND_ADD, :)
23: <OP1_TYPES> & <OP2_TYPES> are masks for allowed operand op_types. Specializer
24: will generate code only for defined combination of types. You can use any
25: combination of the following op_types UNUSED, CONST, VAR, TMP and CV also
26: you can use ANY mask to disable specialization according operand's op_type.
27: <HANDLER'S CODE> is a handler's code itself. For most handlers it stills the
28: same as in old zend_execute.c, but now it uses macros to access opcode operands
29: and some internal executor data.
30:
31: You can see the conformity of new macros to old code in the following list:
32:
33: EXECUTE_DATA
34: execute_data
35: ZEND_VM_DISPATCH_TO_HANDLER(<OP>)
36: return <OP>_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
37: ZEND_VM_DISPATCH_TO_HELPER(<NAME>)
38: return <NAME>(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
39: ZEND_VM_DISPATCH_TO_HELPER_EX(<NAME>,<PARAM>,<VAL>)
40: return <NAME>(<VAL>, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)
41: ZEND_VM_CONTINUE()
42: return 0
43: ZEND_VM_NEXT_OPCODE()
44: NEXT_OPCODE()
45: ZEND_VM_SET_OPCODE(<TARGET>
46: SET_OPCODE(<TARGET>
47: ZEND_VM_INC_OPCODE()
48: INC_OPCOD()
49: ZEND_VM_RETURN_FROM_EXECUTE_LOOP()
50: RETURN_FROM_EXECUTE_LOOP()
51: ZEND_VM_C_LABEL(<LABEL>):
52: <LABEL>:
53: ZEND_VM_C_GOTO(<LABEL>)
54: goto <LABEL>
55: OP<X>_TYPE
56: opline->op<X>.op_type
57: GET_OP<X>_ZVAL_PTR(<TYPE>)
58: get_zval_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
59: GET_OP<X>_ZVAL_PTR_PTR(<TYPE>)
60: get_zval_ptr_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
61: GET_OP<X>_OBJ_ZVAL_PTR(<TYPE>)
62: get_obj_zval_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
63: GET_OP<X>_OBJ_ZVAL_PTR_PTR(<TYPE>)
64: get_obj_zval_ptr_ptr(&opline->op<X>, EX(Ts), &free_op<X>, <TYPE>)
65: IS_OP<X>_TMP_FREE()
66: IS_TMP_FREE(free_op<X>)
67: FREE_OP<X>()
68: FREE_OP(free_op<X>)
69: FREE_OP<X>_IF_VAR()
70: FREE_VAR(free_op<X>)
71: FREE_OP<X>_VAR_PTR()
72: FREE_VAR_PTR(free_op<X>)
73:
74:
75: Executor's helpers can be defined without parameters or with one parameter.
76: This is done with the following constructs:
77:
78: ZEND_VM_HELPER(<HELPER-NAME>, <OP1_TYPES>, <OP2_TYPES>)
79: {
80: <HELPER'S CODE>
81: }
82:
83: ZEND_VM_HELPER_EX(<HELPER-NAME>, <OP1_TYPES>, <OP2_TYPES>, <PARAM_SPEC>)
84: {
85: <HELPER'S CODE>
86: }
87:
88: Executor's code is generated by PHP script zend_vm_gen.php it uses zend_vm_def.h
89: and zend_vm_execute.skl as input and produces zend_vm_opcodes.h and
90: zend_vm_execute.h. The first file is a list of opcode definitions. It is
91: included from zend_compile.h. The second one is an executor code itself. It is
92: included from zend_execute.c.
93:
94: zend_vm_gen.php can produce different kind of executors. You can select
95: different opcode threading model using --with-vm-kind=CALL|SWITCH|GOTO. You can
96: disable opcode specialization using --without-specializer. You can include or
97: exclude old executor together with specialized one using --without-old-executor.
98: At last you can debug executor using original zend_vm_def.h or generated file
99: zend_vm_execute.h. Debugging with original file requires --with-lines
100: option. By default ZE2 uses the following command to generate executor:
101:
102: $ php zend_vm_gen.php --with-vm-kind=CALL
103:
104: Zend Engine II currently includes two executors during the build process, one
105: is the specialized version and the other is the old one non-specialized with
106: function handlers. By default Zend Engine II uses the specialized one but you
107: can switch to the old executor at runtime by calling zend_vm_use_old_executor().
108:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>