先声明一下,这种长系列的大块头博客只能保证尽可能的深入到每一行源码,有些代码我不乐意深究就写个注释说明一下作用。另外,由于本地整理的比较好,博客就随心写了。

  整个Compile过程目前只看到asmjs之前,简单的过了几遍,大部分方法没有点进去看,实在是太复杂了。上一篇的结尾指出了AST的入口,也就是命名空间parsing的一个公共方法,如下。

bool ParseProgram(ParseInfo* info, Isolate* isolate) {// .../*** 生成一个Parser实例* 调用内部方法启动转换*/Parser parser(info);FunctionLiteral* result = nullptr;/*** 转换AST后将结果赋值给ParseInfo的literal_*/result = parser.ParseProgram(isolate, info);info->set_literal(result);// ...return (result != nullptr);
}

  所需要关心的核心代码就是这些,非常简单,Parser对象的初始化属性非常多,这里就不列出来了。

  接下来进入第二个核心方法,即ParseProgram。

FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {// .../*** scanner_为Parser类的一个私有属性* 这里仅仅进行初始化*/scanner_.Initialize();FunctionLiteral* result = DoParseProgram(isolate, info);// ...return result;
}

  同样,所需要关心代码只有两行,其中第一步则是启动了scanner的初始化,第二步则是开始全面解析。

  Scanner包含scanner、scanner-character-strams两个部分,其中stream则是经过初步处理的源String,必须转换后才能进行解析。处理的过程在之前省略的代码中,这里稍微给出大概的转换流程。

bool ParseProgram(ParseInfo* info, Isolate* isolate) {// .../*** 1、info->script()返回的是字符串的描述信息 source是Local<String>类型的源字符串* 2、ScannerStream是scanner-character-streams头文件的类 内部方法均为静态类型 可以直接调用* 3、返回的具体类型根据String类型不同而不同 但是由于均继承于Utf16CharacterStream 所以直接用父类接*/Handle<String> source(String::cast(info->script()->source()), isolate);std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(isolate, source));info->set_character_stream(std::move(stream));// ...
}/*** 有四种特殊的String类型 分别new不同的子类* ScannerStream::For(isolate, data, 0, data->length());*/
Utf16CharacterStream* ScannerStream::For(Isolate* isolate, Handle<String> data, int start_pos, int end_pos) {size_t start_offset = 0;// ...if (data->IsSeqOneByteString()) {return new BufferedCharacterStream<OnHeapStream>(static_cast<size_t>(start_pos), Handle<SeqOneByteString>::cast(data),start_offset, static_cast<size_t>(end_pos));}
}

  常规的字符串一般都是OneByteString,这里就不细讲了。最后返回一个特殊Stream类,其属性记录字符串的长度、当前的解析进度、解析的开始与结束标记等等。

  将字符串转换后,就可以利用Scanner来进行逐步解析,在此之前,需要对Scanner类有一个简单的了解,如下。

/*** Scanner类* 跟Utf16CharacterStream一个文件*/
class V8_EXPORT_PRIVATE Scanner {public:// 返回next_的token类型Token::Value peek() const { return next().token; }// 返回current_的位置信息const Location& location() const { return current().location; }private:// 当前字符的Unicode编码 -1表示结尾(typedef int32_t uc32)
    uc32 c0_;TokenDesc* current_;    // desc for current token (as returned by Next())TokenDesc* next_;       // desc for next token (one token look-ahead)TokenDesc* next_next_;  // desc for the token after next (after PeakAhead())// 从Handle<String>转换后的类型 负责执行解析的实际类Utf16CharacterStream* const source_;
}

  选取了一些比较简单的属性和方法,Scanner内部有三个游标属性负责遍历字符串,分别是current_、next_、next_next_,字面意思理解就行了。source_则是之前说的转换Stream类,所有的解析实际上都是调用这个属性的方法。而两个结构体TokenDesc、Location也非常重要,一个负责词法描述,一个负责记录词法位置信息,如下。

/*** 词法结构体* 每一个TokenDesc代表单独一段词法*/
struct TokenDesc {/*** 词法所在位置* 该结构体比较简单 就不展开了 两个值代表起始、结束位置* 例如sample中 "'Hello' + ' World'" 'Hello'会被解析为TOKEN::STRING location为{0, 7}*/Location location = {0, 0};/*** 字符串词法相关*/LiteralBuffer literal_chars;LiteralBuffer raw_literal_chars;/*** 词法的枚举类型* 例如 '(' 是 TOKEN::LPAREN '===' 是 TOKEN::EQ_STRICT* 所有类型可见token.h*/Token::Value token = Token::UNINITIALIZED;MessageTemplate invalid_template_escape_message = MessageTemplate::kNone;Location invalid_template_escape_location;// 小整数uint32_t smi_value_ = 0;bool after_line_terminator = false;
}

  通过这个结构体和一些方法,就能完整的将源字符串逐步转换为抽象语法树。但是实际转换过程非常复杂,分支极多,后面再继续探究。

转载于:https://www.cnblogs.com/QH-Jimmy/p/11115324.html

深入V8引擎-AST(2)相关推荐

  1. javascript清除map所占内存_【原创.54期】 JavaScript的V8引擎初探

    本文主要就下面三块内容展开 栈和堆空间 垃圾回收 解释器和编译器 一.栈空间和堆空间 先回顾下基本知识 1.静态语言就是强类型?二者的关系 (1-1)静态语言, 使用前 要确定数据类型 (1-2)动态 ...

  2. 精读《V8 引擎 Lazy Parsing》

    1. 引言 本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧! 这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性 ...

  3. V8 引擎是如何工作的?

    作者 | Fundebug 最近,JavaScript生态系统又多了2个非常硬核的项目. 大神Fabrice Bellard发布了一个新的JS引擎QuickJS,可以将JavaScript源码转换为C ...

  4. V8引擎:编译器和解析器是如何执行一段javascript代码的?

    前言 前面我已经说完了js引擎是如何存储数据,如何回收垃圾的,但这只是基础罢了,并不是v8引擎的最主要任务,接下来我要讲v8引擎的核心:如何执行js代码,为什么要学习这些东西呢? 前端工具和框架的自身 ...

  5. Google v8引擎(一)执行流程

    1. 什么是V8 V8 是 JavaScript 虚拟机的一种.我们可以简单地把 JavaScript 虚拟机理解成是一个翻译程序,将人类能够理解的编程语言 JavaScript,翻译成机器能够理解的 ...

  6. Chrome V8引擎介绍

    0.v8引擎出现的原因 这里先说一下什么是编译型语言和解释性语言: 编译型语言: 在程序执行之前必须进行专门的编译过程,有如下特点: 只须编译一次就可以把源代码编译成机器语言,后面的执行无须重新编译, ...

  7. V8引擎解析JavaScript原理

    为什么需要JavaScript引擎呢? 高级的编程语言都是需要转成最终的机器指令执行的 我们编写的JavaScript无论交给浏览器和Node执行,最后都是被CPU执行的 CPU只认识自己的指令集,实 ...

  8. 浏览器执行原理、V8引擎

    前言 对一个前端而言,思考JS在浏览器中如何被执行非常重要.笔者是通过codewhy的课程进行学习的,首先感谢codewhy. 浏览器的功能 浏览器的主要功能就是向服务器发出请求,在浏览器窗口中展示您 ...

  9. 浏览器工作原理和V8引擎

    一.浏览器的工作原理 比如在浏览器中输入网址,然后dns进行解析,解析出的就是服务器的一个ip地址.服务器返回一个html文件,浏览器内核在解析html文件的过程中,遇到link标签和script标签 ...

最新文章

  1. VS2005设计智能客户端(二)使用clickonce部署应用程序
  2. 复习PHP-语言参考-类型
  3. 2.API的调用过程(3环进0环)
  4. 指针是c语言的灵魂,C语言之灵魂 指针学习
  5. python求pai的近似值_PR Sampling Ⅰ: 蒙特卡洛采样、重要性采样及python实现
  6. SSM整合(配置文件)
  7. 计算机描绘的基因结构图,利用IBS软件画基因mRNA的结构图
  8. 在 ML2 中配置 Vlan Network- 每天5分钟玩转 OpenStack(93)
  9. linux ns级定时器_linux学习13,一文弄懂内核的“绝对公平调度”机制是如何设计的...
  10. 可变参数函数——以printf为例子
  11. 14. PHP 数组排序
  12. file is not a zip file_如何使用JavaScript解压压缩后的zip文件
  13. nacos启动报错 db.num is null【已解决】
  14. 计算机网络存在的漏洞,计算机网络安全漏洞及防范措施
  15. 大数运算(加、减、乘、除)
  16. 用Vue3+element-plus+express写个简单的后台管理框架
  17. 如何在腾讯云服务器部署web项目
  18. SuperMap iDesktop许可模块介绍
  19. 乌镇互联网大会官方首次使用AI同传,搜狗为雷军提供机器翻译
  20. MOS管驱动电路设计,如何让MOS管快速开启和关闭?

热门文章

  1. 交互式电子杂志_交互环境中电子杂志的生存发展探析
  2. 从 Demo 中学习 Solidity
  3. 2018年长沙理工大学第十三届程序设计竞赛 G-逃离迷宫
  4. 不认识java代码_程序员进阶:优雅的代码对于一个架构师的重要性
  5. 怎么查找那台电脑中了ARP病毒
  6. jsch 移动服务器上文件,jsch上传文件到服务器
  7. Linux man命令后的参数释义
  8. springboot拦截请求路径_SpringBoot整合Ant Design Pro进行部署
  9. linux+proc+原理,Linux内核中的Proc文件系统(一)
  10. LIBCLNTSH.SO: WRONG ELF CLASS: ELFCLASS32错误一例