1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if defined(TYPE_PROFILING)
6
7#include <config.h>
8
9#include <new>
10#include <stddef.h>
11#include <typeinfo>
12
13#include <gperftools/type_profiler_map.h>
14
15#include "addressmap-inl.h"
16#include "base/logging.h"
17#include "base/low_level_alloc.h"
18#include "base/spinlock.h"
19#include "tcmalloc_guard.h"
20
21namespace {
22
23const TCMallocGuard tcmalloc_initializer;
24
25//----------------------------------------------------------------------
26// A struct to store size and type_info of an object
27//----------------------------------------------------------------------
28
29struct ObjectInfo {
30 public:
31  ObjectInfo(): size(0), type(NULL) {}
32  ObjectInfo(size_t size_arg, const std::type_info* type_arg)
33      : size(size_arg),
34        type(type_arg) {
35  }
36
37  size_t size;
38  const std::type_info* type;
39};
40
41//----------------------------------------------------------------------
42// Locking
43//----------------------------------------------------------------------
44
45SpinLock g_type_profiler_lock(SpinLock::LINKER_INITIALIZED);
46
47//----------------------------------------------------------------------
48// Simple allocator for type_info map's internal memory
49//----------------------------------------------------------------------
50
51LowLevelAlloc::Arena* g_type_profiler_map_memory = NULL;
52
53void* TypeProfilerMalloc(size_t bytes) {
54  return LowLevelAlloc::AllocWithArena(bytes, g_type_profiler_map_memory);
55}
56
57void TypeProfilerFree(void* p) {
58  LowLevelAlloc::Free(p);
59}
60
61//----------------------------------------------------------------------
62// Profiling control/state data
63//----------------------------------------------------------------------
64
65AddressMap<ObjectInfo>* g_type_profiler_map = NULL;
66
67//----------------------------------------------------------------------
68// Manage type_info map
69//----------------------------------------------------------------------
70
71void InitializeTypeProfilerMemory() {
72  if (g_type_profiler_map_memory != NULL) {
73    RAW_DCHECK(g_type_profiler_map != NULL, "TypeProfilerMap is NULL");
74    return;
75  }
76
77  g_type_profiler_map_memory =
78      LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena());
79
80  g_type_profiler_map =
81      new(TypeProfilerMalloc(sizeof(*g_type_profiler_map)))
82          AddressMap<ObjectInfo>(TypeProfilerMalloc, TypeProfilerFree);
83}
84
85}  // namespace
86
87void InsertType(void* address, size_t size, const std::type_info& type) {
88  SpinLockHolder lock(&g_type_profiler_lock);
89  InitializeTypeProfilerMemory();
90
91  g_type_profiler_map->Insert(address, ObjectInfo(size, &type));
92}
93
94void EraseType(void* address) {
95  SpinLockHolder lock(&g_type_profiler_lock);
96  InitializeTypeProfilerMemory();
97
98  ObjectInfo obj;
99  g_type_profiler_map->FindAndRemove(address, &obj);
100}
101
102const std::type_info* LookupType(const void* address) {
103  SpinLockHolder lock(&g_type_profiler_lock);
104  InitializeTypeProfilerMemory();
105
106  const ObjectInfo* found = g_type_profiler_map->Find(address);
107  if (found == NULL)
108    return NULL;
109  return found->type;
110}
111
112#endif  // defined(TYPE_PROFILING)
113