1.V8的内存垃圾回收 #

2.计算机模型 #

2.1 寄存器 #

2.2 内存 #

console.log(0xFFFFFFFF);//4294967295
console.log(0xFFFFFFFF / 1024 / 1024 / 1024);

2.2.1 内存空间分类 #

2.3 指令 #

2.3.1 机器语言指令 #

2.3.2 汇编指令 #

部分 含义
opcode操作码 0 add做加法运算
rs $s1 第一个来源寄存器
rt $s2 第二个来源寄存器
rd $s3 目标寄存器
shamt 0 位移量
funct 32 函数,这个字段选择Opcode操作某个特定变体
助记符 opcode rs rt rd shamt funct 示例 示例含义 操作
add 000000 rs rt rd 00000 100000 add $1,$2,$3 $1=$2+$3 带符号数相加
addu 000000 rs rt rd 00000 100001 add $1,$2,$3 $1=$2+$3 无符号数相加
sll 000000 00000 rt rd sa 000000 sll rd,rt,sa rd = rt << sa 逻辑左移,寄存器rt的值向左移sa位,结果保存到rd寄存器中
add $s3,$s1,$s2
addi $s1,$zero,1
sll s2,s1,1
console.log((0x02329820).toString('2'));

2.4 程序指针 #

汇编指令 含义
addi $s1,$zero,1 把$zero中的值加上数字1保存到寄存器$1中
addi $s2,$zero,2 把$zero中的值加上数字2保存到寄存器$1中
add $s3,$s1,$s2 把寄存器$s1和寄存器$2的和存储到$s3中

3.V8 #

3.1 语言的分类 #

3.1.1 解释执行 #

3.1.2 编译执行 #

3.2 V8执行过程 #

3.2.1 抽象语法树 #

var a = 1;
var b = 2;
var c = a + b;
d8 --print-ast 4.js
[generating bytecode for function: ]
--- AST ---
FUNC at 0
. KIND 0
. SUSPEND COUNT 0
. NAME ""
. INFERRED NAME ""
. DECLS
. . VARIABLE (00000278B965EB88) (mode = VAR) "a"
. . VARIABLE (00000278B965EC78) (mode = VAR) "b"
. . VARIABLE (00000278B965EDB0) (mode = VAR) "c"
. BLOCK NOCOMPLETIONS at -1
. . EXPRESSION STATEMENT at 8
. . . INIT at 8
. . . . VAR PROXY unallocated (00000278B965EB88) (mode = VAR) "a"
. . . . LITERAL 1
. BLOCK NOCOMPLETIONS at -1
. . EXPRESSION STATEMENT at 20
. . . INIT at 20
. . . . VAR PROXY unallocated (00000278B965EC78) (mode = VAR) "b"
. . . . LITERAL 2
. BLOCK NOCOMPLETIONS at -1
. . EXPRESSION STATEMENT at 32
. . . INIT at 32
. . . . VAR PROXY unallocated (00000278B965EDB0) (mode = VAR) "c"
. . . . ADD at 34
. . . . . VAR PROXY unallocated (00000278B965EB88) (mode = VAR) "a"
. . . . . VAR PROXY unallocated (00000278B965EC78) (mode = VAR) "b"

3.2.2 作用域 #

d8 --print-scopes 1.js
Global scope:
global { // (000001D42188BEC0) (0, 38)
  // will be compiled
  // 1 stack slots
  // temporary vars:
  TEMPORARY .result;  // (000001D42188C730) local[0]
  // local vars:
  VAR c;  // (000001D42188C670)
  VAR b;  // (000001D42188C538)
  VAR a;  // (000001D42188C448)
}

3.2.3 字节码 #

var a = 10;
var b = 20;
var c = a + b;
d8 --print-bytecode  4.js
LdaConstant [0] 从常量池中加载索引0的常量到累加寄存器中
Star r1 把累加器的值保存到目标寄存器中
LdaZero 把0保存到累加寄存器中
Star r2 把累加器的值0保存到目标寄存器中
Mov <closure>, r3 保存r3寄存器的值
CallRuntime [DeclareGlobals], r1-r3

StackCheck    检查栈是否溢出

LdaSmi [10]   加载10到累加寄存器中
StaGlobal [1] 把累加寄存器的值保存到常量池索引1处

LdaSmi [20]   加载20到累加寄存器中
StaGlobal [2] 把累加寄存器的值保存到常量池索引2处

LdaGlobal [1] 从常量池加载索引1到累加寄存器
Star r1       把累加器的值10保存到目标计数器中
LdaGlobal [2] 从常量池加载索引2的值20到累加寄存器
Add r1  把r1寄存器的值加到累加寄存器中,累加寄存器值为30
StaGlobal [3] 把累加寄存器的值保存到常量池索引3处
LdaUndefined  把Undefined保存到累加寄存器中
Return        返回累加寄存器中的值

3.2.4 编译器优化 #

function sum() {
    let a = 1;
    let b = 2;
    return a + b;
}
for (let i = 0; i < 10000; i++) {
    sum();
}
d8 --trace-opt sum.js
[marking 0x02ccc2ba2279 <JSFunction (sfi = 000002CCC2BA2091)> for optimized recompilation, reason: small function, ICs with typeinfo: 4/4 (100%), generic ICs: 0/4 (0%)]
[marking 0x02ccc2ba2339 <JSFunction sum (sfi = 000002CCC2BA2141)> for optimized recompilation, reason: small function, ICs with typeinfo: 1/1 (100%), generic ICs: 0/1 (0%)]
[compiling method 0x02ccc2ba2339 <JSFunction sum (sfi = 000002CCC2BA2141)> using TurboFan]