blob: cb65ede1fd521b0ae1203233fabc9f147c855bd3 [file]
/*
* 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_