v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
shared-function-info.cc
Go to the documentation of this file.
1// Copyright 2020 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
6
7#include <optional>
8
9#include "src/ast/ast.h"
10#include "src/ast/scopes.h"
14#include "src/common/globals.h"
15#include "src/debug/debug.h"
21
22namespace v8::internal {
23
26
28 // Hash SharedFunctionInfo based on its start position and script id. Note: we
29 // don't use the function's literal id since getting that is slow for compiled
30 // functions.
31 int start_pos = StartPosition();
32 int script_id = IsScript(script()) ? Cast<Script>(script())->id() : 0;
33 return static_cast<uint32_t>(base::hash_combine(start_pos, script_id));
34}
35
36void SharedFunctionInfo::Init(ReadOnlyRoots ro_roots, int unique_id) {
38
39 // Set the function data to the "illegal" builtin. Ideally we'd use some sort
40 // of "uninitialized" marker here, but it's cheaper to use a valid builtin and
41 // avoid having to do uninitialized checks elsewhere.
42 set_builtin_id(Builtin::kIllegal);
43
44 // Set the name to the no-name sentinel, this can be updated later.
45 set_name_or_scope_info(SharedFunctionInfo::kNoSharedNameSentinel,
47
48 // Generally functions won't have feedback, unless they have been created
49 // from a FunctionLiteral. Those can just reset this field to keep the
50 // SharedFunctionInfo in a consistent state.
51 set_raw_outer_scope_info_or_feedback_metadata(ro_roots.the_hole_value(),
53 set_script(ro_roots.undefined_value(), kReleaseStore, SKIP_WRITE_BARRIER);
54 set_function_literal_id(kInvalidInfoId);
55 set_unique_id(unique_id);
56
57 // Set integer fields (smi or int, depending on the architecture).
58 set_length(0);
60 set_expected_nof_properties(0);
61 set_raw_function_token_offset(0);
62
63 // All flags default to false or 0, except ConstructAsBuiltinBit just because
64 // we're using the kIllegal builtin.
65 set_flags(ConstructAsBuiltinBit::encode(true), kRelaxedStore);
66 set_flags2(0);
67
69
70 set_age(0);
71
73}
74
76 // ======
77 // NOTE: This chain of checks MUST be kept in sync with the equivalent CSA
78 // GetSharedFunctionInfoCode method in code-stub-assembler.cc.
79 // ======
80
81 Tagged<Object> data = GetTrustedData(isolate);
82 if (data != Smi::zero()) {
84
85 if (IsBytecodeArray(data)) {
86 // Having a bytecode array means we are a compiled, interpreted function.
87 DCHECK(HasBytecodeArray());
88 return isolate->builtins()->code(Builtin::kInterpreterEntryTrampoline);
89 }
90 if (IsCode(data)) {
91 // Having baseline Code means we are a compiled, baseline function.
92 DCHECK(HasBaselineCode());
93 return Cast<Code>(data);
94 }
95 if (IsInterpreterData(data)) {
96 Tagged<Code> code = InterpreterTrampoline(isolate);
97 DCHECK(IsCode(code));
98 DCHECK(code->is_interpreter_trampoline_builtin());
99 return code;
100 }
101 if (IsUncompiledData(data)) {
102 // Having uncompiled data (with or without scope) means we need to
103 // compile.
105 return isolate->builtins()->code(Builtin::kCompileLazy);
106 }
107#if V8_ENABLE_WEBASSEMBLY
108 if (IsWasmExportedFunctionData(data)) {
109 // Having a WasmExportedFunctionData means the code is in there.
110 DCHECK(HasWasmExportedFunctionData());
111 return wasm_exported_function_data()->wrapper_code(isolate);
112 }
113 if (IsWasmJSFunctionData(data)) {
114 return wasm_js_function_data()->wrapper_code(isolate);
115 }
116 if (IsWasmCapiFunctionData(data)) {
117 return wasm_capi_function_data()->wrapper_code(isolate);
118 }
119#endif // V8_ENABLE_WEBASSEMBLY
120 } else {
122 data = GetUntrustedData();
123
124 if (IsSmi(data)) {
125 // Holding a Smi means we are a builtin.
127 return isolate->builtins()->code(builtin_id());
128 }
129 if (IsFunctionTemplateInfo(data)) {
130 // Having a function template info means we are an API function.
132 return isolate->builtins()->code(Builtin::kHandleApiCallOrConstruct);
133 }
134#if V8_ENABLE_WEBASSEMBLY
135 if (IsAsmWasmData(data)) {
136 // Having AsmWasmData means we are an asm.js/wasm function.
137 DCHECK(HasAsmWasmData());
138 return isolate->builtins()->code(Builtin::kInstantiateAsmJs);
139 }
140 if (IsWasmResumeData(data)) {
141 if (static_cast<wasm::OnResume>(wasm_resume_data()->on_resume()) ==
143 return isolate->builtins()->code(Builtin::kWasmResume);
144 } else {
145 return isolate->builtins()->code(Builtin::kWasmReject);
146 }
147 }
148#endif // V8_ENABLE_WEBASSEMBLY
149 }
150
151 UNREACHABLE();
152}
153
157
160
162 while (index_ < infos_->length()) {
163 Tagged<MaybeObject> raw = infos_->get(index_++);
164 Tagged<HeapObject> heap_object;
165 if (!raw.GetHeapObject(&heap_object) ||
166 !IsSharedFunctionInfo(heap_object)) {
167 continue;
168 }
169 return Cast<SharedFunctionInfo>(heap_object);
170 }
171 return SharedFunctionInfo();
172}
173
175 Tagged<Script> script) {
176 infos_ = handle(script->infos(), isolate);
177 index_ = 0;
178}
179
181 ReadOnlyRoots roots,
182 Tagged<HeapObject> script_object,
183 int function_literal_id,
184 bool reset_preparsed_scope_data) {
186
187 if (script() == script_object) return;
188
189 if (reset_preparsed_scope_data && HasUncompiledDataWithPreparseData()) {
190 ClearPreparseData(isolate);
191 }
192
193 // Add shared function info to new script's list. If a collection occurs,
194 // the shared function info may be temporarily in two lists.
195 // This is okay because the gc-time processing of these lists can tolerate
196 // duplicates.
197 if (IsScript(script_object)) {
198 DCHECK(!IsScript(script()));
199 Tagged<Script> script = Cast<Script>(script_object);
200 Tagged<WeakFixedArray> list = script->infos();
201#ifdef DEBUG
202 DCHECK_LT(function_literal_id, list->length());
203 Tagged<MaybeObject> maybe_object = list->get(function_literal_id);
204 Tagged<HeapObject> heap_object;
205 if (maybe_object.GetHeapObjectIfWeak(&heap_object)) {
206 DCHECK_EQ(heap_object, *this);
207 }
208#endif
209 list->set(function_literal_id, MakeWeak(Tagged(*this)));
210 } else {
211 DCHECK(IsScript(script()));
212
213 // Remove shared function info from old script's list.
214 Tagged<Script> old_script = Cast<Script>(script());
215
216 // Due to liveedit, it might happen that the old_script doesn't know
217 // about the SharedFunctionInfo, so we have to guard against that.
218 Tagged<WeakFixedArray> infos = old_script->infos();
219 if (function_literal_id < infos->length()) {
220 Tagged<MaybeObject> raw = old_script->infos()->get(function_literal_id);
221 Tagged<HeapObject> heap_object;
222 if (raw.GetHeapObjectIfWeak(&heap_object) && heap_object == *this) {
223 old_script->infos()->set(function_literal_id, roots.undefined_value());
224 }
225 }
226 }
227
228 // Finally set new script.
229 set_script(script_object, kReleaseStore);
230}
231
233 IsolateForSandbox isolate) {
234 if (other->HasTrustedData()) {
235 SetTrustedData(Cast<ExposedTrustedObject>(other->GetTrustedData(isolate)));
236 } else {
237 SetUntrustedData(other->GetUntrustedData());
238 }
239
240 PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
241 set_name_or_scope_info(other->name_or_scope_info(cage_base, kAcquireLoad),
243 set_outer_scope_info_or_feedback_metadata(
244 other->outer_scope_info_or_feedback_metadata(cage_base));
245 set_script(other->script(cage_base, kAcquireLoad), kReleaseStore);
246
247 set_length(other->length());
248 set_formal_parameter_count(other->formal_parameter_count());
249 set_function_token_offset(other->function_token_offset());
250 set_expected_nof_properties(other->expected_nof_properties());
251 set_flags2(other->flags2());
252 set_flags(other->flags(kRelaxedLoad), kRelaxedStore);
253 set_function_literal_id(other->function_literal_id());
254 set_unique_id(other->unique_id());
255 set_age(0);
256
257#if DEBUG
258 // This should now be byte-for-byte identical to the input except for the age
259 // field (could be reset concurrently). Compare content before age field now:
260 DCHECK_EQ(memcmp(reinterpret_cast<void*>(address()),
261 reinterpret_cast<void*>(other.address()),
262 SharedFunctionInfo::kAgeOffset),
263 0);
264 // Compare content after age field.
265 constexpr Address kPastAgeOffset =
266 SharedFunctionInfo::kAgeOffset + SharedFunctionInfo::kAgeSize;
267 DCHECK_EQ(memcmp(reinterpret_cast<void*>(address() + kPastAgeOffset),
268 reinterpret_cast<void*>(other.address() + kPastAgeOffset),
269 SharedFunctionInfo::kSize - kPastAgeOffset),
270 0);
271#endif
272}
273
275 return isolate->debug()->HasDebugInfo(*this);
276}
277
278// Needs to be kept in sync with Scope::UniqueIdInScript and
279// ScopeInfo::UniqueIdInScript.
281 // Script scopes start "before" the script to avoid clashing with a scope that
282 // starts on character 0.
283 if (function_literal_id() == kFunctionLiteralIdTopLevel) return -2;
284 // Wrapped functions start before the function body, but after the script
285 // start, to avoid clashing with a scope starting on character 0.
286 if (syntax_kind() == FunctionSyntaxKind::kWrapped) return -1;
287 // Default constructors have the same start position as their parent class
288 // scope. Use the next char position to distinguish this scope.
290}
291
293 return isolate->debug()->TryGetDebugInfo(*this).value();
294}
295
296std::optional<Tagged<DebugInfo>> SharedFunctionInfo::TryGetDebugInfo(
297 Isolate* isolate) const {
298 return isolate->debug()->TryGetDebugInfo(*this);
299}
300
302 return isolate->debug()->HasBreakInfo(*this);
303}
304
306 return isolate->debug()->BreakAtEntry(*this);
307}
308
310 return isolate->debug()->HasCoverageInfo(*this);
311}
312
314 Isolate* isolate) const {
315 DCHECK(HasCoverageInfo(isolate));
316 return Cast<CoverageInfo>(GetDebugInfo(isolate)->coverage_info());
317}
318
319std::unique_ptr<char[]> SharedFunctionInfo::DebugNameCStr() const {
320#if V8_ENABLE_WEBASSEMBLY
321 if (HasWasmExportedFunctionData()) {
323 wasm_exported_function_data()->sig());
324 }
325#endif // V8_ENABLE_WEBASSEMBLY
327 Tagged<String> function_name = Name();
328 if (function_name->length() == 0) function_name = inferred_name();
329 return function_name->ToCString();
330}
331
332// static
334 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared) {
335#if V8_ENABLE_WEBASSEMBLY
336 if (shared->HasWasmExportedFunctionData()) {
337 return isolate->factory()
338 ->NewStringFromUtf8(base::CStrVector(shared->DebugNameCStr().get()))
339 .ToHandleChecked();
340 }
341#endif // V8_ENABLE_WEBASSEMBLY
342 FunctionKind function_kind = shared->kind();
343 if (IsClassMembersInitializerFunction(function_kind)) {
345 ? isolate->factory()->instance_members_initializer_string()
346 : isolate->factory()->static_initializer_string();
347 }
349 Tagged<String> function_name = shared->Name();
350 if (function_name->length() == 0) function_name = shared->inferred_name();
351 return handle(function_name, isolate);
352}
353
354bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
355 // Filters are almost always "*", so check for that and exit quickly.
356 if (V8_LIKELY(raw_filter[0] == '*' && raw_filter[1] == '\0')) {
357 return true;
358 }
359 base::Vector<const char> filter = base::CStrVector(raw_filter);
361 filter);
362}
363
366 return !IsUndefined(script(), roots) &&
367 !IsUndefined(Cast<Script>(script())->source(), roots) &&
368 Cast<String>(Cast<Script>(script())->source())->length() > 0;
369}
370
372 Isolate* isolate,
373 std::function<void(Tagged<HeapObject> object, ObjectSlot slot,
374 Tagged<HeapObject> target)>
375 gc_notify_updated_slot) {
377 if (HasFeedbackMetadata()) {
378 if (v8_flags.trace_flush_code) {
379 CodeTracer::Scope scope(isolate->GetCodeTracer());
380 PrintF(scope.file(), "[discarding compiled metadata for ");
381 ShortPrint(*this, scope.file());
382 PrintF(scope.file(), "]\n");
383 }
384
385 Tagged<HeapObject> outer_scope_info;
386 if (scope_info()->HasOuterScopeInfo()) {
387 outer_scope_info = scope_info()->OuterScopeInfo();
388 } else {
389 outer_scope_info = ReadOnlyRoots(isolate).the_hole_value();
390 }
391
392 // Raw setter to avoid validity checks, since we're performing the unusual
393 // task of decompiling.
394 set_raw_outer_scope_info_or_feedback_metadata(outer_scope_info);
395 gc_notify_updated_slot(
396 *this,
397 RawField(SharedFunctionInfo::kOuterScopeInfoOrFeedbackMetadataOffset),
398 outer_scope_info);
399 } else {
400 DCHECK(IsScopeInfo(outer_scope_info()) || IsTheHole(outer_scope_info()));
401 }
402
403 // TODO(rmcilroy): Possibly discard ScopeInfo here as well.
404}
405
406// static
408 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared_info) {
409 DCHECK(shared_info->CanDiscardCompiled());
410
411 Handle<String> inferred_name_val(shared_info->inferred_name(), isolate);
412 int start_position = shared_info->StartPosition();
413 int end_position = shared_info->EndPosition();
414
416 if (!shared_info->HasUncompiledDataWithPreparseData()) {
417 // Create a new UncompiledData, without pre-parsed scope.
418 data = isolate->factory()->NewUncompiledDataWithoutPreparseData(
419 inferred_name_val, start_position, end_position);
420 }
421
422 // If the GC runs after changing one but not both fields below, it could see
423 // the SharedFunctionInfo in an unexpected state.
425
426 shared_info->DiscardCompiledMetadata(isolate);
427
428 // Replace compiled data with a new UncompiledData object.
429 if (shared_info->HasUncompiledDataWithPreparseData()) {
430 // If this is uncompiled data with a pre-parsed scope data, we can just
431 // clear out the scope data and keep the uncompiled data.
432 shared_info->ClearPreparseData(isolate);
433 DCHECK(data.is_null());
434 } else {
435 // Update the function data to point to the UncompiledData without preparse
436 // data created above. Use the raw function data setter to avoid validity
437 // checks, since we're performing the unusual task of decompiling.
438 shared_info->SetTrustedData(*data.ToHandleChecked());
439 }
440}
441
442// static
444 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared) {
445 if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
446 Handle<String> source(Cast<String>(Cast<Script>(shared->script())->source()),
447 isolate);
448 return isolate->factory()->NewSubString(source, shared->StartPosition(),
449 shared->EndPosition());
450}
451
452// static
454 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared) {
455 if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
456 Handle<String> script_source(
457 Cast<String>(Cast<Script>(shared->script())->source()), isolate);
458 int start_pos = shared->function_token_position();
459 DCHECK_NE(start_pos, kNoSourcePosition);
460 Handle<String> source = isolate->factory()->NewSubString(
461 script_source, start_pos, shared->EndPosition());
462 if (!shared->is_wrapped()) return source;
463
464 DCHECK(!shared->name_should_print_as_anonymous());
465 IncrementalStringBuilder builder(isolate);
466 builder.AppendCStringLiteral("function ");
467 builder.AppendString(DirectHandle<String>(shared->Name(), isolate));
468 builder.AppendCharacter('(');
470 Cast<Script>(shared->script())->wrapped_arguments(), isolate);
471 int argc = args->length();
472 for (int i = 0; i < argc; i++) {
473 if (i > 0) builder.AppendCStringLiteral(", ");
474 builder.AppendString(
475 DirectHandle<String>(Cast<String>(args->get(i)), isolate));
476 }
477 builder.AppendCStringLiteral(") {\n");
478 builder.AppendString(source);
479 builder.AppendCStringLiteral("\n}");
480 return indirect_handle(builder.Finish().ToHandleChecked(), isolate);
481}
482
484
485// Output the source code without any allocation in the heap.
486std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
488 // For some native functions there is no source.
489 if (!s->HasSourceCode()) return os << "<No Source>";
490
491 // Get the source for the script which this function came from.
492 // Don't use Cast<String> because we don't want more assertion errors while
493 // we are already creating a stack dump.
494 Tagged<String> script_source =
495 UncheckedCast<String>(Cast<Script>(s->script())->source());
496
497 if (!s->is_toplevel()) {
498 os << "function ";
499 Tagged<String> name = s->Name();
500 if (name->length() > 0) {
501 name->PrintUC16(os);
502 }
503 }
504
505 int len = s->EndPosition() - s->StartPosition();
506 if (len <= v.max_length || v.max_length < 0) {
507 script_source->PrintUC16(os, s->StartPosition(), s->EndPosition());
508 return os;
509 } else {
510 script_source->PrintUC16(os, s->StartPosition(),
511 s->StartPosition() + v.max_length);
512 return os << "...\n";
513 }
514}
515
517 BailoutReason reason) {
518 DCHECK_NE(reason, BailoutReason::kNoReason);
519
520 set_flags(DisabledOptimizationReasonBits::update(flags(kRelaxedLoad), reason),
522 // Code should be the lazy compilation stub or else interpreted.
523 if constexpr (DEBUG_BOOL) {
524 CodeKind kind = abstract_code(isolate)->kind(isolate);
525 CHECK(kind == CodeKind::INTERPRETED_FUNCTION || kind == CodeKind::BUILTIN);
526 }
527 PROFILE(isolate,
528 CodeDisableOptEvent(direct_handle(abstract_code(isolate), isolate),
529 direct_handle(*this, isolate)));
530 if (v8_flags.trace_opt) {
531 CodeTracer::Scope scope(isolate->GetCodeTracer());
532 PrintF(scope.file(), "[disabled optimization for ");
533 ShortPrint(*this, scope.file());
534 PrintF(scope.file(), ", reason: %s]\n", GetBailoutReason(reason));
535 }
536}
537
538// static
539template <typename IsolateT>
541 FunctionLiteral* lit,
542 bool is_toplevel) {
543 DCHECK(!IsScopeInfo(
544 lit->shared_function_info()->name_or_scope_info(kAcquireLoad)));
545 {
548 DCHECK_EQ(raw_sfi->function_literal_id(), lit->function_literal_id());
549 // When adding fields here, make sure DeclarationScope::AnalyzePartially is
550 // updated accordingly.
551 raw_sfi->set_internal_formal_parameter_count(
553 raw_sfi->SetFunctionTokenPosition(lit->function_token_position(),
554 lit->start_position());
555 raw_sfi->set_syntax_kind(lit->syntax_kind());
556 raw_sfi->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
557 raw_sfi->set_language_mode(lit->language_mode());
558 // FunctionKind must have already been set.
559 DCHECK(lit->kind() == raw_sfi->kind());
561 IsClassConstructor(lit->kind()));
562 raw_sfi->set_requires_instance_members_initializer(
565 IsClassConstructor(lit->kind()));
566 raw_sfi->set_class_scope_has_private_brand(
569 IsClassConstructor(lit->kind()));
570 raw_sfi->set_has_static_private_methods_or_accessors(
572
573 raw_sfi->set_is_toplevel(is_toplevel);
574 DCHECK(IsTheHole(raw_sfi->outer_scope_info()));
575 Scope* outer_scope = lit->scope()->GetOuterScopeWithContext();
576 if (outer_scope && (!is_toplevel || !outer_scope->is_script_scope())) {
577 raw_sfi->set_outer_scope_info(*outer_scope->scope_info());
578 raw_sfi->set_private_name_lookup_skips_outer_class(
580 }
581 if (lit->scope()->is_reparsed()) {
582 raw_sfi->SetScopeInfo(*lit->scope()->scope_info());
583 }
584
585 raw_sfi->set_length(lit->function_length());
586
587 // For lazy parsed functions, the following flags will be inaccurate since
588 // we don't have the information yet. They're set later in
589 // UpdateSharedFunctionFlagsAfterCompilation (compiler.cc), when the
590 // function is really parsed and compiled.
591 if (lit->ShouldEagerCompile()) {
592 raw_sfi->set_has_duplicate_parameters(lit->has_duplicate_parameters());
593 raw_sfi->UpdateAndFinalizeExpectedNofPropertiesFromEstimate(lit);
595
596 // If we're about to eager compile, we'll have the function literal
597 // available, so there's no need to wastefully allocate an uncompiled
598 // data.
599 return;
600 }
601
602 raw_sfi->UpdateExpectedNofPropertiesFromEstimate(lit);
603 }
604 CreateAndSetUncompiledData(isolate, lit);
605}
606
607template <typename IsolateT>
609 FunctionLiteral* lit) {
610 DCHECK(!lit->shared_function_info()->HasUncompiledData());
612 ProducedPreparseData* scope_data = lit->produced_preparse_data();
613 if (scope_data != nullptr) {
614 Handle<PreparseData> preparse_data = scope_data->Serialize(isolate);
615
616 if (lit->should_parallel_compile()) {
617 data = isolate->factory()->NewUncompiledDataWithPreparseDataAndJob(
618 lit->GetInferredName(isolate), lit->start_position(),
619 lit->end_position(), preparse_data);
620 } else {
621 data = isolate->factory()->NewUncompiledDataWithPreparseData(
622 lit->GetInferredName(isolate), lit->start_position(),
623 lit->end_position(), preparse_data);
624 }
625 } else {
626 if (lit->should_parallel_compile()) {
627 data = isolate->factory()->NewUncompiledDataWithoutPreparseDataWithJob(
628 lit->GetInferredName(isolate), lit->start_position(),
629 lit->end_position());
630 } else {
631 data = isolate->factory()->NewUncompiledDataWithoutPreparseData(
632 lit->GetInferredName(isolate), lit->start_position(),
633 lit->end_position());
634 }
635 }
636
637 lit->shared_function_info()->set_uncompiled_data(*data);
638}
639
642 FunctionLiteral* lit, bool is_toplevel);
645 FunctionLiteral* lit,
646 bool is_toplevel);
647
652 FunctionLiteral* lit);
653
656 int estimate = literal->expected_property_count();
657
658 // If this is a class constructor, we may have already parsed fields.
659 if (is_class_constructor()) {
660 estimate += expected_nof_properties();
661 }
662 return estimate;
663}
664
667 // Limit actual estimate to fit in a 8 bit field, we will never allocate
668 // more than this in any case.
671 set_expected_nof_properties(std::min(estimate, kMaxUInt8));
672}
673
676 DCHECK(literal->ShouldEagerCompile());
677 if (are_properties_final()) {
678 return;
679 }
681
682 // If no properties are added in the constructor, they are more likely
683 // to be added later.
684 if (estimate == 0) estimate = 2;
685
686 // Limit actual estimate to fit in a 8 bit field, we will never allocate
687 // more than this in any case.
689 estimate = std::min(estimate, kMaxUInt8);
690
691 set_expected_nof_properties(estimate);
692 set_are_properties_final(true);
693}
694
696 int start_position) {
697 int offset;
699 offset = 0;
700 } else {
701 offset = start_position - function_token_position;
702 }
703
706 }
707 set_raw_function_token_offset(offset);
708}
709
711 Tagged<Object> maybe_scope_info = name_or_scope_info(kAcquireLoad);
712 if (IsScopeInfo(maybe_scope_info)) {
713 Tagged<ScopeInfo> info = Cast<ScopeInfo>(maybe_scope_info);
714 if (info->HasPositionInfo()) {
715 return info->StartPosition();
716 }
717 }
718 if (HasUncompiledData()) {
719 // Works with or without scope.
720 return uncompiled_data(GetIsolateForSandbox(*this))->start_position();
721 }
722 if (IsApiFunction() || HasBuiltinId()) {
723 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtin::kCompileLazy);
724 return 0;
725 }
726#if V8_ENABLE_WEBASSEMBLY
727 if (HasWasmExportedFunctionData()) {
729 wasm_exported_function_data()->instance_data();
730 int func_index = wasm_exported_function_data()->function_index();
731 auto& function = instance_data->module()->functions[func_index];
732 return static_cast<int>(function.code.offset());
733 }
734#endif // V8_ENABLE_WEBASSEMBLY
735 return kNoSourcePosition;
736}
737
739 Tagged<Object> maybe_scope_info = name_or_scope_info(kAcquireLoad);
740 if (IsScopeInfo(maybe_scope_info)) {
741 Tagged<ScopeInfo> info = Cast<ScopeInfo>(maybe_scope_info);
742 if (info->HasPositionInfo()) {
743 return info->EndPosition();
744 }
745 }
746 if (HasUncompiledData()) {
747 // Works with or without scope.
748 return uncompiled_data(GetIsolateForSandbox(*this))->end_position();
749 }
750 if (IsApiFunction() || HasBuiltinId()) {
751 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtin::kCompileLazy);
752 return 0;
753 }
754#if V8_ENABLE_WEBASSEMBLY
755 if (HasWasmExportedFunctionData()) {
757 wasm_exported_function_data()->instance_data();
758 int func_index = wasm_exported_function_data()->function_index();
759 auto& function = instance_data->module()->functions[func_index];
760 return static_cast<int>(function.code.end_offset());
761 }
762#endif // V8_ENABLE_WEBASSEMBLY
763 return kNoSourcePosition;
764}
765
767 IsolateForSandbox isolate, FunctionLiteral* lit) {
768 Tagged<Object> maybe_scope_info = name_or_scope_info(kAcquireLoad);
769 // TODO(crbug.com/401059828): remove once crashes are gone.
770 set_live_edited(true);
771
772 if (IsScopeInfo(maybe_scope_info)) {
773 // Updating the ScopeInfo is safe since they are identical modulo
774 // source positions.
775 Tagged<ScopeInfo> new_scope_info = *lit->scope()->scope_info();
776 Tagged<ScopeInfo> old_scope_info = Cast<ScopeInfo>(maybe_scope_info);
777 DCHECK(new_scope_info->Equals(old_scope_info, true));
778 old_scope_info->SetPositionInfo(new_scope_info->position_info_start(),
779 new_scope_info->position_info_end());
780 } else if (!is_compiled()) {
783 ClearPreparseData(isolate);
784 }
785 uncompiled_data(isolate)->set_start_position(lit->start_position());
786 uncompiled_data(isolate)->set_end_position(lit->end_position());
787
788 if (!is_toplevel()) {
789 Scope* outer_scope = lit->scope()->GetOuterScopeWithContext();
790 if (outer_scope) {
791 // Use the raw accessor since we have to replace the existing outer
792 // scope.
793 set_raw_outer_scope_info_or_feedback_metadata(
794 *outer_scope->scope_info());
795 }
796 }
797 }
799 lit->start_position());
800}
801
803 return CachedTieringDecisionBits::decode(flags2());
804}
805
807 CachedTieringDecision decision) {
808 set_flags2(CachedTieringDecisionBits::update(flags2(), decision));
809}
810
811// static
813 Isolate* isolate, Handle<SharedFunctionInfo> shared_info,
815 if (!shared_info->HasBytecodeArray()) {
816 if (!Compiler::Compile(isolate, shared_info, Compiler::CLEAR_EXCEPTION,
817 is_compiled_scope, flag)) {
818 FATAL("Failed to compile shared info that was already compiled before");
819 }
820 DCHECK(shared_info->GetBytecodeArray(isolate)->HasSourcePositionTable());
821 } else {
822 *is_compiled_scope = shared_info->is_compiled_scope(isolate);
823 }
824}
825
826// static
828 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared_info) {
829 if (shared_info->CanCollectSourcePosition(isolate)) {
830 std::optional<Isolate::ExceptionScope> exception_scope;
831 if (isolate->has_exception()) {
832 exception_scope.emplace(isolate);
833 }
834 Compiler::CollectSourcePositions(isolate, shared_info);
835 }
836}
837
838// static
840 DirectHandle<SharedFunctionInfo> shared, Isolate* isolate) {
841 DCHECK(shared->HasBytecodeArray());
843 shared->GetBytecodeArray(isolate), isolate);
844 DirectHandle<BytecodeArray> debug_bytecode_array =
845 isolate->factory()->CopyBytecodeArray(original_bytecode_array);
846
847 {
849 base::MutexGuard guard(isolate->shared_function_info_access());
850 Tagged<DebugInfo> debug_info = shared->GetDebugInfo(isolate);
851 debug_info->set_original_bytecode_array(*original_bytecode_array,
853 debug_info->set_debug_bytecode_array(*debug_bytecode_array, kReleaseStore);
854 shared->SetActiveBytecodeArray(*debug_bytecode_array, isolate);
855 }
856}
857
858// static
860 Tagged<SharedFunctionInfo> shared, Isolate* isolate) {
862 base::MutexGuard guard(isolate->shared_function_info_access());
863 Tagged<DebugInfo> debug_info = shared->GetDebugInfo(isolate);
865 debug_info->OriginalBytecodeArray(isolate);
866 DCHECK(!shared->HasBaselineCode());
867 shared->SetActiveBytecodeArray(original_bytecode_array, isolate);
868 debug_info->clear_original_bytecode_array();
869 debug_info->clear_debug_bytecode_array();
870}
871
872// static
874 if (v8_flags.flush_code_based_on_time ||
875 v8_flags.flush_code_based_on_tab_visibility) {
876 sfi->set_age(kMaxAge);
877 } else {
878 sfi->set_age(v8_flags.bytecode_old_age);
879 }
880}
881
882#ifdef DEBUG
883// static
884bool SharedFunctionInfo::UniqueIdsAreUnique(Isolate* isolate) {
885 std::unordered_set<uint32_t> ids({isolate->next_unique_sfi_id()});
886 CombinedHeapObjectIterator it(isolate->heap());
887 for (Tagged<HeapObject> o = it.Next(); !o.is_null(); o = it.Next()) {
888 if (!IsSharedFunctionInfo(o)) continue;
889 auto result = ids.emplace(Cast<SharedFunctionInfo>(o)->unique_id());
890 // If previously inserted...
891 if (!result.second) return false;
892 }
893 return true;
894}
895#endif // DEBUG
896
897std::ostream& operator<<(std::ostream& os,
899 switch (i) {
901 os << "has no script";
902 break;
904 os << "needs binary coverage";
905 break;
907 os << "is builtin";
908 break;
910 os << "is not user code";
911 break;
913 os << "has no bytecode";
914 break;
916 os << "exceeds bytecode limit";
917 break;
919 os << "may contain breakpoints";
920 break;
922 os << "has optimization disabled";
923 break;
925 os << "is inlineable (!)";
926 break;
927 }
928 return os;
929}
930
931} // namespace v8::internal
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static bool Compile(Isolate *isolate, Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag, IsCompiledScope *is_compiled_scope, CreateSourcePositions create_source_positions_flag=CreateSourcePositions::kNo)
Definition compiler.cc:2906
static bool CollectSourcePositions(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
Definition compiler.cc:2799
FunctionSyntaxKind syntax_kind() const
Definition ast.h:2390
FunctionKind kind() const
Definition ast.cc:231
int function_literal_id() const
Definition ast.h:2408
int function_token_position() const
Definition ast.h:2318
bool has_duplicate_parameters() const
Definition ast.h:2369
Handle< SharedFunctionInfo > shared_function_info() const
Definition ast.h:2356
V8_EXPORT_PRIVATE LanguageMode language_mode() const
Definition ast.cc:227
int start_position() const
Definition ast.cc:221
bool has_static_private_methods_or_accessors() const
Definition ast.h:2424
ProducedPreparseData * produced_preparse_data() const
Definition ast.h:2433
bool class_scope_has_private_brand() const
Definition ast.cc:268
Handle< String > GetInferredName(Isolate *isolate)
Definition ast.cc:194
bool requires_instance_members_initializer() const
Definition ast.h:2416
bool should_parallel_compile() const
Definition ast.h:2375
DeclarationScope * scope() const
Definition ast.h:2315
V8_EXPORT_PRIVATE bool ShouldEagerCompile() const
Definition ast.cc:209
MaybeDirectHandle< String > Finish()
V8_INLINE void AppendCharacter(uint8_t c)
V8_INLINE void AppendString(std::string_view str)
V8_INLINE void AppendCStringLiteral(const char(&literal)[N])
static const int kMaxInObjectProperties
Definition js-objects.h:959
virtual Handle< PreparseData > Serialize(Isolate *isolate)=0
bool private_name_lookup_skips_outer_class() const
Definition scopes.h:388
bool is_reparsed() const
Definition scopes.h:116
Scope * GetOuterScopeWithContext()
Definition scopes.cc:1550
bool is_script_scope() const
Definition scopes.h:364
Handle< ScopeInfo > scope_info() const
Definition scopes.h:581
void Reset(Isolate *isolate, Tagged< Script > script)
V8_EXPORT_PRIVATE ScriptIterator(Isolate *isolate, Tagged< Script > script)
V8_EXPORT_PRIVATE Tagged< SharedFunctionInfo > Next()
static void UninstallDebugBytecode(Tagged< SharedFunctionInfo > shared, Isolate *isolate)
void Init(ReadOnlyRoots roots, int unique_id)
Tagged< CoverageInfo > GetCoverageInfo(Isolate *isolate) const
bool HasCoverageInfo(Isolate *isolate) const
void SetFunctionTokenPosition(int function_token_position, int start_position)
static DirectHandle< Object > GetSourceCode(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
static void InstallDebugBytecode(DirectHandle< SharedFunctionInfo > shared, Isolate *isolate)
static const uint16_t kFunctionTokenOutOfRange
void set_cached_tiering_decision(CachedTieringDecision decision)
void DisableOptimization(Isolate *isolate, BailoutReason reason)
void UpdateAndFinalizeExpectedNofPropertiesFromEstimate(FunctionLiteral *literal)
static void EnsureSourcePositionsAvailable(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared_info)
static void EnsureBytecodeArrayAvailable(Isolate *isolate, Handle< SharedFunctionInfo > shared_info, IsCompiledScope *is_compiled_scope, CreateSourcePositions flag=CreateSourcePositions::kNo)
uint16_t get_property_estimate_from_literal(FunctionLiteral *literal)
bool PassesFilter(const char *raw_filter)
V8_EXPORT_PRIVATE uint32_t Hash()
Tagged< AbstractCode > abstract_code(Isolate *isolate)
Tagged< Code > InterpreterTrampoline(IsolateForSandbox isolate) const
static Handle< Object > GetSourceCodeHarmony(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
static V8_EXPORT_PRIVATE constexpr Tagged< Smi > const kNoSharedNameSentinel
void SetTrustedData(Tagged< ExposedTrustedObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
void ClearPreparseData(IsolateForSandbox isolate)
Tagged< HeapObject > script() const
CachedTieringDecision cached_tiering_decision()
V8_EXPORT_PRIVATE std::optional< Tagged< DebugInfo > > TryGetDebugInfo(Isolate *isolate) const
V8_EXPORT_PRIVATE Tagged< DebugInfo > GetDebugInfo(Isolate *isolate) const
void SetUntrustedData(Tagged< Object > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
void CopyFrom(Tagged< SharedFunctionInfo > other, IsolateForSandbox isolate)
V8_EXPORT_PRIVATE int StartPosition() const
Tagged< UncompiledData > uncompiled_data(IsolateForSandbox isolate) const
V8_EXPORT_PRIVATE void UpdateFromFunctionLiteralForLiveEdit(IsolateForSandbox isolate, FunctionLiteral *lit)
bool BreakAtEntry(Isolate *isolate) const
static void CreateAndSetUncompiledData(IsolateT *isolate, FunctionLiteral *lit)
static Handle< String > DebugName(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
static V8_EXPORT_PRIVATE void DiscardCompiled(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared_info)
std::unique_ptr< char[]> DebugNameCStr() const
void UpdateExpectedNofPropertiesFromEstimate(FunctionLiteral *literal)
V8_EXPORT_PRIVATE int EndPosition() const
V8_EXPORT_PRIVATE Tagged< Code > GetCode(Isolate *isolate) const
V8_EXPORT_PRIVATE void SetScript(IsolateForSandbox isolate, ReadOnlyRoots roots, Tagged< HeapObject > script_object, int function_literal_id, bool reset_preparsed_scope_data=true)
static V8_EXPORT_PRIVATE void EnsureOldForTesting(Tagged< SharedFunctionInfo > sfu)
IsCompiledScope is_compiled_scope(IsolateT *isolate) const
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) {})
V8_EXPORT_PRIVATE bool HasBreakInfo(Isolate *isolate) const
static void InitFromFunctionLiteral(IsolateT *isolate, FunctionLiteral *lit, bool is_toplevel)
bool HasDebugInfo(Isolate *isolate) const
static constexpr Tagged< Smi > zero()
Definition smi.h:99
bool GetHeapObjectIfWeak(Tagged< HeapObject > *result) const
bool GetHeapObject(Tagged< HeapObject > *result) const
static std::unique_ptr< char[]> GetDebugName(const wasm::CanonicalSig *sig)
#define PROFILE(the_isolate, Call)
Definition code-events.h:59
Register const index_
Handle< Code > code
#define DEBUG_BOOL
Definition globals.h:87
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
#define EXPORT_TEMPLATE_DEFINE(export)
int32_t offset
ZoneVector< RpoNumber > & result
FunctionLiteral * literal
Definition liveedit.cc:294
InstructionOperand source
V8_INLINE size_t hash_combine(size_t seed, size_t hash)
Definition hashing.h:77
Vector< const char > CStrVector(const char *data)
Definition vector.h:331
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
@ SKIP_WRITE_BARRIER
Definition objects.h:52
constexpr int kNoSourcePosition
Definition globals.h:850
constexpr int kMaxUInt8
Definition globals.h:378
bool IsClassConstructor(FunctionKind kind)
ReadOnlyRoots GetReadOnlyRoots()
Definition roots-inl.h:86
void PrintF(const char *format,...)
Definition utils.cc:39
SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit SharedFunctionInfo::MaglevCompilationFailedBit syntax_kind
Tagged(T object) -> Tagged< T >
kWasmInternalFunctionIndirectPointerTag instance_data
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
V8_INLINE IndirectHandle< T > indirect_handle(DirectHandle< T > handle)
Definition handles.h:757
kInterpreterTrampolineOffset Tagged< HeapObject >
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
Flag flags[]
Definition flags.cc:3797
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
V8_INLINE IsolateForSandbox GetIsolateForSandbox(Tagged< HeapObject >)
Definition isolate.h:75
constexpr int kInvalidInfoId
Definition globals.h:2766
Handle< To > UncheckedCast(Handle< From > value)
Definition handles-inl.h:55
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
void ShortPrint(Tagged< Object > obj, FILE *out)
Definition objects.cc:1865
const char * GetBailoutReason(BailoutReason reason)
bool PassesFilter(base::Vector< const char > name, base::Vector< const char > filter)
Definition utils.cc:238
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
Definition tagged.h:893
constexpr int kFunctionLiteralIdTopLevel
Definition globals.h:2767
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int JSParameterCount(int param_count_without_receiver)
Definition globals.h:2782
bool IsClassMembersInitializerFunction(FunctionKind kind)
bool IsDefaultConstructor(FunctionKind kind)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr ReleaseStoreTag kReleaseStore
Definition globals.h:2910
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
#define FATAL(...)
Definition logging.h:47
#define DCHECK_NULL(val)
Definition logging.h:491
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
const Tagged< SharedFunctionInfo > value
#define V8_LIKELY(condition)
Definition v8config.h:661