php-5.6.26源代码 - PHP文件汇编成opcode(require、include的差异)

 

文件 php-5.6.26/Zend/zend_language_scanner.c

ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
    zend_lex_state original_lex_state;
    zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
    zend_op_array *original_active_op_array = CG(active_op_array); // 保存 op_code 现场(保存现场)
    zend_op_array *retval=NULL;
    int compiler_result;
    zend_bool compilation_successful=0;
    znode retval_znode;
    zend_bool original_in_compilation = CG(in_compilation);

    retval_znode.op_type = IS_CONST;
    INIT_PZVAL(&retval_znode.u.constant);
    ZVAL_LONG(&retval_znode.u.constant, 1);

    zend_save_lexical_state(&original_lex_state TSRMLS_CC);  // 保存词法分析器的状态(保存现场)

    retval = op_array; /* success oriented */

    if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) { // 打开文件、设置扫描器的指针
        if (type==ZEND_REQUIRE) {
            zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
            zend_bailout(); // !!! require、require_once 会抛出异常 -----------------
        } else {
            zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
            // 没有抛出异常 -----------------
        }
        compilation_successful=0;
    } else {
        // 扫描后、初始化 op_array
        init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);  // 1、初始化一些数据、申请空间  2、迭代调用所有zend扩展的op_array_ctor函数
        CG(in_compilation) = 1;  // 是否处于汇编状态
        CG(active_op_array) = op_array; // 操作码数组
        zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); // 把当前上下文入栈
        zend_init_compiler_context(TSRMLS_C); // 初始化编译器上下文
        compiler_result = zendparse(TSRMLS_C); // 开始解析
        zend_do_return(&retval_znode, 0 TSRMLS_CC); // 返回
        CG(in_compilation) = original_in_compilation;  // 还原现场
        if (compiler_result != 0) { /* parser error */
            zend_bailout();
        }
        compilation_successful=1;  // 汇编成功
    }

    if (retval) {
        CG(active_op_array) = original_active_op_array; // 还原原来 op_code 现场(还原现场)
        if (compilation_successful) {  // 汇编成功
            pass_two(op_array TSRMLS_CC); // 注入“opcode处理器”
            zend_release_labels(0 TSRMLS_CC);
        } else {
            efree(op_array);
            retval = NULL;
        }
    }
    zend_restore_lexical_state(&original_lex_state TSRMLS_CC);  // 还原原来词法解析器的状态(还原现场)
    return retval;
}

 

posted on 2018-03-23 10:24  周~~  阅读(206)  评论(0编辑  收藏  举报

导航