本篇文章是Builtin专题的第五篇,详细分析Builtin的调用过程。在Bytecodehandler中使用CallBuiltin()调用Builtin是最常见的情况,本文将详解CallBuiltin()源码和相关的数据结构。本文内容组织方式:重要数据结构(章节2);CallBuiltin()源码(章节3)。
02数据结构提示:Just-In-TimeCompiler是本文的前导知识,请读者自行查阅。Builtin的调用过程主要分为两部分:查询Builtin表找到相应的入口函数、计算calldescriptor。下面解释相关的数据结构:(1)Builtin名字(例如Builtin::kStoreGlobalIC),名字是枚举类型变量,CallBuiltin()使用该名字查询Builtin表,找到相应的入口函数,源码如下:
classBuiltins{//...............省略....................enumName:int32_t{#defineDEF_ENUM(Name,...)k##Name,BUILTIN_LIST(DEF_ENUM,DEF_ENUM,DEF_ENUM,DEF_ENUM,DEF_ENUM,DEF_ENUM,DEF_ENUM)#undefDEF_ENUMbuiltin_count,}
展开之后如下:
enumName:int32_t{kRecordWrite,kEphemeronKeyBarrier,kAdaptorWithBuiltinExitFrame,kArgumentsAdaptorTrampoline,......}
(2)Builtin表存储Builtin的地址。Builtin表的位置是isoate-isolatedata-builtins_,源码如下:
classIsolateDatafinal{public:explicitIsolateData(Isolate*isolate):stack_guard_(isolate){}//............省略....................Address*builtins(){returnbuiltins_;}}
builtins_是Address类型的数组,与enumName:int32_t{}配合使用可查询对应的Builtin地址(下面的第2行代码就完成了地址查询),源码如下:
1.CallableBuiltins::CallableFor(Isolate*isolate,Namename){2.HandleCodecode=isolate-builtins()-builtin_handle(name);3.returnCallable{code,CallInterfaceDescriptorFor(name)};4.}
上述代码第3行CallInterfaceDescriptorFor返回Builtin的调用信息,该信息与code共同组成了Callable。(3)Code类,该类包括Builtin地址、指令的开始和结束以及填充信息,它的作用之一是创建snapshot文件,源码如下:
1.classCode:publicHeapObject{2.public:3.#defineCODE_KIND_LIST(V)\4.V(OPTIMIZED_FUNCTION)V(BYTECODE_HANDLER)\5.V(STUB)V(BUILTIN)V(REGEXP)V(WASM_FUNCTION)V(WASM_TO_CAPI_FUNCTION)\6.V(WASM_TO_JS_FUNCTION)V(JS_TO_WASM_FUNCTION)V(JS_TO_JS_FUNCTION)\7.V(WASM_INTERPRETER_ENTRY)V(C_WASM_ENTRY)8.inlineintbuiltin_index()const;9.inlineinthandler_table_offset()const;10.inlinevoidset_handler_table_offset(intoffset);11.//Thebodyofallcodeobjectshasthefollowinglayout.12.//+--------------------------+--raw_instruction_start()13.//
instructions
14.//
...
15.//+--------------------------+16.//
embeddedmetadata
--safepoint_table_offset()17.//
...
--handler_table_offset()18.//
--constant_pool_offset()19.//
--code_