V8 Code Caching
概述
v8使用JIT执行JavaScript代码,因此在执行前需要解析并编译,由于每次执行前都需要做此操作的话开销过大,引入code cache来优化(version >= 4.2)。
script 第一次执行后,会保存其cache data。下一次v8编译相同script时(不同的v8实例也可以使用)则会使用cache data。
一个早期版本的code cache功能api测试用例:testcase
当v8编译一个script脚本后,可以通过添加v8::ScriptCompiler::kProduceCodeCache选项来生成相应的cache data用于后续的编译。如果编译成功,则会将cache data添加到source object并且可以通过调用v8::ScriptCompiler::Source::GetCacheData获取。
注:
v8::ScriptCompiler::kProduceCodeCache被废弃,新api:v8::ScriptCompiler::GetCodeCache
在后续的编译中,先前生成的cache data可以被添加到source object并添加v8::ScriptCompiler::kConsumeCodeCache选项来启用cache。此时code可以更快执行。
v8 6.6版本以后不仅会cache保存top-level代码,而且会保存top-level code执行后产生的代码,即“懒编译”的函数也被涵盖在内。
Chrome的Code Cache功能:
- cold load:第一次加载page,没有cache data
- warm load:之前加载过page,存在相应cache(需要在72h内并且script source需要超过1KB)
- hot load:page加载过两次,可以使用cached data
比较深入的版本
参考:https://swarm.ptsecurity.com/how-we-bypassed-bytenode-and-decompiled-node-js-bytecode-in-ghidra/
该文章介绍了对v8 bytecode的ghidra反汇编插件。