summaryrefslogtreecommitdiffstats
path: root/src/compiler/dex/arena_allocator.cc
blob: 7f1bfb386dbcab633eec7e396b96993dccc7fcc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * Copyright (C) 2013 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.
 */

#include "compiler_internals.h"
#include "dex_file-inl.h"
#include "arena_allocator.h"
#include "base/logging.h"

namespace art {

static const char* alloc_names[ArenaAllocator::kNumAllocKinds] = {
  "Misc       ",
  "BasicBlock ",
  "LIR        ",
  "MIR        ",
  "DataFlow   ",
  "GrowList   ",
  "GrowBitMap ",
  "Dalvik2SSA ",
  "DebugInfo  ",
  "Successor  ",
  "RegAlloc   ",
  "Data       ",
  "Preds      ",
};

ArenaAllocator::ArenaAllocator(size_t default_size)
  : default_size_(default_size),
    block_size_(default_size - sizeof(ArenaMemBlock)),
    arena_head_(NULL),
    current_arena_(NULL),
    num_arena_blocks_(0),
    malloc_bytes_(0) {
  memset(&alloc_stats_[0], 0, sizeof(alloc_stats_));
  // Start with an empty arena.
  arena_head_ = current_arena_ = EmptyArena();
  num_arena_blocks_++;
}

ArenaAllocator::~ArenaAllocator() {
  // Reclaim all the arena blocks allocated so far.
  ArenaMemBlock* head = arena_head_;
  while (head != NULL) {
    ArenaMemBlock* p = head;
    head = head->next;
    free(p);
  }
  arena_head_ = current_arena_ = NULL;
  num_arena_blocks_ = 0;
}

// Return an arena with no storage for use as a sentinal.
ArenaAllocator::ArenaMemBlock* ArenaAllocator::EmptyArena() {
  ArenaMemBlock* res = static_cast<ArenaMemBlock*>(malloc(sizeof(ArenaMemBlock)));
  malloc_bytes_ += sizeof(ArenaMemBlock);
  res->block_size = 0;
  res->bytes_allocated = 0;
  res->next = NULL;
  return res;
}

// Arena-based malloc for compilation tasks.
void* ArenaAllocator::NewMem(size_t size, bool zero, ArenaAllocKind kind) {
  DCHECK(current_arena_ != NULL);
  DCHECK(arena_head_ != NULL);
  size = (size + 3) & ~3;
  alloc_stats_[kind] += size;
  if (size + current_arena_->bytes_allocated > current_arena_->block_size) {
    size_t block_size = (size <= block_size_) ?  block_size_ : size;
    /* Time to allocate a new block */
    size_t allocation_size = sizeof(ArenaMemBlock) + block_size;
    ArenaMemBlock *new_arena =
        static_cast<ArenaMemBlock*>(malloc(allocation_size));
    if (new_arena == NULL) {
      LOG(FATAL) << "Arena allocation failure";
    }
    malloc_bytes_ += allocation_size;
    new_arena->block_size = block_size;
    new_arena->bytes_allocated = 0;
    new_arena->next = NULL;
    current_arena_->next = new_arena;
    current_arena_ = new_arena;
    num_arena_blocks_++;
  }
  void* ptr = &current_arena_->ptr[current_arena_->bytes_allocated];
  current_arena_->bytes_allocated += size;
  if (zero) {
    memset(ptr, 0, size);
  }
  return ptr;
}

// Dump memory usage stats.
void ArenaAllocator::DumpMemStats(std::ostream& os) const {
  size_t total = 0;
  for (int i = 0; i < kNumAllocKinds; i++) {
    total += alloc_stats_[i];
  }
  os << " MEM: used: " << total << ", allocated: " << malloc_bytes_ << ", wasted: "
     << malloc_bytes_ - (total + (num_arena_blocks_ * sizeof(ArenaMemBlock))) << "\n";
  os << "Number of arenas allocated: " << num_arena_blocks_ << "\n";
  os << "===== Allocation by kind\n";
  for (int i = 0; i < kNumAllocKinds; i++) {
      os << alloc_names[i] << std::setw(10) << alloc_stats_[i] << "\n";
  }
}

}  // namespace art