File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / README.ZEND_VM
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 08:02:46 2013 UTC (11 years, 2 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29p0, v5_4_29, v5_4_20p0, v5_4_20, HEAD
v 5.4.20

    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>