v8引擎源码分析
文章平均质量分 82
theanarkh
这个作者很懒,什么都没留下…
展开
-
如何实现 JS 运行时的 Inspector 能力
无原创 2022-10-03 03:21:11 · 756 阅读 · 0 评论 -
聊聊 JS 断点的实现
无原创 2022-09-29 21:27:53 · 595 阅读 · 0 评论 -
V8 GC 的实现
V8 GC原创 2022-08-18 00:51:19 · 516 阅读 · 0 评论 -
如何追踪 JS 对象是否被 GC
如何追踪 JS 对象是否被 GC原创 2022-08-08 02:00:47 · 542 阅读 · 2 评论 -
如何优雅地 hack 用户的代码
前言:做基础技术的时候,会经常碰到一个问题就是如何让自己提供的代码对用户少侵入,无感。比如我提供了一个 SDK 收集 Node.js 进程的 HTTP 请求耗时,最简单的方式就是给用户提供一个 request 方法,然后让用户统一调用,这样我就可以在 request 里拿到这些数据。但是这种方式很多时候并不方便,这时候我们就需要去 hack Node.js 的 HTTP 模块或者给 Node.js 提 PR。在操作系统层面,有提供很多技术解决这种问题,比如 ebpf、uprobe、kprobe。但是应用层无原创 2022-05-24 01:19:52 · 447 阅读 · 0 评论 -
V8 global.gc() 的实现
前言:在 Node.js 中我们有时候会使用 global.gc() 主动触发 gc 来测试一些代码,因为我们知道 V8 gc 的执行时机是不定的。但是可能很少同学知道 global.gc() 的实现,本文介绍一些在 V8 中关于这部分的实现。了解 global.gc() 实现之前,首先看一下 V8 的 Extension 机制。Extension 机制用于拓展 V8 的能力。在 V8 初始化的过程中,V8::Initialize 会初始化 Extension 机制,具体在 Bootstrapper::原创 2022-05-23 23:15:35 · 945 阅读 · 0 评论 -
V8 CPU Profiler 的实现
前言:CPU Profiler 是应用性能诊断和优化的利器,本文介绍 V8 中关于这部分的实现,细节比较多也比较复杂,大致分析一下原理,代码来自 V8 10.2。开始分析前,先来看一下对象的关系图(从左往右看),这个对后面的分析比较重要,因为他们的关系错综复杂。下面开始分析。入口对象为 CpuProfiler。CpuProfiler 负责管理多个 CpuProfile,而我们进行一次 CPU Profile 时对应的就是一个 CpuProfile 对象。首先看一下 CpuProfiler 的构造函数。原创 2022-05-06 22:51:07 · 801 阅读 · 0 评论 -
V8 Heap Profiler 的实现
前言:V8 Heap Profiler 用于收集哪些代码分析了多少内存的信息。本文介绍 V8 中关于这部分的实现,代码来自 V8 10.2。入口函数是 StartSamplingHeapProfiler。 bool StartSamplingHeapProfiler(uint64_t sample_interval, int stack_depth, v8::HeapProfiler::SamplingFlags);主要的参数是 sample_interval。bool HeapProfile原创 2022-05-06 22:49:33 · 463 阅读 · 0 评论 -
利用 V8 的 trace API 追踪代码
V8 和 Node.js 提供了 trace_event 机制,但是因为稳定性原因,Node.js 目前没有支持用户自定义 trace event 能力,所以写了一个 addon 支持该能力(npm i v8_trace_event)。更多信息可以参考。https://github.com/nodejs/node/pull/42462https://nodejs.org/dist/latest-v18.x/docs/api/tracing.htmlhttps://zhuanlan.zhihu.com原创 2022-05-04 05:24:25 · 828 阅读 · 0 评论 -
V8 堆外内存 ArrayBuffer 垃圾回收的实现
前言:V8 除了我们经常讲到的新生代和老生代的常规堆内存外,还有另一种堆内存,就是堆外内存。堆外内存本质上也是堆内存,只不过不是由 V8 进行分配,而是由 V8 的调用方分配,比如 Node.js,但是是由 V8 负责 GC 的。本文介绍堆外内存的一种类型 ArrayBuffer 的 GC 实现。1 创建 ArrayBufferArrayBuffer 的创建有很多种方式,比如在 JS 层创建 Uint8Array 或者 ArrayBuffer(对应实现 builtins-arraybuffer.cc),原创 2022-04-29 04:30:00 · 1005 阅读 · 0 评论 -
V8 新生代垃圾回收的实现
前言:因为最近在做一些 gc track 的事情,所以打算了解一下 V8 GC 的实现。介绍 V8 GC 的文章网上已经有很多,就不打算再重复介绍。本文主要介绍一下新生代 GC 的实现,代码参考 V8 10.2,因为 GC 的实现非常复杂,只能介绍一些大致的实现,读者需要对 V8 GC 有一定的了解,比如新生代是分为 from 和 to 两个 space,然后在 GC 时是如何处理的。说到 GC 首先需要介绍内存,具体来说,是堆内存,V8 把内存分为新生代和老生代,其中老生代又分为很多种类型,不过本文只关原创 2022-04-29 02:36:49 · 364 阅读 · 0 评论 -
Node.js 的 trace events 架构
前言: trace 系统用于收集内核的数据,本文介绍在 Node.js 中 trace 系统的架构和实现,因为 Node.js 的 trace 系统是基于 V8 的,所以也会介绍 V8 部分。Node.js 中 trace 数据通过两种方式产生,第一种方式是在 JS 层通过 V8 提供的 trace C++ API,第二种方式是通过 Node.js C++ 层。下面首先看一下第一种。// binding.trace(phase, category, name, id, data) SimpleIns原创 2022-03-26 16:18:06 · 1461 阅读 · 0 评论 -
Node.js ObjectWrap 的弱引用问题
前言:最近在写 Node.js Addon 的过程中,遇到了一个问题,然后发现是 ObjectWrap 弱引用导致的,本文介绍一下具体的问题和排查过程,以及 ObjectWrap 的使用问题。ObjectWrap 用于写 Addon 的时候导出 C++ 对象给 JS 层使用,大致用法如下。首先定义一个 C++ 类。class Demo: public node::ObjectWrap { public: static void create(const FunctionCallbackInfo原创 2022-01-02 05:29:43 · 897 阅读 · 0 评论 -
Node.js 的底层原理
前言:之前分享了 Node.js 的底层原理,主要是简单介绍了 Node.js 的一些基础原理和一些核心模块的实现,本文从 Node.js 整体方面介绍 Node.js 的底层原理。分享内容主要包括五个部分。第一部分是首先介绍一下 Node.js 的组成,还有他的代码架构。然后接下来会介绍一下 Node.js 中的 Libuv, 还有 V8 和模块加载器。然后最后介绍一下 Node.js 的服务器架构。1 Node.js 的组成下面我们先来看一下Node.js 的组成。Node.js 主要是由 V8、原创 2021-11-06 16:12:19 · 2712 阅读 · 7 评论 -
Node.js 抓取堆快照过程解析
前言:在 Node.js 中,我们有时候需要抓取进程堆快照来判断是否有内存泄漏,本文介绍Node.js 中抓取堆快照的实现。首先来看一下 Node.js 中如何抓取堆快照。const { Session } = require('inspector');const session = new Session();let chunk = '';const cb = (result) => { chunk += result.params.chunk;};session.on('Hea原创 2021-10-23 01:35:32 · 942 阅读 · 0 评论 -
深入理解 V8 Inspector
前言:本文介绍一下 V8 关于 Inspector 的实现,不过不会涉及到具体命令的实现,V8 Inspector 的命令非常多,了解了处理流程后,如果对某个命令感兴趣的话,可以单独去分析。首先来看一下 V8 Inspector 中几个关键的角色。1. V8InspectorSessionclass V8_EXPORT V8InspectorSession { public: // 收到对端端消息,调用这个方法判断是否可以分发 static bool canDispatchMethod(St原创 2021-10-22 21:22:09 · 757 阅读 · 0 评论 -
深入理解 Node.js 的 Buffer
前言:Buffer 模块是 Node.js 非常重要的模块,很多模块都依赖它。本文介绍一下 Buffer 模块底层的原理,包括 Buffer 的核心实现和 V8 堆外内存等内容。Buffer 的实现Buffer 模块的实现虽然非常复杂,代码也非常多,但是很多都是编码解码以及内存分配管理的逻辑,我们从常用的使用方式 Buffer.from 来看看 Buffer 的实现。Buffer.from = function from(value, encodingOrOffset, length) { ret原创 2021-10-16 00:00:48 · 1381 阅读 · 0 评论 -
No.js 中 V8 堆外内存管理和字符编码解码的实现
前言:对于基于 V8 的 JS 运行时来说,堆外内存的管理是非常重要的一部分,因为 gc 的原因,V8 自己管理堆内存大小是有限制的,我们不能什么数据都往 V8 的堆里存储,比如我们想一下读取一个 1G 的文件,如果存到 V8 的堆,一下子就满了,所以我们需要定义堆外内存并进行管理。本文介绍 No.js 里目前支持的简单堆内存管理机制和字符编码解码的实现。1 字符串的使用数据的读写,在底层都是一个个字节,那么我们在 JS 层定义的字符串,C++ 层是怎么获取的呢?比如我们在 JS 里调用自定义 log原创 2021-10-05 19:14:01 · 419 阅读 · 0 评论 -
No.js 的模块加载器实现
前言:最近在 No.js 里实现了一个简单的模块加载器,本文简单介绍一下加载器的实现。因为 JS 本身没有模块加载的概念,随着前端的发展,各种加载技术也发展了起来,早期的seajs,requirejs,现在的 webpack,Node.js等等,模块加载器的背景是代码的模块化,因为我们不可能把所有代码写到同一个文件,所以模块加载器主要是解决模块中加载其他模块的问题,不仅是前端语言,c语言、python、php同样也是这样。No.js 参考的是 Node.js的实现。比如我们有以下两个模块。module1原创 2021-09-16 00:53:21 · 569 阅读 · 0 评论 -
No.js---基于V8和io_uring的JS运行时
前言:阅读Node.js的源码已经有一段时间了,最近也看了一下新的JS运行时Just的一些实现,就产生了自己写一个JS运行时的想法,虽然几个月前就基于V8写了一个简单的JS运行时,但功能比较简单,这次废弃了之前的代码,重新写了一遍,写这个JS运行时的目的最主要是为了学习,事实也证明,写一个JS运行时的确可以学到很多东西。本文介绍运行时No.js的一些设计和实现,取名No.js一来是受Node.js的影响,二来是为了说明不仅仅是JS,也就是利用V8拓展了JS的功能,同时,前端开发者要学习的知识也不仅仅是JS了原创 2021-09-05 17:34:47 · 234 阅读 · 0 评论 -
编译和使用V8
1 下载工具:git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git2 追加路径,后续执行命令用到。export PATH=$PATH:depot_tools父目录路径/depot_tools3 gclient更新文件,报错则配置gclient config https://chromium.googlesource.com/chromium/src.git(很久,最后要看有没有下载失败的文件)4 mkdir原创 2021-08-29 16:00:15 · 884 阅读 · 7 评论 -
使用Node.js Addon实现类继承
前言:昨天有个同学问怎么通过NAPI把C++类的继承关系映射到JS,很遗憾,NAPI貌似还不支持,但是V8支持,因为V8在头文件里导出了这些API,并Node.js里也依赖这些API,所以可以说是比较稳定的。本文介绍一下如何实现这种映射(不确定是否能满足这位同学的需求)。下面我们看一下Addon的实现。会涉及到V8的一些使用,可以先阅读该文章《一段js理解nodejs中js调用c++/c的过程》。首先看一下基类的实现。#ifndef BASE_H#define BASE_H#include <原创 2021-07-16 01:43:41 · 399 阅读 · 1 评论 -
编写自己的js运行时第二篇
前言:第一版基于V8实现了一个朴素版的服务器,第二版支持了多进程架构,并且支持了SO_REUSEPORT。本文介绍一下第二版的一些实现,设计上还是比较随意的,目前主要关注功能。首先我们看看第二版怎么使用。1 通过fork共享端口const TCPServer = TCP();const tcpServer = new TCPServer('127.0.0.1', 8989);tcpServer.socket();tcpServer.setReusePort(1);tcpServer.bind(原创 2021-07-10 06:14:01 · 178 阅读 · 2 评论 -
从No.js看Node.js原理
前言:越来越多同学在使用Node.js,大家也不同程度地理解Node.js是什么。比如Node.js是由V8、Libuv、JS组成的,Node.js底层是C\C++,Node.js不是语言是运行时。本文通过实现一个类Node.js的JS运行时No.js,去理解Node.js的本质。No.js是我之前写的一个JS运行时,概念上是这么说,但是它算不上真正的运行时,它只是个demo,但是它让你看到如果你有兴趣,你也可以写个Node.js。首先我们看看V8的基本用法。#include <stdio.h&g原创 2021-07-09 00:11:03 · 228 阅读 · 1 评论 -
编写自己的js运行时第一篇
最近休假期间编译了一下V8,然后最近想着顺便学习一下V8。所以参考Node.js,写个No.js,也是在V8的基础上拓展js的功能,当然,这只是学习用的。目前只写了个阻塞版的TCP服务器。本文介绍一下如何拓展js。首先定义main函数,在里面注册个全局变量TCP,下面只列出核心代码。{ Local<Object> global = context->Global(); Local<Value> key = String::NewFromUtf8(i原创 2021-06-12 01:37:47 · 415 阅读 · 4 评论 -
通过Handle理解V8的代码设计(基于V0.1.5)
前言:Handle在V8里是一个非常重要的概念,本文从早期的源码分析Handle的原理,在分析的过程中我们还可以看到V8在代码设计上的一些细节。假设我们有以下代码HandleScope scope;Local<String> hello = String::New(参数);这个看起来很简单的过程,其实在V8的内部实现起来比较复杂。HandleScope我们从创建一个HandleScope对象开始分析。HandleScope是负责管理多个Handle的对象,主要是为了方便管理Hand原创 2021-05-28 01:04:00 · 280 阅读 · 0 评论 -
v8源码解析之Dictionary(v8 0.1.5)
Dictionary我们应该不陌生,他是HashTable的基类。我们看一下定义// 字典基类,prefix大小为两个指针元素,数组中每个元素大小是3个指针class DictionaryBase: public HashTable<2, 3> {};class Dictionary: public DictionaryBase {}由定义可以看到Dictionary的布局如下Dictionary底层是数组实现的,每个元素的大小是三个指针(key、value、detail)。接着我原创 2020-10-17 13:57:36 · 453 阅读 · 0 评论 -
v8源码解析之ByteArray(v8 0.1.5)
ByteArray是字节数组的实现,顾名思义,该数组的元素大小的一个字节,不过类似js的Uint16Array,Uint32Array数组一样,我们可以把多个元素看做一个,把多个字节合并成一个元素看待。下面我们看一下实现。class ByteArray: public Array { public: // 按照一个元素一个字节的方式存取 inline byte get(int index); inline void set(int index, byte value); // 按照一个元原创 2020-10-17 11:46:12 · 291 阅读 · 0 评论 -
v8源码解析之SymbolTable(v8 0.1.5)
SymbolTable是哈希表的子类,元素大小是一个Object*。SymbolTable主要使用哈希表来存储字符串,给定一个字符串,算出哈希值,然后插入哈希表中。后续根据哈希值进行读取。哈希表本身不负责对元素进行哈希,而是由数据方提供哈希值。哈希表只是根据这个哈希值计算出该元素在哈希表的位置。class SymbolTable: public HashTable<0, 1> { public: // 查找str对应的Symbol对象,存到s中,如果没有则新增 Object* Loo原创 2020-10-17 10:56:37 · 259 阅读 · 0 评论 -
v8源码解析之HashTable(v8 0.1.5)
HashTable是v8中哈希表的实现,HashTable继承Array。HashTable提供一些公共的逻辑,供后续子类使用。我们看一下他 大内存布局。然后看一下类的定义。HashTable是个模板类,prefix_size是,element_size是哈希表中每个元素的大小。template<int prefix_size, int element_size>class HashTable: public FixedArray { public: // 哈希表已使用的元素个数原创 2020-10-17 10:23:03 · 470 阅读 · 0 评论 -
v8源码解析之Array和FixedArray(v8 0.1.5)
v8中很多数据结构都具备数组的特性,今天我们先介绍Array和FixedArray。他们是V8中很多数据结构的基类。1 Array我们先看Array的定义。class Array: public HeapObject { public: // 数组的长度 inline int length(); inline void set_length(int value); // 把对象object转成数字,存到index中 static inline bool IndexFromObje原创 2020-10-17 00:07:24 · 673 阅读 · 0 评论 -
nodejs源码分析之c++层的通用逻辑
我们知道nodejs分为js、c++、c三层,本文以tcp_wrap.cc为例子分析的是c++层实现的一些通用的逻辑。nodejs的js和c++通信原理之前已经分析过,所以直接从tcp模块导出的功能开始分析(Initialize函数)。void TCPWrap::Initialize(Local<Object> target, Local<Value> unused, Local&l原创 2020-07-20 00:37:51 · 395 阅读 · 0 评论 -
理解nodejs中js和c++的通信原理
本文分享一下nodejs中js调用c++模块的一些内容。js调用c++模块是v8提供的能力,nodejs是使用了这个能力。这样我们只需要面对js,剩下的事情交给nodejs就行。本文首先讲一下利用v8如何实现js调用c++,然后再讲一下nodejs是怎么做的。1 js调用c++首先介绍一下v8中两个非常核心的类FunctionTemplate和ObjectTemplate。顾名思义,这两个类是定义模板的,好比建房子时的设计图一样,通过设计图,我们就可以造出对应的房子。v8也是,定义某种模板,就可以通过这原创 2020-07-19 03:40:36 · 1719 阅读 · 0 评论 -
js引擎v8源码分析之GlobalHandles(基于v8 0.1.5)
GlobalHandles是实现v8中持久句柄功能的类。GlobalHandles主要是维护一个链表,每个节点维护堆对象的状态。我们先看看节点的定义。class GlobalHandles::Node : public Malloced { public: void Initialize(Object* object) { // 指向堆对象地址 object_ = obj...原创 2020-02-16 01:29:58 · 531 阅读 · 6 评论 -
js引擎v8源码分析之HeapNumber(基于v8 0.1.5)
HeapNumber是保存大整形的对象。v8里有smi保存整形,但是他只有31位,超过31位的就需要用HeapNumber。// 存储了数字的堆对象class HeapNumber: public HeapObject { public: inline double value(); inline void set_value(double value); static inl...原创 2020-02-15 14:17:56 · 387 阅读 · 0 评论 -
js引擎v8源码分析之HeapObject(基于v8 0.1.5)
HeapObject是Object的子类。是所有基于堆分配的对象的基类。class HeapObject: public Object { public: // 每个堆对象都有一个map对象,记录对象的类型,大小等信息 inline Map* map(); inline void set_map(Map* value); // 对象的地址+对象标记 static inli...原创 2020-02-15 13:58:31 · 356 阅读 · 0 评论 -
js引擎v8源码分析之Handle(基于v8 0.1.5)
Handle是使用v8的时候很重要的一个概念和类。他本质是堆对象的封装。我们通过Handle管理真正的对象,而不是直接操作对象。Handle在v8中有两个实现。一个是对外使用的一个是内部使用的。我们先看一下内部使用的。1 内部handletemplate<class T>class Handle { public: INLINE(Handle(T** location)) ...原创 2020-02-15 02:07:20 · 879 阅读 · 0 评论 -
js引擎v8源码分析之Object(基于v8 0.1.5)
Object是所有js对象在c++层的基类。class Object BASE_EMBEDDED { public: inline bool IsSmi(); inline bool IsHeapObject(); inline bool IsHeapNumber(); inline bool IsString(); inline bool IsSeqString();...原创 2020-02-14 22:44:32 · 669 阅读 · 0 评论 -
js引擎v8源码分析之MemoryAllocator(基于v8 0.1.5)
MemoryAllocator是负责内存的管理和分配的。MemoryAllocator可以直接申请内存,也可以初始化时申请一块内存。然后把这些内存,分成多个chunk,每一个chunk里面多个page。下面是定义。class MemoryAllocator : public AllStatic { public: static bool Setup(int max_capacity)...原创 2020-02-10 00:37:42 · 293 阅读 · 0 评论 -
js引擎v8源码分析之NewSpace(基于v8 0.1.5)
NewSpace是v8内存管理中,负责管理新生代区的类。分为from和to两个区,每个区由SemiSpace对象管理。和SemiSpace一样,NewSpace也不负责内存的分配和释放,他只负责内存的使用和管理。下面是类的定义。class NewSpace : public Malloced { public: NewSpace(int initial_semispace_capacity...原创 2020-02-09 00:42:06 · 339 阅读 · 0 评论