php代码的opcode
echo 1; 1 function test(){ 2 $a="abc"; 3 echo $a; 4 } test(); 5
多个opcode组成一个op_array, 函数内的opcode与函数外的opcode属于不同的op_array
也就是说 第1行代码 和第2行代码 ,第5行代码 是属于同一个op_array
第3行代码 ,第4行代码 属于另一个op_array
//echo 1; zend_op_array op_array = emalloc(sizeof(zend_op_array)); op_array->opcodes = emalloc(64*sizeof(zend_op)); //默认64个zend_op INITIAL_OP_ARRAY_SIZE CG(active_op_array) = op_array; op_array->type = ZEND_EVAL_CODE; zend_op *opline= CG(active_op_array)->opcodes+CG(active_op_array)->last++; opline->opcode=ZEND_ECHO; opline->op1=1; opline->op1_type=IS_CONST;
//function test() zend_op *opline= CG(active_op_array)->opcodes+op_array->last++; zend_op opline = CG(active_op_array)->opcodes+CG(active_op_array)->last++; opline->opcode=ZEND_DECLARE_FUNCTION; opline->op1_type=CONST; opline->op1=op_array->function_name; opline->op2=null; //保留之前的op_array tmp = CG(active_op_array); zend_op_array op_array = emalloc(sizeof(zend_op_array)); op_array->opcodes = emalloc(64*sizeof(zend_op)); //默认64个zend_op INITIAL_OP_ARRAY_SIZE op_array->type = ZEND_USER_FUNCTIOIN op_array->function_name = strtolower(function_name) CG(function_table)[hash(op_array->function_name)] = op_array; CG(active_op_array) = op_array; zend_op *opline= CG(active_op_array)->opcodes+CG(active_op_array)->last++; opline->opcode=ZEND_ASSIGN; opline->op1="a"; opline->op1_type=IS_CV; opline->op2="abc" opline->op2_type=IS_CONST; pass_two(CG(active_op_array) TSRMLS_CC); //设置handler CG(active_op_array) = function_token->u.op_array
//test(); zend_op *opline =CG(active_op_array)->opcodes+CG(active_op_array)->last_count++; opline->opcode=ZEND_DO_FCALL; opline->op1=function_name; opline->op1_type=IS_CONST; 最后再执行pass_two(CG(active_op_array) TSRMLS_CC); 设置下面三个的handler echo 1; function test() test();
那么执行的时候,EG(active_op_array)=CG(active_op_array)
遍历其内部的opcodes,挨个执行
先执行 echo 1;
再执行 test(); 从EG(function_table)找到相应的op_array,再遍历其内部的opcode,再逐个执行
在执行ZEND_DECLARE_FUNCTION的时候,如果重复,会报错,编译期间不会报错
函数编译这块见 这里
java 的字节码 和php的opcode 完全不一样 见这里, php的opcode 还是C语言代码 ,而java的字节码是二进制的,只不过不能被OS执行执行,需要专门的虚拟机
echo 的 实现 这里 使用了fwrite(str,1,str_len,stderr);
stderr没有缓冲, stdout 有缓冲 (stdin也有),当遇到\n才输出
http://www.php-internals.com/book/?p=chapt03/03-06-02-var-scope