| /* |
| * Copyright (C) 2025 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef SRC_TRACE_PROCESSOR_DATAFRAME_IMPL_BYTECODE_INTERPRETER_H_ |
| #define SRC_TRACE_PROCESSOR_DATAFRAME_IMPL_BYTECODE_INTERPRETER_H_ |
| |
| #include <cstdint> |
| #include <cstring> |
| #include <type_traits> |
| |
| #include "perfetto/public/compiler.h" |
| #include "src/trace_processor/containers/string_pool.h" |
| #include "src/trace_processor/dataframe/impl/bytecode_core.h" |
| #include "src/trace_processor/dataframe/impl/bytecode_interpreter_state.h" |
| #include "src/trace_processor/dataframe/impl/bytecode_registers.h" |
| #include "src/trace_processor/dataframe/impl/types.h" |
| #include "src/trace_processor/dataframe/types.h" |
| #include "src/trace_processor/dataframe/value_fetcher.h" |
| |
| namespace perfetto::trace_processor::dataframe::impl::bytecode { |
| |
| // The Interpreter class implements a virtual machine that executes bytecode |
| // instructions for dataframe query operations. It maintains an internal |
| // register state, processes sequences of bytecode operations, and applies |
| // filter and transformation operations to data columns. The interpreter is |
| // designed for high-performance data filtering and manipulation, with |
| // specialized handling for different data types and comparison operations. |
| // |
| // This class is templated on a subclass of ValueFetcher, which is used to |
| // fetch filter values for each filter spec. |
| template <typename FilterValueFetcherImpl> |
| class Interpreter { |
| public: |
| static_assert(std::is_base_of_v<ValueFetcher, FilterValueFetcherImpl>, |
| "FilterValueFetcherImpl must be a subclass of ValueFetcher"); |
| |
| Interpreter() = default; |
| |
| void Initialize(const BytecodeVector& bytecode, |
| uint32_t num_registers, |
| const Column* const* columns, |
| const dataframe::Index* indexes, |
| const StringPool* string_pool) { |
| state_.Initialize(bytecode, num_registers, columns, indexes, string_pool); |
| } |
| |
| // Not movable because it's a very large object and the move cost would be |
| // high. Prefer constructing in place. |
| Interpreter(Interpreter&&) = delete; |
| Interpreter& operator=(Interpreter&&) = delete; |
| |
| // Executes the bytecode sequence, processing each bytecode instruction in |
| // turn, and dispatching to the appropriate function in this class. |
| PERFETTO_ALWAYS_INLINE void Execute( |
| FilterValueFetcherImpl& filter_value_fetcher); |
| |
| // Returns the value of the specified register if it contains the expected |
| // type. Returns nullptr if the register holds a different type or is empty. |
| template <typename T> |
| PERFETTO_ALWAYS_INLINE const T* GetRegisterValue(reg::ReadHandle<T> reg) { |
| return state_.MaybeReadFromRegister(reg); |
| } |
| |
| // Sets the value of the specified register for testing purposes. |
| // |
| // Makes it easier to test certain bytecode instructions which depend on |
| // the preexisting value of a register. |
| template <typename T> |
| void SetRegisterValueForTesting(reg::WriteHandle<T> reg, T value) { |
| state_.WriteToRegister(reg, std::move(value)); |
| } |
| |
| private: |
| InterpreterState state_; |
| }; |
| |
| } // namespace perfetto::trace_processor::dataframe::impl::bytecode |
| |
| #endif // SRC_TRACE_PROCESSOR_DATAFRAME_IMPL_BYTECODE_INTERPRETER_H_ |