/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/objects/shared-function-info.h
993 строки
39 KB
Michaël Zasso
deps: update V8 to 14.6.202.33
24 апр 2026, 19:01
Не верифицирован
24 апр 2026, 19:01
f1e0b83
Код
Авторство
О чём код?
// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_OBJECTS_SHARED_FUNCTION_INFO_H_ #define V8_OBJECTS_SHARED_FUNCTION_INFO_H_ #include <memory> #include <optional> #include "src/base/bit-field.h" #include "src/base/macros.h" #include "src/builtins/builtins.h" #include "src/codegen/bailout-reason.h" #include "src/common/globals.h" #include "src/objects/compressed-slots.h" #include "src/objects/function-kind.h" #include "src/objects/function-syntax-kind.h" #include "src/objects/name.h" #include "src/objects/objects.h" #include "src/objects/script.h" #include "src/objects/slots.h" #include "src/objects/smi.h" #include "src/objects/struct.h" #include "src/objects/tagged-field.h" #include "src/objects/trusted-object.h" #include "src/roots/roots.h" #include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck #include "torque-generated/bit-fields.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" namespace v8::internal { class AsmWasmData; class BytecodeArray; class CoverageInfo; class DebugInfo; class IsCompiledScope; template <typename> class Signature; class WasmFunctionData; class WasmCapiFunctionData; class WasmExportedFunctionData; class WasmJSFunctionData; class WasmResumeData; #if V8_ENABLE_WEBASSEMBLY namespace wasm { class CanonicalValueType; struct WasmModule; class ValueType; } // namespace wasm #endif #include "torque-generated/src/objects/shared-function-info-tq.inc" // Defines whether the source positions should be created during function // compilation. enum class CreateSourcePositions { kNo, kYes }; // Data collected by the pre-parser storing information about scopes and inner // functions. // // PreparseData Layout: // +-------------------------------+ // | data_length | children_length | // +-------------------------------+ // | Scope Byte Data ... | // | ... | // +-------------------------------+ // | [Padding] | // +-------------------------------+ // | Inner PreparseData 1 | // +-------------------------------+ // | ... | // +-------------------------------+ // | Inner PreparseData N | // +-------------------------------+ V8_OBJECT class PreparseData : public HeapObjectLayout { public: int32_t data_length() const { return data_length_; } void set_data_length(int32_t value) { data_length_ = value; } int32_t children_length() const { return children_length_; } void set_children_length(int32_t value) { children_length_ = value; } inline uint8_t get(int index) const; inline void set(int index, uint8_t value); inline void copy_in(int index, const uint8_t* buffer, int length); inline Tagged<PreparseData> get_child(int index) const; inline void set_child(int index, Tagged<PreparseData> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); // Clear uninitialized padding space. inline void clear_padding(); DECL_PRINTER(PreparseData) DECL_VERIFIER(PreparseData) class BodyDescriptor; static inline int SizeFor(int data_length, int children_length); private: friend class TorqueGeneratedPreparseDataAsserts; template <typename Impl> friend class FactoryBase; static int ChildrenOffsetInData(int data_length) { return RoundUp(data_length * kByteSize, kTaggedSize); } uint8_t* data() { return reinterpret_cast<uint8_t*>(data_and_children()); } const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(data_and_children()); } TaggedMember<PreparseData>* children() { return reinterpret_cast<TaggedMember<PreparseData>*>( &data_and_children()[ChildrenOffsetInData(data_length())]); } const TaggedMember<PreparseData>* children() const { return reinterpret_cast<const TaggedMember<PreparseData>*>( &data_and_children()[ChildrenOffsetInData(data_length())]); } inline int children_start_offset() const; int32_t data_length_; int32_t children_length_; FLEXIBLE_ARRAY_MEMBER(char, data_and_children); } V8_OBJECT_END; static_assert(IsAligned(OFFSET_OF_DATA_START(PreparseData), alignof(TaggedMember<PreparseData>))); // Abstract class representing extra data for an uncompiled function, which is // not stored in the SharedFunctionInfo. V8_OBJECT class UncompiledData : public ExposedTrustedObjectLayout { public: inline Tagged<String> inferred_name() const; inline void set_inferred_name(Tagged<String> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline int32_t start_position() const { return start_position_; } inline void set_start_position(int32_t value) { start_position_ = value; } inline int32_t end_position() const { return end_position_; } inline void set_end_position(int32_t value) { end_position_ = value; } inline void InitAfterBytecodeFlush( Isolate* isolate, Tagged<String> inferred_name, int start_position, int end_position, std::function<void(Tagged<HeapObject> object, ObjectSlot slot, Tagged<HeapObject> target)> gc_notify_updated_slot); DECL_VERIFIER(UncompiledData) friend class Torque; friend struct OffsetsForDebug; TaggedMember<String> inferred_name_; int32_t start_position_; int32_t end_position_; } V8_OBJECT_END; // Class representing data for an uncompiled function that does not have any // data from the pre-parser, either because it's a leaf function or because the // pre-parser bailed out. V8_OBJECT class UncompiledDataWithoutPreparseData : public UncompiledData { public: DECL_PRINTER(UncompiledDataWithoutPreparseData) DECL_VERIFIER(UncompiledDataWithoutPreparseData) class BodyDescriptor; } V8_OBJECT_END; // Class representing data for an uncompiled function that has pre-parsed scope // data. V8_OBJECT class UncompiledDataWithPreparseData : public UncompiledData { public: inline Tagged<PreparseData> preparse_data() const; inline void set_preparse_data(Tagged<PreparseData> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); DECL_PRINTER(UncompiledDataWithPreparseData) DECL_VERIFIER(UncompiledDataWithPreparseData) class BodyDescriptor; TaggedMember<PreparseData> preparse_data_; } V8_OBJECT_END; // Class representing data for an uncompiled function that does not have any // data from the pre-parser, either because it's a leaf function or because the // pre-parser bailed out, but has a job pointer. V8_OBJECT class UncompiledDataWithoutPreparseDataWithJob : public UncompiledDataWithoutPreparseData { public: inline Address job() const { return job_; } inline void set_job(Address value) { job_ = value; } DECL_PRINTER(UncompiledDataWithoutPreparseDataWithJob) DECL_VERIFIER(UncompiledDataWithoutPreparseDataWithJob) class BodyDescriptor; Address job_; } V8_OBJECT_END; // Class representing data for an uncompiled function that has pre-parsed scope // data and a job pointer. V8_OBJECT class UncompiledDataWithPreparseDataAndJob : public UncompiledDataWithPreparseData { public: inline Address job() const { return job_; } inline void set_job(Address value) { job_ = value; } DECL_PRINTER(UncompiledDataWithPreparseDataAndJob) DECL_VERIFIER(UncompiledDataWithPreparseDataAndJob) class BodyDescriptor; Address job_; } V8_OBJECT_END; V8_OBJECT class InterpreterData : public ExposedTrustedObjectLayout { public: inline Tagged<BytecodeArray> bytecode_array() const; inline void set_bytecode_array(Tagged<BytecodeArray> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline bool has_bytecode_array() const; inline void clear_bytecode_array(); inline Tagged<Code> interpreter_trampoline() const; inline void set_interpreter_trampoline( Tagged<Code> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline bool has_interpreter_trampoline() const; inline void clear_interpreter_trampoline(); DECL_VERIFIER(InterpreterData) DECL_PRINTER(InterpreterData) class BodyDescriptor; private: friend class TorqueGeneratedInterpreterDataAsserts; friend class MacroAssembler; friend class CodeStubAssembler; ProtectedTaggedMember<BytecodeArray> bytecode_array_; ProtectedTaggedMember<Code> interpreter_trampoline_; } V8_OBJECT_END; using NameOrScopeInfoT = UnionOf<Smi, String, ScopeInfo>; // SharedFunctionInfo describes the JSFunction information that can be // shared by multiple instances of the function. class SharedFunctionInfo : public TorqueGeneratedSharedFunctionInfo<SharedFunctionInfo, HeapObject> { public: DEFINE_TORQUE_GENERATED_SHARED_FUNCTION_INFO_FLAGS() DEFINE_TORQUE_GENERATED_SHARED_FUNCTION_INFO_FLAGS2() // This initializes the SharedFunctionInfo after allocation. It must // initialize all fields, and leave the SharedFunctionInfo in a state where // it is safe for the GC to visit it. // // Important: This function MUST not allocate. void Init(ReadOnlyRoots roots, int unique_id); V8_EXPORT_PRIVATE static constexpr Tagged<Smi> const kNoSharedNameSentinel = Smi::zero(); // [name]: Returns shared name if it exists or an empty string otherwise. inline Tagged<String> Name() const; inline void SetName(Tagged<String> name); // Get the code object which represents the execution of this function. V8_EXPORT_PRIVATE Tagged<Code> GetCode(Isolate* isolate) const; // Get the abstract code associated with the function, which will either be // a Code object or a BytecodeArray. inline Tagged<AbstractCode> abstract_code(Isolate* isolate); // Set up the link between shared function info and the script. The shared // function info is added to the list on the script. V8_EXPORT_PRIVATE void SetScript(IsolateForSandbox isolate, ReadOnlyRoots roots, Tagged<HeapObject> script_object, int function_literal_id, bool reset_preparsed_scope_data = true); // Copy the data from another SharedFunctionInfo. Used for copying data into // and out of a placeholder SharedFunctionInfo, for off-thread compilation // which is not allowed to touch a main-thread-visible SharedFunctionInfo. void CopyFrom(Tagged<SharedFunctionInfo> other, IsolateForSandbox isolate); // Layout description of the optimized code map. static const int kEntriesStart = 0; static const int kContextOffset = 0; static const int kCachedCodeOffset = 1; static const int kEntryLength = 2; static const int kInitialLength = kEntriesStart + kEntryLength; static const int kNotFound = -1; static constexpr int kAgeSize = kAgeOffsetEnd - kAgeOffset + 1; static constexpr uint16_t kMaxAge = UINT16_MAX; DECL_ACQUIRE_GETTER(scope_info, Tagged<ScopeInfo>) // Deprecated, use the ACQUIRE version instead. DECL_GETTER(scope_info, Tagged<ScopeInfo>) // Slow but safe: inline Tagged<ScopeInfo> EarlyScopeInfo(AcquireLoadTag tag); // Set scope_info without moving the existing name onto the ScopeInfo. inline void set_raw_scope_info(Tagged<ScopeInfo> scope_info, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline void SetScopeInfo(Tagged<ScopeInfo> scope_info, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline bool is_script() const; inline bool needs_script_context() const; // End position of this function in the script source. V8_EXPORT_PRIVATE int EndPosition() const; // Start position of this function in the script source. V8_EXPORT_PRIVATE int StartPosition() const; V8_EXPORT_PRIVATE void UpdateFromFunctionLiteralForLiveEdit( IsolateForSandbox isolate, FunctionLiteral* lit); // [outer scope info | feedback metadata] Shared storage for outer scope info // (on uncompiled functions) and feedback metadata (on compiled functions). DECL_ACCESSORS(raw_outer_scope_info_or_feedback_metadata, Tagged<UnionOf<ScopeInfo, FeedbackMetadata, TheHole>>) DECL_ACQUIRE_GETTER(raw_outer_scope_info_or_feedback_metadata, Tagged<UnionOf<ScopeInfo, FeedbackMetadata, TheHole>>) private: using TorqueGeneratedSharedFunctionInfo:: outer_scope_info_or_feedback_metadata; using TorqueGeneratedSharedFunctionInfo:: set_outer_scope_info_or_feedback_metadata; public: // Get the outer scope info whether this function is compiled or not. inline bool HasOuterScopeInfo() const; inline Tagged<ScopeInfo> GetOuterScopeInfo() const; // [feedback metadata] Metadata template for feedback vectors of instances of // this function. inline bool HasFeedbackMetadata() const; inline bool HasFeedbackMetadata(AcquireLoadTag tag) const; DECL_GETTER(feedback_metadata, Tagged<FeedbackMetadata>) DECL_RELEASE_ACQUIRE_ACCESSORS(feedback_metadata, Tagged<FeedbackMetadata>) // Returns if this function has been compiled yet. Note: with bytecode // flushing, any GC after this call is made could cause the function // to become uncompiled. If you need to ensure the function remains compiled // for some period of time, use IsCompiledScope instead. inline bool is_compiled() const; // Returns an IsCompiledScope which reports whether the function is compiled, // and if compiled, will avoid the function becoming uncompiled while it is // held. template <typename IsolateT> inline IsCompiledScope is_compiled_scope(IsolateT* isolate) const; // [internal formal parameter count]: The declared number of parameters. // For subclass constructors, also includes new.target. // // NOTE: SharedFunctionInfo objects are located inside the sandbox, so an // attacker able to corrupt in-sandbox memory can change this field // arbitrarily. As such, it is not safe to use this field for invoking a // JSFunction or computing the size of stack frames (or similar use-cases // that involve accessing out-of-sandbox memory such as the stack). Instead, // for such purposes, a trusted parameter count must be used, the source of // which depends on the concrete use case. For example, a (trusted) parameter // count can be obtained from a BytecodeArray (e.g. for interpreting // bytecode), a Code object (e.g. for deoptimizing optimized code), or the // JSDispatchTable (e.g. for invoking a JSFunction). inline void set_internal_formal_parameter_count(int value); inline uint16_t internal_formal_parameter_count_with_receiver() const; inline uint16_t internal_formal_parameter_count_without_receiver() const; inline uint32_t unused_parameter_bits() const; inline bool CanOnlyAccessFixedFormalParameters() const; inline bool IsSloppyNormalJSFunction() const; private: using TorqueGeneratedSharedFunctionInfo::formal_parameter_count; using TorqueGeneratedSharedFunctionInfo::set_formal_parameter_count; public: // Set the formal parameter count so the function code will be // called without using argument adaptor frames. inline void DontAdaptArguments(); // Accessors for the data associated with this SFI. // // Currently it can be one of: // - a FunctionTemplateInfo to make benefit the API [IsApiFunction()]. // - a BytecodeArray for the interpreter [HasBytecodeArray()]. // - a InterpreterData with the BytecodeArray and a copy of the // interpreter trampoline [HasInterpreterData()] // - an AsmWasmData with Asm->Wasm conversion [HasAsmWasmData()]. // - a Smi containing the builtin id [HasBuiltinId()] // - a UncompiledDataWithoutPreparseData for lazy compilation // [HasUncompiledDataWithoutPreparseData()] // - a UncompiledDataWithPreparseData for lazy compilation // [HasUncompiledDataWithPreparseData()] // - a WasmExportedFunctionData for Wasm [HasWasmExportedFunctionData()] // - a WasmJSFunctionData for functions created with WebAssembly.Function // - a WasmCapiFunctionData for Wasm C-API functions // - a WasmResumeData for JSPI Wasm functions // // If the (expected) type of data is known, prefer to use the specialized // accessors (e.g. bytecode_array(), uncompiled_data(), etc.). inline Tagged<Object> GetTrustedData(IsolateForSandbox isolate) const; inline Tagged<Object> GetUntrustedData() const; // Helper function for use when a specific data type is expected. template <typename T, IndirectPointerTagRange tag_range> inline Tagged<T> GetTrustedData(IsolateForSandbox isolate) const; // Some code may encounter unreachable unusable objects and needs to skip // over them without crashing. // If we end up needing to check for this condition in many places, it might // be easier to instead clear the trusted pointer of these SFIs as they are // anyway unusable (and should always be unreachable as well). inline bool HasUnpublishedTrustedData(IsolateForSandbox isolate) const; private: // For the sandbox, the function's data is split across two fields, with the // "trusted" part containing a trusted pointer and the regular/untrusted part // containing a tagged pointer. In that case, code accessing the data field // will first load the trusted data field. If that is empty (i.e. // kNullIndirectPointerHandle), it will then load the regular field. With // that, the only racy transition would be a tagged -> trusted transition // (one thread may first read the empty trusted pointer, then another thread // transitions to the trusted field, clearing the tagged field, and then the // first thread continues to load the tagged field). As such, this transition // is only allowed on the main thread. From a GC perspective, both fields // always contain a valid value and so can be processed unconditionally. // Only one of these two fields should be in use at any time and the other // field should be cleared. As such, when setting these fields use // SetTrustedData() and SetUntrustedData() which automatically clear the // inactive field. // TODO(chromium:1490564): try to merge these two fields back together, for // example by moving all data objects into trusted space. inline void SetTrustedData(Tagged<ExposedTrustedObject> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline void SetUntrustedData(Tagged<Object> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline bool HasTrustedData() const; inline bool HasUntrustedData() const; public: static constexpr IndirectPointerTagRange kTrustedDataIndirectPointerRange = kAllIndirectPointerTags; inline bool IsApiFunction() const; inline bool is_class_constructor() const; DECL_ACCESSORS(api_func_data, Tagged<FunctionTemplateInfo>) DECL_GETTER(HasBytecodeArray, bool) template <typename IsolateT> inline Tagged<BytecodeArray> GetBytecodeArray(IsolateT* isolate) const; inline Tagged<BytecodeArray> GetBytecodeArrayForGC(Isolate* isolate) const; // Sets the bytecode for this SFI. This is only allowed when this SFI has not // yet been compiled or if it has been "uncompiled", or in other words when // there is no existing bytecode yet. inline void set_bytecode_array(Tagged<BytecodeArray> bytecode); // Like set_bytecode_array but allows overwriting existing bytecode. inline void overwrite_bytecode_array(Tagged<BytecodeArray> bytecode); inline Tagged<Code> InterpreterTrampoline(IsolateForSandbox isolate) const; inline bool HasInterpreterData(IsolateForSandbox isolate) const; inline Tagged<InterpreterData> interpreter_data( IsolateForSandbox isolate) const; inline void set_interpreter_data( Isolate* isolate, Tagged<InterpreterData> interpreter_data, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); DECL_GETTER(HasBaselineCode, bool) DECL_RELEASE_ACQUIRE_ACCESSORS(baseline_code, Tagged<Code>) inline void FlushBaselineCode(); inline Tagged<BytecodeArray> GetActiveBytecodeArray(Isolate* isolate) const; inline void SetActiveBytecodeArray(Tagged<BytecodeArray> bytecode, IsolateForSandbox isolate); #if V8_ENABLE_WEBASSEMBLY inline bool HasAsmWasmData() const; inline bool HasWasmFunctionData(IsolateForSandbox) const; inline bool HasWasmExportedFunctionData(IsolateForSandbox) const; inline bool HasWasmJSFunctionData(IsolateForSandbox) const; inline bool HasWasmCapiFunctionData(IsolateForSandbox) const; inline bool HasWasmResumeData() const; DECL_ACCESSORS(asm_wasm_data, Tagged<AsmWasmData>) // Note: The accessors below will read a trusted pointer; when accessing it // again, you must assume that it might have been swapped out e.g. by a // concurrently running worker. DECL_GETTER(wasm_function_data, Tagged<WasmFunctionData>) DECL_GETTER(wasm_exported_function_data, Tagged<WasmExportedFunctionData>) DECL_GETTER(wasm_js_function_data, Tagged<WasmJSFunctionData>) DECL_GETTER(wasm_capi_function_data, Tagged<WasmCapiFunctionData>) DECL_GETTER(wasm_resume_data, Tagged<WasmResumeData>) #endif // V8_ENABLE_WEBASSEMBLY // builtin corresponds to the auto-generated Builtin enum. inline bool HasBuiltinId() const; DECL_PRIMITIVE_ACCESSORS(builtin_id, Builtin) inline bool HasUncompiledData(IsolateForSandbox isolate) const; inline Tagged<UncompiledData> uncompiled_data( IsolateForSandbox isolate) const; inline void set_uncompiled_data(Tagged<UncompiledData> data, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline bool HasUncompiledDataWithPreparseData( IsolateForSandbox isolate) const; inline Tagged<UncompiledDataWithPreparseData> uncompiled_data_with_preparse_data(IsolateForSandbox isolate) const; inline void set_uncompiled_data_with_preparse_data( Tagged<UncompiledDataWithPreparseData> data, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); inline bool HasUncompiledDataWithoutPreparseData( IsolateForSandbox isolate) const; inline void ClearUncompiledDataJobPointer(IsolateForSandbox isolate); // Clear out pre-parsed scope data from UncompiledDataWithPreparseData, // turning it into UncompiledDataWithoutPreparseData. inline void ClearPreparseData(IsolateForSandbox isolate); // The inferred_name is inferred from variable or property assignment of this // function. It is used to facilitate debugging and profiling of JavaScript // code written in OO style, where almost all functions are anonymous but are // assigned to object properties. inline bool HasInferredName(); DECL_GETTER(inferred_name, Tagged<String>) // All DebugInfo accessors forward to the Debug object which stores DebugInfo // objects in a sidetable. bool HasDebugInfo(Isolate* isolate) const; V8_EXPORT_PRIVATE Tagged<DebugInfo> GetDebugInfo(Isolate* isolate) const; V8_EXPORT_PRIVATE std::optional<Tagged<DebugInfo>> TryGetDebugInfo( Isolate* isolate) const; V8_EXPORT_PRIVATE bool HasBreakInfo(Isolate* isolate) const; bool BreakAtEntry(Isolate* isolate) const; bool HasCoverageInfo(Isolate* isolate) const; Tagged<CoverageInfo> GetCoverageInfo(Isolate* isolate) const; // The function's name if it is non-empty, otherwise the inferred name. std::unique_ptr<char[]> DebugNameCStr() const; static Handle<String> DebugName(Isolate* isolate, DirectHandle<SharedFunctionInfo> shared); // Used for flags such as --turbo-filter. bool PassesFilter(const char* raw_filter); // [script]: the Script from which the function originates, or undefined. DECL_RELEASE_ACQUIRE_ACCESSORS(script, Tagged<HeapObject>) // Use `raw_script` if deserialization of this SharedFunctionInfo may still // be in progress and thus the `script` field still equal to // Smi::uninitialized_deserialization_value. DECL_RELEASE_ACQUIRE_ACCESSORS(raw_script, Tagged<Object>) // TODO(jgruber): Remove these overloads and pass the kAcquireLoad tag // explicitly. inline Tagged<HeapObject> script() const; inline Tagged<HeapObject> script(PtrComprCageBase cage_base) const; inline bool has_script(AcquireLoadTag tag) const; // True if the underlying script was parsed and compiled in REPL mode. inline bool is_repl_mode() const; // The offset of the 'function' token in the script source relative to the // start position. Can return kFunctionTokenOutOfRange if offset doesn't // fit in 16 bits. DECL_UINT16_ACCESSORS(raw_function_token_offset) private: using TorqueGeneratedSharedFunctionInfo::function_token_offset; using TorqueGeneratedSharedFunctionInfo::set_function_token_offset; public: // The position of the 'function' token in the script source. Can return // kNoSourcePosition if raw_function_token_offset() returns // kFunctionTokenOutOfRange. inline int function_token_position() const; // Returns true if the function has shared name. inline bool HasSharedName() const; // [flags] Bit field containing various flags about the function. DECL_RELAXED_INT32_ACCESSORS(flags) DECL_RELAXED_INT32_ACCESSORS(function_literal_id) DECL_UINT8_ACCESSORS(flags2) DECL_UINT16_ACCESSORS(age) // True if the outer class scope contains a private brand for // private instance methods. DECL_BOOLEAN_ACCESSORS(class_scope_has_private_brand) DECL_BOOLEAN_ACCESSORS(has_static_private_methods_or_accessors) DECL_BOOLEAN_ACCESSORS(is_sparkplug_compiling) DECL_BOOLEAN_ACCESSORS(maglev_compilation_failed) CachedTieringDecision cached_tiering_decision(); void set_cached_tiering_decision(CachedTieringDecision decision); DECL_BOOLEAN_ACCESSORS(function_context_independent_compiled) // Is this function a top-level function (scripts, evals). DECL_BOOLEAN_ACCESSORS(is_toplevel) // Indicates if this function can be lazy compiled. DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation) // Indicates the language mode. inline LanguageMode language_mode() const; inline void set_language_mode(LanguageMode language_mode); // How the function appears in source text. DECL_PRIMITIVE_ACCESSORS(syntax_kind, FunctionSyntaxKind) // Indicates whether the source is implicitly wrapped in a function. inline bool is_wrapped() const; // True if the function has any duplicated parameter names. DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters) // Indicates whether the function is a native function. // These needs special treatment in .call and .apply since // null passed as the receiver should not be translated to the // global object. DECL_BOOLEAN_ACCESSORS(native) #if V8_ENABLE_WEBASSEMBLY // Indicates that asm->wasm conversion failed and should not be re-attempted. DECL_BOOLEAN_ACCESSORS(is_asm_wasm_broken) #endif // V8_ENABLE_WEBASSEMBLY // Indicates that the function was created by the Function function. // Though it's anonymous, toString should treat it as if it had the name // "anonymous". We don't set the name itself so that the system does not // see a binding for it. DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous) // Whether or not the number of expected properties may change. DECL_BOOLEAN_ACCESSORS(are_properties_final) // Indicates that the function has been reported for binary code coverage. DECL_BOOLEAN_ACCESSORS(has_reported_binary_coverage) // Indicates that the private name lookups inside the function skips the // closest outer class scope. DECL_BOOLEAN_ACCESSORS(private_name_lookup_skips_outer_class) // Indicates that the shared function info was live-edited. DECL_BOOLEAN_ACCESSORS(live_edited) inline FunctionKind kind() const; int UniqueIdInScript() const; // Defines the index in a native context of closure's map instantiated using // this shared function info. DECL_INT_ACCESSORS(function_map_index) // Recalculates the |map_index| value after modifications of this shared info. inline void UpdateFunctionMapIndex(); // Indicates whether optimizations have been disabled for this shared function // info. If we cannot optimize the function we disable optimization to avoid // spending time attempting to optimize it again. inline bool optimization_disabled(CodeKind kind) const; inline bool all_optimization_disabled() const; // The reason why optimization was disabled. inline BailoutReason disabled_optimization_reason() const; // Disable (further) attempted optimization of all functions sharing this // shared function info. void DisableOptimization(Isolate* isolate, BailoutReason reason); // This class constructor needs to call out to an instance fields // initializer. This flag is set when creating the // SharedFunctionInfo as a reminder to emit the initializer call // when generating code later. DECL_BOOLEAN_ACCESSORS(requires_instance_members_initializer) // [source code]: Source code for the function. bool HasSourceCode() const; static DirectHandle<Object> GetSourceCode( Isolate* isolate, DirectHandle<SharedFunctionInfo> shared); static Handle<Object> GetSourceCodeHarmony( Isolate* isolate, DirectHandle<SharedFunctionInfo> shared); // Tells whether this function should be subject to debugging, e.g. for // - scope inspection // - internal break points // - coverage and type profile // - error stack trace inline bool IsSubjectToDebugging() const; // Whether this function is defined in user-provided JavaScript code. inline bool IsUserJavaScript() const; // True if one can flush compiled code from this function, in such a way that // it can later be re-compiled. inline bool CanDiscardCompiled() const; // Flush compiled data from this function, setting it back to CompileLazy and // clearing any compiled metadata. V8_EXPORT_PRIVATE static void DiscardCompiled( Isolate* isolate, DirectHandle<SharedFunctionInfo> shared_info); // Discard the compiled metadata. If called during GC then // |gc_notify_updated_slot| should be used to record any slot updates. void DiscardCompiledMetadata( Isolate* isolate, std::function<void(Tagged<HeapObject> object, ObjectSlot slot, Tagged<HeapObject> target)> gc_notify_updated_slot = [](Tagged<HeapObject> object, ObjectSlot slot, Tagged<HeapObject> target) {}); // Returns true if the function has old bytecode that could be flushed. This // function shouldn't access any flags as it is used by concurrent marker. // Hence it takes the mode as an argument. inline bool ShouldFlushCode(base::EnumSet<CodeFlushMode> code_flush_mode); enum Inlineability { // Different reasons for not being inlineable: kHasNoScript, kNeedsBinaryCoverage, kIsBuiltin, kIsNotUserCode, kHasNoBytecode, kExceedsBytecodeLimit, kMayContainBreakPoints, kHasOptimizationDisabled, // Actually inlineable! kIsInlineable, }; // Returns the first value that applies (see enum definition for the order). template <typename IsolateT> Inlineability GetInlineability(CodeKind code_kind, IsolateT* isolate) const; // Source size of this function. int SourceSize(); // Returns `false` if formal parameters include rest parameters, optional // parameters, or destructuring parameters. // TODO(caitp): make this a flag set during parsing inline bool has_simple_parameters() const; // Initialize a SharedFunctionInfo from a parsed or preparsed function // literal. template <typename IsolateT> static void InitFromFunctionLiteral(IsolateT* isolate, FunctionLiteral* lit, bool is_toplevel); template <typename IsolateT> static void CreateAndSetUncompiledData(IsolateT* isolate, FunctionLiteral* lit); // Updates the expected number of properties based on estimate from parser. void UpdateExpectedNofPropertiesFromEstimate(FunctionLiteral* literal); void UpdateAndFinalizeExpectedNofPropertiesFromEstimate( FunctionLiteral* literal); // Sets the FunctionTokenOffset field based on the given token position and // start position. void SetFunctionTokenPosition(int function_token_position, int start_position); static void EnsureBytecodeArrayAvailable( Isolate* isolate, Handle<SharedFunctionInfo> shared_info, IsCompiledScope* is_compiled_scope, CreateSourcePositions flag = CreateSourcePositions::kNo); inline bool CanCollectSourcePosition(Isolate* isolate); static void EnsureSourcePositionsAvailable( Isolate* isolate, DirectHandle<SharedFunctionInfo> shared_info); template <typename IsolateT> bool AreSourcePositionsAvailable(IsolateT* isolate) const; // Hash based on function literal id and script id. V8_EXPORT_PRIVATE uint32_t Hash(); inline bool construct_as_builtin() const; // Determines and sets the ConstructAsBuiltinBit in |flags|, based on the // |function_data|. Must be called when creating the SFI after other fields // are initialized. The ConstructAsBuiltinBit determines whether // JSBuiltinsConstructStub or JSConstructStubGeneric should be called to // construct this function. inline void CalculateConstructAsBuiltin(); // Replaces the current age with a new value if the current value matches the // one expected. Returns the value before this operation. inline uint16_t CompareExchangeAge(uint16_t expected_age, uint16_t new_age); // Bytecode aging V8_EXPORT_PRIVATE static void EnsureOldForTesting( Tagged<SharedFunctionInfo> sfu); // Dispatched behavior. DECL_PRINTER(SharedFunctionInfo) DECL_VERIFIER(SharedFunctionInfo) #ifdef VERIFY_HEAP void SharedFunctionInfoVerify(LocalIsolate* isolate); #endif #ifdef OBJECT_PRINT void PrintSourceCode(std::ostream& os); #endif // Iterate over all shared function infos in a given script. class ScriptIterator { public: V8_EXPORT_PRIVATE ScriptIterator(Isolate* isolate, Tagged<Script> script); explicit ScriptIterator(Handle<WeakFixedArray> infos); ScriptIterator(const ScriptIterator&) = delete; ScriptIterator& operator=(const ScriptIterator&) = delete; V8_EXPORT_PRIVATE Tagged<SharedFunctionInfo> Next(); int CurrentIndex() const { return index_ - 1; } // Reset the iterator to run on |script|. void Reset(Isolate* isolate, Tagged<Script> script); private: Handle<WeakFixedArray> infos_; int index_; }; // Constants. static const int kMaximumFunctionTokenOffset = kMaxUInt16 - 1; static const uint16_t kFunctionTokenOutOfRange = static_cast<uint16_t>(-1); static_assert(kMaximumFunctionTokenOffset + 1 == kFunctionTokenOutOfRange); static_assert(kSize % kTaggedSize == 0); class BodyDescriptor; // Bailout reasons must fit in the DisabledOptimizationReason bitfield. static_assert(DisabledOptimizationReasonBits::is_valid( BailoutReason::kLastErrorMessage)); static_assert(FunctionKindBits::is_valid(FunctionKind::kLastFunctionKind)); static_assert(FunctionSyntaxKindBits::is_valid( FunctionSyntaxKind::kLastFunctionSyntaxKind)); // Sets the bytecode in {shared}'s DebugInfo as the bytecode to // be returned by following calls to GetActiveBytecodeArray. Stores a // reference to the original bytecode in the DebugInfo. static void InstallDebugBytecode(DirectHandle<SharedFunctionInfo> shared, Isolate* isolate); // Removes the debug bytecode and restores the original bytecode to be // returned by following calls to GetActiveBytecodeArray. static void UninstallDebugBytecode(Tagged<SharedFunctionInfo> shared, Isolate* isolate); #ifdef DEBUG // Verifies that all SFI::unique_id values on the heap are unique, including // Isolate::new_unique_sfi_id_. static bool UniqueIdsAreUnique(Isolate* isolate); #endif // DEBUG private: #ifdef VERIFY_HEAP void SharedFunctionInfoVerify(ReadOnlyRoots roots); #endif // [name_or_scope_info]: Function name string, kNoSharedNameSentinel or // ScopeInfo. DECL_RELEASE_ACQUIRE_ACCESSORS(name_or_scope_info, Tagged<NameOrScopeInfoT>) // [outer scope info] The outer scope info, needed to lazily parse this // function. DECL_ACCESSORS(outer_scope_info, Tagged<UnionOf<ScopeInfo, TheHole>>) // [properties_are_final]: This bit is used to track if we have finished // parsing its properties. The properties final bit is only used by // class constructors to handle lazily parsed properties. DECL_BOOLEAN_ACCESSORS(properties_are_final) inline void set_kind(FunctionKind kind); inline uint16_t get_property_estimate_from_literal(FunctionLiteral* literal); // For ease of use of the BITFIELD macro. inline int32_t relaxed_flags() const; inline void set_relaxed_flags(int32_t flags); template <typename Impl> friend class FactoryBase; friend class V8HeapExplorer; FRIEND_TEST(PreParserTest, LazyFunctionLength); TQ_OBJECT_CONSTRUCTORS(SharedFunctionInfo) private: inline Tagged<BytecodeArray> GetBytecodeArrayInternal(Isolate* isolate) const; }; std::ostream& operator<<(std::ostream& os, SharedFunctionInfo::Inlineability i); // A SharedFunctionInfoWrapper wraps a SharedFunctionInfo from trusted space. // It can be useful when a protected pointer reference to a SharedFunctionInfo // is needed, for example for a ProtectedFixedArray. class SharedFunctionInfoWrapper : public TrustedObject { public: DECL_ACCESSORS(shared_info, Tagged<SharedFunctionInfo>) DECL_PRINTER(SharedFunctionInfoWrapper) DECL_VERIFIER(SharedFunctionInfoWrapper) #define FIELD_LIST(V) \ V(kSharedInfoOffset, kTaggedSize) \ V(kHeaderSize, 0) \ V(kSize, 0) DEFINE_FIELD_OFFSET_CONSTANTS(TrustedObject::kHeaderSize, FIELD_LIST) #undef FIELD_LIST class BodyDescriptor; OBJECT_CONSTRUCTORS(SharedFunctionInfoWrapper, TrustedObject); }; static constexpr int kStaticRootsSFISize = 48; #ifdef V8_STATIC_ROOTS static_assert(SharedFunctionInfo::kSize == kStaticRootsSFISize); #endif // V8_STATIC_ROOTS // Printing support. struct SourceCodeOf { explicit SourceCodeOf(Tagged<SharedFunctionInfo> v, int max = -1) : value(v), max_length(max) {} const Tagged<SharedFunctionInfo> value; int max_length; }; // IsCompiledScope enables a caller to check if a function is compiled, and // ensure it remains compiled (i.e., doesn't have it's bytecode flushed) while // the scope is retained. class V8_NODISCARD IsCompiledScope { public: inline IsCompiledScope(const Tagged<SharedFunctionInfo> shared, Isolate* isolate); inline IsCompiledScope(const Tagged<SharedFunctionInfo> shared, LocalIsolate* isolate); inline IsCompiledScope() = default; inline bool is_compiled() const { return is_compiled_; } private: MaybeHandle<HeapObject> retain_code_ = {}; bool is_compiled_ = false; }; // IsBaselineCompiledScope enables a caller to check if a function is baseline // compiled, and ensure it remains compiled (i.e., doesn't have it's baseline // code flushed) while the scope is retained. class V8_NODISCARD IsBaselineCompiledScope { public: inline IsBaselineCompiledScope(const Tagged<SharedFunctionInfo> shared, Isolate* isolate); inline IsBaselineCompiledScope() = default; inline bool is_compiled() const { return is_compiled_; } private: MaybeHandle<Code> retain_code_ = {}; bool is_compiled_ = false; }; std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v); } // namespace v8::internal #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_SHARED_FUNCTION_INFO_H_