xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/jit_cache.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/common/jit_cache.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstring>
22 #include <memory>
23 #include <optional>
24 #include <string>
25 #include <utility>
26 
27 #include "perfetto/base/logging.h"
28 #include "perfetto/ext/base/base64.h"
29 #include "perfetto/ext/base/string_utils.h"
30 #include "perfetto/ext/base/string_view.h"
31 #include "perfetto/trace_processor/trace_blob_view.h"
32 #include "src/trace_processor/importers/common/address_range.h"
33 #include "src/trace_processor/importers/common/mapping_tracker.h"
34 #include "src/trace_processor/importers/common/stack_profile_tracker.h"
35 #include "src/trace_processor/storage/stats.h"
36 #include "src/trace_processor/storage/trace_storage.h"
37 #include "src/trace_processor/tables/jit_tables_py.h"
38 #include "src/trace_processor/tables/metadata_tables_py.h"
39 #include "src/trace_processor/tables/profiler_tables_py.h"
40 #include "src/trace_processor/types/trace_processor_context.h"
41 
42 namespace perfetto {
43 namespace trace_processor {
44 
InternFrame(TraceProcessorContext * context,FrameKey frame_key)45 std::pair<FrameId, bool> JitCache::JittedFunction::InternFrame(
46     TraceProcessorContext* context,
47     FrameKey frame_key) {
48   if (FrameId* id = interned_frames_.Find(frame_key); id) {
49     return {*id, false};
50   }
51 
52   FrameId frame_id =
53       context->storage->mutable_stack_profile_frame_table()
54           ->Insert({context->storage->jit_code_table()
55                         .FindById(jit_code_id_)
56                         ->function_name(),
57                     frame_key.mapping_id,
58                     static_cast<int64_t>(frame_key.rel_pc), symbol_set_id_})
59           .id;
60   interned_frames_.Insert(frame_key, frame_id);
61   context->stack_profile_tracker->OnFrameCreated(frame_id);
62 
63   context->storage->mutable_jit_frame_table()->Insert({jit_code_id_, frame_id});
64 
65   return {frame_id, true};
66 }
67 
LoadCode(int64_t timestamp,UniqueTid utid,AddressRange code_range,StringId function_name,std::optional<SourceLocation> source_location,TraceBlobView native_code)68 tables::JitCodeTable::Id JitCache::LoadCode(
69     int64_t timestamp,
70     UniqueTid utid,
71     AddressRange code_range,
72     StringId function_name,
73     std::optional<SourceLocation> source_location,
74     TraceBlobView native_code) {
75   PERFETTO_CHECK(range_.Contains(code_range));
76   PERFETTO_CHECK(context_->storage->thread_table()
77                      .FindById(tables::ThreadTable::Id(utid))
78                      ->upid() == upid_);
79 
80   PERFETTO_CHECK(native_code.size() == 0 ||
81                  native_code.size() == code_range.size());
82 
83   std::optional<uint32_t> symbol_set_id;
84   if (source_location.has_value()) {
85     // TODO(carlscab): Remove duplication via new SymbolTracker class
86     symbol_set_id = context_->storage->symbol_table().row_count();
87     context_->storage->mutable_symbol_table()->Insert(
88         {*symbol_set_id, function_name, source_location->file_name,
89          source_location->line_number});
90   }
91 
92   auto* jit_code_table = context_->storage->mutable_jit_code_table();
93   const auto jit_code_id =
94       jit_code_table
95           ->Insert({timestamp, std::nullopt, utid,
96                     static_cast<int64_t>(code_range.start()),
97                     static_cast<int64_t>(code_range.size()), function_name,
98                     Base64Encode(native_code)})
99           .id;
100 
101   functions_.DeleteOverlapsAndEmplace(
102       [&](std::pair<const AddressRange, JittedFunction>& entry) {
103         jit_code_table->FindById(entry.second.jit_code_id())
104             ->set_estimated_delete_ts(timestamp);
105       },
106       code_range, jit_code_id, symbol_set_id);
107 
108   return jit_code_id;
109 }
110 
InternFrame(VirtualMemoryMapping * mapping,uint64_t rel_pc,base::StringView function_name)111 std::pair<FrameId, bool> JitCache::InternFrame(VirtualMemoryMapping* mapping,
112                                                uint64_t rel_pc,
113                                                base::StringView function_name) {
114   FrameKey key{mapping->mapping_id(), rel_pc};
115 
116   if (auto it = functions_.Find(mapping->ToAddress(rel_pc));
117       it != functions_.end()) {
118     return it->second.InternFrame(context_, key);
119   }
120 
121   if (FrameId* id = unknown_frames_.Find(key); id) {
122     return {*id, false};
123   }
124 
125   context_->storage->IncrementStats(stats::jit_unknown_frame);
126 
127   FrameId id =
128       context_->storage->mutable_stack_profile_frame_table()
129           ->Insert({context_->storage->InternString(
130                         function_name.empty()
131                             ? base::StringView(
132                                   "[+" + base::Uint64ToHexString(rel_pc) + "]")
133                             : function_name),
134                     key.mapping_id, static_cast<int64_t>(rel_pc)})
135           .id;
136   unknown_frames_.Insert(key, id);
137   return {id, true};
138 }
139 
CreateMapping()140 UserMemoryMapping& JitCache::CreateMapping() {
141   CreateMappingParams params;
142   params.memory_range = range_;
143   params.name = "[jit: " + name_ + "]";
144   return context_->mapping_tracker->CreateUserMemoryMapping(upid_,
145                                                             std::move(params));
146 }
147 
Base64Encode(const TraceBlobView & data)148 StringId JitCache::Base64Encode(const TraceBlobView& data) {
149   return context_->storage->InternString(
150       base::StringView(base::Base64Encode(data.data(), data.size())));
151 }
152 
153 }  // namespace trace_processor
154 }  // namespace perfetto
155