前言
详情
<script>var n = 10;console.log(n);</script>
0x38f00800078 @ 0 : 13 00 LdaConstant0x38f0080007a @ 2 : d1 Star10x38f0080007b @ 3 : 1b fe f7 Mov <closure>, r20x38f0080007e @ 6 : 6e 70 01 f8 02 CallRuntime0x38f00800083 @ 11 : 0d 0a LdaSmi [10]0x38f00800085 @ 13 : 25 01 00 StaGlobal0x38f00800088 @ 16 : 23 02 02 LdaGlobal0x38f0080008b @ 19 : d0 Star20x38f0080008c @ 20 : 33 f7 03 04 GetNamedProperty r2,0x38f00800090 @ 24 : d1 Star10x38f00800091 @ 25 : 23 01 06 LdaGlobal0x38f00800094 @ 28 : cf Star30x38f00800095 @ 29 : 67 f8 f7 f6 08 CallProperty1 r1, r2, r3,0x38f0080009a @ 34 : d2 Star00x38f0080009b @ 35 : b7 Return
0x... ed3 6a14 push 0x14 //var n=100x... ed5 48b9... console map...0x... eea 49b8... JSFunction log...0x... efc 48bb... Builtin_ConsoleLog...0x... f15 call CEntry_Return1_ArgvOnStack_BuiltinExit //console.log(n)1e d1fa sarl rdx,1
0xA二进制:1010把它左移1位等于20也即是十六进制的0x14用的时候把它右移1位,还原成0xA,上面代码最后一行sarl rdx,1所以代码中看不到0xA
var n=10;console.log(n);
stub_entry.Call-》return fn_ptr_(args...)->
Builtins_JSEntryBuiltins_JSEntryTrampolineBuiltins_InterpreterEntryTrampoline
0x38f00800078 @ 0 : 13 00 LdaConstant
Builtin_字节码名称Handler
Builtins_LdaConstantHandler
Builtins_CallRuntimeHandler
Builtins_LdaSmiHandler
V8极致优化
Builtins_JSEntryBuiltins_JSEntryTrampolineBuiltins_InterpreterEntryTrampoline
"Builtins_JSEntry:\n"".def Builtins_JSEntry; .scl 2; .type 32; .endef;\n"" .octa 0x56415541544108ec8348026ae5894855,0x7f0f48f3000000a0ec81485356575741\n"" .octa 0x2024447f0f4cf310247c7f0f48f32434,0x4cf34024547f0f4cf330244c7f0f4cf3\n"" .octa 0x7f0f4cf36024647f0f4cf350245c7f0f,0xf4cf30000008024b47f0f4cf370246c\n"//便于观看,后面省略
Builtins_JSEntry没有函数名称,函数参数,以及函数代码,有的只是这些十六进数据。它就是Builtins_JSEntry函数的代码。这种做法,自然是提高了性能和效率。
更关键的是字节码的执行他同样是这种十六进制的形式,比如例子里面第一个被执行的字节码函数是Builtins_LdaConstantHandler,它的原型如下:
"Builtins_LdaConstantHandler:\n"".def Builtins_LdaConstantHandler; .scl 2; .type 32; .endef;\n"" .octa 0x90ba0d74d93b48fffffff91d8d48,0x48266ae5894855cc0000602095ff4100\n"" .octa 0x894cf0e4834828ec8348e2894930ec83,0x4cd0458948e07d894ce865894c202454\n"" .octa 0x4500002470858b4d00000216bad84d89,0x60858b49e1894cc6034d0000e94b808b\n"//便于观看,后面省略
相对于代码:
var n=10;
如果你在汇编代码中找类似于:
mov rax 10mov rcx 10
这种是找不到的,因为它只有
push 0x14
它变成了Smi格式存储,这种也是一种优化的方式。举个例子,如果要检查一个数值是不是Smi,只需要如下:
; 检查是否为 Smi,只需要一个位操作testb rax, 0x1 ; 测试最低位jz is_smi ; 如果是0,跳转到Smi处理
而不是:
if(数值==Smi){do something}else{do something}
V8的解释执行和V8的JIT执行的差距急剧缩小。
结尾
© 版权声明
文章版权归作者所有,未经允许请勿转载。
暂无评论...




