// 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_INL_H_ #define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_ #include "src/objects/shared-function-info.h" #include "src/handles/handles-inl.h" #include "src/heap/heap-write-barrier-inl.h" #include "src/objects/debug-objects-inl.h" #include "src/objects/feedback-vector-inl.h" #include "src/objects/scope-info.h" #include "src/objects/templates.h" #include "src/wasm/wasm-objects-inl.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" namespace v8 { namespace internal { TQ_OBJECT_CONSTRUCTORS_IMPL(PreparseData) int PreparseData::inner_start_offset() const { return InnerOffset(data_length()); } ObjectSlot PreparseData::inner_data_start() const { return RawField(inner_start_offset()); } void PreparseData::clear_padding() { int data_end_offset = kDataStartOffset + data_length(); int padding_size = inner_start_offset() - data_end_offset; DCHECK_LE(0, padding_size); if (padding_size == 0) return; memset(reinterpret_cast<void*>(address() + data_end_offset), 0, padding_size); } byte PreparseData::get(int index) const { DCHECK_LE(0, index); DCHECK_LT(index, data_length()); int offset = kDataStartOffset + index * kByteSize; return ReadField<byte>(offset); } void PreparseData::set(int index, byte value) { DCHECK_LE(0, index); DCHECK_LT(index, data_length()); int offset = kDataStartOffset + index * kByteSize; WriteField<byte>(offset, value); } void PreparseData::copy_in(int index, const byte* buffer, int length) { DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index && index + length <= this->data_length()); Address dst_addr = FIELD_ADDR(*this, kDataStartOffset + index * kByteSize); memcpy(reinterpret_cast<void*>(dst_addr), buffer, length); } PreparseData PreparseData::get_child(int index) const { return PreparseData::cast(get_child_raw(index)); } Object PreparseData::get_child_raw(int index) const { DCHECK_LE(0, index); DCHECK_LT(index, this->children_length()); int offset = inner_start_offset() + index * kTaggedSize; return RELAXED_READ_FIELD(*this, offset); } void PreparseData::set_child(int index, PreparseData value, WriteBarrierMode mode) { DCHECK_LE(0, index); DCHECK_LT(index, this->children_length()); int offset = inner_start_offset() + index * kTaggedSize; RELAXED_WRITE_FIELD(*this, offset, value); CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); } TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledData) TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithoutPreparseData) TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithPreparseData) OBJECT_CONSTRUCTORS_IMPL(InterpreterData, Struct) CAST_ACCESSOR(InterpreterData) ACCESSORS(InterpreterData, bytecode_array, BytecodeArray, kBytecodeArrayOffset) ACCESSORS(InterpreterData, interpreter_trampoline, Code, kInterpreterTrampolineOffset) OBJECT_CONSTRUCTORS_IMPL(SharedFunctionInfo, HeapObject) NEVER_READ_ONLY_SPACE_IMPL(SharedFunctionInfo) CAST_ACCESSOR(SharedFunctionInfo) DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object) ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object, kNameOrScopeInfoOffset) ACCESSORS(SharedFunctionInfo, script_or_debug_info, HeapObject, kScriptOrDebugInfoOffset) INT32_ACCESSORS(SharedFunctionInfo, function_literal_id, kFunctionLiteralIdOffset) #if V8_SFI_HAS_UNIQUE_ID INT_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset) #endif UINT16_ACCESSORS(SharedFunctionInfo, length, kLengthOffset) UINT16_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count, kFormalParameterCountOffset) UINT8_ACCESSORS(SharedFunctionInfo, expected_nof_properties, kExpectedNofPropertiesOffset) UINT16_ACCESSORS(SharedFunctionInfo, raw_function_token_offset, kFunctionTokenOffsetOffset) RELAXED_INT32_ACCESSORS(SharedFunctionInfo, flags, kFlagsOffset) UINT8_ACCESSORS(SharedFunctionInfo, flags2, kFlags2Offset) bool SharedFunctionInfo::HasSharedName() const { Object value = name_or_scope_info(); if (value.IsScopeInfo()) { return ScopeInfo::cast(value).HasSharedFunctionName(); } return value != kNoSharedNameSentinel; } String SharedFunctionInfo::Name() const { if (!HasSharedName()) return GetReadOnlyRoots().empty_string(); Object value = name_or_scope_info(); if (value.IsScopeInfo()) { if (ScopeInfo::cast(value).HasFunctionName()) { return String::cast(ScopeInfo::cast(value).FunctionName()); } return GetReadOnlyRoots().empty_string(); } return String::cast(value); } void SharedFunctionInfo::SetName(String name) { Object maybe_scope_info = name_or_scope_info(); if (maybe_scope_info.IsScopeInfo()) { ScopeInfo::cast(maybe_scope_info).SetFunctionName(name); } else { DCHECK(maybe_scope_info.IsString() || maybe_scope_info == kNoSharedNameSentinel); set_name_or_scope_info(name); } UpdateFunctionMapIndex(); } bool SharedFunctionInfo::is_script() const { return scope_info().is_script_scope() && Script::cast(script()).compilation_type() == Script::COMPILATION_TYPE_HOST; } bool SharedFunctionInfo::needs_script_context() const { return is_script() && scope_info().ContextLocalCount() > 0; } AbstractCode SharedFunctionInfo::abstract_code() { if (HasBytecodeArray()) { return AbstractCode::cast(GetBytecodeArray()); } else { return AbstractCode::cast(GetCode()); } } Object SharedFunctionInfo::function_data() const { return ACQUIRE_READ_FIELD(*this, kFunctionDataOffset); } void SharedFunctionInfo::set_function_data(Object data, WriteBarrierMode mode) { RELEASE_WRITE_FIELD(*this, kFunctionDataOffset, data); CONDITIONAL_WRITE_BARRIER(*this, kFunctionDataOffset, data, mode); } int SharedFunctionInfo::function_token_position() const { int offset = raw_function_token_offset(); if (offset == kFunctionTokenOutOfRange) { return kNoSourcePosition; } else { return StartPosition() - offset; } } BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, class_scope_has_private_brand, SharedFunctionInfo::ClassScopeHasPrivateBrandBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, has_static_private_methods_or_accessors, SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, syntax_kind, SharedFunctionInfo::FunctionSyntaxKindBits) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, allows_lazy_compilation, SharedFunctionInfo::AllowLazyCompilationBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_duplicate_parameters, SharedFunctionInfo::HasDuplicateParametersBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, native, SharedFunctionInfo::IsNativeBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_asm_wasm_broken, SharedFunctionInfo::IsAsmWasmBrokenBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, requires_instance_members_initializer, SharedFunctionInfo::RequiresInstanceMembersInitializerBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, name_should_print_as_anonymous, SharedFunctionInfo::NameShouldPrintAsAnonymousBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_reported_binary_coverage, SharedFunctionInfo::HasReportedBinaryCoverageBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_toplevel, SharedFunctionInfo::IsTopLevelBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_oneshot_iife_or_properties_are_final, SharedFunctionInfo::IsOneshotIifeOrPropertiesAreFinalBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_safe_to_skip_arguments_adaptor, SharedFunctionInfo::IsSafeToSkipArgumentsAdaptorBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, private_name_lookup_skips_outer_class, SharedFunctionInfo::PrivateNameLookupSkipsOuterClassBit) bool SharedFunctionInfo::optimization_disabled() const { return disable_optimization_reason() != BailoutReason::kNoReason; } BailoutReason SharedFunctionInfo::disable_optimization_reason() const { return DisabledOptimizationReasonBits::decode(flags()); } LanguageMode SharedFunctionInfo::language_mode() const { STATIC_ASSERT(LanguageModeSize == 2); return construct_language_mode(IsStrictBit::decode(flags())); } void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) { STATIC_ASSERT(LanguageModeSize == 2); // We only allow language mode transitions that set the same language mode // again or go up in the chain: DCHECK(is_sloppy(this->language_mode()) || is_strict(language_mode)); int hints = flags(); hints = IsStrictBit::update(hints, is_strict(language_mode)); set_flags(hints); UpdateFunctionMapIndex(); } FunctionKind SharedFunctionInfo::kind() const { return FunctionKindBits::decode(flags()); } void SharedFunctionInfo::set_kind(FunctionKind kind) { int hints = flags(); hints = FunctionKindBits::update(hints, kind); hints = IsClassConstructorBit::update(hints, IsClassConstructor(kind)); set_flags(hints); UpdateFunctionMapIndex(); } bool SharedFunctionInfo::is_wrapped() const { return syntax_kind() == FunctionSyntaxKind::kWrapped; } bool SharedFunctionInfo::needs_home_object() const { return NeedsHomeObjectBit::decode(flags()); } void SharedFunctionInfo::set_needs_home_object(bool value) { int hints = flags(); hints = NeedsHomeObjectBit::update(hints, value); set_flags(hints); UpdateFunctionMapIndex(); } bool SharedFunctionInfo::construct_as_builtin() const { return ConstructAsBuiltinBit::decode(flags()); } void SharedFunctionInfo::CalculateConstructAsBuiltin() { bool uses_builtins_construct_stub = false; if (HasBuiltinId()) { int id = builtin_id(); if (id != Builtins::kCompileLazy && id != Builtins::kEmptyFunction) { uses_builtins_construct_stub = true; } } else if (IsApiFunction()) { uses_builtins_construct_stub = true; } int f = flags(); f = ConstructAsBuiltinBit::update(f, uses_builtins_construct_stub); set_flags(f); } int SharedFunctionInfo::function_map_index() const { // Note: Must be kept in sync with the FastNewClosure builtin. int index = Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::decode(flags()); DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX); return index; } void SharedFunctionInfo::set_function_map_index(int index) { STATIC_ASSERT(Context::LAST_FUNCTION_MAP_INDEX <= Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::kMax); DCHECK_LE(Context::FIRST_FUNCTION_MAP_INDEX, index); DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX); index -= Context::FIRST_FUNCTION_MAP_INDEX; set_flags(FunctionMapIndexBits::update(flags(), index)); } void SharedFunctionInfo::clear_padding() { memset(reinterpret_cast<void*>(this->address() + kSize), 0, kAlignedSize - kSize); } void SharedFunctionInfo::UpdateFunctionMapIndex() { int map_index = Context::FunctionMapIndex( language_mode(), kind(), HasSharedName(), needs_home_object()); set_function_map_index(map_index); } void SharedFunctionInfo::DontAdaptArguments() { // TODO(leszeks): Revise this DCHECK now that the code field is gone. DCHECK(!HasWasmExportedFunctionData()); set_internal_formal_parameter_count(kDontAdaptArgumentsSentinel); } bool SharedFunctionInfo::IsInterpreted() const { return HasBytecodeArray(); } ScopeInfo SharedFunctionInfo::scope_info() const { Object maybe_scope_info = name_or_scope_info(); if (maybe_scope_info.IsScopeInfo()) { return ScopeInfo::cast(maybe_scope_info); } return GetReadOnlyRoots().empty_scope_info(); } void SharedFunctionInfo::set_scope_info(ScopeInfo scope_info, WriteBarrierMode mode) { // Move the existing name onto the ScopeInfo. Object name = name_or_scope_info(); if (name.IsScopeInfo()) { name = ScopeInfo::cast(name).FunctionName(); } DCHECK(name.IsString() || name == kNoSharedNameSentinel); // Only set the function name for function scopes. scope_info.SetFunctionName(name); if (HasInferredName() && inferred_name().length() != 0) { scope_info.SetInferredFunctionName(inferred_name()); } set_raw_scope_info(scope_info, mode); } void SharedFunctionInfo::set_raw_scope_info(ScopeInfo scope_info, WriteBarrierMode mode) { WRITE_FIELD(*this, kNameOrScopeInfoOffset, scope_info); CONDITIONAL_WRITE_BARRIER(*this, kNameOrScopeInfoOffset, scope_info, mode); } ACCESSORS(SharedFunctionInfo, raw_outer_scope_info_or_feedback_metadata, HeapObject, kOuterScopeInfoOrFeedbackMetadataOffset) HeapObject SharedFunctionInfo::outer_scope_info() const { DCHECK(!is_compiled()); DCHECK(!HasFeedbackMetadata()); return raw_outer_scope_info_or_feedback_metadata(); } bool SharedFunctionInfo::HasOuterScopeInfo() const { ScopeInfo outer_info; if (!is_compiled()) { if (!outer_scope_info().IsScopeInfo()) return false; outer_info = ScopeInfo::cast(outer_scope_info()); } else { if (!scope_info().HasOuterScopeInfo()) return false; outer_info = scope_info().OuterScopeInfo(); } return outer_info.length() > 0; } ScopeInfo SharedFunctionInfo::GetOuterScopeInfo() const { DCHECK(HasOuterScopeInfo()); if (!is_compiled()) return ScopeInfo::cast(outer_scope_info()); return scope_info().OuterScopeInfo(); } void SharedFunctionInfo::set_outer_scope_info(HeapObject value, WriteBarrierMode mode) { DCHECK(!is_compiled()); DCHECK(raw_outer_scope_info_or_feedback_metadata().IsTheHole()); DCHECK(value.IsScopeInfo() || value.IsTheHole()); set_raw_outer_scope_info_or_feedback_metadata(value, mode); } bool SharedFunctionInfo::HasFeedbackMetadata() const { return raw_outer_scope_info_or_feedback_metadata().IsFeedbackMetadata(); } FeedbackMetadata SharedFunctionInfo::feedback_metadata() const { DCHECK(HasFeedbackMetadata()); return FeedbackMetadata::cast(raw_outer_scope_info_or_feedback_metadata()); } void SharedFunctionInfo::set_feedback_metadata(FeedbackMetadata value, WriteBarrierMode mode) { DCHECK(!HasFeedbackMetadata()); DCHECK(value.IsFeedbackMetadata()); set_raw_outer_scope_info_or_feedback_metadata(value, mode); } bool SharedFunctionInfo::is_compiled() const { Object data = function_data(); return data != Smi::FromEnum(Builtins::kCompileLazy) && !data.IsUncompiledData(); } IsCompiledScope SharedFunctionInfo::is_compiled_scope() const { return IsCompiledScope(*this, GetIsolate()); } IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared, Isolate* isolate) : retain_bytecode_(shared.HasBytecodeArray() ? handle(shared.GetBytecodeArray(), isolate) : MaybeHandle<BytecodeArray>()), is_compiled_(shared.is_compiled()) { DCHECK_IMPLIES(!retain_bytecode_.is_null(), is_compiled()); } bool SharedFunctionInfo::has_simple_parameters() { return scope_info().HasSimpleParameters(); } bool SharedFunctionInfo::IsApiFunction() const { return function_data().IsFunctionTemplateInfo(); } FunctionTemplateInfo SharedFunctionInfo::get_api_func_data() const { DCHECK(IsApiFunction()); return FunctionTemplateInfo::cast(function_data()); } bool SharedFunctionInfo::HasBytecodeArray() const { return function_data().IsBytecodeArray() || function_data().IsInterpreterData(); } BytecodeArray SharedFunctionInfo::GetBytecodeArray() const { DCHECK(HasBytecodeArray()); if (HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray()) { return GetDebugInfo().OriginalBytecodeArray(); } else if (function_data().IsBytecodeArray()) { return BytecodeArray::cast(function_data()); } else { DCHECK(function_data().IsInterpreterData()); return InterpreterData::cast(function_data()).bytecode_array(); } } BytecodeArray SharedFunctionInfo::GetDebugBytecodeArray() const { DCHECK(HasBytecodeArray()); DCHECK(HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray()); if (function_data().IsBytecodeArray()) { return BytecodeArray::cast(function_data()); } else { DCHECK(function_data().IsInterpreterData()); return InterpreterData::cast(function_data()).bytecode_array(); } } void SharedFunctionInfo::SetDebugBytecodeArray(BytecodeArray bytecode) { DCHECK(HasBytecodeArray()); if (function_data().IsBytecodeArray()) { set_function_data(bytecode); } else { DCHECK(function_data().IsInterpreterData()); interpreter_data().set_bytecode_array(bytecode); } } void SharedFunctionInfo::set_bytecode_array(BytecodeArray bytecode) { DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy) || HasUncompiledData()); set_function_data(bytecode); } bool SharedFunctionInfo::ShouldFlushBytecode(BytecodeFlushMode mode) { if (mode == BytecodeFlushMode::kDoNotFlushBytecode) return false; // TODO(rmcilroy): Enable bytecode flushing for resumable functions. if (IsResumableFunction(kind()) || !allows_lazy_compilation()) { return false; } // Get a snapshot of the function data field, and if it is a bytecode array, // check if it is old. Note, this is done this way since this function can be // called by the concurrent marker. Object data = function_data(); if (!data.IsBytecodeArray()) return false; if (mode == BytecodeFlushMode::kStressFlushBytecode) return true; BytecodeArray bytecode = BytecodeArray::cast(data); return bytecode.IsOld(); } Code SharedFunctionInfo::InterpreterTrampoline() const { DCHECK(HasInterpreterData()); return interpreter_data().interpreter_trampoline(); } bool SharedFunctionInfo::HasInterpreterData() const { return function_data().IsInterpreterData(); } InterpreterData SharedFunctionInfo::interpreter_data() const { DCHECK(HasInterpreterData()); return InterpreterData::cast(function_data()); } void SharedFunctionInfo::set_interpreter_data( InterpreterData interpreter_data) { DCHECK(FLAG_interpreted_frames_native_stack); set_function_data(interpreter_data); } bool SharedFunctionInfo::HasAsmWasmData() const { return function_data().IsAsmWasmData(); } AsmWasmData SharedFunctionInfo::asm_wasm_data() const { DCHECK(HasAsmWasmData()); return AsmWasmData::cast(function_data()); } void SharedFunctionInfo::set_asm_wasm_data(AsmWasmData data) { DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy) || HasUncompiledData() || HasAsmWasmData()); set_function_data(data); } bool SharedFunctionInfo::HasBuiltinId() const { return function_data().IsSmi(); } int SharedFunctionInfo::builtin_id() const { DCHECK(HasBuiltinId()); int id = Smi::ToInt(function_data()); DCHECK(Builtins::IsBuiltinId(id)); return id; } void SharedFunctionInfo::set_builtin_id(int builtin_id) { DCHECK(Builtins::IsBuiltinId(builtin_id)); set_function_data(Smi::FromInt(builtin_id), SKIP_WRITE_BARRIER); } bool SharedFunctionInfo::HasUncompiledData() const { return function_data().IsUncompiledData(); } UncompiledData SharedFunctionInfo::uncompiled_data() const { DCHECK(HasUncompiledData()); return UncompiledData::cast(function_data()); } void SharedFunctionInfo::set_uncompiled_data(UncompiledData uncompiled_data) { DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy) || HasUncompiledData()); DCHECK(uncompiled_data.IsUncompiledData()); set_function_data(uncompiled_data); } bool SharedFunctionInfo::HasUncompiledDataWithPreparseData() const { return function_data().IsUncompiledDataWithPreparseData(); } UncompiledDataWithPreparseData SharedFunctionInfo::uncompiled_data_with_preparse_data() const { DCHECK(HasUncompiledDataWithPreparseData()); return UncompiledDataWithPreparseData::cast(function_data()); } void SharedFunctionInfo::set_uncompiled_data_with_preparse_data( UncompiledDataWithPreparseData uncompiled_data_with_preparse_data) { DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy)); DCHECK(uncompiled_data_with_preparse_data.IsUncompiledDataWithPreparseData()); set_function_data(uncompiled_data_with_preparse_data); } bool SharedFunctionInfo::HasUncompiledDataWithoutPreparseData() const { return function_data().IsUncompiledDataWithoutPreparseData(); } void SharedFunctionInfo::ClearPreparseData() { DCHECK(HasUncompiledDataWithPreparseData()); UncompiledDataWithPreparseData data = uncompiled_data_with_preparse_data(); // Trim off the pre-parsed scope data from the uncompiled data by swapping the // map, leaving only an uncompiled data without pre-parsed scope. DisallowHeapAllocation no_gc; Heap* heap = GetHeapFromWritableObject(data); // Swap the map. heap->NotifyObjectLayoutChange(data, no_gc); STATIC_ASSERT(UncompiledDataWithoutPreparseData::kSize < UncompiledDataWithPreparseData::kSize); STATIC_ASSERT(UncompiledDataWithoutPreparseData::kSize == UncompiledData::kHeaderSize); data.synchronized_set_map( GetReadOnlyRoots().uncompiled_data_without_preparse_data_map()); // Fill the remaining space with filler. heap->CreateFillerObjectAt( data.address() + UncompiledDataWithoutPreparseData::kSize, UncompiledDataWithPreparseData::kSize - UncompiledDataWithoutPreparseData::kSize, ClearRecordedSlots::kYes); // Ensure that the clear was successful. DCHECK(HasUncompiledDataWithoutPreparseData()); } template <typename LocalIsolate> void UncompiledData::Init(LocalIsolate* isolate, String inferred_name, int start_position, int end_position) { set_inferred_name(inferred_name); set_start_position(start_position); set_end_position(end_position); } void UncompiledData::InitAfterBytecodeFlush( String inferred_name, int start_position, int end_position, std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)> gc_notify_updated_slot) { set_inferred_name(inferred_name); gc_notify_updated_slot(*this, RawField(UncompiledData::kInferredNameOffset), inferred_name); set_start_position(start_position); set_end_position(end_position); } template <typename LocalIsolate> void UncompiledDataWithPreparseData::Init(LocalIsolate* isolate, String inferred_name, int start_position, int end_position, PreparseData scope_data) { this->UncompiledData::Init(isolate, inferred_name, start_position, end_position); set_preparse_data(scope_data); } bool SharedFunctionInfo::HasWasmExportedFunctionData() const { return function_data().IsWasmExportedFunctionData(); } bool SharedFunctionInfo::HasWasmJSFunctionData() const { return function_data().IsWasmJSFunctionData(); } bool SharedFunctionInfo::HasWasmCapiFunctionData() const { return function_data().IsWasmCapiFunctionData(); } HeapObject SharedFunctionInfo::script() const { HeapObject maybe_script = script_or_debug_info(); if (maybe_script.IsDebugInfo()) { return DebugInfo::cast(maybe_script).script(); } return maybe_script; } void SharedFunctionInfo::set_script(HeapObject script) { HeapObject maybe_debug_info = script_or_debug_info(); if (maybe_debug_info.IsDebugInfo()) { DebugInfo::cast(maybe_debug_info).set_script(script); } else { set_script_or_debug_info(script); } } bool SharedFunctionInfo::is_repl_mode() const { return script().IsScript() && Script::cast(script()).is_repl_mode(); } bool SharedFunctionInfo::HasDebugInfo() const { return script_or_debug_info().IsDebugInfo(); } DebugInfo SharedFunctionInfo::GetDebugInfo() const { DCHECK(HasDebugInfo()); return DebugInfo::cast(script_or_debug_info()); } void SharedFunctionInfo::SetDebugInfo(DebugInfo debug_info) { DCHECK(!HasDebugInfo()); DCHECK_EQ(debug_info.script(), script_or_debug_info()); set_script_or_debug_info(debug_info); } bool SharedFunctionInfo::HasInferredName() { Object scope_info = name_or_scope_info(); if (scope_info.IsScopeInfo()) { return ScopeInfo::cast(scope_info).HasInferredFunctionName(); } return HasUncompiledData(); } String SharedFunctionInfo::inferred_name() { Object maybe_scope_info = name_or_scope_info(); if (maybe_scope_info.IsScopeInfo()) { ScopeInfo scope_info = ScopeInfo::cast(maybe_scope_info); if (scope_info.HasInferredFunctionName()) { Object name = scope_info.InferredFunctionName(); if (name.IsString()) return String::cast(name); } } else if (HasUncompiledData()) { return uncompiled_data().inferred_name(); } return GetReadOnlyRoots().empty_string(); } bool SharedFunctionInfo::IsUserJavaScript() const { Object script_obj = script(); if (script_obj.IsUndefined()) return false; Script script = Script::cast(script_obj); return script.IsUserJavaScript(); } bool SharedFunctionInfo::IsSubjectToDebugging() const { return IsUserJavaScript() && !HasAsmWasmData(); } bool SharedFunctionInfo::CanDiscardCompiled() const { bool can_decompile = (HasBytecodeArray() || HasAsmWasmData() || HasUncompiledDataWithPreparseData()); return can_decompile; } bool SharedFunctionInfo::is_class_constructor() const { return IsClassConstructorBit::decode(flags()); } bool SharedFunctionInfo::is_oneshot_iife() const { bool bit = is_oneshot_iife_or_properties_are_final(); return bit && !is_class_constructor(); } void SharedFunctionInfo::set_is_oneshot_iife(bool value) { DCHECK(!value || !is_class_constructor()); if (!is_class_constructor()) { set_is_oneshot_iife_or_properties_are_final(value); } } void SharedFunctionInfo::set_are_properties_final(bool value) { if (is_class_constructor()) { set_is_oneshot_iife_or_properties_are_final(value); } } bool SharedFunctionInfo::are_properties_final() const { bool bit = is_oneshot_iife_or_properties_are_final(); return bit && is_class_constructor(); } } // namespace internal } // namespace v8 #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_