Skip to content

Commit ef645a4

Browse files
committed
tp: integrate ProtoVM
Change-Id: Ia5d69ed4f3f7314630c7a0217a0f4d3a43f9d1a8
1 parent d320fa3 commit ef645a4

File tree

10 files changed

+480
-1
lines changed

10 files changed

+480
-1
lines changed

Android.bp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15655,6 +15655,7 @@ filegroup {
1565515655
"src/trace_processor/importers/proto/proto_trace_parser_impl.cc",
1565615656
"src/trace_processor/importers/proto/proto_trace_reader.cc",
1565715657
"src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
15658+
"src/trace_processor/importers/proto/protovm_module.cc",
1565815659
"src/trace_processor/importers/proto/stack_profile_sequence_state.cc",
1565915660
"src/trace_processor/importers/proto/track_event_module.cc",
1566015661
"src/trace_processor/importers/proto/track_event_parser.cc",
@@ -16881,6 +16882,7 @@ cc_library_static {
1688116882
":perfetto_src_base_version",
1688216883
":perfetto_src_kernel_utils_kernel_wakelock_errors",
1688316884
":perfetto_src_kernel_utils_syscall_table",
16885+
":perfetto_src_protovm_protovm",
1688416886
":perfetto_src_protozero_proto_ring_buffer",
1688516887
":perfetto_src_protozero_protozero",
1688616888
":perfetto_src_protozero_text_to_proto_text_to_proto",
@@ -20224,6 +20226,7 @@ cc_library_static {
2022420226
":perfetto_src_base_clock_snapshots",
2022520227
":perfetto_src_kernel_utils_kernel_wakelock_errors",
2022620228
":perfetto_src_kernel_utils_syscall_table",
20229+
":perfetto_src_protovm_protovm",
2022720230
":perfetto_src_protozero_protozero",
2022820231
":perfetto_src_protozero_text_to_proto_text_to_proto",
2022920232
":perfetto_src_trace_processor_containers_containers",
@@ -20755,6 +20758,7 @@ cc_binary_host {
2075520758
":perfetto_src_base_version",
2075620759
":perfetto_src_kernel_utils_kernel_wakelock_errors",
2075720760
":perfetto_src_kernel_utils_syscall_table",
20761+
":perfetto_src_protovm_protovm",
2075820762
":perfetto_src_protozero_proto_ring_buffer",
2075920763
":perfetto_src_protozero_protozero",
2076020764
":perfetto_src_protozero_text_to_proto_text_to_proto",

BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ perfetto_cc_library(
351351
srcs = [
352352
":src_kernel_utils_kernel_wakelock_errors",
353353
":src_kernel_utils_syscall_table",
354+
":src_protovm_protovm",
354355
":src_protozero_proto_ring_buffer",
355356
":src_protozero_text_to_proto_text_to_proto",
356357
":src_trace_processor_core_common_common",
@@ -564,6 +565,7 @@ perfetto_cc_library(
564565
srcs = [
565566
":src_kernel_utils_kernel_wakelock_errors",
566567
":src_kernel_utils_syscall_table",
568+
":src_protovm_protovm",
567569
":src_protozero_proto_ring_buffer",
568570
":src_protozero_text_to_proto_text_to_proto",
569571
":src_trace_processor_core_common_common",
@@ -2834,6 +2836,8 @@ perfetto_filegroup(
28342836
"src/trace_processor/importers/proto/proto_trace_reader.h",
28352837
"src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
28362838
"src/trace_processor/importers/proto/proto_trace_tokenizer.h",
2839+
"src/trace_processor/importers/proto/protovm_module.cc",
2840+
"src/trace_processor/importers/proto/protovm_module.h",
28372841
"src/trace_processor/importers/proto/stack_profile_sequence_state.cc",
28382842
"src/trace_processor/importers/proto/stack_profile_sequence_state.h",
28392843
"src/trace_processor/importers/proto/track_event_event_importer.h",
@@ -8454,6 +8458,7 @@ perfetto_cc_library(
84548458
srcs = [
84558459
":src_kernel_utils_kernel_wakelock_errors",
84568460
":src_kernel_utils_syscall_table",
8461+
":src_protovm_protovm",
84578462
":src_protozero_text_to_proto_text_to_proto",
84588463
":src_trace_processor_core_common_common",
84598464
":src_trace_processor_core_dataframe_dataframe",
@@ -8695,6 +8700,7 @@ perfetto_cc_binary(
86958700
":include_perfetto_trace_processor_util",
86968701
":src_kernel_utils_kernel_wakelock_errors",
86978702
":src_kernel_utils_syscall_table",
8703+
":src_protovm_protovm",
86988704
":src_protozero_proto_ring_buffer",
86998705
":src_protozero_text_to_proto_text_to_proto",
87008706
":src_trace_processor_core_common_common",

src/trace_processor/importers/proto/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ source_set("minimal") {
5454
"proto_trace_reader.h",
5555
"proto_trace_tokenizer.cc",
5656
"proto_trace_tokenizer.h",
57+
"protovm_module.cc",
58+
"protovm_module.h",
5759
"stack_profile_sequence_state.cc",
5860
"stack_profile_sequence_state.h",
5961
"track_event_event_importer.h",
@@ -92,6 +94,7 @@ source_set("minimal") {
9294
"../../../../protos/perfetto/trace/translation:zero",
9395
"../../../../protos/third_party/chromium:zero",
9496
"../../../base",
97+
"../../../protovm",
9598
"../../../protozero",
9699
"../../containers",
97100
"../../sorter",

src/trace_processor/importers/proto/default_modules.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "src/trace_processor/importers/proto/memory_tracker_snapshot_module.h"
2323
#include "src/trace_processor/importers/proto/metadata_minimal_module.h"
2424
#include "src/trace_processor/importers/proto/proto_importer_module.h"
25+
#include "src/trace_processor/importers/proto/protovm_module.h"
2526
#include "src/trace_processor/importers/proto/track_event_module.h"
2627

2728
namespace perfetto::trace_processor {
@@ -49,6 +50,8 @@ void RegisterDefaultModules(ProtoImporterModuleContext* module_context,
4950
new ChromeSystemProbesModule(module_context, context));
5051
module_context->modules.emplace_back(
5152
new MetadataMinimalModule(module_context, context));
53+
module_context->modules.emplace_back(
54+
new ProtoVmModule(module_context, context));
5255
}
5356

5457
} // namespace perfetto::trace_processor
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright (C) 2026 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/protovm_module.h"
18+
19+
#include <memory>
20+
#include <string>
21+
22+
#include "perfetto/protozero/field.h"
23+
#include "perfetto/protozero/scattered_heap_buffer.h"
24+
#include "perfetto/trace_processor/trace_blob_view.h"
25+
#include "protos/perfetto/trace/perfetto/trace_provenance.pbzero.h"
26+
#include "protos/perfetto/trace/trace_packet.pbzero.h"
27+
#include "src/trace_processor/importers/common/import_logs_tracker.h"
28+
#include "src/trace_processor/storage/stats.h"
29+
#include "src/trace_processor/types/trace_processor_context.h"
30+
31+
namespace perfetto {
32+
namespace trace_processor {
33+
34+
ProtoVmModule::ProtoVmModule(ProtoImporterModuleContext* context,
35+
TraceProcessorContext* trace_context)
36+
: ProtoImporterModule(context), trace_context_(trace_context) {
37+
RegisterForField(protos::pbzero::TracePacket::kTraceProvenanceFieldNumber);
38+
RegisterForField(protos::pbzero::TracePacket::kProtovmsFieldNumber);
39+
RegisterForField(
40+
protos::pbzero::TracePacket::kSurfaceflingerTransactionsFieldNumber);
41+
}
42+
43+
ProtoVmModule::~ProtoVmModule() = default;
44+
45+
ModuleResult ProtoVmModule::TokenizePacket(
46+
const protos::pbzero::TracePacket::Decoder& decoder,
47+
TraceBlobView* packet,
48+
int64_t packet_timestamp,
49+
RefPtr<PacketSequenceStateGeneration> state,
50+
uint32_t field_id) {
51+
if (field_id == protos::pbzero::TracePacket::kTraceProvenanceFieldNumber) {
52+
ProcessTraceProvenancePacket(decoder.trace_provenance());
53+
return ModuleResult::Ignored();
54+
}
55+
if (field_id == protos::pbzero::TracePacket::kProtovmsFieldNumber) {
56+
ProcessProtoVmsPacket(decoder.protovms());
57+
return ModuleResult::Ignored();
58+
}
59+
return TryProcessPatch(decoder, packet, packet_timestamp, state);
60+
}
61+
62+
void ProtoVmModule::ProcessTraceProvenancePacket(protozero::ConstBytes blob) {
63+
protos::pbzero::TraceProvenance::Decoder trace_provenance(blob);
64+
for (auto it_buf = trace_provenance.buffers(); it_buf; ++it_buf) {
65+
protos::pbzero::TraceProvenance::Buffer::Decoder buffer(*it_buf);
66+
for (auto it_seq = buffer.sequences(); it_seq; ++it_seq) {
67+
protos::pbzero::TraceProvenance::Sequence::Decoder sequence(*it_seq);
68+
producer_id_to_sequence_ids_[sequence.producer_id()].push_back(
69+
sequence.id());
70+
}
71+
}
72+
}
73+
74+
void ProtoVmModule::ProcessProtoVmsPacket(protozero::ConstBytes blob) {
75+
protos::pbzero::TracePacket::ProtoVms::Decoder decoder(blob);
76+
for (auto it = decoder.instance(); it; ++it) {
77+
protos::pbzero::TracePacket::ProtoVms::Instance::Decoder instance(*it);
78+
protozero::ConstBytes state = instance.has_state()
79+
? instance.state()
80+
: protozero::ConstBytes{nullptr, 0};
81+
vms_.push_back(std::make_unique<protovm::Vm>(
82+
instance.program(), 1024 * instance.memory_limit_kb(), state));
83+
protovm::Vm* vm = vms_.back().get();
84+
for (auto producer_id = instance.producer_id(); producer_id;
85+
++producer_id) {
86+
auto* sequence_ids = producer_id_to_sequence_ids_.Find(*producer_id);
87+
PERFETTO_CHECK(sequence_ids); // TODO: increment stats
88+
for (auto sequence_id : *sequence_ids) {
89+
sequence_id_to_vms_[sequence_id].push_back(vm);
90+
}
91+
}
92+
}
93+
}
94+
95+
ModuleResult ProtoVmModule::TryProcessPatch(
96+
const protos::pbzero::TracePacket::Decoder& decoder,
97+
TraceBlobView* packet,
98+
int64_t,
99+
RefPtr<PacketSequenceStateGeneration> state) {
100+
std::vector<protovm::Vm*>* vms =
101+
sequence_id_to_vms_.Find(decoder.trusted_packet_sequence_id());
102+
if (!vms) {
103+
return ModuleResult::Ignored();
104+
}
105+
for (auto* vm : *vms) {
106+
auto status = vm->ApplyPatch({packet->data(), packet->size()});
107+
if (status.IsOk()) {
108+
protozero::HeapBuffered<protozero::Message> incremental_state;
109+
TraceBlob serialized = SerializeIncrementalState(*vm, decoder);
110+
// TODO(lalitm): I suspect there will be discussions about this. FYI here
111+
// we read the timestamp from the serialized incremental state, so that a
112+
// ProtoVM's program also has the power of setting timestamps. Primiano
113+
// wanted this feature so you might want to chat directly with him. We can
114+
// always make the implementation below more efficient avoiding to
115+
// construct a full TracePacket::Decoder.
116+
protos::pbzero::TracePacket::Decoder serialized_decoder(
117+
protozero::ConstBytes{serialized.data(), serialized.size()});
118+
auto serialized_timestamp = serialized_decoder.timestamp();
119+
module_context_->trace_packet_stream->Push(
120+
static_cast<int64_t>(serialized_timestamp),
121+
TracePacketData{TraceBlobView{std::move(serialized)},
122+
std::move(state)});
123+
return ModuleResult::Handled();
124+
}
125+
if (status.IsAbort()) {
126+
trace_context_->import_logs_tracker->RecordTokenizationError(
127+
stats::protovm_abort, packet->offset());
128+
return ModuleResult::Handled();
129+
}
130+
}
131+
return ModuleResult::Ignored();
132+
}
133+
134+
TraceBlob ProtoVmModule::SerializeIncrementalState(
135+
const protovm::Vm& vm,
136+
const protos::pbzero::TracePacket::Decoder& patch) const {
137+
protozero::HeapBuffered<protos::pbzero::TracePacket> proto;
138+
vm.SerializeIncrementalState(proto.get());
139+
proto->set_trusted_uid(patch.trusted_uid());
140+
proto->set_trusted_pid(patch.trusted_pid());
141+
proto->set_trusted_packet_sequence_id(patch.trusted_packet_sequence_id());
142+
auto [data, size] = proto.SerializeAsUniquePtr();
143+
return TraceBlob::TakeOwnership(std::move(data), size);
144+
}
145+
146+
} // namespace trace_processor
147+
} // namespace perfetto
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (C) 2026 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+
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTOVM_MODULE_H_
18+
#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTOVM_MODULE_H_
19+
20+
#include <map>
21+
#include <memory>
22+
#include <vector>
23+
24+
#include "perfetto/trace_processor/trace_blob_view.h"
25+
#include "protos/perfetto/trace/trace_packet.pbzero.h"
26+
#include "src/protovm/vm.h"
27+
#include "src/trace_processor/importers/proto/proto_importer_module.h"
28+
#include "src/trace_processor/types/trace_processor_context.h"
29+
30+
namespace perfetto {
31+
namespace trace_processor {
32+
33+
class ProtoVmModule : public ProtoImporterModule {
34+
public:
35+
explicit ProtoVmModule(ProtoImporterModuleContext* context,
36+
TraceProcessorContext* trace_context);
37+
~ProtoVmModule() override;
38+
39+
ModuleResult TokenizePacket(
40+
const protos::pbzero::TracePacket::Decoder& decoder,
41+
TraceBlobView* packet,
42+
int64_t packet_timestamp,
43+
RefPtr<PacketSequenceStateGeneration> state,
44+
uint32_t field_id) override;
45+
46+
private:
47+
void ProcessTraceProvenancePacket(protozero::ConstBytes blob);
48+
void ProcessProtoVmsPacket(protozero::ConstBytes blob);
49+
ModuleResult TryProcessPatch(
50+
const protos::pbzero::TracePacket::Decoder& decoder,
51+
TraceBlobView* packet,
52+
int64_t packet_timestamp,
53+
RefPtr<PacketSequenceStateGeneration> state);
54+
TraceBlob SerializeIncrementalState(
55+
const protovm::Vm& vm,
56+
const protos::pbzero::TracePacket::Decoder& patch) const;
57+
58+
base::FlatHashMap<int32_t, std::vector<uint32_t>>
59+
producer_id_to_sequence_ids_;
60+
base::FlatHashMap<uint32_t, std::vector<protovm::Vm*>> sequence_id_to_vms_;
61+
std::vector<std::unique_ptr<protovm::Vm>> vms_;
62+
63+
TraceProcessorContext* trace_context_;
64+
};
65+
66+
} // namespace trace_processor
67+
} // namespace perfetto
68+
69+
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTOVM_MODULE_H_

src/trace_processor/storage/stats.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,16 @@ namespace perfetto::trace_processor::stats {
826826
F(primes_missing_parent_id, kSingle, kInfo, kAnalysis, \
827827
"The parent_id field was missing from an edge that requires it."), \
828828
F(primes_malformed_timestamp, kSingle, kDataLoss, kAnalysis, \
829-
"The timestamp for an edge or trace was not able to be parsed") // clang-format on
829+
"The timestamp for an edge or trace was not able to be parsed"), \
830+
F(protovm_prod_id_to_seq_ids_mapping_not_found, kSingle, kError, kAnalysis, \
831+
"Failed to map a ProtoVM's producer ID to the corresponding sequence " \
832+
"IDs. The error occurred while processing a ProtoVms packet. The mapping " \
833+
"should be provided by a preceding TraceProvenance packet."), \
834+
F(protovm_abort, kSingle, kError, kAnalysis, \
835+
"A proto VM instance aborted the execution while applying the patch. " \
836+
"This might be due to inconsistencies between VM program logic and " \
837+
"actual patch format.")
838+
// clang-format on
830839

831840
enum Type {
832841
kSingle, // Single-value property, one value per key.

test/trace_processor/diff_tests/include_index.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
from diff_tests.parser.android.tests_inputmethod_manager_service import InputMethodManagerService
5858
from diff_tests.parser.android.tests_inputmethod_service import InputMethodService
5959
from diff_tests.parser.android.tests_protolog import ProtoLog
60+
from diff_tests.parser.android.tests_protovm_incremental_tracing import ProtoVmIncrementalTracing
6061
from diff_tests.parser.android.tests_shell_transitions import ShellTransitions
6162
from diff_tests.parser.android.tests_surfaceflinger_layers import SurfaceFlingerLayers
6263
from diff_tests.parser.android.tests_surfaceflinger_transactions import SurfaceFlingerTransactions
@@ -248,6 +249,7 @@ def fetch_all_diff_tests(
248249
SurfaceFlingerTransactions,
249250
ShellTransitions,
250251
ProtoLog,
252+
ProtoVmIncrementalTracing,
251253
ViewCapture,
252254
WindowManager,
253255
TrackEvent,

0 commit comments

Comments
 (0)