blob: 0014724979bf1a7d61e6afc504d7d649e2206e4d [file] [log] [blame]
Brian Carlstromdb4d5402011-08-09 12:18:28 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "image_writer.h"
4
5#include <sys/mman.h>
6#include <vector>
7
8#include "file.h"
9#include "globals.h"
10#include "heap.h"
11#include "logging.h"
12#include "object.h"
13#include "space.h"
14#include "utils.h"
15
16namespace art {
17
18bool ImageWriter::Write(Space* space, const char* filename, byte* image_base) {
19 image_base_ = image_base;
20 if (!Init(space)) {
21 return false;
22 }
23 CalculateNewObjectOffsets();
24 CopyAndFixupObjects();
25
26 scoped_ptr<File> file(OS::OpenBinaryFile(filename, true));
27 if (file == NULL) {
28 return false;
29 }
30 return file->WriteFully(mem_map_->GetAddress(), top_);
31}
32
33bool ImageWriter::Init(Space* space) {
34 size_t size = space->Size();
35 int prot = PROT_READ | PROT_WRITE;
36 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
37 size_t length = RoundUp(size, kPageSize);
38 mem_map_.reset(MemMap::Map(length, prot, flags));
39 if (mem_map_ == NULL) {
40 PLOG(ERROR) << "mmap failed";
41 return false;
42 }
43 return true;
44}
45
46void ImageWriter::CalculateNewObjectOffsets() {
47 HeapBitmap* heap_bitmap = Heap::GetLiveBits();
48 DCHECK(heap_bitmap != NULL);
49 DCHECK_EQ(0U, top_);
50 top_ += sizeof(uint64_t); // leave a header, ensures objects have non-zero offset for DCHECKs
51 heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this);
52 DCHECK_LT(top_, mem_map_->GetLength());
53 // Note that top_ is left at end of used space
54}
55
56void ImageWriter::CalculateNewObjectOffsetsCallback(Object *obj, void *arg) {
57 DCHECK(obj != NULL);
58 DCHECK(arg != NULL);
59 ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
60 image_writer->SetImageOffset(obj, image_writer->top_);
61 image_writer->top_ += RoundUp(obj->Size(), 8); // 64-bit alignment
62 DCHECK_LT(image_writer->top_, image_writer->mem_map_->GetLength());
63}
64
65void ImageWriter::CopyAndFixupObjects() {
66 HeapBitmap* heap_bitmap = Heap::GetLiveBits();
67 DCHECK(heap_bitmap != NULL);
68 heap_bitmap->Walk(CopyAndFixupObjectsCallback, this);
69}
70
71void ImageWriter::CopyAndFixupObjectsCallback(Object *obj, void *arg) {
72 DCHECK(obj != NULL);
73 DCHECK(arg != NULL);
74 ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
75
76 size_t offset = image_writer->GetImageOffset(obj);
77 byte* dst = image_writer->mem_map_->GetAddress() + offset;
78 byte* src = reinterpret_cast<byte*>(obj);
79 size_t n = obj->Size();
80 DCHECK_LT(offset + n, image_writer->mem_map_->GetLength());
81 memcpy(dst, src, n);
82 Object* copy = reinterpret_cast<Object*>(dst);
83 image_writer->FixupObject(obj, copy);
84}
85
86void ImageWriter::FixupObject(Object* orig, Object* copy) {
87 DCHECK(orig != NULL);
88 DCHECK(copy != NULL);
89 copy->klass_ = down_cast<Class*>(GetImageAddress(orig->klass_));
90 // TODO specical case init of pointers to malloc data (or removal of these pointers)
91 if (orig->IsObjectArray()) {
92 FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
93 } else {
94 FixupInstanceFields(orig, copy);
95 }
96}
97
98void ImageWriter::FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
99 for (size_t i = 0; i < orig->GetLength(); ++i) {
100 const Object* element = orig->Get(i);
101 copy->Set(i, GetImageAddress(element));
102 }
103}
104
105void ImageWriter::FixupInstanceFields(Object* orig, Object* copy) {
106 uint32_t ref_offsets = orig->GetClass()->GetReferenceOffsets();
107 if (ref_offsets != CLASS_WALK_SUPER) {
108 // Found a reference offset bitmap. Fixup the specified offsets.
109 while (ref_offsets != 0) {
110 size_t right_shift = CLZ(ref_offsets);
111 size_t byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
112 const Object* ref = orig->GetFieldObject(byte_offset);
113 copy->SetFieldObject(byte_offset, GetImageAddress(ref));
114 ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
115 }
116 } else {
117 // There is no reference offset bitmap for this class. Walk up
118 // the class inheritance hierarchy and find reference offsets the
119 // hard way.
120 for (Class *klass = orig->GetClass();
121 klass != NULL;
122 klass = klass->GetSuperClass()) {
123 for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
124 size_t field_offset = klass->GetInstanceField(i)->GetOffset();
125 const Object* ref = orig->GetFieldObject(field_offset);
126 copy->SetFieldObject(field_offset, GetImageAddress(ref));
127 }
128 }
129 }
130}
131
132} // namespace art