• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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