关于JS运行机制和JS引擎(V8)的内部结构,我相信这就是你需要了解的。其实也是零碎知识的整合。希望带给大家从0-1的理解,而不是模块。另一个初衷是,作为前端的视角,应该在浏览器中理解什么内容。(很多人想深入看WebKit源码,个人觉得V8源码有点离谱,不适合每个前端同学练习,会让你感到绝望。)希望大家可以在仔细阅读的过程中纠正我的问题。过来打我脸!今天就来介绍大家日常接触最多的模块JS引擎相关的内容;本文内容包括:JavaScript运行机制引擎内部术语的简单了解(熟悉的略过,熟悉的回忆,不懂的仔细看完,后续会有用)最小单元一个进程的CPU资源分配(一个进程可以包含多个进程,暂时不需要了解)Thread线程是CPU调度的最小单位ECS:ExecutionEnvironmentStack,ExecutionContextStackJavaScript运行机制概述JS是一种单线程脚本语言。JS之所以被设计成单线程语言,主要是因为和它的目的有关系。作为一种浏览器脚本语言,JS的主要用途是操作DOM。如果设计成多线程,必然会导致操作冲突和复杂的同步问题;为了解决单线程排队的问题,有一个让你头疼的运行机制,包括主线程、任务队列、事件循环。为了更好的理解EventLoop,请看下上图。主线程运行时会产生堆和栈。栈中的代码调用各种外部API,在“任务队列”中添加各种事件(onClick、onLoad)。只要栈中的代码执行完,主线程就会读取“任务队列”,依次执行那些事件对应的回调函数。执行栈中的代码总是在读取“任务队列”之前执行。主线程(执行栈)执行上下文栈(executioncontextstack)是JavaScript执行事件任务的线程。请看下面的动图:当在全局代码中调用一个函数时,程序会进入被调用的函数,创建一个新的执行上下文,并将新创建的上下文压入执行栈的顶部。在调用函数内部调用其他函数会重复第一步(程序进入调用函数,新建一个执行上下文并压入执行栈顶),从栈顶依次执行:Executetheexecutioncontext栈顶,一旦当前上下文函数执行结束,就会从栈顶弹出,上下文控制权交给当前栈;继续执行,直到栈为空。任务队列任务队列(taskqueue)用于存放异步任务运行结果事件。一种是同步任务(synchronous),一种是异步任务(asynchronous):同步任务是指在主线程上排队等待执行的任务,只有上一个任务完成后才能执行下一个任务。异步任务是指直接进入任务队列,等待条件满足(发出通知),最后进入主线程执行的任务。请看下面的gif:(学过C++的都知道main是主入口,不懂的可以忽略这里的main函数)~~进入全局执行上下文console.log(“开始”);进入主线程(Push到栈顶)Timer1在执行过程中进入主线程,发现是WEBapi,超时时间结束后进入队列。Timer2在执行过程中进入主线程,发现是WEBapi,超时时间结束后进入队列。console.log("end);进入主线程执行执行顺序2-5-4-3EventLoopevent-loop可以理解为一种处理机制,主线程任务执行==主线程从"任务队列"中读取事件==execution...,这是一个循环的过程,这种的运行机制称为EventLoop(事件循环),对比上面的动画,简单理解为当主线程为空时,读取pendingevents(timer1,timer2)从任务队列中取出,进入主线程执行JS引擎(V8)概述JavaScript引擎是执行JavaScript代码的程序或解释器,JavaScript引擎可以实现为单独的解释器,也可以只是-以某种方式将JavaScript编译成字节码的实时编译器。通常被称为JavaScript引擎:JavaScriptCore代表浏览器SafariRhino代表浏览器MozillaFirefoxChakra代表浏览器InternetExplorer(IE)V8代表浏览器Chrome开源,用C++实现下面介绍一下V8的一些内部实现和优势。JS执行内部过程,将JS代码转换为AST语法树表示。//函数functiongreet(){console.log("wlove");}//AST树json{"type":"Program","start":0,"end":47,"body":[{"type":"FunctionDeclaration","start":0,"end":46,"id":{"type":"Identifier","start":9,"end":14,"name":"greet"},"expression":false,"generator":false,"async":false,"params":[],"body":{"type":"BlockStatement","start":17,"end":46,"body":[{"type":"ExpressionStatement"“开始”:23,“结束”:44,“表达式”:{“类型”:“CallExpression”,“开始”:23,“结束”:43,“被调用者”:{“类型”:“MemberExpression”,“开始”:23,“结束”:34,“对象”:{“类型”:“我标识符”,“开始”:23,“结束”:30,“名称”:“控制台”},“属性”:{“类型”:“标识符”,“开始”:31,“结束”:34,“name":"log"},"computed":false,"optional":false},"arguments":[{"type":"Literal","start":35,"end":42,"value":"wlove","raw":"\"wlove\""}],"optional":false}}]}}],"sourceType":"module"}AST转换成字节码应该是我知道前面的v8直接转换机器码但是机器码占用空间大,如果v8缓存机制将js代码全部编译成机器码缓存起来,会导致缓存占用大量内存和磁盘空间,并退出Chrome并再次打开时间序列化和反序列化缓存的时间成本也很高,在时间空间成本高的情况下引入字节码,字节码解释器TurboFan也有很多工作要做,简单列举几点:段代码处理程序生成字节码生成解释器寄存器分配上下文链异常处理JS代码解释执行....混合编译器和解释器的JIT(JustInTime)技术。编译器启动速度慢,执行速度快。解释器启动速度快,但执行速度慢。而JIT技术则是两者的结合(Ignition(字节码解释器)+TurboFan(JIT编译器);后者应用也越来越广泛)虚拟机(垃圾收集,内存管理等)V8用于分代和大数据内存分配,在回收内存时,使用流水线排序算法标记未被引用的对象,然后剔除未标记的对象,最后对那些未保存的对象进行排序压缩,完成垃圾回收。内存分配:新生代:为新创建的对象分配内存空间,经常需要进行垃圾回收。为了方便年轻代中内容的回收,可以将年轻代分为两半,一半用于分配,另一半负责在回收时复制之前需要保留的对象。Oldgenerationgeneration:按需保存旧对象、指针、代码等数据,较少进行垃圾回收。大对象:为那些需要占用更多内存的对象分配内存。当然,它也可能包含为数据和代码分配的内存。一个页面只分配一个对象。内存(垃圾)收集:对象在新生代的垃圾收集主要通过Scavenge算法进行。考虑到老年代中存活的对象居多,主要采用标记-清除(MarkSweep)和标记-紧凑(MarkSweep)的组合方式进行垃圾回收。代码执行工作流程编译运行V8引擎编译阶段:主要类如下:Script:Script类包含JS代码和编译后的native代码。(这里是编译入口)Compiler:Compiler类:Script类调用编译生成代码,包括生成AST,本地代码等AstNode:抽象语法树节点类(作为节点基类,包括很多子类辅助后续代码生成)AstVisitor:抽象语法树访问类,主要用于遍历异构抽象语法树;FullCodeGenerator:调用访问类,遍历AST生成JS原生可执行代码。编译过程大致是:Script类调用Compiler类为其生成AST和native代码。Compile函数首先使用Parser类生成AST,然后使用FullCodeGenerator类生成本机代码。FullCodeGenerator使用多个后端来生成平台匹配的本机汇编代码。V8引擎运行阶段:主要类如下:这里的Script是运行入口编译后生成的本地代码;Execution:JS运行过程中的辅助组类;包含调用函数等一些功能;JSFunction:需要执行的JavaScript函数表示类;Runtime:运行这些本地代码的辅助类,主要提供运行时需要的辅助组函数,如:属性访问、类型转换、编译、算术运算、位运算、比较、正则表达式等;Heap:运行本地代码需要使用的内存堆类;MarkCompactCollector:垃圾回收机制的主要实现类,用于标记、清除、排序等基本的垃圾回收过程;SweeperThread:负责垃圾回收的线程。执行过程大致是:V8在调用函数的时候会检测是否有native代码,如果有则进行调用。V8会在调用函数时检查是否有原生代码,如果没有则生成原生代码。执行编译代码构建JS对象需要Runtime类协助创建对象,需要从Heap类分配内存。最后,标记并清除未使用的空间并收集垃圾。当然V8内部还有很多,比如隐藏类,扩展机制等等。有兴趣的可以看看《WebKit技术内幕》如果想阅读源码,建议从V8开始阅读,代码量小。来吧男孩。最后跟大家分享一下,最近工作很忙(对接外部资源,对内整合,做技术研发……);生活很忙(一件事就是运动一定要坚持。。)写作也会坚持下来(每周1-3篇)。如果您有任何想了解的内容,欢迎随时留言。只要我知道的,我都会第一时间分享出来,帮助大家。如果你不会,我可以学习它。哎,下篇文章待定。加油,前途光明,美男美女!!!以上部分图片来自网络。如有侵权,请联系删除。谢谢。
