xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/proto/v8_sequence_state.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/importers/proto/v8_sequence_state.h"
18 #include <optional>
19 
20 #include "protos/perfetto/trace/chrome/v8.pbzero.h"
21 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
22 #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
23 #include "src/trace_processor/importers/proto/string_encoding_utils.h"
24 #include "src/trace_processor/importers/proto/v8_tracker.h"
25 #include "src/trace_processor/storage/stats.h"
26 #include "src/trace_processor/storage/trace_storage.h"
27 #include "src/trace_processor/tables/v8_tables_py.h"
28 
29 namespace perfetto {
30 namespace trace_processor {
31 namespace {
32 
33 using ::perfetto::protos::pbzero::InternedData;
34 using ::perfetto::protos::pbzero::InternedV8JsFunction;
35 using ::perfetto::protos::pbzero::InternedV8String;
36 
ToConstBytes(const TraceBlobView & view)37 protozero::ConstBytes ToConstBytes(const TraceBlobView& view) {
38   return {view.data(), view.size()};
39 }
40 
41 }  // namespace
42 
V8SequenceState(TraceProcessorContext * context)43 V8SequenceState::V8SequenceState(TraceProcessorContext* context)
44     : context_(context), v8_tracker_(V8Tracker::GetOrCreate(context_)) {}
45 
46 V8SequenceState::~V8SequenceState() = default;
47 
GetOrInsertIsolate(uint64_t iid)48 std::optional<IsolateId> V8SequenceState::GetOrInsertIsolate(uint64_t iid) {
49   if (auto* id = isolates_.Find(iid); id != nullptr) {
50     return *id;
51   }
52 
53   auto* view = GetInternedMessageView(InternedData::kV8IsolateFieldNumber, iid);
54   if (!view) {
55     context_->storage->IncrementStats(stats::v8_intern_errors);
56     return std::nullopt;
57   }
58 
59   auto isolate_id = v8_tracker_->InternIsolate(ToConstBytes(view->message()));
60   isolates_.Insert(iid, isolate_id);
61   return isolate_id;
62 }
63 
64 std::optional<tables::V8JsFunctionTable::Id>
GetOrInsertJsFunction(uint64_t iid,IsolateId isolate_id)65 V8SequenceState::GetOrInsertJsFunction(uint64_t iid, IsolateId isolate_id) {
66   if (auto* id = js_functions_.Find(iid); id != nullptr) {
67     return *id;
68   }
69 
70   auto* view =
71       GetInternedMessageView(InternedData::kV8JsFunctionFieldNumber, iid);
72   if (!view) {
73     context_->storage->IncrementStats(stats::v8_intern_errors);
74     return std::nullopt;
75   }
76 
77   InternedV8JsFunction::Decoder function(ToConstBytes(view->message()));
78 
79   std::optional<tables::V8JsScriptTable::Id> script_id =
80       GetOrInsertJsScript(function.v8_js_script_iid(), isolate_id);
81   if (!script_id) {
82     return std::nullopt;
83   }
84 
85   auto name = GetOrInsertJsFunctionName(function.v8_js_function_name_iid());
86   if (!name) {
87     return std::nullopt;
88   }
89 
90   auto function_id = v8_tracker_->InternJsFunction(
91       ToConstBytes(view->message()), *name, *script_id);
92 
93   js_functions_.Insert(iid, function_id);
94   return function_id;
95 }
96 
97 std::optional<tables::V8WasmScriptTable::Id>
GetOrInsertWasmScript(uint64_t iid,IsolateId isolate_id)98 V8SequenceState::GetOrInsertWasmScript(uint64_t iid, IsolateId isolate_id) {
99   if (auto* id = wasm_scripts_.Find(iid); id != nullptr) {
100     return *id;
101   }
102   auto* view =
103       GetInternedMessageView(InternedData::kV8WasmScriptFieldNumber, iid);
104   if (!view) {
105     context_->storage->IncrementStats(stats::v8_intern_errors);
106     return std::nullopt;
107   }
108 
109   tables::V8WasmScriptTable::Id script_id =
110       v8_tracker_->InternWasmScript(ToConstBytes(view->message()), isolate_id);
111   wasm_scripts_.Insert(iid, script_id);
112   return script_id;
113 }
114 
GetOrInsertJsScript(uint64_t iid,IsolateId v8_isolate_id)115 std::optional<tables::V8JsScriptTable::Id> V8SequenceState::GetOrInsertJsScript(
116     uint64_t iid,
117     IsolateId v8_isolate_id) {
118   if (auto* id = js_scripts_.Find(iid); id != nullptr) {
119     return *id;
120   }
121   auto* view =
122       GetInternedMessageView(InternedData::kV8JsScriptFieldNumber, iid);
123   if (!view) {
124     context_->storage->IncrementStats(stats::v8_intern_errors);
125     return std::nullopt;
126   }
127 
128   tables::V8JsScriptTable::Id script_id =
129       v8_tracker_->InternJsScript(ToConstBytes(view->message()), v8_isolate_id);
130   js_scripts_.Insert(iid, script_id);
131   return script_id;
132 }
133 
GetOrInsertJsFunctionName(uint64_t iid)134 std::optional<StringId> V8SequenceState::GetOrInsertJsFunctionName(
135     uint64_t iid) {
136   if (auto* id = js_function_names_.Find(iid); id != nullptr) {
137     return *id;
138   }
139 
140   auto* view =
141       GetInternedMessageView(InternedData::kV8JsFunctionNameFieldNumber, iid);
142 
143   if (!view) {
144     context_->storage->IncrementStats(stats::v8_intern_errors);
145     return std::nullopt;
146   }
147 
148   InternedV8String::Decoder function_name(ToConstBytes(view->message()));
149   auto& storage = *context_->storage;
150   StringId id;
151   if (function_name.has_latin1()) {
152     id = storage.InternString(
153         base::StringView(ConvertLatin1ToUtf8(function_name.latin1())));
154   } else if (function_name.has_utf16_le()) {
155     id = storage.InternString(
156         base::StringView(ConvertUtf16LeToUtf8(function_name.utf16_le())));
157   } else if (function_name.has_utf16_be()) {
158     id = storage.InternString(
159         base::StringView(ConvertUtf16BeToUtf8(function_name.utf16_be())));
160   } else {
161     id = storage.InternString("");
162   }
163 
164   js_function_names_.Insert(iid, id);
165   return id;
166 }
167 
168 }  // namespace trace_processor
169 }  // namespace perfetto
170