当前位置: 首页 > news >正文

[前端] V8引擎编译原理

文章目录

      • 1.什么是V8
        • 1.1 扫描器Scanner
        • 1.2 解析器parser
        • 1.3 预解析PreParser
        • 1.4 解释器Ignition
        • 1.5 编译器TurboFan

1.什么是V8

V8是谷歌的开源高性能JavaScript和WebAssembly引擎,用C++编写。它被用于Chrome和Node.js等。它实现ECMAScript和WebAssembly,并在Windows 7或更高版本、macOS 10.12+以及使用x64、IA-32、ARM或MIPS处理器的Linux系统上运行。V8可以独立运行,也可以嵌入到任何C++应用程序中。

在这里插入图片描述

  • 扫描器Scanner

  • 解析器Parser

  • 预解析PreParser

  • 解释器Ignition

  • 编译器TurboFan

在这里插入图片描述

1.1 扫描器Scanner

Blink(谷歌浏览器的渲染引擎,基于webkit分支开发)主要负责HTML DOM CSS 渲染,嵌入V8引擎,执行js,计算样式和布局,嵌入合成器,绘制图形。

Blink 拿到html代码分析,找到script代码交给V8引擎解析,注意Blink是通过流的形式传给V8的。

通过以流的形式传输数据,Blink可以逐步接收和处理来自网络的字节流,并在需要时将相应的数据传递给V8引擎执行。这种流式处理方式使得浏览器可以在数据到达的同时并行处理不同的任务,提高了页面的加载速度和用户体验

Scanner(扫描器)首先会进行词法分析:

V8_INLINE Token::Value Scanner::ScanSingleToken() {Token::Value token;do {next().location.beg_pos = source_pos();if (V8_LIKELY(static_cast<unsigned>(c0_) <= kMaxAscii)) {token = one_char_tokens[c0_];switch (token) {case Token::LPAREN:case Token::RPAREN:case Token::LBRACE:case Token::RBRACE:case Token::LBRACK:case Token::RBRACK:case Token::COLON:case Token::SEMICOLON:case Token::COMMA:case Token::BIT_NOT:case Token::ILLEGAL:// One character tokens.return Select(token);case Token::CONDITIONAL:// ? ?. ?? ??=Advance();if (c0_ == '.') {Advance();if (!IsDecimalDigit(c0_)) return Token::QUESTION_PERIOD;PushBack('.');} else if (c0_ == '?') {return Select('=', Token::ASSIGN_NULLISH, Token::NULLISH);}return Token::CONDITIONAL;case Token::STRING:return ScanString();case Token::LT:// < <= << <<= <!--Advance();if (c0_ == '=') return Select(Token::LTE);if (c0_ == '<') return Select('=', Token::ASSIGN_SHL, Token::SHL);if (c0_ == '!') {token = ScanHtmlComment();continue;}return Token::LT;case Token::GT:// > >= >> >>= >>> >>>=Advance();if (c0_ == '=') return Select(Token::GTE);if (c0_ == '>') {// >> >>= >>> >>>=Advance();if (c0_ == '=') return Select(Token::ASSIGN_SAR);if (c0_ == '>') return Select('=', Token::ASSIGN_SHR, Token::SHR);return Token::SAR;}return Token::GT;case Token::ASSIGN:// = == === =>Advance();if (c0_ == '=') return Select('=', Token::EQ_STRICT, Token::EQ);if (c0_ == '>') return Select(Token::ARROW);return Token::ASSIGN;case Token::NOT:// ! != !==Advance();if (c0_ == '=') return Select('=', Token::NE_STRICT, Token::NE);return Token::NOT;case Token::ADD:// + ++ +=Advance();if (c0_ == '+') return Select(Token::INC);if (c0_ == '=') return Select(Token::ASSIGN_ADD);return Token::ADD;case Token::SUB:// - -- --> -=Advance();if (c0_ == '-') {Advance();if (c0_ == '>' && next().after_line_terminator) {// For compatibility with SpiderMonkey, we skip lines that// start with an HTML comment end '-->'.token = SkipSingleHTMLComment();continue;}return Token::DEC;}if (c0_ == '=') return Select(Token::ASSIGN_SUB);return Token::SUB;case Token::MUL:// * *=Advance();if (c0_ == '*') return Select('=', Token::ASSIGN_EXP, Token::EXP);if (c0_ == '=') return Select(Token::ASSIGN_MUL);return Token::MUL;case Token::MOD:// % %=return Select('=', Token::ASSIGN_MOD, Token::MOD);case Token::DIV:// /  // /* /=Advance();if (c0_ == '/') {uc32 c = Peek();if (c == '#' || c == '@') {Advance();Advance();token = SkipSourceURLComment();continue;}token = SkipSingleLineComment();continue;}if (c0_ == '*') {token = SkipMultiLineComment();continue;}if (c0_ == '=') return Select(Token::ASSIGN_DIV);return Token::DIV;case Token::BIT_AND:// & && &= &&=Advance();if (c0_ == '&') return Select('=', Token::ASSIGN_AND, Token::AND);if (c0_ == '=') return Select(Token::ASSIGN_BIT_AND);return Token::BIT_AND;case Token::BIT_OR:// | || |= ||=Advance();if (c0_ == '|') return Select('=', Token::ASSIGN_OR, Token::OR);if (c0_ == '=') return Select(Token::ASSIGN_BIT_OR);return Token::BIT_OR;case Token::BIT_XOR:// ^ ^=return Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);case Token::PERIOD:// . NumberAdvance();if (IsDecimalDigit(c0_)) return ScanNumber(true);if (c0_ == '.') {if (Peek() == '.') {Advance();Advance();return Token::ELLIPSIS;}}return Token::PERIOD;case Token::TEMPLATE_SPAN:Advance();return ScanTemplateSpan();case Token::PRIVATE_NAME:if (source_pos() == 0 && Peek() == '!') {token = SkipSingleLineComment();continue;}return ScanPrivateName();case Token::WHITESPACE:token = SkipWhiteSpace();continue;case Token::NUMBER:return ScanNumber(false);case Token::IDENTIFIER:return ScanIdentifierOrKeyword();default:UNREACHABLE();}}if (IsIdentifierStart(c0_) ||(CombineSurrogatePair() && IsIdentifierStart(c0_))) {return ScanIdentifierOrKeyword();}if (c0_ == kEndOfInput) {return source_->has_parser_error() ? Token::ILLEGAL : Token::EOS;}token = SkipWhiteSpace();// Continue scanning for tokens as long as we're just skipping whitespace.} while (token == Token::WHITESPACE);return token;
}
  1. 首先获取当前字符c0_的值,并设置token为初始值。
  2. 判断c0_是否是ASCII字符,如果是,则根据c0_的值来确定token的类型,并返回相应的Token。
  3. 对于一些特殊情况,如条件运算符、字符串、小于号、大于号、等号、逻辑非、加号、减号、乘号、取模、除号、按位与、按位或等,根据当前字符和后续字符的组合来确定token的类型,并返回相应的Token。
  4. 如果c0_不是ASCII字符,或者不满足以上条件,则判断c0_是否是标识符的起始字符,如果是,则调用ScanIdentifierOrKeyword()函数来获取标识符或关键字的Token。
  5. 如果c0_是HTML注释的结束符’-',则调用SkipSingleHTMLComment()函数来跳过整个HTML注释。
  6. 如果扫描到文件末尾,则返回Token::EOS。
  7. 否则,如果遇到空白字符,则调用SkipWhiteSpace()函数来跳过连续的空白字符,并继续扫描下一个Token。
  8. 返回扫描到的Token。

js代码就会变成tokens 接下来进行语法分析。

1.2 解析器parser

parser 的作用就是将 tokens 转化为 AST 抽象语法树。

Program 
└── VariableDeclaration 
├── Identifier (name: "2") 
└── StringLiteral (value: "'1'")
1.3 预解析PreParser

作用是在 JavaScript 代码执行之前对代码进行可选的预处理。预解析器的存在是为了提高代码的执行效率。

V8 引擎采用了延迟解析(Lazy Parsing)的策略,它的原理是只解析当前需要的内容,而把其他内容推迟到函数被调用时再进行解析。这样可以减少不必要的解析工作,提高网页的运行效率。

例如,在一个函数 outer 内部定义了另一个函数 inner,那么 inner 函数就会进行预解析。这意味着在函数 outer 被调用之前,只会对 outer 函数的内容进行解析,而对于 inner 函数的解析会在 outer 函数调用到 inner 函数时才进行。

通过延迟解析的方式,V8 引擎可以避免解析和编译未被执行的函数,节省了不必要的时间和资源开销,提高了 JavaScript 代码的执行效率。这种优化策略在大型复杂的 JavaScript 应用程序中尤为重要,可以帮助提升整体性能和用户体验。

1.4 解释器Ignition

作用主要就是将AST 抽象语法树 转化成 字节码(bytecode)

  1. 跨平台执行:不同的硬件架构和操作系统有不同的机器码格式。通过将代码转换为字节码,可以使得同一份字节码在不同的平台上都能执行,实现跨平台的能力。
  2. 快速启动和解析:将代码转换为字节码可以比直接生成机器码更快速地进行启动和解析。字节码通常具有更简单的格式和结构,可以更快地被引擎加载和解释执行。
  3. 动态优化:现代的JavaScript引擎通常具有即时编译(JIT)功能,可以将热点代码编译成高效的机器码。通过首先将代码转换为字节码,引擎可以更好地进行动态优化和编译,根据实际执行情况生成最优的机器码。这种方式可以在运行时根据代码的实际执行情况进行优化,而不需要提前生成固定的机器码。
  4. 代码安全性:字节码作为中间表示形式,可以提供一定的代码安全性。字节码相对于源代码或机器码来说更难以理解和修改,可以提供一定程度的代码保护。
Program 
└── VariableDeclaration 
├── Identifier (name: "2") 
└── StringLiteral (value: "'1'")
0001: PushString "'1'" 
0002: StoreVar "2"

将字符串字面量 “‘1’” 推入堆栈(栈帧)。在这个例子中,它将字符串 “‘1’” 推入堆栈。

将栈顶的值存储到变量 “2” 中。在这个例子中,它将栈顶的字符串值存储到变量 “2”。

1.5 编译器TurboFan

编译器就是将字节码也可以叫中间代码 最后 转换成 机器码 能让我们的CPU识别。

CPU有不同的架构 ARM X86。

X86机器码

MOV EAX, '1' ; 将字符串 '1' 存储到寄存器 
EAX MOV [2], EAX ; 将寄存器 EAX 的值存储到变量 2 对应的内存地址中

ARM机器码。

LDR R0, ='1' ; 将字符串 '1' 的地址加载到寄存器
R0 STR R0, [2] ; 将寄存器 R0 中的值存储到变量 2 对应的内存地址中

相关文章:

[前端] V8引擎编译原理

文章目录 1.什么是V81.1 扫描器Scanner1.2 解析器parser1.3 预解析PreParser1.4 解释器Ignition1.5 编译器TurboFan 1.什么是V8 V8是谷歌的开源高性能JavaScript和WebAssembly引擎&#xff0c;用C编写。它被用于Chrome和Node.js等。它实现ECMAScript和WebAssembly&#xff0c;…...

使用Pytorch实现linear_regression

使用Pytorch实现线性回归 # import necessary packages import torch import torch.nn as nn import numpy as np import matplotlib.pyplot as plt# Set necessary Hyper-parameters. input_size 1 output_size 1 num_epochs 60 learning_rate 0.001# Define a Toy datas…...

网络安全等级保护收费标准?

不同省份价格会略有不同&#xff0c;二级等保一般不低于5万元;三级等保不低于9万元&#xff0c;个别省份也可能7万也能办理&#xff0c;根据企业实际情况和省市选定的代理机构确定。 等级保护二级? 第二级等保是指信息系统受到破坏后&#xff0c;会对公民、法人和其他组织的合…...

16 Go的反射

概述 在上一节的内容中&#xff0c;我们介绍了Go的并发&#xff0c;包括&#xff1a;Goroutines、Channels、WaitGroups、Mutex、Select等。在本节中&#xff0c;我们将介绍Go的反射。Go语言中的反射是一种在运行时检查类型信息并操作对象的能力&#xff0c;通过反射&#xff0…...

SQL Server 百万数据查询优化技巧三十则

点击上方蓝字关注我 互联网时代的进程越走越深&#xff0c;使用MySQL的人也越来越多&#xff0c;关于MySQL的数据库优化指南很多&#xff0c;而关于SQL SERVER的T-SQL优化指南看上去比较少&#xff0c;近期有学习SQLSERVER的同学问到SQL SERVER数据库有哪些优化建议&#xff1f…...

list转map(根据某个或多个属性分组)

需要将对应的list换成本地list&#xff0c;和对象换成本地对象 1、List转Map<String,List> // 根据一个字段分组 Map<String, List<String>> map objectLists.stream().collect(Collectors.groupingBy(Object::getName,Collectors.mapping(Object::getId, …...

常见树种(贵州省):012茶、花椒、八角、肉桂、杜仲、厚朴、枸杞、忍冬

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、茶 灌…...

千云物流 - 使用k8s负载均衡openelb

openelb的介绍 具体根据官方文档进行安装官方文档,这里作为测试环境的安装使用. OpenELB 是一个开源的云原生负载均衡器实现,可以在基于裸金属服务器、边缘以及虚拟化的 Kubernetes 环境中使用 LoadBalancer 类型的 Service 对外暴露服务。OpenELB 项目最初由 KubeSphere 社区…...

C语言之字符串函数

C语言之字符串函数 文章目录 C语言之字符串函数1. strlen的使用和模拟实现1.1 strlen的使用1.2 strlen的模拟实现 2. strcpy的使用和模拟实现2.1 strcpy的使用2.2 strncpy的使用2.3 strcpy的模拟实现 3. strcat的使用和模拟实现3.1 strcat的使用3.2 strncat3.3 strcat的模拟实现…...

python中一个文件(A.py)怎么调用另一个文件(B.py)中定义的类AA详解和示例

本文主要讲解python文件中怎么调用另外一个py文件中定义的类&#xff0c;将通过代码和示例解读&#xff0c;帮助大家理解和使用。 目录 代码B.pyA.py 调用过程 代码 B.py 如在文件B.py,定义了类别Bottleneck&#xff0c;其包含卷积层、正则化和激活函数层&#xff0c;主要对…...

spark shuffle 剖析

ShuffleExchangeExec private lazy val writeMetrics SQLShuffleWriteMetricsReporter.createShuffleWriteMetrics(sparkContext)private[sql] lazy val readMetrics SQLShuffleReadMetricsReporter.createShuffleReadMetrics(sparkContext)用在了两个地方&#xff0c;承接的是…...

C语言之认识柔性数组(flexible array)

在学习之前&#xff0c;我们首先要了解柔性数组是放在结构体当中的&#xff0c;知道这一点&#xff0c;我们就开始今天的学习吧&#xff01; 1.柔性数组的声明 在C99中&#xff0c;结构中的最后一个元素允许是未知大小的数组&#xff0c;这就叫做柔性数组成员 这里的结构是结构…...

【MATLAB基础绘图第17棒】绘制玫瑰图

MATLAB绘制玫瑰图 玫瑰图&#xff08;Nightingale Rose Chart&#xff09;风玫瑰图&#xff08;WindRose&#xff09;准备工作&#xff1a;WindRose工具包下载案例案例1&#xff1a;基础绘图 参考 玫瑰图&#xff08;Nightingale Rose Chart&#xff09; 玫瑰图&#xff08;Ni…...

Qt 基于海康相机的视频绘图

需求 在视频窗口上进行绘图&#xff0c;包括圆&#xff0c;矩形&#xff0c;扇形等 效果&#xff1a; 思路&#xff1a; 自己取图然后转成QImage &#xff0c;再向QWidget 进行渲染&#xff0c;根据以往的经验&#xff0c;无法达到很高的帧率。因此决定使用相机SDK自带的渲染…...

FlinkCDC实现主数据与各业务系统数据的一致性(瀚高、TIDB)

文章末尾附有flinkcdc对应瀚高数据库flink-cdc-connector代码下载地址 1、业务需求 目前项目有主数据系统和N个业务系统,为保障“一数一源”,各业务系统表涉及到主数据系统的字段都需用主数据系统表中的字段进行实时覆盖,这里以某个业务系统的一张表举例说明:业务系统表Ta…...

JSP:Servlet

Servlet处理请求过程 B/S请求响应模型 Servlet介绍 JSP是Servlet的一个成功应用&#xff0c;其子集。 JSP页面负责前台用户界面&#xff0c;JavaBean负责后台数据处理&#xff0c;一般的Web应用采用JSPJavaBean就可以设计得很好了。 JSPServletJavaBean是MVC Servlet的核心…...

react中的state

没想到hooks中也有state这一说法 看下面的两个案例 1、无state变化不会执行父子函数 2、有state更改执行父子函数...

VR全景航拍要注意什么,航拍图片如何处理

引言: VR全景航拍技术是当前摄影和航拍领域的新潮流。它采用虚拟现实技术&#xff0c;通过360度全景镜头捕捉画面&#xff0c;可以为观众提供身临其境的视觉体验。在宣传展示中&#xff0c;利用VR全景航拍技术可以为品牌宣传带来更加生动、震撼的视觉效果。 一、航拍注意事项 …...

Spark---集群搭建

Standalone集群搭建与Spark on Yarn配置 1、Standalone Standalone集群是Spark自带的资源调度框架&#xff0c;支持分布式搭建&#xff0c;这里建议搭建Standalone节点数为3台&#xff0c;1台master节点&#xff0c;2台worker节点&#xff0c;这虚拟机中每台节点的内存至少给…...

Linux上通过SSL/TLS和start tls连接到LDAP服务器

一&#xff0c;大致流程。 1.首先在Linux上搭建一个LDAP服务器 2.在LDAP服务器上安装CA证书&#xff0c;服务器证书&#xff0c;因为SSL/TLS&#xff0c;start tls都属于机密通信&#xff0c;需要客户端和服务器都存在一个相同的证书认证双方的身份。3.安装phpldapadmin工具&am…...

Semtech AirLink 5G RedCap路由器工业应用解析

1. Semtech AirLink RX400/EX400 5G RedCap路由器深度解析工业物联网领域最近迎来了一对重量级选手——Semtech最新发布的AirLink RX400和EX400 5G RedCap路由器。作为长期跟踪工业通信设备的技术从业者&#xff0c;我第一时间研究了这两款产品的技术细节和应用场景。不同于市面…...

Reset Windows Update Tool:你的Windows更新问题终极修复方案

Reset Windows Update Tool&#xff1a;你的Windows更新问题终极修复方案 【免费下载链接】Reset-Windows-Update-Tool Troubleshooting Tool with Windows Updates (Developed in Dev-C). 项目地址: https://gitcode.com/gh_mirrors/re/Reset-Windows-Update-Tool 你是…...

手把手教你用AURIX TC397和SafeTpack实现E-GAS三层监控(附代码示例)

手把手教你用AURIX TC397和SafeTpack实现E-GAS三层监控&#xff08;附代码示例&#xff09; 在汽车电子开发领域&#xff0c;功能安全始终是重中之重。面对日益复杂的电控系统&#xff0c;如何确保关键功能在硬件故障或软件异常时仍能安全运行&#xff1f;E-GAS三层监控架构提供…...

ValueCAN3硬件接线图详解:手把手教你连接车载CAN网络(附引脚图)

ValueCAN3硬件接线图详解&#xff1a;手把手教你连接车载CAN网络&#xff08;附引脚图&#xff09; 第一次拿到ValueCAN3设备时&#xff0c;许多工程师会被金属外壳上那排神秘的引脚难住。这些直径不到2毫米的金属触点&#xff0c;却是连接整车CAN网络的神经末梢。本文将用实验…...

别再只用ACC了!用Python的sklearn计算NMI评估你的聚类模型(附完整代码)

超越准确率&#xff1a;用Python实现NMI评估聚类模型的实战指南 当我们在客户分群项目中第一次发现K-means算法的准确率(ACC)高达90%时&#xff0c;整个团队都欢呼雀跃——直到我们意识到这只是因为标签排列巧合造成的假象。这个教训让我深刻认识到&#xff0c;在聚类评估中&am…...

PowerPoint 练习题(2)

1&#xff0e;将第2张幻灯片的一级文本的项目符号均设置为“✓”&#xff0e;2&#xff0e;将第3张幻灯片的图片超级链接到第2张幻灯片。3&#xff0e;将第1张幻灯片的版式设置为“标题幻灯片”。4&#xff0e;在第4张幻灯片的日期区中插入自动更新的日期和时间&#xff08;采用…...

XUnity自动翻译器:打破语言壁垒,让Unity游戏无障碍畅玩

XUnity自动翻译器&#xff1a;打破语言壁垒&#xff0c;让Unity游戏无障碍畅玩 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 你是否曾因语言障碍而错过心仪的游戏&#xff1f;面对精美的日式RPG、精彩的…...

如何用PythonDataScienceHandbook掌握自监督学习:无标签数据训练的终极指南

如何用PythonDataScienceHandbook掌握自监督学习&#xff1a;无标签数据训练的终极指南 【免费下载链接】PythonDataScienceHandbook Python Data Science Handbook: full text in Jupyter Notebooks 项目地址: https://gitcode.com/gh_mirrors/py/PythonDataScienceHandbook…...

深度学习中批归一化技术的原理与实践

1. 深度神经网络加速训练的核心挑战在训练深度神经网络时&#xff0c;我们经常会遇到一个令人头疼的现象&#xff1a;随着网络层数的增加&#xff0c;训练过程变得越来越不稳定。这种现象在2015年之前尤为明显&#xff0c;当时的研究者们发现&#xff0c;当网络深度超过某个临界…...

Unsloth Sglang Vllm核心区别和使用场景

(一)核心总结 Unsloth:主打「微调/训练加速」,推理只是附带 vLLM:通用推理引擎,主打「高吞吐、高显存利用率」 SGLang:推理引擎,主打「前缀复用、结构化输出、低延迟」 下面从定位、核心技术、性能、适用场景四个维度拆开讲。 一、定位 1. Unsloth 定位:微调优先、推…...