php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器
# ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 实现在文件 php-5.6.\Zend\zend_vm_execute.h
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_op_array *new_op_array=NULL; zval *inc_filename;
zval *tmp_inc_filename = NULL;
zend_bool failure_retval=; SAVE_OPLINE();
inc_filename = opline->op1.zv; // 要include的文件 if (inc_filename->type!=IS_STRING) {
MAKE_STD_ZVAL(tmp_inc_filename);
ZVAL_COPY_VALUE(tmp_inc_filename, inc_filename);
zval_copy_ctor(tmp_inc_filename);
convert_to_string(tmp_inc_filename);
inc_filename = tmp_inc_filename;
} if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
}
} else {
switch (opline->extended_value) {
// include_once 和 require_once
case ZEND_INCLUDE_ONCE: // 只 included 一次
case ZEND_REQUIRE_ONCE: {
zend_file_handle file_handle;
char *resolved_path; resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC); // 解析文件路径
if (resolved_path) {
failure_retval = zend_hash_exists(&EG(included_files), resolved_path, strlen(resolved_path)+); // 是否已经 included
} else {
resolved_path = Z_STRVAL_P(inc_filename);
} if (failure_retval) { // 如已经 included
/* do nothing, file already included */
} else if (SUCCESS == zend_stream_open(resolved_path, &file_handle TSRMLS_CC)) { // 尝试打开文件流 if (!file_handle.opened_path) {
file_handle.opened_path = estrdup(resolved_path);
} if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+)==SUCCESS) { // 添加到已经 included
// zend_compile_file == compile_file
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); // 编译文件,获取新的opcode列表
{
# compile_file 实现在文件 php-5.6.\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=;
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, ); 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=;
} else {
// 扫描后、初始化 op_array
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); // 1、初始化一些数据、申请空间 2、迭代调用所有 zend_extensions 扩展的 op_array_ctor 函数
CG(in_compilation) = ; // 是否处于汇编状态
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); // 开始解析 zendparse == phpparse == yyparse
zend_do_return(&retval_znode, TSRMLS_CC); // 返回
CG(in_compilation) = original_in_compilation; // 还原现场
if (compiler_result != ) { /* parser error */
zend_bailout(); // !!! 抛出异常
}
compilation_successful=; // 汇编成功
} if (retval) {
CG(active_op_array) = original_active_op_array; // 还原原来 op_code 现场(还原现场)
if (compilation_successful) { // 汇编成功
pass_two(op_array TSRMLS_CC); // !!!! 给每个op_code注册“op_code处理器”
zend_release_labels( TSRMLS_CC);
} else {
efree(op_array);
retval = NULL;
}
}
zend_restore_lexical_state(&original_lex_state TSRMLS_CC); // 还原原来词法解析器的状态(还原现场)
return retval;
} }
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
zend_file_handle_dtor(&file_handle TSRMLS_CC);
failure_retval=;
}
} else {
if (opline->extended_value == ZEND_INCLUDE_ONCE) { // include_once 执行失败,消息通知
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else { // require_once 执行失败,消息通知
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
}
}
if (resolved_path != Z_STRVAL_P(inc_filename)) {
efree(resolved_path);
}
}
break;
// include 和 require
case ZEND_INCLUDE: // 可以 included 多次
case ZEND_REQUIRE:
new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC); // 编译文件,获取新的opcode列表
break;
// eval
case ZEND_EVAL: { // 使用的是 eval 指令
char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); new_op_array = zend_compile_string(inc_filename, eval_desc TSRMLS_CC); // 编译后,获取新的opcode列表
efree(eval_desc);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
if (tmp_inc_filename) {
zval_ptr_dtor(&tmp_inc_filename);
} if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
} else if (EXPECTED(new_op_array != NULL)) {
EX(original_return_value) = EG(return_value_ptr_ptr);
EG(active_op_array) = new_op_array;
if (RETURN_VALUE_USED(opline)) {
EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
EG(return_value_ptr_ptr) = EX_T(opline->result.var).var.ptr_ptr;
} else {
EG(return_value_ptr_ptr) = NULL;
} EX(function_state).function = (zend_function *) new_op_array;
EX(object) = NULL; if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
} if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array TSRMLS_CC); // 执行opcode列表
{
# zend_execute 实现在文件 php-5.6.\Zend\zend_vm_execute.h
ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC)
{
if (EG(exception)) {
return;
}
zend_execute_ex(i_create_execute_data_from_op_array(op_array, TSRMLS_CC) TSRMLS_CC); // zend_execute_ex = execute_ex
}
}
} EX(function_state).function = (zend_function *) EX(op_array); EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
} } else if (RETURN_VALUE_USED(opline)) {
zval *retval; ALLOC_ZVAL(retval);
ZVAL_BOOL(retval, failure_retval);
INIT_PZVAL(retval);
EX_T(opline->result.var).var.ptr = retval;
}
ZEND_VM_NEXT_OPCODE();
}
php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器的更多相关文章
- php学习笔记6--php中的文件包含 include,require,include_once,require_once
php中的文件包含 include,require,include_once,require_once 文件包含:是指将一个文件的内容包含进另外一个文件,有利于代码的复用等.php中文件包含指令有4个 ...
- 关于require,require_once,include和include_once的区别
一.定义 require,require_once,include,include_once都属于PHP的关键字,也就是说它们实际都是PHP的语句,而不是函数,类似于print,echo一样,也是PH ...
- include require include_once require_once
include 使用方法: include "test.php"; 一般是放在流程控制的处理部分中使用,将文件内容引入.PHP程序在遇到include语句时,才将它读进来,这种方式 ...
- php include,require,include_once,require_once 的区别
include(),require(),include_once(),require_once()作用都是包含并运行指定文件,但是使用场景又有很大区别. 1.include()和require()的区 ...
- 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 *fi ...
- php-7.2.3源代码和php-5.6.26源代码摘录,对比 “汇编php文件”和“执行opcode代码”
php-7.2.3 在“汇编php文件”和“执行opcode代码”上做了大量改变php-5.6.26 没见到支持抽象语法树的相关代码,php-7.2.3 见到支持抽象语法树的相关代码php-5.6.2 ...
- php-5.6.26源代码 - opcode处理器,“函数调用opcode”处理器,如何调用扩展模块的函数
// opcode处理器 --- ZEND_DO_FCALL_SPEC_CONST_HANDLER实现在 php-5.6.26\Zend\zend_vm_execute.h static int ZE ...
- php-5.6.26源代码 - 扩展模块的种类,扩展模块的执行埋点
模块种类(两种) 类型一:zend的模块:(类似zend_extension=test.so) 识别方法: php.ini中以zend_extension开头的配置,如zend_extension=t ...
- php-5.6.26源代码 - opcode处理器的注入
.初始化 opcode处理器列表 // main实现在文件“php-5.6.26\sapi\cgi\cgi_main.c” int main(int argc, char *argv[]) { if ...
随机推荐
- 刚在虚拟机上装的Linux系统,ifconfig后IP地址怎么成了127.0.0.1了
之前在虚拟机上装了Linux系统,用了一段时间后想删除了重新装一下,然而装完以后ifconfig后,出现的是 [root@localhost ~]# ifconfig lo Link encap:Lo ...
- visual studio 调试 不进断点 断点失效 提示当前不会命中该断点等问题解决
1.首先看一下 当前调试模式是否为debug 2. 点击[调试]>[选项和设置] 将[要求源文件与原始文件完全匹配]勾选掉 3.点击调试的最后一个选项 点击[web] 将调试器内部勾选上需要测 ...
- PHP Swoole 基于纯真IP库根据IP匹配城市
把纯真IP库读到内存,纯真IP库本来就是有序的,然后每次请求二分查找就行,44WIP查找十几次就搞定了 dispatch_mode最好写3,不然做服务的时候,会导致进程任务分配不均匀. max_req ...
- 面条代码 vs. 馄沌代码
转载自:https://blog.csdn.net/godsme_yuan/article/details/6594013
- bzoj5029 贴小广告
Description 现在有一堵墙,墙上分为若干个单元.接下来会来n个人在墙上贴小广告.每次每个人选择墙上连续一段的单元贴上自己公司与众不同的小广告.因为小广告可能会出现被覆盖的情况,由于公司之间存 ...
- 泛型约束-swift
1.泛型定义本体有参量类型约束: 2.泛型扩展对参量类型约束: 3.函数参量约束: 泛型类型的访问控制: 1.与类型无关的通用函数,泛型的任何实例都可以访问: 2.与类型有关的函数(通过扩展约束实现) ...
- python:协程
1,如何实现在两个函数之间的切换? def func1(): print(l) yield print(3) yield def func2(): g =func1() next(g) print(2 ...
- POJ 3694 无向图的桥
Network Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10404 Accepted: 3873 Descript ...
- CF549BLooksery Party题解
题目描述 The Looksery company, consisting of nn staff members, is planning another big party. Every empl ...
- XCode项目配置可访问 非 https 接口的方法
打开项目的info.plist文件,右键- open as sourceCode .在代码中添加: <key>NSAppTransportSecurity</key> < ...