js图片转二进制流_V8是如何执行一段JS代码的?

  • 汇编器 编译器 解释器
  • 解释执行和解释执行
  • 什么是V8?
  • V8执行Js代码的过程

汇编器 编译器 解释器

众所周知,计算机只能理解机器语言,而我们平时编程用的通常是高级语言,所以源代码通常都要经过层层转换最终变成机器语言运行。

9011e14546fa533794726cbeb8076b4e.png

早期只有汇编语言没有高级语言,不同的设备有一套自己的对应不同机器语言指令集的汇编语言,也就是说,汇编语言不能在不同CPU架构(intel ARM MIPS)之间移植。同一个软件为了让不同类型的处理器架构都能兼容要写好几套代码,实在太不方便了,我们需要一种屏蔽了计算机架构细节的语言,能适应多种不同CPU架构的语言,专心处理业务逻辑,所以后来发展出了跨平台的高级语言。诸如 C C++ Java JavaScript。

bf11282bdaae3900a23ffa2633ba93c1.png
汇编时代
73aff3009ee1dc9c5bf80f754d9f2072.png
高级语言时代

随着计算机发展,编译器也越来越复杂,发展了很多分支,像是本地编译器、交叉编译器等,这里就不多说了。

那么源码一定要经过编译才能运行吗?

解释器的出现给出了一种不用编译就能运行的能力

651586c58fc5edda70f62355af370d7e.png
7673bef92290ad1e487757802b8ec58e.png

先静态编译到可执行的文件,然后运行可执行的文件来执行程序,而解释器提供了一种边编译边运行的动态运行方法,而也正因为通过解释器运行的代码是边编译边运行的,所以运行的速度比静态编译的那种慢很多。

所以程序运行的方式分为编译执行和解释执行。

解释执行和解释执行

解释执行:需要先将输入的源代码通过解析器编译成中间代码,之后直接使用解释器解释执行中间代码,然后直接输出结果。

d2147ae888cda122b319950c8f4a21f8.png

第二种是编译执行。采用这种方式时,也需要先将源代码转换为中间代码,然后我们的编译器再将中间代码编译成机器代码。通常编译成的机器代码是以二进制文件形式存储的,需要执行这段程序的时候直接执行二进制文件就可以了。还可以使用虚拟机将编译后的机器代码保存在内存中,然后直接执行内存中的二进制代码。

6e3c991c1687a3b83c94df15e086865b.png

什么是V8

JavaScript引擎是执行JavaScript代码的程序或解释器。javaScript引擎可以实现为标准解释器或即时编译器,它以某种形式将JavaScript编译为字节码。

那么除了v8引擎,你还知道那些js引擎

  • V8 - 开源,由Google开发,用C ++编写

  • Rhin- 由Mozilla基金会开源,完全用Java开发

  • SpiderMonkey 第一个JavaScript引擎,Netscape Navigator,Firefox

  • JavaScriptCore 苹果公司为Safari开发

  • KJS 最初由Harri Porten为KDE项目的Konqueror网络浏览器开发

  • Chakra** (JScript9) Microsoft Edge

  • Chakra** (JavaScript) Microsoft IE9-IE11

  • Nashorn 作为OpenJDK的一部分,由Oracle Java语言和工具组编写

  • JerryScript 一个物联网的轻量级引擎

V8 是用 C++ 写的,使用了即时编译技术,工作模式如下图

f1815dd21f3bbd271ad7e3c998e15251.png在这个过程中,V8同时使用了Parser(解析器)、Ignition(解释器) 和TurboFan(编译器) 来执行Js代码。V8是被设计用来提高网页浏览器内部JavaScript执行的性能,那么如何提高性能呢?

为了提高性能,v8会把js代码转换为高效的机器码,而不在是依赖于解释器去执行。v8引入了 JIT在运行时把js代码进行转换为机器码。这里的主要区别在于V8不生成字节码或任何中间代码。

v8曾经有两个编译器(v5.9之前)

full-codegen — 一个简单且速度非常快的编译器,可以生成简单且相对较慢的机器码 Crankshaft —  一个更复杂的(Just-In-Time)优化编译器,生成高度优化的代码

v8充分多进程,主进程负责获取代码,编译生成机器码,有专门负责优化的进程,,还有一个监控进程负责分析那些代码执行比较慢,以遍Crankshaft 做优化,最后还有一个就是GC进程,负责内存垃圾回收。

V8执行Js代码的过程

1 Parser生成抽象语法树

在Chrome中开始下载Javascript文件后,Parser就会开始并行在单独的线程上解析代码。这意味着解析可以在下载完成后仅几毫秒内完成,并生成AST。

0eaeb725439a7168985009eb26416f83.png
函数
6b5d92e5c9b5f85897c1241e38ebd926.png
编译AST后

AST还广泛应用于各类项目中,比如Babel、ESLint,以及我们面试常说手写loader,那么AST的生成过程是怎么样的呢?

我们首先看一下Babel的实现:

// 解析 
let esprima = require('esprima') 
// 转换 
let estraverse = require('estraverse') 
// 生成 
let escodegen = require('escodegen') 
 
let code = `function code () {}` 
 
// 解析 
let ast = esprima.parseScript(code) 
// 转换 
estraverse.traverse(ast, { 
  enter (node) { 
    console.log('enter' + node.type) 
    if (node.type === 'enterIdentifier') { 
      node.name = 'hello' 
    } 
  }, 
  leave (node) { 
    console.log('enter' + node.type) 
  } 
}) 
// 生成 
let newCode = escodegen.generate(ast)

我们常说的生成AST不管是Babel 还是vue中 都是 解析这一步:

解析步骤接收代码并输出 AST。这个步骤分为两个阶段:词法分析(Lexical Analysis)和 语法分析(Syntactic Analysis)。

词法分析:将代码(字符串)分割为token流,即语法单元成的数组 语法分析:分析token流(上面生成的数组)并生成 AST 转换

var name = "react"
//转成token后为

[
    {
        "type": "Keyword",
        "value": "var"
    },
    {
        "type": "Identifier",
        "value": "name"
    },
    {
        "type": "Punctuator",
        "value": "="
    },
    {
        "type": "String",
        "value": "\"react\""
    },
    {
        "type": "Punctuator",
        "value": ";"
    }
]

从上面可以看出,var name = "ivweb"; 这样一段代码,会有关键字"var"、标识符"name"、赋值运算符"="、字符串"ivweb"、分隔符";",共5个token。

2.Ignition生成字节码

解释器 Ignition 根据语法树生成字节码。TurboFan 是 V8 的优化编译器,TurboFan 将字节码生成优化的机器代码。

9a862bb952394f57875dd0d59aaa3474.png

如果想知道为什么会有两种执行模式?点击查看视频 [](Franziska Hinkelmann: JavaScript engines - how do they even? | JSConf EU 2017)

字节码是机器代码的抽象。如果字节码采用和物理 CPU 相同的计算模型进行设计,则将字节码编译为机器代码更容易。这就是为什么解释器(interpreter)常常是寄存器或堆栈。Ignition 是具有累加器的寄存器。

8339c497c9d5f9d53e9cab88a2ec69e6.png

您可以将 V8 的字节码看作是小型的构建块(bytecodes as small building blocks),这些构建块组合在一起构成任何 JavaScript 功能。V8 有数以百计的字节码。比如 Add 或 TypeOf 这样的操作符,或者像 LdaNamedProperty 这样的属性加载符,还有很多类似的字节码。V8还有一些非常特殊的字节码,如 CreateObjectLiteral 或 SuspendGenerator。头文件 bytecodes.h 定义了 V8 字节码的完整列表。

每个字节码指定其输入和输出作为寄存器操作数。Ignition 使用寄存器 r0,r1,r2,... 和累加器寄存器(accumulator register)。几乎所有的字节码都使用累加器寄存器。它像一个常规寄存器,除了字节码没有指定。例如,Add r1 将寄存器 r1 中的值和累加器中的值进行加法运算。这使得字节码更短,节省内存。

许多字节码以 Lda 或 Sta 开头。Lda 和 Stastands 中的 a 为累加器(accumulator)。例如,LdaSmi [42] 将小整数(Smi)42 加载到累加器寄存器中。Star r0 将当前在累加器中的值存储在寄存器 r0 中。

以现在掌握的基础知识,花点时间来看一个具有实际功能的字节码。

function incrementX(obj) {
  return 1 + obj.x;
}

incrementX({x: 42});
// V8 的编译器是惰性的,
// 如果一个函数没有运行,V8 将不会解释它

ps 如果要查看 V8 的 JavaScript 字节码,可以使用在命令行参数中添加 --print-bytecode 运行 D8 或Node.js(8.3 或更高版本)来打印。对于 Chrome,请从命令行启动 Chrome,使用 --js-flags="--print-bytecode",请参考 Run Chromium with flags。

$ node --print-bytecode incrementX.js
...
[generating bytecode for function: incrementX]
Parameter count 2
Frame size 8
  12 E> 0x2ddf8802cf6e @    StackCheck
  19 S> 0x2ddf8802cf6f @    LdaSmi [1]
        0x2ddf8802cf71 @    Star r0
  34 E> 0x2ddf8802cf73 @    LdaNamedProperty a0, [0], [4]
  28 E> 0x2ddf8802cf77 @    Add r0, [6]
  36 S> 0x2ddf8802cf7a @    Return
Constant pool (size = 1)
0x2ddf8802cf21: [FixedArray] in OldSpace
 - map = 0x2ddfb2d02309 
 - length: 1
           0: 0x2ddf8db91611 
Handler Table (size = 16)

3.执行代码及优化

441854d2d8746eb28dfb121878f09a13.png

Ignition执行上一步生成的字节码,并记录代码运行的次数等信息,如果同一段代码执行了很多次,就会被标记为 “HotSpot”(热点代码),然后把这段代码发送给 编译器TurboFan,然后TurboFan把它编译为更高效的机器码储存起来,等到下次再执行到这段代码时,就会用现在的机器码替换原来的字节码进行执行,这样大大提升了代码的执行效率。另外,当TurboFan判断一段代码不再为热点代码的时候,会执行去优化的过程,把优化的机器码丢掉,然后执行过程回到Ignition。

其实字节码配合解释器和编译器是很火的一种技术,例如 Python 和 Java 的虚拟机也是基于这种技术,我们把这种技术称为即时编译(JIT)。

这么多语言和工作引擎都使用了“字节码 + JIT”技术,其具体工作流程如下:

eefc924325da592ea988bc9037ce9ecb.png

推荐阅读

(点击标题可跳转阅读)

RxJS入门

一文掌握Webpack编译流程

一文深度剖析Axios源码

Javascript条件逻辑设计重构Promise知识点自测你不知道的React Diff你不知道的GIT神操作程序中代码坏味道(上)

程序中代码坏味道(下)

学习Less,看这篇就够了

一文掌握GO语言实战技能(一)

一文掌握GO语言实战技能(二)

Linux-

Linux-

一文达到Mysql实战水平

一文达到Mysql实战水平-习题答案

从表单抽象到表单中台

vue(1)- new Vue

实战LeetCode 系列(一) (题目+解析)

一文掌握Javascript函数式编程重点

实战LeetCode - 前端面试必备二叉树算法

 React16.0-16.6 ( )

阿里、网易、滴滴、今日头条、有赞.....等20家面试真题

30分钟学会 snabbdom 源码,实现精简的 Virtual DOM 库

觉得本文对你有帮助?请分享给更多人

关注「React中文社区」加星标,每天进步

84d5c8c2343fd2ad0de34ae404f3961c.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567625.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mockito mock void方法_一文让你快速上手 Mockito 单元测试框架

前言在计算机编程中,单元测试是一种软件测试方法,通过该方法可以测试源代码的各个单元功能是否适合使用。为代码编写单元测试有很多好处,包括可以及早的发现代码错误,促进更改,简化集成,方便代码重构以及许…

vs winform常用函数_使用.net core3.0 正式版创建Winform程序

前阵子一直期待.net core3.0正式版本的出来,以为这个版本出来,Winform程序又迎来一次新生了,不过9.23日出来的马上下载更新VS,创建新的.net core Winform项目,发现并没有Winform窗体设计器。而微软目前则是通过插件的方…

VScode中编写运行C/html文件

VScode运行C程序的所需配置 VScode只是一个编辑器,并不自带C编译器,所以需要 下载mingw 下载安装版本或者压缩文件,解压缩后,配置系统的环境变量。 path中添加mingw/bin的路径 新建include变量,添加mingw/include的路径…

linq结果转换object_你知道Object.entries(),但你还知道有Object.fromEntries()吗?

我们得到 object.entries(),它转换一个object → array。但是,如果您想做相反的事情怎么办?不用再想了! 使用 Object.fromEntries() 来array → object 。const keyValuePair [ [cow, ], [pig, ],];Object.fromEntries(keyValu…

C语言中数组越界访问造成死循环现象

大家请看这样一段代码&#xff08;工具&#xff1a;VC6.0&#xff09;&#xff1a; #include <stdio.h> int main(int argc, char *argv[]) { int i; int arr[10];/* 这里注意循环变量i与数组arr的定义顺序 */ for(i 0; i < 10; i)/* 这里越界了 */ …

java 同步锁_Java多线程:synchronized同步锁的使用和实现原理

作用和用法在多线程对共享资源进行并发访问方面&#xff0c;JDK提供了synchronized关键字来进行线程同步&#xff0c;实现多线程并发访问的线程安全。synchronized的作用主要体现在三个方面&#xff1a;(1)确保线程互斥地访问同步代码&#xff1b;(2)保证共享变量的线程可见性&…

java基础代码实例_基础篇:详解JAVA对象实例化过程

1 对象的实例化过程对象的实例化过程是分成两部分&#xff1a;类的加载初始化&#xff0c;对象的初始化要创建类的对象实例需要先加载并初始化该类&#xff0c;main方法所在的类需要先加载和初始化类初始化就是执行方法&#xff0c;对象实例化是执行方法一个子类要初始化需要先…

搭建webUI自动化及问题解决:Message: ‘chromedriver‘ executable needs to be in PATH.解决办法

搭建webUI自动化环境 1、conda install selenium即可。 若出现&#xff1a;Message: chromedriver executable needs to be in PATH.Please see https://sites.google.com/a/chromium.org/chromedriver/home。 报错原因&#xff1a;没有配置chrome浏览器的chromedriver 解决…

C语言-字符串处理函数strcpy

strcpy 原型&#xff1a;strcpy(char destination[], const char source[]); 功能&#xff1a;将字符串source拷贝到字符串destination中。此处将source中的字符串结束标志符‘\0’也一同复制。所以在输出时&#xff0c;切不可以用‘\0’&#xff0c;puts&#xff0c;printf输…

C语言-字符串处理函数strcat

strccat-字符串拼接函数 char*strcat(char* strDestination, const char* strSource); 参数说明&#xff1a; strDestination&#xff1a;目的字符串&#xff1b;strSource&#xff1a;源字符串。 strcat() 函数把 strSource 所指向的字符串追加到 strDestination 所指向的字…

js数组截取前5个_我不能没有的5个Vue.js库

1.Click Off to Close有的时候&#xff0c;我们需要在用户点击元素之外的时候触发一个事件。最常见的用例是当你想通过点击关闭一个下拉框或对话框时。这是一个必不可少的包&#xff0c;几乎在我构建的每个应用中都会用到。首选&#xff1a;vue-clickawayhttps://github.com/si…

this.$router.push如何刷新页面_小程序丨微信小程序如何实现页面下拉刷新

微信小程序蕴含着众多功能&#xff0c;本期将简单介绍实现页面下拉刷新的方法&#xff0c;通过阅读本文&#xff0c;读者们可以自行动手操作&#xff0c;在实践中认识微信小程序。首先&#xff0c;我们需在json配置中写出以下配置&#xff1a;"enablePullDownRefresh"…

C语言-字符串处理函数strcmp

strcmp-字符串比较函数 原型&#xff1a;int strcmp(const char firststring[], const char secondstring); 功能&#xff1a;比较两个字符串firststring和secondstring 如果等于 返回值为0 如果字符串1大于字符串2 函数值返回为1 如果字符串1小于字符串2 函数值返回为-1 …

导出excel数字前面的0消失_Excel操作中常见的3大坑你遇到过吗?遇到应该这么解决...

在excel中的我们获取数据的方式一是自己录入数据&#xff0c;二是通过网络或其他的途径导出的源数据&#xff0c;不管哪种的方式&#xff0c;对我们处理数据的来说都十分重要&#xff0c;这里我们需要注意这些点并成功跳过这些不按原理只按自己习惯的坑。今天要聊的坑有3个&…

matplot绘制图形入门

一、折线图 """ File: 折线图.py Author: chde_wang Date: 2021-05-23 22&#xff1a;26&#xff1a;04 Description: """ # 绘制折线图 import numpy as np import matplotlib.pyplot as plt x np.linspace(0, 2 * np.pi, 100) y1, y2 np.si…

kafka使用_Kafka介绍与使用

最近在研究kafka&#xff0c;觉得需要输出点东西才能更好的吸收&#xff0c;遂总结与大家分享&#xff0c;话不多说。一、先上思维导图&#xff1a;二、再上kafka整体架构图&#xff1a;2.1、Producer&#xff1a;消息生产者&#xff0c;就是向kafka broker发消息的客户端。2.2…

linux 关闭端口_手把手教你在Linux中快速检测端口的 3 个小技巧

一个执着于技术的公众号前言 无论是要解决网络连接问题还是配置防火墙&#xff0c;第一件事是要检查系统实际打开了哪些端口。本文介绍了几种快速查找 Linux 系统上哪些端口向外部开放的方法。什么是开放端口 监听端口是应用程序监听的网络端口。你要得到的监听端口名单通常可以…

2020-11-20

ln -s /bis_data/mysql/tmp/mysql.sock /tmp/ find / -name mysql.sock 2>/dev/null

未能找到程序集“platform.winmd_应用程序崩溃后 微软错误报告工具到底是如何联机检查解决方案的?...

在 Windows 应用意外崩溃后&#xff0c;系统似乎会努力地寻找解决方案。但是在绝大多数情况下&#xff0c;这一切都是徒劳的&#xff0c;并不会向用户给出任何结果。即便如此&#xff0c;很多人还是想要知道这个无效的过程期间到底都发生了什么。好消息是&#xff0c;近日微软 …

mysql索引创建和使用注意事项

总结&#xff1a; 1、在使用索引时&#xff0c;一般情况下不建议使用like操作。如果使用&#xff0c;则%放在后面。否则不会使用索引。like ‘%abd%’不会使用索引,而like ‘aaa%’可以使用索引.&#xff08;最左缀原则&#xff09; 2、单列索引的使用&#xff1a; 《1》 只…