blob: 7f1bfb386dbcab633eec7e396b96993dccc7fcc7 [file] [log] [blame]
buzbee862a7602013-04-05 10:58:54 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "compiler_internals.h"
18#include "dex_file-inl.h"
19#include "arena_allocator.h"
20#include "base/logging.h"
21
22namespace art {
23
24static const char* alloc_names[ArenaAllocator::kNumAllocKinds] = {
25 "Misc ",
26 "BasicBlock ",
27 "LIR ",
28 "MIR ",
29 "DataFlow ",
30 "GrowList ",
31 "GrowBitMap ",
32 "Dalvik2SSA ",
33 "DebugInfo ",
34 "Successor ",
35 "RegAlloc ",
36 "Data ",
37 "Preds ",
38};
39
40ArenaAllocator::ArenaAllocator(size_t default_size)
41 : default_size_(default_size),
42 block_size_(default_size - sizeof(ArenaMemBlock)),
43 arena_head_(NULL),
44 current_arena_(NULL),
45 num_arena_blocks_(0),
46 malloc_bytes_(0) {
47 memset(&alloc_stats_[0], 0, sizeof(alloc_stats_));
48 // Start with an empty arena.
49 arena_head_ = current_arena_ = EmptyArena();
50 num_arena_blocks_++;
51}
52
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070053ArenaAllocator::~ArenaAllocator() {
54 // Reclaim all the arena blocks allocated so far.
55 ArenaMemBlock* head = arena_head_;
56 while (head != NULL) {
57 ArenaMemBlock* p = head;
58 head = head->next;
59 free(p);
60 }
61 arena_head_ = current_arena_ = NULL;
62 num_arena_blocks_ = 0;
63}
64
buzbee862a7602013-04-05 10:58:54 -070065// Return an arena with no storage for use as a sentinal.
66ArenaAllocator::ArenaMemBlock* ArenaAllocator::EmptyArena() {
67 ArenaMemBlock* res = static_cast<ArenaMemBlock*>(malloc(sizeof(ArenaMemBlock)));
68 malloc_bytes_ += sizeof(ArenaMemBlock);
69 res->block_size = 0;
70 res->bytes_allocated = 0;
71 res->next = NULL;
72 return res;
73}
74
75// Arena-based malloc for compilation tasks.
76void* ArenaAllocator::NewMem(size_t size, bool zero, ArenaAllocKind kind) {
77 DCHECK(current_arena_ != NULL);
78 DCHECK(arena_head_ != NULL);
79 size = (size + 3) & ~3;
80 alloc_stats_[kind] += size;
81 if (size + current_arena_->bytes_allocated > current_arena_->block_size) {
82 size_t block_size = (size <= block_size_) ? block_size_ : size;
83 /* Time to allocate a new block */
84 size_t allocation_size = sizeof(ArenaMemBlock) + block_size;
85 ArenaMemBlock *new_arena =
86 static_cast<ArenaMemBlock*>(malloc(allocation_size));
87 if (new_arena == NULL) {
88 LOG(FATAL) << "Arena allocation failure";
89 }
90 malloc_bytes_ += allocation_size;
91 new_arena->block_size = block_size;
92 new_arena->bytes_allocated = 0;
93 new_arena->next = NULL;
94 current_arena_->next = new_arena;
95 current_arena_ = new_arena;
96 num_arena_blocks_++;
97 }
98 void* ptr = &current_arena_->ptr[current_arena_->bytes_allocated];
99 current_arena_->bytes_allocated += size;
100 if (zero) {
101 memset(ptr, 0, size);
102 }
103 return ptr;
104}
105
buzbee862a7602013-04-05 10:58:54 -0700106// Dump memory usage stats.
107void ArenaAllocator::DumpMemStats(std::ostream& os) const {
108 size_t total = 0;
109 for (int i = 0; i < kNumAllocKinds; i++) {
110 total += alloc_stats_[i];
111 }
112 os << " MEM: used: " << total << ", allocated: " << malloc_bytes_ << ", wasted: "
113 << malloc_bytes_ - (total + (num_arena_blocks_ * sizeof(ArenaMemBlock))) << "\n";
114 os << "Number of arenas allocated: " << num_arena_blocks_ << "\n";
115 os << "===== Allocation by kind\n";
116 for (int i = 0; i < kNumAllocKinds; i++) {
117 os << alloc_names[i] << std::setw(10) << alloc_stats_[i] << "\n";
118 }
119}
120
121} // namespace art