php-5.6.26源代码 - opcode处理器,“函数调用opcode”处理器,如何调用扩展模块的函数
// opcode处理器 --- ZEND_DO_FCALL_SPEC_CONST_HANDLER实现在 php-5.6.26\Zend\zend_vm_execute.h
static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE zval *fname = opline->op1.zv;
call_slot *call = EX(call_slots) + opline->op2.num; if (CACHED_PTR(opline->op1.literal->cache_slot)) {
EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot);
} else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) { // 查找函数,把函数指针放入 EX(function_state).function
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
} else {
CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function);
} call->fbc = EX(function_state).function; // 函数信息指针
call->object = NULL;
call->called_scope = NULL;
call->num_additional_args = ;
call->is_ctor_call = ;
EX(call) = call; // ZEND_OPCODE_HANDLER_ARGS_PASSTHRU ---> execute_data TSRMLS_CC return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); // zend_do_fcall_common_helper_SPEC(execute_data)
{
... if (fbc->type == ZEND_INTERNAL_FUNCTION) { // 内建函数 --- 执行的是函数指针(扩展中定义的函数)
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
zend_uint i;
void **p = EX(function_state).arguments - num_args; for (i = ; i < num_args; ++i, ++p) {
zend_verify_arg_type(fbc, i + , (zval *) *p, , NULL TSRMLS_CC);
}
} if (EXPECTED(EG(exception) == NULL)) {
temp_variable *ret = &EX_T(opline->result.var); MAKE_STD_ZVAL(ret->var.ptr);
ZVAL_NULL(ret->var.ptr);
ret->var.ptr_ptr = &ret->var.ptr;
ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != ; if (!zend_execute_internal) { // !!! 执行函数
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(num_args, ret->var.ptr, &ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); // 调用扩展模块的函数
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
} if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&ret->var.ptr);
}
} else if (RETURN_VALUE_USED(opline)) {
EX_T(opline->result.var).var.ptr = NULL;
}
} else if (fbc->type == ZEND_USER_FUNCTION) { // 用户定义的函数 --- 执行的opcode
temp_variable *ret = &EX_T(opline->result.var);
EX(original_return_value) = EG(return_value_ptr_ptr);
EG(active_symbol_table) = NULL;
EG(active_op_array) = &fbc->op_array; // !!! 用户函数编译出来的操作码
EG(return_value_ptr_ptr) = NULL;
if (RETURN_VALUE_USED(opline)) {
ret->var.ptr = NULL;
EG(return_value_ptr_ptr) = &ret->var.ptr;
ret->var.ptr_ptr = &ret->var.ptr;
ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != ;
} if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != )) {
if (RETURN_VALUE_USED(opline)) {
ret->var.ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC);
ret->var.fcall_returned_reference = ;
}
} else if (EXPECTED(zend_execute_ex == execute_ex)) {
if (EXPECTED(EG(exception) == NULL)) {
ZEND_VM_ENTER();
}
} else {
zend_execute(EG(active_op_array) TSRMLS_CC); // 执行操作码
} EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
if (EG(active_symbol_table)) {
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr);
ZVAL_NULL(EX_T(opline->result.var).var.ptr); /* Not sure what should be done here if it's a static method */
if (EXPECTED(EX(object) != NULL)) {
// 调用对象方法
Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, num_args, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
} if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
efree((char*)fbc->common.function_name);
}
efree(fbc); if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
} else {
Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, );
EX_T(opline->result.var).var.fcall_returned_reference = ;
EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
} ... EX(call)--; zend_vm_stack_clear_multiple( TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC); // 抛异常
if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
}
HANDLE_EXCEPTION();
} ZEND_VM_NEXT_OPCODE(); ...
}
}
php-5.6.26源代码 - opcode处理器,“函数调用opcode”处理器,如何调用扩展模块的函数的更多相关文章
- php-5.6.26源代码 - opcode处理器的注入
		
.初始化 opcode处理器列表 // main实现在文件“php-5.6.26\sapi\cgi\cgi_main.c” int main(int argc, char *argv[]) { if ...
 - php-5.6.26源代码 - 扩展模块的加载、注册
		
// main实现在文件 php-5.6.26\sapi\cgi\cgi_main.c int main(int argc, char *argv[]) { .... cgi_sapi_module- ...
 - SQL SERVER 2008:内部查询处理器错误: 查询处理器在执行过程中遇到意外错误
		
今天一个同事突然告诉我,以前跑得很正常的一个SQL语句,执行时突然报如下错误: 消息1222,级别16,状态18,第1 行 已超过了锁请求超时时段. ...
 - css预处理器和后处理器
		
因为我是前端刚入门,昨天看了一个大神写的的初级前端需要掌握的知识,然后我就开始一一搜索,下面是我对css预处理器和后处理器的搜索结果,一是和大家分享下这方面的知识,另一方面方便自己以后翻阅.所以感兴趣 ...
 - 2018/1/21 Netty通过解码处理器和编码处理器来发送接收POJO,Zookeeper深入学习
		
package com.demo.netty; import org.junit.Before;import org.junit.Test; import io.netty.bootstrap.Boo ...
 - JS的一些总结(函数声明和函数表达式的区别,函数中的this指向的问题,函数不同的调用方式,函数也是对象,数组中的函数调用)
		
一.函数声明和函数表达式的区别: 函数声明放在if——else语句中,在IE8中会出现问题 函数表达式则不会 <script> if(true){ function f1(){ conso ...
 - DSP处理器和ARM处理器的区别以及各自应用在那些领域
		
由于工作经常接触到各种多核的处理器,如TI的达芬奇系列芯片拥有1个DSP核3个ARM核.那么DSP处理器和ARM处理器各自有什么区别,各自适合那些领域? DSP:digital signal proc ...
 - 二、冯式结构与哈佛结构及ARM处理器状态和处理器模式
		
2.1 冯式结构与哈佛结构 2.1.1 两者的区别 如果是独立的存储架构和信号通道那就是哈佛结构,否则就是冯式结构 结构与是否统一编址没有关系,也与 CPU 没有关系,与计算机的整体设计有关 CACH ...
 - php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器
		
# ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 实现在文件 php-\Zend\zend_vm_execute.h static int ZEND_FASTCALL ...
 
随机推荐
- wpf 查找父元素、子元素方法
			
1 /// <summary> 2 /// 根据类型查找子元素 3 /// </summary> 4 /// <typeparam name="T"& ...
 - sqlmap 命令笔记
			
基础命令 注入 MySQL mssql access 直接爆表.然后你懂的BT5里面的话前面就要加pythonsqlmap.py -u url --dbs //爆数据库sqlmap.py -u url ...
 - Redis入门--(二)Jedis的入门
			
Jedis相应的jar包 编写一段程序来测试一下 1.新建一个Java的项目 2.引入jedis开发包 3.将包添加到构建路径中 4.创建一个测试类 5.创建一个Jedis的单实例的测试
 - IE浏览器在线更新GitHub客户端
			
在IE中输入网址:http://github-windows.s3.amazonaws.com/GitHub.application
 - Errors while uninstall the reporting extensions
			
"Microsoft.crm.setup.Srsdataconnector UnregisterServer Action操作失败:Requested value 'geo' was not ...
 - System.Data.SqlClient.SqlException: 从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值
			
System.Data.SqlClient.SqlException: 从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值.解决办法是: 而这位大哥提出的解决办法 ...
 - class类重定义
			
C++项目中如果一个头文件被多个文件包含,#include"xxx.h",将可能导致头文件里面定义的类被多次编译,解决方法是加编译指示: #pragma once //告诉编译器只 ...
 - 如何把某个网站的SSL Server certificate链导入到ABAP Netweaver系统里
			
我们在用ABAP代码消费外网的url时会遇到一些异常,比如ICM_HTTP_SSL_PEER_CERT_UNTRUSTED,这是因为请求的url所在的网站的SSL Server certificate ...
 - IOS tableView的性能优化(缓存池)
			
使用缓存池(标识类型) 1.通过 一个 标识 去 缓存池 中寻找可循环得用的cell 2.如果缓存池找不到可循环得用的cell:创建一个新的cell(给cell贴个标识) 3.给cell设置新的数据 ...
 - linux下安装mysql并修改密码
			
删除已有mysql并重新安装mysql 查看是否已安装过mysql rpm -qa |grep -i mysql 2.移除安装的包 (在之前如果有启动mysql最好关掉服务) 使用rpm –ev 包名 ...