Welcome to other chapters of Let’s Understand Chrome V8
When we learn V8, the SharedFunction and JSFunction are two very common and important terminologies that may confuse beginners. So what are they? What is the difference between them? In general, the main role of the ShardFunction is the place that lays the bytecodes, there is other stuff like the trampoline which I’ll talk about in the future. “Shared”, you can roughly think of the SharedFunction as a DLL library that can be called in anywhere. The compiler compiles a JavaScript function to a SharedFunction, and the SharedFunction can be used anywhere, like a DLL. This is the reason its name is Shared-function.
Roughly, a JSFunction equals a SharedFunction + a context. When V8 is going to call a SharedFunction, V8 needs to bind a context to the ShareFunction, the bind is a term of V8 which means it binds a SharedFuncton and a context together, namely a JSFunction. A JSFunction is an executable instance that can be executed by V8 interpreter ignition.
The following code is SharedFucntion class.
1. // SharedFunctionInfo describes the JSFunction information that can be
2. // shared by multiple instances of the function.
3. class SharedFunctionInfo : public HeapObject {
4. public:
5. V8_EXPORT_PRIVATE Code GetCode() const;
6. V8_EXPORT_PRIVATE static void SetScript(
7. Handle<SharedFunctionInfo> shared, Handle<Object> script_object,
8. int function_literal_id, bool reset_preparsed_scope_data = true);
9. V8_EXPORT_PRIVATE int EndPosition() const;
10. V8_EXPORT_PRIVATE int StartPosition() const;
11. V8_EXPORT_PRIVATE void SetPosition(int start_position, int end_position);
12. inline bool IsApiFunction() const;
13. inline bool is_class_constructor() const;
14. inline FunctionTemplateInfo get_api_func_data();
15. inline void set_api_func_data(FunctionTemplateInfo data);
16. inline bool HasBytecodeArray() const;
17. inline BytecodeArray GetBytecodeArray() const;
18. inline void set_bytecode_array(BytecodeArray bytecode);
19. inline Code InterpreterTrampoline() const;
20. inline bool HasInterpreterData() const;
21. inline InterpreterData interpreter_data() const;
22. inline void set_interpreter_data(InterpreterData interpreter_data);
23. // builtin_id corresponds to the auto-generated Builtins::Name id.
24. inline bool HasBuiltinId() const;
25. inline int builtin_id() const;
26. inline void set_builtin_id(int builtin_id);
27. inline bool HasUncompiledData() const;
28. inline UncompiledData uncompiled_data() const;
29. inline void set_uncompiled_data(UncompiledData data);
30. inline bool HasUncompiledDataWithPreparseData() const;
31. inline UncompiledDataWithPreparseData uncompiled_data_with_preparse_data()
32. const;
33. inline void set_uncompiled_data_with_preparse_data(
34. UncompiledDataWithPreparseData data);
35. inline bool HasUncompiledDataWithoutPreparseData() const;
36. inline LanguageMode language_mode() const;
37. inline void set_language_mode(LanguageMode language_mode);
38. DECL_PRIMITIVE_ACCESSORS(syntax_kind, FunctionSyntaxKind)
39. inline bool is_wrapped() const;
40. DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters)
41. DECL_BOOLEAN_ACCESSORS(native)
42. DECL_BOOLEAN_ACCESSORS(is_asm_wasm_broken)
43. DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous)
44. DECL_BOOLEAN_ACCESSORS(is_oneshot_iife)
45. DECL_BOOLEAN_ACCESSORS(are_properties_final)
46. DECL_BOOLEAN_ACCESSORS(is_safe_to_skip_arguments_adaptor)
47. DECL_BOOLEAN_ACCESSORS(has_reported_binary_coverage)
48. DECL_BOOLEAN_ACCESSORS(private_name_lookup_skips_outer_class)
49. inline FunctionKind kind() const;
50. DECL_INT_ACCESSORS(function_map_index)
51. inline void clear_padding();
52. inline void UpdateFunctionMapIndex();
53. inline bool optimization_disabled() const;
54. inline BailoutReason disable_optimization_reason() const;
55. void DisableOptimization(BailoutReason reason);
56. DECL_BOOLEAN_ACCESSORS(requires_instance_members_initializer)
57. bool HasSourceCode() const;
58. static Handle<Object> GetSourceCode(Handle<SharedFunctionInfo> shared);
59. static Handle<Object> GetSourceCodeHarmony(Handle<SharedFunctionInfo> shared);
60. inline bool IsSubjectToDebugging();
61. inline bool IsUserJavaScript();
62. inline bool CanDiscardCompiled() const;
63. void UpdateExpectedNofPropertiesFromEstimate(FunctionLiteral* literal);
64. void UpdateAndFinalizeExpectedNofPropertiesFromEstimate(
65. FunctionLiteral* literal);
66. DECL_CAST(SharedFunctionInfo)
67. // Constants.
68. static const uint16_t kDontAdaptArgumentsSentinel = static_cast<uint16_t>(-1);
69. static const int kMaximumFunctionTokenOffset = kMaxUInt16 - 1;
70. static const uint16_t kFunctionTokenOutOfRange = static_cast<uint16_t>(-1);
71. STATIC_ASSERT(kMaximumFunctionTokenOffset + 1 == kFunctionTokenOutOfRange);
72. DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
73. TORQUE_GENERATED_SHARED_FUNCTION_INFO_FIELDS)
74.//............omit..............
75. };
Lines 1–2 comment that a SharedFunction can be shared by multiple instances.
Here, I give you some important members of a SharedFunction.
#define BAILOUT_MESSAGES_LIST(V) \
V(kNoReason, "no reason") \
\
V(kBailedOutDueToDependencyChange, "Bailed out due to dependency change") \
V(kCodeGenerationFailed, "Code generation failed") \
V(kCyclicObjectStateDetectedInEscapeAnalysis, \
"Cyclic object state detected by escape analysis") \
V(kFunctionBeingDebugged, "Function is being debugged") \
V(kGraphBuildingFailed, "Optimized graph construction failed") \
V(kFunctionTooBig, "Function is too big to be optimized") \
V(kLiveEdit, "LiveEdit") \
V(kNativeFunctionLiteral, "Native function literal") \
V(kNotEnoughVirtualRegistersRegalloc, \
"Not enough virtual registers (regalloc)") \
V(kOptimizationDisabled, "Optimization disabled") \
V(kNeverOptimize, "Optimization is always disabled")
#define DECL_PRIMITIVE_ACCESSORS(name, type) \
inline type name() const; \
inline void set_##name(type value);
#define DECL_BOOLEAN_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, bool)
#define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO) \
enum { \
LIST_MACRO##_StartOffset = StartOffset - 1, \
LIST_MACRO(DEFINE_ONE_FIELD_OFFSET) \
};
//==================omit===========================
#define TORQUE_GENERATED_SHARED_FUNCTION_INFO_FIELDS(V) \
V(kStartOfWeakFieldsOffset, 0) \
V(kFunctionDataOffset, kTaggedSize) \
V(kEndOfWeakFieldsOffset, 0) \
V(kStartOfStrongFieldsOffset, 0) \
V(kNameOrScopeInfoOffset, kTaggedSize) \
V(kOuterScopeInfoOrFeedbackMetadataOffset, kTaggedSize) \
V(kScriptOrDebugInfoOffset, kTaggedSize) \
V(kEndOfStrongFieldsOffset, 0) \
V(kLengthOffset, kUInt16Size) \
V(kFormalParameterCountOffset, kUInt16Size) \
V(kExpectedNofPropertiesOffset, kUInt16Size) \
V(kFunctionTokenOffsetOffset, kUInt16Size) \
V(kFlagsOffset, kInt32Size) \
V(kFunctionLiteralIdOffset, kInt32Size) \
V(kUniqueIdOffset, kInt32Size) \
V(kSize, 0) \
//==============omit====================
#define FLAGS_BIT_FIELDS(V, _)//see line 70 above
The function NewFunctionFromSharedFunctionInfo reads a SharedFunction and generates the corresponding JSFunction. The following is the source code:
1. Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
2. Handle<SharedFunctionInfo> info, Handle<Context> context,
3. AllocationType allocation) {
4. Handle<Map> initial_map(
5. Map::cast(context->native_context().get(info->function_map_index())),
6. isolate());
7. return NewFunctionFromSharedFunctionInfo(initial_map, info, context,
8. allocation);
9. }
10. //==============分隔线============
11. Handle<JSFunction> Factory::NewFunction(Handle<Map> map,
12. Handle<SharedFunctionInfo> info,
13. Handle<Context> context,
14. AllocationType allocation) {
15. Handle<JSFunction> function(JSFunction::cast(New(map, allocation)),
16. isolate());
17. function->initialize_properties(isolate());
18. function->initialize_elements();
19. function->set_shared(*info);
20. function->set_code(info->GetCode());
21. function->set_context(*context);
22. function->set_raw_feedback_cell(*many_closures_cell());
23. //........omit...............
24. }
In the above code, line 7 calls the NewFunction().
Here, I give you some details about the NewFunction.
Okay, a SharedFunction can be shared by multiple instances and a JSFunction is an executable instance.
Okay, that wraps it up for this share. I’ll see you guys next time, take care!
Please reach out to me if you have any issues. WeChat: qq9123013 Email: [email protected]
Also published here.