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
echo1;
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