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

posted @ 2019-03-22 11:08  taek  阅读(997)  评论(0编辑  收藏  举报