blob: caf14e8bc32f4b26d54fb6c26a05080c5ce4501d [file] [log] [blame]
// 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/base/macros.h"
#include "src/handles/handles-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/local-heap-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/shared-function-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 {
#include "torque-generated/src/objects/shared-function-info-tq-inl.inc"
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_address(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)
RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, function_data, Object,
kFunctionDataOffset)
RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object,
kNameOrScopeInfoOffset)
RELEASE_ACQUIRE_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(kAcquireLoad);
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(kAcquireLoad);
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(kAcquireLoad);
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, kReleaseStore);
}
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());
}
}
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, flags2, has_optimized_at_least_once,
SharedFunctionInfo::HasOptimizedAtLeastOnceBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, may_have_cached_code,
SharedFunctionInfo::MayHaveCachedCodeBit)
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,
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 {
STATIC_ASSERT(FunctionKindBits::kSize == kFunctionKindBitSize);
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(kAcquireLoad);
if (maybe_scope_info.IsScopeInfo()) {
return ScopeInfo::cast(maybe_scope_info);
}
return GetReadOnlyRoots().empty_scope_info();
}
void SharedFunctionInfo::SetScopeInfo(ScopeInfo scope_info,
WriteBarrierMode mode) {
// Move the existing name onto the ScopeInfo.
Object name = name_or_scope_info(kAcquireLoad);
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_name_or_scope_info(scope_info, kReleaseStore, 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(kAcquireLoad);
return data != Smi::FromEnum(Builtins::kCompileLazy) &&
!data.IsUncompiledData();
}
template <typename LocalIsolate>
IsCompiledScope SharedFunctionInfo::is_compiled_scope(
LocalIsolate* isolate) const {
return IsCompiledScope(*this, isolate);
}
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());
}
IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
LocalIsolate* isolate)
: retain_bytecode_(
shared.HasBytecodeArray()
? isolate->heap()->NewPersistentHandle(shared.GetBytecodeArray())
: 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(kAcquireLoad).IsFunctionTemplateInfo();
}
FunctionTemplateInfo SharedFunctionInfo::get_api_func_data() const {
DCHECK(IsApiFunction());
return FunctionTemplateInfo::cast(function_data(kAcquireLoad));
}
bool SharedFunctionInfo::HasBytecodeArray() const {
Object data = function_data(kAcquireLoad);
return data.IsBytecodeArray() || data.IsInterpreterData();
}
BytecodeArray SharedFunctionInfo::GetBytecodeArray() const {
DCHECK(HasBytecodeArray());
if (HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray()) {
return GetDebugInfo().OriginalBytecodeArray();
}
Object data = function_data(kAcquireLoad);
if (data.IsBytecodeArray()) {
return BytecodeArray::cast(data);
} else {
DCHECK(data.IsInterpreterData());
return InterpreterData::cast(data).bytecode_array();
}
}
BytecodeArray SharedFunctionInfo::GetDebugBytecodeArray() const {
DCHECK(HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray());
Object data = function_data(kAcquireLoad);
if (data.IsBytecodeArray()) {
return BytecodeArray::cast(data);
} else {
DCHECK(data.IsInterpreterData());
return InterpreterData::cast(data).bytecode_array();
}
}
void SharedFunctionInfo::SetDebugBytecodeArray(BytecodeArray bytecode) {
Object data = function_data(kAcquireLoad);
if (data.IsBytecodeArray()) {
set_function_data(bytecode, kReleaseStore);
} else {
DCHECK(data.IsInterpreterData());
interpreter_data().set_bytecode_array(bytecode);
}
}
void SharedFunctionInfo::set_bytecode_array(BytecodeArray bytecode) {
DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy) ||
HasUncompiledData());
set_function_data(bytecode, kReleaseStore);
}
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(kAcquireLoad);
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(kAcquireLoad).IsInterpreterData();
}
InterpreterData SharedFunctionInfo::interpreter_data() const {
DCHECK(HasInterpreterData());
return InterpreterData::cast(function_data(kAcquireLoad));
}
void SharedFunctionInfo::set_interpreter_data(
InterpreterData interpreter_data) {
DCHECK(FLAG_interpreted_frames_native_stack);
set_function_data(interpreter_data, kReleaseStore);
}
bool SharedFunctionInfo::HasAsmWasmData() const {
return function_data(kAcquireLoad).IsAsmWasmData();
}
AsmWasmData SharedFunctionInfo::asm_wasm_data() const {
DCHECK(HasAsmWasmData());
return AsmWasmData::cast(function_data(kAcquireLoad));
}
void SharedFunctionInfo::set_asm_wasm_data(AsmWasmData data) {
DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy) ||
HasUncompiledData() || HasAsmWasmData());
set_function_data(data, kReleaseStore);
}
bool SharedFunctionInfo::HasBuiltinId() const {
return function_data(kAcquireLoad).IsSmi();
}
int SharedFunctionInfo::builtin_id() const {
DCHECK(HasBuiltinId());
int id = Smi::ToInt(function_data(kAcquireLoad));
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), kReleaseStore,
SKIP_WRITE_BARRIER);
}
bool SharedFunctionInfo::HasUncompiledData() const {
return function_data(kAcquireLoad).IsUncompiledData();
}
UncompiledData SharedFunctionInfo::uncompiled_data() const {
DCHECK(HasUncompiledData());
return UncompiledData::cast(function_data(kAcquireLoad));
}
void SharedFunctionInfo::set_uncompiled_data(UncompiledData uncompiled_data) {
DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy) ||
HasUncompiledData());
DCHECK(uncompiled_data.IsUncompiledData());
set_function_data(uncompiled_data, kReleaseStore);
}
bool SharedFunctionInfo::HasUncompiledDataWithPreparseData() const {
return function_data(kAcquireLoad).IsUncompiledDataWithPreparseData();
}
UncompiledDataWithPreparseData
SharedFunctionInfo::uncompiled_data_with_preparse_data() const {
DCHECK(HasUncompiledDataWithPreparseData());
return UncompiledDataWithPreparseData::cast(function_data(kAcquireLoad));
}
void SharedFunctionInfo::set_uncompiled_data_with_preparse_data(
UncompiledDataWithPreparseData uncompiled_data_with_preparse_data) {
DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy));
DCHECK(uncompiled_data_with_preparse_data.IsUncompiledDataWithPreparseData());
set_function_data(uncompiled_data_with_preparse_data, kReleaseStore);
}
bool SharedFunctionInfo::HasUncompiledDataWithoutPreparseData() const {
return function_data(kAcquireLoad).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(kAcquireLoad).IsWasmExportedFunctionData();
}
bool SharedFunctionInfo::HasWasmJSFunctionData() const {
return function_data(kAcquireLoad).IsWasmJSFunctionData();
}
bool SharedFunctionInfo::HasWasmCapiFunctionData() const {
return function_data(kAcquireLoad).IsWasmCapiFunctionData();
}
HeapObject SharedFunctionInfo::script() const {
HeapObject maybe_script = script_or_debug_info(kAcquireLoad);
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(kAcquireLoad);
if (maybe_debug_info.IsDebugInfo()) {
DebugInfo::cast(maybe_debug_info).set_script(script);
} else {
set_script_or_debug_info(script, kReleaseStore);
}
}
bool SharedFunctionInfo::is_repl_mode() const {
return script().IsScript() && Script::cast(script()).is_repl_mode();
}
bool SharedFunctionInfo::HasDebugInfo() const {
return script_or_debug_info(kAcquireLoad).IsDebugInfo();
}
DebugInfo SharedFunctionInfo::GetDebugInfo() const {
auto debug_info = script_or_debug_info(kAcquireLoad);
DCHECK(debug_info.IsDebugInfo());
return DebugInfo::cast(debug_info);
}
void SharedFunctionInfo::SetDebugInfo(DebugInfo debug_info) {
DCHECK(!HasDebugInfo());
DCHECK_EQ(debug_info.script(), script_or_debug_info(kAcquireLoad));
set_script_or_debug_info(debug_info, kReleaseStore);
}
bool SharedFunctionInfo::HasInferredName() {
Object scope_info = name_or_scope_info(kAcquireLoad);
if (scope_info.IsScopeInfo()) {
return ScopeInfo::cast(scope_info).HasInferredFunctionName();
}
return HasUncompiledData();
}
String SharedFunctionInfo::inferred_name() {
Object maybe_scope_info = name_or_scope_info(kAcquireLoad);
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_