`
dengbaoleng
  • 浏览: 1162859 次
文章分类
社区版块
存档分类
最新评论

原:PHP内核研究 函数的定义

 
阅读更多
声明:本文为斯人原创,全部为作者一一分析得之,有不对的地方望赐教。
博客地址:PHP技术博客在CSDN也会同步更新的哦.
欢迎转载,转载请注明出处

PHP中,函数的定义 是用关键字 function来定义的.

function hello($str){
echo $str;
}
在/zend/zend_language_parse.y中找到 关键字 T_FUNCTION

[c]
function:
T_FUNCTION { $$.u.opline_num = CG(zend_lineno); }
;
[/c]

发现这个只是用来保存当前函数设置的位置的..
而真正parse的地方在哪里?我找了很久没找到,不得已 Google了一下,才知道是在这里

[c]
unticked_function_declaration_statement: //译为 "函数声明语句"
function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); }
'(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
;
[/c]

is_reference :是引用吗?
T_STRING :我们定义的函数名 ,等于hello
zend_do_begin_function_declaration:开始声明函数.
parameter_list :是参数表
inner_statement_list :函数体语句
zend_do_end_function_declaration:结束声明

一个一个来 先进 zend_do_begin_function_declaration看看,
比较长 一点点来看

[c]
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
{
zend_op_array op_array;
char *name = function_name->u.constant.value.str.val; //函数名
int name_len = function_name->u.constant.value.str.len;//函数名长度
int function_begin_line = function_token->u.opline_num;//函数定义的位置
zend_uint fn_flags;
char *lcname;
zend_bool orig_interactive;
if (is_method) { //是类的方法? 这里不涉及到类的方法的内容 所以暂时跳过
if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
}
Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
}
fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
} else {
fn_flags = 0;
}
//类相关 跳过
if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
}
//转换为小写
lcname = zend_str_tolower_dup(name, name_len);

orig_interactive = CG(interactive);
CG(interactive) = 0;
//初始化zend_op_array
/*要特别说明一下 在PHP里面 函数有两种一种是自定义函数:ZEND_USER_FUNCTION,
*一种是内置函数ZEND_INTERNAL_FUNCTION,这里我们是自定义函数所以 类型为ZEND_USER_FUNCTION
*/
init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
CG(interactive) = orig_interactive;

op_array.function_name = name; //函数名称
op_array.return_reference = return_reference; //是否是引用函数
op_array.fn_flags |= fn_flags; //可能是标示声明为类的方法
op_array.pass_rest_by_reference = 0; //所有参数都强制为引用?
op_array.prototype = NULL;//

op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);//开始行
if (is_method) {//类的方法 以下....省略

} else {//到这里 ,用户函数
//生成一个 zend_op
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

if (CG(current_namespace)) { //5.3新特性 支持命名空间
/* Prefix function name with current namespcae name */
znode tmp;

tmp.u.constant = *CG(current_namespace);
zval_copy_ctor(&tmp.u.constant);
zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
op_array.function_name = Z_STRVAL(tmp.u.constant);
efree(lcname);
name_len = Z_STRLEN(tmp.u.constant);
lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
}
//生成的中间代码
opline->opcode = ZEND_DECLARE_FUNCTION;
//类型
opline->op1.op_type = IS_CONST;
build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
opline->op2.op_type = IS_CONST;
opline->op2.u.constant.type = IS_STRING;
opline->op2.u.constant.value.str.val = lcname;
opline->op2.u.constant.value.str.len = name_len;
Z_SET_REFCOUNT(opline->op2.u.constant, 1);
opline->extended_value = ZEND_DECLARE_FUNCTION;
//更新函数表的HashTable
zend_hash_update(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
}

if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

opline->opcode = ZEND_EXT_NOP;
opline->lineno = function_begin_line;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
}

{
/* Push a seperator to the switch and foreach stacks */
zend_switch_entry switch_entry;

switch_entry.cond.op_type = IS_UNUSED;
switch_entry.default_case = 0;
switch_entry.control_var = 0;

zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));

{
/* Foreach stack separator */
zend_op dummy_opline;

dummy_opline.result.op_type = IS_UNUSED;
dummy_opline.op1.op_type = IS_UNUSED;

zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
}
}

if (CG(doc_comment)) {
CG(active_op_array)->doc_comment = CG(doc_comment);
CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
CG(doc_comment) = NULL;
CG(doc_comment_len) = 0;
}

zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
CG(labels) = NULL;
}
[/c]


保存自定义函数的结构如下

[c]
typedef union _zend_function {
zend_uchar type; /* MUST be the first element of this struct! */

struct {
zend_uchar type; /* never used */
char *function_name; //函数名称
zend_class_entry *scope;
zend_uint fn_flags;
union _zend_function *prototype;
zend_uint num_args; //参数个数
zend_uint required_num_args;
zend_arg_info *arg_info;
zend_bool pass_rest_by_reference;
unsigned char return_reference;
} common;

zend_op_array op_array;
zend_internal_function internal_function;
} zend_function;
[/c]


初始化op_array
生成 zend_op
生成的中间码 ZEND_DECLARE_FUNCTION
更新函数表function_table
这样 函数的定义就完了..
下一节详细介绍 函数的参数.


分享到:
评论

相关推荐

    深入理解PHP内核-php宝典

    ### 深入理解PHP内核的关键知识点 #### 一、引言 《深入理解PHP内核—PHP宝典》是一本系统介绍PHP内部工作原理和技术细节的专业书籍。该书首次发布于2011年7月29日,旨在帮助开发者更深刻地理解PHP的运行机制,并为...

    深入理解PHP内核

    内核中处理了变量类型、语法解析、函数定义、内存管理等众多核心功能。对于Web开发来说,PHP内核的一个重要特性是它的弱类型变量原理。在PHP中,变量并不需要明确的类型声明,PHP会根据上下文自动推断变量的类型,...

    Zend API:深入 PHP 内核

    深入了解PHP内核及Zend API不仅可以帮助开发者克服语言本身的限制,还能大幅提升应用程序的性能和灵活性。通过合理选择扩展策略,无论是外部模块还是内建模块,都可以有效地解决不同场景下的问题。而对于更加复杂的...

    TIPI:深入理解PHP内核-PHP内核程序详解chm文档

    《TIPI:深入理解PHP内核》是一本深入解析PHP内核设计与程序逻辑的珍贵文档,对于PHP开发者来说,是提升技术深度的宝贵资源。本文将基于该文档的要点,详细阐述PHP内核的关键概念和技术细节。 1. **PHP内核结构** ...

    Zend API:深入 PHP 内核.7z

    通过使用Zend API,开发者可以直接与PHP内核交互,创建自定义的PHP模块、函数或者对象模型,甚至实现更高效的脚本处理。这些API涵盖了诸如变量操作、函数注册、类定义、异常处理、内存管理等各个方面。 深入理解...

    深入理解PHP内核.mobi

    《深入理解PHP内核》是一本专为PHP开发者和爱好者量身打造的开源书籍,它深入探讨了PHP的内部机制,旨在帮助读者更好地理解和优化PHP应用程序。这本书涵盖了从基础到高级的各种主题,包括PHP的环境配置、源码解读、...

    php扩展开发与内核应用

    7. Array与HashTable:介绍数组在PHP内核中的表现形式,如何操作HashTable以及在内核中操作PHP语言中的数组。 8. PHP中的资源类型:资源是PHP中用来表示外部资源的一种特殊类型,包括持久化资源和它们的引用计数...

    深入php内核分析与讲解

    ### 深入PHP内核分析与讲解 #### 核心知识点详解 ##### 1. PHP内核概览 **标题**: “深入php内核分析与讲解” **描述**: “深入php内核分析,讲诉zend Engine工作原理,并附录php扩展开发图文教程” **关键词**:...

    PHP内核介绍及扩展开发指南

    PHP内核和扩展开发是一个复杂但有趣的领域,它涉及到内存管理、数据结构、函数调用等多个层面。掌握这些知识不仅可以帮助开发者更有效地编写PHP扩展,还能深化对PHP内核的理解,提升编程技能。通过本文的详细介绍,...

    PHP内核扩展教程及文档_ppt_code等

    在深入探讨PHP内核扩展教程及文档之前,我们先来理解一下PHP内核的基本概念。PHP(PHP: Hypertext Preprocessor)是一种广泛使用的开源脚本语言,尤其适用于Web开发,可嵌入到HTML中。PHP内核是其核心部分,负责解析...

    PHP7内核剖析.zip

    FPM(FastCGI Process Manager)是PHP FastCGI运行模式的一个进程管理器,从它的定义可以看出,FPM的核心功能是进程管理,那么它用来管理什么进程呢?这个问题就需要从FastCGI说起了。 FastCGI是Web服务器(如:Nginx...

    PHP深度分析:101个核心技巧、窍门和问题解决方法(原书第2版).pdf+PHP 内核文档.chm

    此外,书中可能会讨论变量作用域、函数与方法的定义与调用,以及面向对象编程的概念,包括类、对象、继承、多态和接口。 "窍门"部分则可能包含提高代码性能的技巧,如优化查询、减少内存消耗、利用缓存机制等。还会...

    PHP内核介绍及扩展开发指南.pdf

    接下来,我们将详细介绍PHP内核的一些基础知识和扩展开发的相关知识。 ### PHP内核基础知识 #### PHP变量的存储 - zval结构 PHP使用`zval`结构存储变量值,这个结构包括变量的值和类型信息。`zval`包含两个主要...

    PHP-内核解析-深入PHP

    《PHP-内核解析-深入PHP》这本书是针对PHP开发者深入理解PHP内核的重要参考资料,旨在帮助读者从底层原理的角度掌握PHP的运行机制。通过学习本书,你可以了解PHP的架构设计、内存管理、变量处理、函数调用、执行流程...

    深入_PHP_内核(pdf格式)

    深入研究PHP内核的核心在于理解Zend API,即Zend Application Programming Interface。这是PHP内核的核心组成部分之一,提供了用于编写PHP扩展的接口和工具。 ##### 1. Zend API的基本概念 - **数据结构**:例如`...

    PHP内核介绍及扩展开发指南—基础知识.pdf

    在了解PHP内核和扩展开发之前,我们需要了解一些基础知识,包括PHP的数据结构、内存管理以及哈希表的实现。 首先,让我们来谈谈PHP中的zval结构。zval是PHP内部用于存储变量的所有信息的数据结构。每一个变量在PHP...

    PHP扩展开发及内核应用

    本文将详细介绍PHP扩展开发和内核应用的核心知识点。首先,关于PHP的生命周期,它是从SAPI(Server API)开始的,涉及PHP的启动和终止过程。在这一过程中,线程安全是不可忽视的部分,尤其是在多线程环境下。PHP变量...

    PHP实例开发源码-拓商企业服务网 DT内核 php版.zip

    【PHP实例开发源码-拓商企业服务网 DT内核 php版.zip】是一个包含PHP编程语言的源代码实例,主要用于企业服务网站的建设。这个压缩包着重展示了如何使用PHP与DT内核构建一个功能丰富的商业服务网络平台。DT内核通常...

Global site tag (gtag.js) - Google Analytics