blob: 8a5c13db32ae67c0ea87e9263266d0a67a66912d [file] [log] [blame]
//===-- ProfileObjectiveC.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Created by Greg Clayton on 10/4/07.
//
//===----------------------------------------------------------------------===//
#ifndef __ProfileObjectiveC_h__
#define __ProfileObjectiveC_h__
#include "DNB.h"
#include "DNBRuntimeAction.h"
#include <map>
#include <sys/time.h>
class ProfileObjectiveC : public DNBRuntimeAction
{
public:
ProfileObjectiveC();
virtual ~ProfileObjectiveC();
//------------------------------------------------------------------
// DNBRuntimeAction required functions
//------------------------------------------------------------------
virtual void Initialize(nub_process_t pid);
virtual void ProcessStateChanged(nub_state_t state);
virtual void SharedLibraryStateChanged(DNBExecutableImageInfo *image_infos, nub_size_t num_image_infos);
protected:
typedef uint32_t objc_selector_t;
typedef uint32_t objc_class_ptr_t;
void Clear();
static nub_bool_t MessageSendBreakpointCallback(nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *userData);
static nub_bool_t MessageSendSuperBreakpointCallback(nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *userData);
void DumpStats(nub_process_t pid, FILE *f);
void SetStartTime();
void SelectorHit(objc_class_ptr_t isa, objc_selector_t sel);
typedef std::map<objc_selector_t, uint32_t> SelectorHitCount;
typedef std::map<objc_class_ptr_t, SelectorHitCount> ClassStatsMap;
typedef struct Probe
{
nub_addr_t addr;
nub_break_t breakID;
Probe() : addr(INVALID_NUB_ADDRESS), breakID(INVALID_NUB_BREAK_ID) {}
void Clear()
{
addr = INVALID_NUB_ADDRESS;
breakID = INVALID_NUB_BREAK_ID;
}
bool IsValid() const
{
return (addr != INVALID_NUB_ADDRESS) && (NUB_BREAK_ID_IS_VALID(breakID));
}
};
uint32_t IncrementHitCount() { return ++m_hit_count; }
bool ShouldDumpStats() const { return m_dump_count && (m_hit_count % m_dump_count) == 0; }
nub_process_t m_pid;
Probe m_objc_msgSend;
Probe m_objc_msgSendSuper;
uint32_t m_hit_count; // Number of times we have gotten one of our breakpoints hit
uint32_t m_dump_count; // Dump stats every time the hit count reaches a multiple of this value
#if defined (__powerpc__) || defined (__ppc__)
enum
{
k_opcode_size = 4
};
uint8_t m_objc_msgSend_opcode[k_opcode_size]; // Saved copy of first opcode in objc_msgSend
Probe m_objc_msgSend_rtp; // COMM page probe info for objc_msgSend
#endif
struct timeval m_begin_time;
ClassStatsMap m_objcStats;
};
#endif // #ifndef __ProfileObjectiveC_h__