blob: 46c39378d755407b740de0969a50056f33103a2e [file] [log] [blame]
Ian Rogers1d54e732013-05-02 21:10:01 -07001/*
2 * Copyright (C) 2011 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 "image_space.h"
18
19#include "base/unix_file/fd_file.h"
20#include "gc/accounting/space_bitmap-inl.h"
21#include "mirror/abstract_method.h"
22#include "mirror/class-inl.h"
23#include "mirror/object-inl.h"
24#include "os.h"
25#include "runtime.h"
26#include "space-inl.h"
27#include "utils.h"
28
29namespace art {
30namespace gc {
31namespace space {
32
33size_t ImageSpace::bitmap_index_ = 0;
34
35ImageSpace::ImageSpace(const std::string& name, MemMap* mem_map)
36: MemMapSpace(name, mem_map, mem_map->Size(), kGcRetentionPolicyNeverCollect) {
37 const size_t bitmap_index = bitmap_index_++;
38 live_bitmap_.reset(accounting::SpaceBitmap::Create(
39 StringPrintf("imagespace %s live-bitmap %d", name.c_str(), static_cast<int>(bitmap_index)),
40 Begin(), Capacity()));
41 DCHECK(live_bitmap_.get() != NULL) << "could not create imagespace live bitmap #" << bitmap_index;
42}
43
44ImageSpace* ImageSpace::Create(const std::string& image_file_name) {
45 CHECK(!image_file_name.empty());
46
47 uint64_t start_time = 0;
48 if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
49 start_time = NanoTime();
50 LOG(INFO) << "Space::CreateImageSpace entering" << " image_file_name=" << image_file_name;
51 }
52
53 UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false));
54 if (file.get() == NULL) {
55 LOG(ERROR) << "Failed to open " << image_file_name;
56 return NULL;
57 }
58 ImageHeader image_header;
59 bool success = file->ReadFully(&image_header, sizeof(image_header));
60 if (!success || !image_header.IsValid()) {
61 LOG(ERROR) << "Invalid image header " << image_file_name;
62 return NULL;
63 }
64 UniquePtr<MemMap> map(MemMap::MapFileAtAddress(image_header.GetImageBegin(),
65 file->GetLength(),
66 PROT_READ | PROT_WRITE,
67 MAP_PRIVATE | MAP_FIXED,
68 file->Fd(),
69 0,
70 false));
71 if (map.get() == NULL) {
72 LOG(ERROR) << "Failed to map " << image_file_name;
73 return NULL;
74 }
75 CHECK_EQ(image_header.GetImageBegin(), map->Begin());
76 DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader)));
77
78 Runtime* runtime = Runtime::Current();
79 mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
80 runtime->SetResolutionMethod(down_cast<mirror::AbstractMethod*>(resolution_method));
81
82 mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
83 runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kSaveAll);
84 callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
85 runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsOnly);
86 callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
87 runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsAndArgs);
88
89 ImageSpace* space = new ImageSpace(image_file_name, map.release());
90 if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
91 LOG(INFO) << "Space::CreateImageSpace exiting (" << PrettyDuration(NanoTime() - start_time)
92 << ") " << *space;
93 }
94 return space;
95}
96
97void ImageSpace::RecordImageAllocations(accounting::SpaceBitmap* live_bitmap) const {
98 uint64_t start_time = 0;
99 if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
100 LOG(INFO) << "ImageSpace::RecordImageAllocations entering";
101 start_time = NanoTime();
102 }
103 DCHECK(!Runtime::Current()->IsStarted());
104 CHECK(live_bitmap != NULL);
105 byte* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
106 byte* end = End();
107 while (current < end) {
108 DCHECK_ALIGNED(current, kObjectAlignment);
109 const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(current);
110 live_bitmap->Set(obj);
111 current += RoundUp(obj->SizeOf(), kObjectAlignment);
112 }
113 if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
114 LOG(INFO) << "ImageSpace::RecordImageAllocations exiting ("
115 << PrettyDuration(NanoTime() - start_time) << ")";
116 }
117}
118
119void ImageSpace::Dump(std::ostream& os) const {
120 os << GetType()
121 << "begin=" << reinterpret_cast<void*>(Begin())
122 << ",end=" << reinterpret_cast<void*>(End())
123 << ",size=" << PrettySize(Size())
124 << ",name=\"" << GetName() << "\"]";
125}
126
127} // namespace space
128} // namespace gc
129} // namespace art