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 #include "src/debug/debug-type-profile.h"
6
7 #include "src/execution/isolate.h"
8 #include "src/objects/feedback-vector.h"
9 #include "src/objects/objects-inl.h"
10 #include "src/objects/objects.h"
11
12 namespace v8 {
13 namespace internal {
14
Collect(Isolate * isolate)15 std::unique_ptr<TypeProfile> TypeProfile::Collect(Isolate* isolate) {
16 std::unique_ptr<TypeProfile> result(new TypeProfile());
17
18 // Feedback vectors are already listed to prevent losing them to GC.
19 DCHECK(isolate->factory()
20 ->feedback_vectors_for_profiling_tools()
21 ->IsArrayList());
22 Handle<ArrayList> list = Handle<ArrayList>::cast(
23 isolate->factory()->feedback_vectors_for_profiling_tools());
24
25 Script::Iterator scripts(isolate);
26
27 for (Script script = scripts.Next(); !script.is_null();
28 script = scripts.Next()) {
29 if (!script.IsUserJavaScript()) {
30 continue;
31 }
32
33 Handle<Script> script_handle(script, isolate);
34
35 TypeProfileScript type_profile_script(script_handle);
36 std::vector<TypeProfileEntry>* entries = &type_profile_script.entries;
37
38 // TODO(franzih): Sort the vectors by script first instead of iterating
39 // the list multiple times.
40 for (int i = 0; i < list->Length(); i++) {
41 FeedbackVector vector = FeedbackVector::cast(list->Get(i));
42 SharedFunctionInfo info = vector.shared_function_info();
43 DCHECK(info.IsSubjectToDebugging());
44
45 // Match vectors with script.
46 if (script != info.script()) {
47 continue;
48 }
49 if (!info.HasFeedbackMetadata() || info.feedback_metadata().is_empty() ||
50 !info.feedback_metadata().HasTypeProfileSlot()) {
51 continue;
52 }
53 FeedbackSlot slot = vector.GetTypeProfileSlot();
54 FeedbackNexus nexus(vector, slot);
55 Handle<String> name(info.DebugName(), isolate);
56 std::vector<int> source_positions = nexus.GetSourcePositions();
57 for (int position : source_positions) {
58 DCHECK_GE(position, 0);
59 entries->emplace_back(position, nexus.GetTypesForSourcePositions(
60 static_cast<uint32_t>(position)));
61 }
62
63 // Releases type profile data collected so far.
64 nexus.ResetTypeProfile();
65 }
66 if (!entries->empty()) {
67 result->emplace_back(type_profile_script);
68 }
69 }
70 return result;
71 }
72
SelectMode(Isolate * isolate,debug::TypeProfileMode mode)73 void TypeProfile::SelectMode(Isolate* isolate, debug::TypeProfileMode mode) {
74 if (mode != isolate->type_profile_mode()) {
75 // Changing the type profile mode can change the bytecode that would be
76 // generated for a function, which can interfere with lazy source positions,
77 // so just force source position collection whenever there's such a change.
78 isolate->CollectSourcePositionsForAllBytecodeArrays();
79 }
80
81 HandleScope handle_scope(isolate);
82
83 if (mode == debug::TypeProfileMode::kNone) {
84 if (!isolate->factory()
85 ->feedback_vectors_for_profiling_tools()
86 ->IsUndefined(isolate)) {
87 // Release type profile data collected so far.
88
89 // Feedback vectors are already listed to prevent losing them to GC.
90 DCHECK(isolate->factory()
91 ->feedback_vectors_for_profiling_tools()
92 ->IsArrayList());
93 Handle<ArrayList> list = Handle<ArrayList>::cast(
94 isolate->factory()->feedback_vectors_for_profiling_tools());
95
96 for (int i = 0; i < list->Length(); i++) {
97 FeedbackVector vector = FeedbackVector::cast(list->Get(i));
98 SharedFunctionInfo info = vector.shared_function_info();
99 DCHECK(info.IsSubjectToDebugging());
100 if (info.feedback_metadata().HasTypeProfileSlot()) {
101 FeedbackSlot slot = vector.GetTypeProfileSlot();
102 FeedbackNexus nexus(vector, slot);
103 nexus.ResetTypeProfile();
104 }
105 }
106
107 // Delete the feedback vectors from the list if they're not used by code
108 // coverage.
109 if (isolate->is_best_effort_code_coverage()) {
110 isolate->SetFeedbackVectorsForProfilingTools(
111 ReadOnlyRoots(isolate).undefined_value());
112 }
113 }
114 } else {
115 DCHECK_EQ(debug::TypeProfileMode::kCollect, mode);
116 isolate->MaybeInitializeVectorListFromHeap();
117 }
118 isolate->set_type_profile_mode(mode);
119 }
120
121 } // namespace internal
122 } // namespace v8
123