blob: 2db8445be05d91f15301f857fa43e861ad473345 [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
53// Return an arena with no storage for use as a sentinal.
54ArenaAllocator::ArenaMemBlock* ArenaAllocator::EmptyArena() {
55 ArenaMemBlock* res = static_cast<ArenaMemBlock*>(malloc(sizeof(ArenaMemBlock)));
56 malloc_bytes_ += sizeof(ArenaMemBlock);
57 res->block_size = 0;
58 res->bytes_allocated = 0;
59 res->next = NULL;
60 return res;
61}
62
63// Arena-based malloc for compilation tasks.
64void* ArenaAllocator::NewMem(size_t size, bool zero, ArenaAllocKind kind) {
65 DCHECK(current_arena_ != NULL);
66 DCHECK(arena_head_ != NULL);
67 size = (size + 3) & ~3;
68 alloc_stats_[kind] += size;
69 if (size + current_arena_->bytes_allocated > current_arena_->block_size) {
70 size_t block_size = (size <= block_size_) ? block_size_ : size;
71 /* Time to allocate a new block */
72 size_t allocation_size = sizeof(ArenaMemBlock) + block_size;
73 ArenaMemBlock *new_arena =
74 static_cast<ArenaMemBlock*>(malloc(allocation_size));
75 if (new_arena == NULL) {
76 LOG(FATAL) << "Arena allocation failure";
77 }
78 malloc_bytes_ += allocation_size;
79 new_arena->block_size = block_size;
80 new_arena->bytes_allocated = 0;
81 new_arena->next = NULL;
82 current_arena_->next = new_arena;
83 current_arena_ = new_arena;
84 num_arena_blocks_++;
85 }
86 void* ptr = &current_arena_->ptr[current_arena_->bytes_allocated];
87 current_arena_->bytes_allocated += size;
88 if (zero) {
89 memset(ptr, 0, size);
90 }
91 return ptr;
92}
93
94// Reclaim all the arena blocks allocated so far.
95void ArenaAllocator::ArenaReset() {
96 ArenaMemBlock* head = arena_head_;
97 while (head != NULL) {
98 ArenaMemBlock* p = head;
99 head = head->next;
100 free(p);
101 }
102 // We must always have an arena. Create a zero-length one.
103 arena_head_ = current_arena_ = EmptyArena();
104 num_arena_blocks_ = 1;
105}
106
107// Dump memory usage stats.
108void ArenaAllocator::DumpMemStats(std::ostream& os) const {
109 size_t total = 0;
110 for (int i = 0; i < kNumAllocKinds; i++) {
111 total += alloc_stats_[i];
112 }
113 os << " MEM: used: " << total << ", allocated: " << malloc_bytes_ << ", wasted: "
114 << malloc_bytes_ - (total + (num_arena_blocks_ * sizeof(ArenaMemBlock))) << "\n";
115 os << "Number of arenas allocated: " << num_arena_blocks_ << "\n";
116 os << "===== Allocation by kind\n";
117 for (int i = 0; i < kNumAllocKinds; i++) {
118 os << alloc_names[i] << std::setw(10) << alloc_stats_[i] << "\n";
119 }
120}
121
122} // namespace art