| // 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. |
| |
| #include "src/debug/debug-type-profile.h" |
| |
| #include "src/execution/isolate.h" |
| #include "src/objects/feedback-vector.h" |
| #include "src/objects/objects-inl.h" |
| #include "src/objects/objects.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| std::unique_ptr<TypeProfile> TypeProfile::Collect(Isolate* isolate) { |
| std::unique_ptr<TypeProfile> result(new TypeProfile()); |
| |
| // Feedback vectors are already listed to prevent losing them to GC. |
| DCHECK(isolate->factory() |
| ->feedback_vectors_for_profiling_tools() |
| ->IsArrayList()); |
| Handle<ArrayList> list = Handle<ArrayList>::cast( |
| isolate->factory()->feedback_vectors_for_profiling_tools()); |
| |
| Script::Iterator scripts(isolate); |
| |
| for (Script script = scripts.Next(); !script.is_null(); |
| script = scripts.Next()) { |
| if (!script.IsUserJavaScript()) { |
| continue; |
| } |
| |
| Handle<Script> script_handle(script, isolate); |
| |
| TypeProfileScript type_profile_script(script_handle); |
| std::vector<TypeProfileEntry>* entries = &type_profile_script.entries; |
| |
| // TODO(franzih): Sort the vectors by script first instead of iterating |
| // the list multiple times. |
| for (int i = 0; i < list->Length(); i++) { |
| FeedbackVector vector = FeedbackVector::cast(list->Get(i)); |
| SharedFunctionInfo info = vector.shared_function_info(); |
| DCHECK(info.IsSubjectToDebugging()); |
| |
| // Match vectors with script. |
| if (script != info.script()) { |
| continue; |
| } |
| if (!info.HasFeedbackMetadata() || info.feedback_metadata().is_empty() || |
| !info.feedback_metadata().HasTypeProfileSlot()) { |
| continue; |
| } |
| FeedbackSlot slot = vector.GetTypeProfileSlot(); |
| FeedbackNexus nexus(vector, slot); |
| std::vector<int> source_positions = nexus.GetSourcePositions(); |
| for (int position : source_positions) { |
| DCHECK_GE(position, 0); |
| entries->emplace_back(position, nexus.GetTypesForSourcePositions( |
| static_cast<uint32_t>(position))); |
| } |
| |
| // Releases type profile data collected so far. |
| nexus.ResetTypeProfile(); |
| } |
| if (!entries->empty()) { |
| result->emplace_back(type_profile_script); |
| } |
| } |
| return result; |
| } |
| |
| void TypeProfile::SelectMode(Isolate* isolate, debug::TypeProfileMode mode) { |
| if (mode != isolate->type_profile_mode()) { |
| // Changing the type profile mode can change the bytecode that would be |
| // generated for a function, which can interfere with lazy source positions, |
| // so just force source position collection whenever there's such a change. |
| isolate->CollectSourcePositionsForAllBytecodeArrays(); |
| } |
| |
| HandleScope handle_scope(isolate); |
| |
| if (mode == debug::TypeProfileMode::kNone) { |
| if (!isolate->factory() |
| ->feedback_vectors_for_profiling_tools() |
| ->IsUndefined(isolate)) { |
| // Release type profile data collected so far. |
| |
| // Feedback vectors are already listed to prevent losing them to GC. |
| DCHECK(isolate->factory() |
| ->feedback_vectors_for_profiling_tools() |
| ->IsArrayList()); |
| Handle<ArrayList> list = Handle<ArrayList>::cast( |
| isolate->factory()->feedback_vectors_for_profiling_tools()); |
| |
| for (int i = 0; i < list->Length(); i++) { |
| FeedbackVector vector = FeedbackVector::cast(list->Get(i)); |
| SharedFunctionInfo info = vector.shared_function_info(); |
| DCHECK(info.IsSubjectToDebugging()); |
| if (info.feedback_metadata().HasTypeProfileSlot()) { |
| FeedbackSlot slot = vector.GetTypeProfileSlot(); |
| FeedbackNexus nexus(vector, slot); |
| nexus.ResetTypeProfile(); |
| } |
| } |
| |
| // Delete the feedback vectors from the list if they're not used by code |
| // coverage. |
| if (isolate->is_best_effort_code_coverage()) { |
| isolate->SetFeedbackVectorsForProfilingTools( |
| ReadOnlyRoots(isolate).undefined_value()); |
| } |
| } |
| } else { |
| DCHECK_EQ(debug::TypeProfileMode::kCollect, mode); |
| isolate->MaybeInitializeVectorListFromHeap(); |
| } |
| isolate->set_type_profile_mode(mode); |
| } |
| |
| } // namespace internal |
| } // namespace v8 |