Annotation of embedaddon/php/Zend/README.ZEND_VM, revision 1.1.1.2

1.1       misho       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
1.1.1.2 ! misho       9: factor but system calls and database calls are, your mileage with this patch
1.1       misho      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>