blob: 4e617f6e8728623f998c9563a29ae1e39270ea01 [file] [log] [blame]
/*
* Copyright (C) 2021 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_UTIL_ANNOTATED_CALLSITES_H_
#define SRC_TRACE_PROCESSOR_UTIL_ANNOTATED_CALLSITES_H_
#include <unordered_map>
#include "perfetto/ext/base/optional.h"
#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/storage/trace_storage.h"
namespace perfetto {
namespace trace_processor {
class TraceProcessorContext;
enum class CallsiteAnnotation {
kNone,
kCommonFrame,
kArtInterpreted,
kArtJit,
kArtAot,
};
// Helper class to augment callsite with (currently Android-specific)
// annotations. A given callsite will always have the same annotation. This
// class will internally cache already computed annotations. An annotation
// depends only of the current callsite and the annotation sof its parent
// callsites (going to the root).
class AnnotatedCallsites {
public:
explicit AnnotatedCallsites(const TraceProcessorContext* context);
CallsiteAnnotation GetAnnotation(
const tables::StackProfileCallsiteTable::ConstRowReference& callsite) {
return Get(callsite).second;
}
private:
enum class MapType {
kArtInterp,
kArtJit,
kArtAot,
kNativeLibart,
kNativeOther,
kOther
};
// Annotation FSM states:
// * kInitial: default, native-only callstacks never leave this state.
// * kEraseLibart: we've seen a managed frame, and will now "erase" (i.e. tag
// as a common-frame) frames belonging to the ART runtime.
// * kKeepNext: we've seen a special JNI trampoline for managed->native
// transition, keep the immediate child (even if it is in ART),
// and then go back to kEraseLibart.
// Regardless of the state, managed frames get annotated with their execution
// mode, based on the mapping.
enum class State { kInitial, kEraseLibart, kKeepNext };
State GetState(base::Optional<CallsiteId> id);
std::pair<State, CallsiteAnnotation> Get(
const tables::StackProfileCallsiteTable::ConstRowReference& callsite);
MapType GetMapType(MappingId id);
MapType ClassifyMap(NullTermStringView map);
const TraceProcessorContext& context_;
const base::Optional<StringPool::Id> art_jni_trampoline_;
std::unordered_map<MappingId, MapType> map_types_;
std::unordered_map<CallsiteId, State> states_;
};
} // namespace trace_processor
} // namespace perfetto
#endif // SRC_TRACE_PROCESSOR_UTIL_ANNOTATED_CALLSITES_H_