1 // Copyright 2017 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_ 6 #define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_ 7 8 #include "src/objects/shared-function-info.h" 9 10 #include "src/handles-inl.h" 11 #include "src/heap/heap-inl.h" 12 #include "src/objects/debug-objects-inl.h" 13 #include "src/objects/scope-info.h" 14 #include "src/objects/templates.h" 15 16 // Has to be the last include (doesn't have include guards): 17 #include "src/objects/object-macros.h" 18 19 namespace v8 { 20 namespace internal { 21 22 CAST_ACCESSOR(PreParsedScopeData) 23 ACCESSORS(PreParsedScopeData, scope_data, PodArray<uint8_t>, kScopeDataOffset) 24 INT_ACCESSORS(PreParsedScopeData, length, kLengthOffset) 25 26 Object* PreParsedScopeData::child_data(int index) const { 27 DCHECK_GE(index, 0); 28 DCHECK_LT(index, this->length()); 29 int offset = kChildDataStartOffset + index * kPointerSize; 30 return RELAXED_READ_FIELD(this, offset); 31 } 32 33 void PreParsedScopeData::set_child_data(int index, Object* value, 34 WriteBarrierMode mode) { 35 DCHECK_GE(index, 0); 36 DCHECK_LT(index, this->length()); 37 int offset = kChildDataStartOffset + index * kPointerSize; 38 RELAXED_WRITE_FIELD(this, offset, value); 39 CONDITIONAL_WRITE_BARRIER(this, offset, value, mode); 40 } 41 42 Object** PreParsedScopeData::child_data_start() const { 43 return HeapObject::RawField(this, kChildDataStartOffset); 44 } 45 46 void PreParsedScopeData::clear_padding() { 47 // For archs where kIntSize < kPointerSize, there will be padding between the 48 // length field and the start of the child data. 49 if (kUnalignedChildDataStartOffset < kChildDataStartOffset) { 50 memset(reinterpret_cast<void*>(address() + kUnalignedChildDataStartOffset), 51 0, kChildDataStartOffset - kUnalignedChildDataStartOffset); 52 } 53 } 54 55 CAST_ACCESSOR(UncompiledData) 56 ACCESSORS(UncompiledData, inferred_name, String, kInferredNameOffset) 57 INT32_ACCESSORS(UncompiledData, start_position, kStartPositionOffset) 58 INT32_ACCESSORS(UncompiledData, end_position, kEndPositionOffset) 59 INT32_ACCESSORS(UncompiledData, function_literal_id, kFunctionLiteralIdOffset) 60 61 void UncompiledData::clear_padding() { 62 // For archs where kIntSize < kPointerSize, there will be padding at the end 63 // of the data. 64 if (kUnalignedSize < kSize) { 65 memset(reinterpret_cast<void*>(address() + kUnalignedSize), 0, 66 kSize - kUnalignedSize); 67 } 68 } 69 70 CAST_ACCESSOR(UncompiledDataWithoutPreParsedScope) 71 72 CAST_ACCESSOR(UncompiledDataWithPreParsedScope) 73 ACCESSORS(UncompiledDataWithPreParsedScope, pre_parsed_scope_data, 74 PreParsedScopeData, kPreParsedScopeDataOffset) 75 76 CAST_ACCESSOR(InterpreterData) 77 ACCESSORS(InterpreterData, bytecode_array, BytecodeArray, kBytecodeArrayOffset) 78 ACCESSORS(InterpreterData, interpreter_trampoline, Code, 79 kInterpreterTrampolineOffset) 80 81 CAST_ACCESSOR(SharedFunctionInfo) 82 DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object) 83 84 ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object, 85 kNameOrScopeInfoOffset) 86 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset) 87 ACCESSORS(SharedFunctionInfo, script_or_debug_info, Object, 88 kScriptOrDebugInfoOffset) 89 90 #if V8_SFI_HAS_UNIQUE_ID 91 INT_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset) 92 #endif 93 UINT16_ACCESSORS(SharedFunctionInfo, length, kLengthOffset) 94 UINT16_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count, 95 kFormalParameterCountOffset) 96 UINT8_ACCESSORS(SharedFunctionInfo, expected_nof_properties, 97 kExpectedNofPropertiesOffset) 98 UINT8_ACCESSORS(SharedFunctionInfo, raw_builtin_function_id, kBuiltinFunctionId) 99 UINT16_ACCESSORS(SharedFunctionInfo, raw_function_token_offset, 100 kFunctionTokenOffsetOffset) 101 INT_ACCESSORS(SharedFunctionInfo, flags, kFlagsOffset) 102 103 bool SharedFunctionInfo::HasSharedName() const { 104 Object* value = name_or_scope_info(); 105 if (value->IsScopeInfo()) { 106 return ScopeInfo::cast(value)->HasSharedFunctionName(); 107 } 108 return value != kNoSharedNameSentinel; 109 } 110 111 String* SharedFunctionInfo::Name() const { 112 if (!HasSharedName()) return GetReadOnlyRoots().empty_string(); 113 Object* value = name_or_scope_info(); 114 if (value->IsScopeInfo()) { 115 if (ScopeInfo::cast(value)->HasFunctionName()) { 116 return String::cast(ScopeInfo::cast(value)->FunctionName()); 117 } 118 return GetReadOnlyRoots().empty_string(); 119 } 120 return String::cast(value); 121 } 122 123 void SharedFunctionInfo::SetName(String* name) { 124 Object* maybe_scope_info = name_or_scope_info(); 125 if (maybe_scope_info->IsScopeInfo()) { 126 ScopeInfo::cast(maybe_scope_info)->SetFunctionName(name); 127 } else { 128 DCHECK(maybe_scope_info->IsString() || 129 maybe_scope_info == kNoSharedNameSentinel); 130 set_name_or_scope_info(name); 131 } 132 UpdateFunctionMapIndex(); 133 } 134 135 AbstractCode* SharedFunctionInfo::abstract_code() { 136 if (HasBytecodeArray()) { 137 return AbstractCode::cast(GetBytecodeArray()); 138 } else { 139 return AbstractCode::cast(GetCode()); 140 } 141 } 142 143 int SharedFunctionInfo::function_token_position() const { 144 int offset = raw_function_token_offset(); 145 if (offset == kFunctionTokenOutOfRange) { 146 return kNoSourcePosition; 147 } else { 148 return StartPosition() - offset; 149 } 150 } 151 152 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_wrapped, 153 SharedFunctionInfo::IsWrappedBit) 154 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, allows_lazy_compilation, 155 SharedFunctionInfo::AllowLazyCompilationBit) 156 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_duplicate_parameters, 157 SharedFunctionInfo::HasDuplicateParametersBit) 158 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_declaration, 159 SharedFunctionInfo::IsDeclarationBit) 160 161 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, native, 162 SharedFunctionInfo::IsNativeBit) 163 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_asm_wasm_broken, 164 SharedFunctionInfo::IsAsmWasmBrokenBit) 165 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, 166 requires_instance_fields_initializer, 167 SharedFunctionInfo::RequiresInstanceFieldsInitializer) 168 169 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, name_should_print_as_anonymous, 170 SharedFunctionInfo::NameShouldPrintAsAnonymousBit) 171 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_anonymous_expression, 172 SharedFunctionInfo::IsAnonymousExpressionBit) 173 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, deserialized, 174 SharedFunctionInfo::IsDeserializedBit) 175 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_reported_binary_coverage, 176 SharedFunctionInfo::HasReportedBinaryCoverageBit) 177 178 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_named_expression, 179 SharedFunctionInfo::IsNamedExpressionBit) 180 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_toplevel, 181 SharedFunctionInfo::IsTopLevelBit) 182 183 bool SharedFunctionInfo::optimization_disabled() const { 184 return disable_optimization_reason() != BailoutReason::kNoReason; 185 } 186 187 BailoutReason SharedFunctionInfo::disable_optimization_reason() const { 188 return DisabledOptimizationReasonBits::decode(flags()); 189 } 190 191 LanguageMode SharedFunctionInfo::language_mode() const { 192 STATIC_ASSERT(LanguageModeSize == 2); 193 return construct_language_mode(IsStrictBit::decode(flags())); 194 } 195 196 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) { 197 STATIC_ASSERT(LanguageModeSize == 2); 198 // We only allow language mode transitions that set the same language mode 199 // again or go up in the chain: 200 DCHECK(is_sloppy(this->language_mode()) || is_strict(language_mode)); 201 int hints = flags(); 202 hints = IsStrictBit::update(hints, is_strict(language_mode)); 203 set_flags(hints); 204 UpdateFunctionMapIndex(); 205 } 206 207 FunctionKind SharedFunctionInfo::kind() const { 208 return FunctionKindBits::decode(flags()); 209 } 210 211 void SharedFunctionInfo::set_kind(FunctionKind kind) { 212 int hints = flags(); 213 hints = FunctionKindBits::update(hints, kind); 214 hints = IsClassConstructorBit::update(hints, IsClassConstructor(kind)); 215 hints = IsDerivedConstructorBit::update(hints, IsDerivedConstructor(kind)); 216 set_flags(hints); 217 UpdateFunctionMapIndex(); 218 } 219 220 bool SharedFunctionInfo::needs_home_object() const { 221 return NeedsHomeObjectBit::decode(flags()); 222 } 223 224 void SharedFunctionInfo::set_needs_home_object(bool value) { 225 int hints = flags(); 226 hints = NeedsHomeObjectBit::update(hints, value); 227 set_flags(hints); 228 UpdateFunctionMapIndex(); 229 } 230 231 bool SharedFunctionInfo::construct_as_builtin() const { 232 return ConstructAsBuiltinBit::decode(flags()); 233 } 234 235 void SharedFunctionInfo::CalculateConstructAsBuiltin() { 236 bool uses_builtins_construct_stub = false; 237 if (HasBuiltinId()) { 238 int id = builtin_id(); 239 if (id != Builtins::kCompileLazy && id != Builtins::kEmptyFunction) { 240 uses_builtins_construct_stub = true; 241 } 242 } else if (IsApiFunction()) { 243 uses_builtins_construct_stub = true; 244 } 245 246 int f = flags(); 247 f = ConstructAsBuiltinBit::update(f, uses_builtins_construct_stub); 248 set_flags(f); 249 } 250 251 int SharedFunctionInfo::function_map_index() const { 252 // Note: Must be kept in sync with the FastNewClosure builtin. 253 int index = 254 Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::decode(flags()); 255 DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX); 256 return index; 257 } 258 259 void SharedFunctionInfo::set_function_map_index(int index) { 260 STATIC_ASSERT(Context::LAST_FUNCTION_MAP_INDEX <= 261 Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::kMax); 262 DCHECK_LE(Context::FIRST_FUNCTION_MAP_INDEX, index); 263 DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX); 264 index -= Context::FIRST_FUNCTION_MAP_INDEX; 265 set_flags(FunctionMapIndexBits::update(flags(), index)); 266 } 267 268 void SharedFunctionInfo::clear_padding() { 269 memset(reinterpret_cast<void*>(this->address() + kSize), 0, 270 kAlignedSize - kSize); 271 } 272 273 void SharedFunctionInfo::UpdateFunctionMapIndex() { 274 int map_index = Context::FunctionMapIndex( 275 language_mode(), kind(), true, HasSharedName(), needs_home_object()); 276 set_function_map_index(map_index); 277 } 278 279 void SharedFunctionInfo::DontAdaptArguments() { 280 // TODO(leszeks): Revise this DCHECK now that the code field is gone. 281 DCHECK(!HasWasmExportedFunctionData()); 282 set_internal_formal_parameter_count(kDontAdaptArgumentsSentinel); 283 } 284 285 int SharedFunctionInfo::StartPosition() const { 286 Object* maybe_scope_info = name_or_scope_info(); 287 if (maybe_scope_info->IsScopeInfo()) { 288 ScopeInfo* info = ScopeInfo::cast(maybe_scope_info); 289 if (info->HasPositionInfo()) { 290 return info->StartPosition(); 291 } 292 } else if (HasUncompiledData()) { 293 // Works with or without scope. 294 return uncompiled_data()->start_position(); 295 } else if (IsApiFunction() || HasBuiltinId()) { 296 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy); 297 return 0; 298 } 299 return kNoSourcePosition; 300 } 301 302 int SharedFunctionInfo::EndPosition() const { 303 Object* maybe_scope_info = name_or_scope_info(); 304 if (maybe_scope_info->IsScopeInfo()) { 305 ScopeInfo* info = ScopeInfo::cast(maybe_scope_info); 306 if (info->HasPositionInfo()) { 307 return info->EndPosition(); 308 } 309 } else if (HasUncompiledData()) { 310 // Works with or without scope. 311 return uncompiled_data()->end_position(); 312 } else if (IsApiFunction() || HasBuiltinId()) { 313 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy); 314 return 0; 315 } 316 return kNoSourcePosition; 317 } 318 319 void SharedFunctionInfo::SetPosition(int start_position, int end_position) { 320 Object* maybe_scope_info = name_or_scope_info(); 321 if (maybe_scope_info->IsScopeInfo()) { 322 ScopeInfo* info = ScopeInfo::cast(maybe_scope_info); 323 if (info->HasPositionInfo()) { 324 info->SetPositionInfo(start_position, end_position); 325 } 326 } else if (HasUncompiledData()) { 327 if (HasUncompiledDataWithPreParsedScope()) { 328 // Clear out preparsed scope data, since the position setter invalidates 329 // any scope data. 330 ClearPreParsedScopeData(); 331 } 332 uncompiled_data()->set_start_position(start_position); 333 uncompiled_data()->set_end_position(end_position); 334 } else { 335 UNREACHABLE(); 336 } 337 } 338 339 bool SharedFunctionInfo::IsInterpreted() const { return HasBytecodeArray(); } 340 341 ScopeInfo* SharedFunctionInfo::scope_info() const { 342 Object* maybe_scope_info = name_or_scope_info(); 343 if (maybe_scope_info->IsScopeInfo()) { 344 return ScopeInfo::cast(maybe_scope_info); 345 } 346 return ScopeInfo::Empty(GetIsolate()); 347 } 348 349 void SharedFunctionInfo::set_scope_info(ScopeInfo* scope_info, 350 WriteBarrierMode mode) { 351 // Move the existing name onto the ScopeInfo. 352 Object* name = name_or_scope_info(); 353 if (name->IsScopeInfo()) { 354 name = ScopeInfo::cast(name)->FunctionName(); 355 } 356 DCHECK(name->IsString() || name == kNoSharedNameSentinel); 357 // Only set the function name for function scopes. 358 scope_info->SetFunctionName(name); 359 if (HasInferredName() && inferred_name()->length() != 0) { 360 scope_info->SetInferredFunctionName(inferred_name()); 361 } 362 WRITE_FIELD(this, kNameOrScopeInfoOffset, 363 reinterpret_cast<Object*>(scope_info)); 364 CONDITIONAL_WRITE_BARRIER(this, kNameOrScopeInfoOffset, 365 reinterpret_cast<Object*>(scope_info), mode); 366 } 367 368 ACCESSORS(SharedFunctionInfo, raw_outer_scope_info_or_feedback_metadata, 369 HeapObject, kOuterScopeInfoOrFeedbackMetadataOffset) 370 371 HeapObject* SharedFunctionInfo::outer_scope_info() const { 372 DCHECK(!is_compiled()); 373 DCHECK(!HasFeedbackMetadata()); 374 return raw_outer_scope_info_or_feedback_metadata(); 375 } 376 377 bool SharedFunctionInfo::HasOuterScopeInfo() const { 378 ScopeInfo* outer_info = nullptr; 379 if (!is_compiled()) { 380 if (!outer_scope_info()->IsScopeInfo()) return false; 381 outer_info = ScopeInfo::cast(outer_scope_info()); 382 } else { 383 if (!scope_info()->HasOuterScopeInfo()) return false; 384 outer_info = scope_info()->OuterScopeInfo(); 385 } 386 return outer_info->length() > 0; 387 } 388 389 ScopeInfo* SharedFunctionInfo::GetOuterScopeInfo() const { 390 DCHECK(HasOuterScopeInfo()); 391 if (!is_compiled()) return ScopeInfo::cast(outer_scope_info()); 392 return scope_info()->OuterScopeInfo(); 393 } 394 395 void SharedFunctionInfo::set_outer_scope_info(HeapObject* value, 396 WriteBarrierMode mode) { 397 DCHECK(!is_compiled()); 398 DCHECK(raw_outer_scope_info_or_feedback_metadata()->IsTheHole()); 399 DCHECK(value->IsScopeInfo() || value->IsTheHole()); 400 return set_raw_outer_scope_info_or_feedback_metadata(value, mode); 401 } 402 403 bool SharedFunctionInfo::HasFeedbackMetadata() const { 404 return raw_outer_scope_info_or_feedback_metadata()->IsFeedbackMetadata(); 405 } 406 407 FeedbackMetadata* SharedFunctionInfo::feedback_metadata() const { 408 DCHECK(HasFeedbackMetadata()); 409 return FeedbackMetadata::cast(raw_outer_scope_info_or_feedback_metadata()); 410 } 411 412 void SharedFunctionInfo::set_feedback_metadata(FeedbackMetadata* value, 413 WriteBarrierMode mode) { 414 DCHECK(!HasFeedbackMetadata()); 415 DCHECK(value->IsFeedbackMetadata()); 416 return set_raw_outer_scope_info_or_feedback_metadata(value, mode); 417 } 418 419 bool SharedFunctionInfo::is_compiled() const { 420 Object* data = function_data(); 421 return data != Smi::FromEnum(Builtins::kCompileLazy) && 422 !data->IsUncompiledData(); 423 } 424 425 uint16_t SharedFunctionInfo::GetLength() const { 426 DCHECK(is_compiled()); 427 DCHECK(HasLength()); 428 return length(); 429 } 430 431 bool SharedFunctionInfo::HasLength() const { 432 return length() != kInvalidLength; 433 } 434 435 bool SharedFunctionInfo::has_simple_parameters() { 436 return scope_info()->HasSimpleParameters(); 437 } 438 439 bool SharedFunctionInfo::IsApiFunction() const { 440 return function_data()->IsFunctionTemplateInfo(); 441 } 442 443 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() { 444 DCHECK(IsApiFunction()); 445 return FunctionTemplateInfo::cast(function_data()); 446 } 447 448 bool SharedFunctionInfo::HasBytecodeArray() const { 449 return function_data()->IsBytecodeArray() || 450 function_data()->IsInterpreterData(); 451 } 452 453 BytecodeArray* SharedFunctionInfo::GetBytecodeArray() const { 454 DCHECK(HasBytecodeArray()); 455 if (HasDebugInfo() && GetDebugInfo()->HasInstrumentedBytecodeArray()) { 456 return GetDebugInfo()->OriginalBytecodeArray(); 457 } else if (function_data()->IsBytecodeArray()) { 458 return BytecodeArray::cast(function_data()); 459 } else { 460 DCHECK(function_data()->IsInterpreterData()); 461 return InterpreterData::cast(function_data())->bytecode_array(); 462 } 463 } 464 465 BytecodeArray* SharedFunctionInfo::GetDebugBytecodeArray() const { 466 DCHECK(HasBytecodeArray()); 467 DCHECK(HasDebugInfo() && GetDebugInfo()->HasInstrumentedBytecodeArray()); 468 if (function_data()->IsBytecodeArray()) { 469 return BytecodeArray::cast(function_data()); 470 } else { 471 DCHECK(function_data()->IsInterpreterData()); 472 return InterpreterData::cast(function_data())->bytecode_array(); 473 } 474 } 475 476 void SharedFunctionInfo::SetDebugBytecodeArray(BytecodeArray* bytecode) { 477 DCHECK(HasBytecodeArray()); 478 if (function_data()->IsBytecodeArray()) { 479 set_function_data(bytecode); 480 } else { 481 DCHECK(function_data()->IsInterpreterData()); 482 interpreter_data()->set_bytecode_array(bytecode); 483 } 484 } 485 486 void SharedFunctionInfo::set_bytecode_array(BytecodeArray* bytecode) { 487 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy) || 488 HasUncompiledData()); 489 set_function_data(bytecode); 490 } 491 492 Code* SharedFunctionInfo::InterpreterTrampoline() const { 493 DCHECK(HasInterpreterData()); 494 return interpreter_data()->interpreter_trampoline(); 495 } 496 497 bool SharedFunctionInfo::HasInterpreterData() const { 498 return function_data()->IsInterpreterData(); 499 } 500 501 InterpreterData* SharedFunctionInfo::interpreter_data() const { 502 DCHECK(HasInterpreterData()); 503 return InterpreterData::cast(function_data()); 504 } 505 506 void SharedFunctionInfo::set_interpreter_data( 507 InterpreterData* interpreter_data) { 508 DCHECK(FLAG_interpreted_frames_native_stack); 509 set_function_data(interpreter_data); 510 } 511 512 bool SharedFunctionInfo::HasAsmWasmData() const { 513 return function_data()->IsFixedArray(); 514 } 515 516 FixedArray* SharedFunctionInfo::asm_wasm_data() const { 517 DCHECK(HasAsmWasmData()); 518 return FixedArray::cast(function_data()); 519 } 520 521 void SharedFunctionInfo::set_asm_wasm_data(FixedArray* data) { 522 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy) || 523 HasUncompiledData() || HasAsmWasmData()); 524 set_function_data(data); 525 } 526 527 bool SharedFunctionInfo::HasBuiltinId() const { 528 return function_data()->IsSmi(); 529 } 530 531 int SharedFunctionInfo::builtin_id() const { 532 DCHECK(HasBuiltinId()); 533 int id = Smi::ToInt(function_data()); 534 DCHECK(Builtins::IsBuiltinId(id)); 535 return id; 536 } 537 538 void SharedFunctionInfo::set_builtin_id(int builtin_id) { 539 DCHECK(Builtins::IsBuiltinId(builtin_id)); 540 DCHECK_NE(builtin_id, Builtins::kDeserializeLazy); 541 set_function_data(Smi::FromInt(builtin_id), SKIP_WRITE_BARRIER); 542 } 543 544 bool SharedFunctionInfo::HasUncompiledData() const { 545 return function_data()->IsUncompiledData(); 546 } 547 548 UncompiledData* SharedFunctionInfo::uncompiled_data() const { 549 DCHECK(HasUncompiledData()); 550 return UncompiledData::cast(function_data()); 551 } 552 553 void SharedFunctionInfo::set_uncompiled_data(UncompiledData* uncompiled_data) { 554 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy)); 555 DCHECK(uncompiled_data->IsUncompiledData()); 556 set_function_data(uncompiled_data); 557 } 558 559 bool SharedFunctionInfo::HasUncompiledDataWithPreParsedScope() const { 560 return function_data()->IsUncompiledDataWithPreParsedScope(); 561 } 562 563 UncompiledDataWithPreParsedScope* 564 SharedFunctionInfo::uncompiled_data_with_pre_parsed_scope() const { 565 DCHECK(HasUncompiledDataWithPreParsedScope()); 566 return UncompiledDataWithPreParsedScope::cast(function_data()); 567 } 568 569 void SharedFunctionInfo::set_uncompiled_data_with_pre_parsed_scope( 570 UncompiledDataWithPreParsedScope* uncompiled_data_with_pre_parsed_scope) { 571 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy)); 572 DCHECK(uncompiled_data_with_pre_parsed_scope 573 ->IsUncompiledDataWithPreParsedScope()); 574 set_function_data(uncompiled_data_with_pre_parsed_scope); 575 } 576 577 bool SharedFunctionInfo::HasUncompiledDataWithoutPreParsedScope() const { 578 return function_data()->IsUncompiledDataWithoutPreParsedScope(); 579 } 580 581 void SharedFunctionInfo::ClearPreParsedScopeData() { 582 DCHECK(HasUncompiledDataWithPreParsedScope()); 583 UncompiledDataWithPreParsedScope* data = 584 uncompiled_data_with_pre_parsed_scope(); 585 586 // Trim off the pre-parsed scope data from the uncompiled data by swapping the 587 // map, leaving only an uncompiled data without pre-parsed scope. 588 DisallowHeapAllocation no_gc; 589 Heap* heap = Heap::FromWritableHeapObject(data); 590 591 // Swap the map. 592 heap->NotifyObjectLayoutChange(data, UncompiledDataWithPreParsedScope::kSize, 593 no_gc); 594 STATIC_ASSERT(UncompiledDataWithoutPreParsedScope::kSize < 595 UncompiledDataWithPreParsedScope::kSize); 596 STATIC_ASSERT(UncompiledDataWithoutPreParsedScope::kSize == 597 UncompiledData::kSize); 598 data->synchronized_set_map( 599 GetReadOnlyRoots().uncompiled_data_without_pre_parsed_scope_map()); 600 601 // Fill the remaining space with filler. 602 heap->CreateFillerObjectAt( 603 data->address() + UncompiledDataWithoutPreParsedScope::kSize, 604 UncompiledDataWithPreParsedScope::kSize - 605 UncompiledDataWithoutPreParsedScope::kSize, 606 ClearRecordedSlots::kNo); 607 608 // Ensure that the clear was successful. 609 DCHECK(HasUncompiledDataWithoutPreParsedScope()); 610 } 611 612 bool SharedFunctionInfo::HasWasmExportedFunctionData() const { 613 return function_data()->IsWasmExportedFunctionData(); 614 } 615 616 int SharedFunctionInfo::FunctionLiteralId(Isolate* isolate) const { 617 // Fast path for the common case when the SFI is uncompiled and so the 618 // function literal id is already in the uncompiled data. 619 if (HasUncompiledData()) { 620 int id = uncompiled_data()->function_literal_id(); 621 // Make sure the id is what we should have found with the slow path. 622 DCHECK_EQ(id, FindIndexInScript(isolate)); 623 return id; 624 } 625 626 // Otherwise, search for the function in the SFI's script's function list, 627 // and return its index in that list.e 628 return FindIndexInScript(isolate); 629 } 630 631 Object* SharedFunctionInfo::script() const { 632 Object* maybe_script = script_or_debug_info(); 633 if (maybe_script->IsDebugInfo()) { 634 return DebugInfo::cast(maybe_script)->script(); 635 } 636 return maybe_script; 637 } 638 639 void SharedFunctionInfo::set_script(Object* script) { 640 Object* maybe_debug_info = script_or_debug_info(); 641 if (maybe_debug_info->IsDebugInfo()) { 642 DebugInfo::cast(maybe_debug_info)->set_script(script); 643 } else { 644 set_script_or_debug_info(script); 645 } 646 } 647 648 bool SharedFunctionInfo::HasDebugInfo() const { 649 return script_or_debug_info()->IsDebugInfo(); 650 } 651 652 DebugInfo* SharedFunctionInfo::GetDebugInfo() const { 653 DCHECK(HasDebugInfo()); 654 return DebugInfo::cast(script_or_debug_info()); 655 } 656 657 void SharedFunctionInfo::SetDebugInfo(DebugInfo* debug_info) { 658 DCHECK(!HasDebugInfo()); 659 DCHECK_EQ(debug_info->script(), script_or_debug_info()); 660 set_script_or_debug_info(debug_info); 661 } 662 663 bool SharedFunctionInfo::HasBuiltinFunctionId() { 664 return builtin_function_id() != BuiltinFunctionId::kInvalidBuiltinFunctionId; 665 } 666 667 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() { 668 return static_cast<BuiltinFunctionId>(raw_builtin_function_id()); 669 } 670 671 void SharedFunctionInfo::set_builtin_function_id(BuiltinFunctionId id) { 672 set_raw_builtin_function_id(static_cast<uint8_t>(id)); 673 } 674 675 bool SharedFunctionInfo::HasInferredName() { 676 Object* scope_info = name_or_scope_info(); 677 if (scope_info->IsScopeInfo()) { 678 return ScopeInfo::cast(scope_info)->HasInferredFunctionName(); 679 } 680 return HasUncompiledData(); 681 } 682 683 String* SharedFunctionInfo::inferred_name() { 684 Object* maybe_scope_info = name_or_scope_info(); 685 if (maybe_scope_info->IsScopeInfo()) { 686 ScopeInfo* scope_info = ScopeInfo::cast(maybe_scope_info); 687 if (scope_info->HasInferredFunctionName()) { 688 Object* name = ScopeInfo::cast(maybe_scope_info)->InferredFunctionName(); 689 if (name->IsString()) return String::cast(name); 690 } 691 } else if (HasUncompiledData()) { 692 return uncompiled_data()->inferred_name(); 693 } 694 return GetReadOnlyRoots().empty_string(); 695 } 696 697 bool SharedFunctionInfo::IsUserJavaScript() { 698 Object* script_obj = script(); 699 if (script_obj->IsUndefined()) return false; 700 Script* script = Script::cast(script_obj); 701 return script->IsUserJavaScript(); 702 } 703 704 bool SharedFunctionInfo::IsSubjectToDebugging() { 705 return IsUserJavaScript() && !HasAsmWasmData(); 706 } 707 708 bool SharedFunctionInfo::CanDiscardCompiled() const { 709 bool can_decompile = (HasBytecodeArray() || HasAsmWasmData() || 710 HasUncompiledDataWithPreParsedScope()); 711 return can_decompile; 712 } 713 714 // static 715 void SharedFunctionInfo::DiscardCompiled( 716 Isolate* isolate, Handle<SharedFunctionInfo> shared_info) { 717 DCHECK(shared_info->CanDiscardCompiled()); 718 719 int start_position = shared_info->StartPosition(); 720 int end_position = shared_info->EndPosition(); 721 int function_literal_id = shared_info->FunctionLiteralId(isolate); 722 723 if (shared_info->is_compiled()) { 724 DisallowHeapAllocation no_gc; 725 726 HeapObject* outer_scope_info; 727 if (shared_info->scope_info()->HasOuterScopeInfo()) { 728 outer_scope_info = shared_info->scope_info()->OuterScopeInfo(); 729 } else { 730 outer_scope_info = ReadOnlyRoots(isolate).the_hole_value(); 731 } 732 // Raw setter to avoid validity checks, since we're performing the unusual 733 // task of decompiling. 734 shared_info->set_raw_outer_scope_info_or_feedback_metadata( 735 outer_scope_info); 736 } else { 737 DCHECK(shared_info->outer_scope_info()->IsScopeInfo() || 738 shared_info->outer_scope_info()->IsTheHole()); 739 } 740 741 if (shared_info->HasUncompiledDataWithPreParsedScope()) { 742 // If this is uncompiled data with a pre-parsed scope data, we can just 743 // clear out the scope data and keep the uncompiled data. 744 shared_info->ClearPreParsedScopeData(); 745 } else { 746 // Create a new UncompiledData, without pre-parsed scope, and update the 747 // function data to point to it. Use the raw function data setter to avoid 748 // validity checks, since we're performing the unusual task of decompiling. 749 Handle<UncompiledData> data = 750 isolate->factory()->NewUncompiledDataWithoutPreParsedScope( 751 handle(shared_info->inferred_name(), isolate), start_position, 752 end_position, function_literal_id); 753 shared_info->set_function_data(*data); 754 } 755 } 756 757 } // namespace internal 758 } // namespace v8 759 760 #include "src/objects/object-macros-undef.h" 761 762 #endif // V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_ 763