blob: 7240c3da1e00ff1221ad586660a9871a55df79b7 [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();
Elliott Hughesd8ddfd52011-08-15 14:32:53 -070025
Brian Carlstrom4e777d42011-08-15 13:53:52 -070026 scoped_ptr<File> file(OS::OpenFile(filename, true));
Brian Carlstromdb4d5402011-08-09 12:18:28 -070027 if (file == NULL) {
28 return false;
29 }
Brian Carlstrom4e777d42011-08-15 13:53:52 -070030 return file->WriteFully(image_->GetAddress(), image_top_);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070031}
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);
Brian Carlstrom4e777d42011-08-15 13:53:52 -070038 image_.reset(MemMap::Map(length, prot, flags));
39 if (image_ == NULL) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -070040 PLOG(ERROR) << "mmap failed";
41 return false;
42 }
43 return true;
44}
45
Brian Carlstromdb4d5402011-08-09 12:18:28 -070046void ImageWriter::CalculateNewObjectOffsetsCallback(Object *obj, void *arg) {
47 DCHECK(obj != NULL);
48 DCHECK(arg != NULL);
49 ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
Brian Carlstrom4e777d42011-08-15 13:53:52 -070050 image_writer->SetImageOffset(obj, image_writer->image_top_);
51 image_writer->image_top_ += RoundUp(obj->Size(), 8); // 64-bit alignment
52 DCHECK_LT(image_writer->image_top_, image_writer->image_->GetLength());
53}
54
55void ImageWriter::CalculateNewObjectOffsets() {
56 HeapBitmap* heap_bitmap = Heap::GetLiveBits();
57 DCHECK(heap_bitmap != NULL);
58 DCHECK_EQ(0U, image_top_);
59 // leave a header, ensures objects have non-zero offset for DCHECKs
60 image_top_ += 8; // 64-bit-alignment
61 heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this);
62 DCHECK_LT(image_top_, image_->GetLength());
63 // Note that top_ is left at end of used space
Brian Carlstromdb4d5402011-08-09 12:18:28 -070064}
65
66void ImageWriter::CopyAndFixupObjects() {
67 HeapBitmap* heap_bitmap = Heap::GetLiveBits();
68 DCHECK(heap_bitmap != NULL);
69 heap_bitmap->Walk(CopyAndFixupObjectsCallback, this);
70}
71
72void ImageWriter::CopyAndFixupObjectsCallback(Object *obj, void *arg) {
73 DCHECK(obj != NULL);
74 DCHECK(arg != NULL);
75 ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -070076
Brian Carlstromdb4d5402011-08-09 12:18:28 -070077 size_t offset = image_writer->GetImageOffset(obj);
Brian Carlstrom4e777d42011-08-15 13:53:52 -070078 byte* dst = image_writer->image_->GetAddress() + offset;
Brian Carlstromdb4d5402011-08-09 12:18:28 -070079 byte* src = reinterpret_cast<byte*>(obj);
80 size_t n = obj->Size();
Brian Carlstrom4e777d42011-08-15 13:53:52 -070081 DCHECK_LT(offset + n, image_writer->image_->GetLength());
Brian Carlstromdb4d5402011-08-09 12:18:28 -070082 memcpy(dst, src, n);
83 Object* copy = reinterpret_cast<Object*>(dst);
84 image_writer->FixupObject(obj, copy);
85}
86
87void ImageWriter::FixupObject(Object* orig, Object* copy) {
88 DCHECK(orig != NULL);
89 DCHECK(copy != NULL);
90 copy->klass_ = down_cast<Class*>(GetImageAddress(orig->klass_));
91 // TODO specical case init of pointers to malloc data (or removal of these pointers)
92 if (orig->IsObjectArray()) {
93 FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
94 } else {
95 FixupInstanceFields(orig, copy);
96 }
97}
98
99void ImageWriter::FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700100 for (int32_t i = 0; i < orig->GetLength(); ++i) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700101 const Object* element = orig->Get(i);
102 copy->Set(i, GetImageAddress(element));
103 }
104}
105
106void ImageWriter::FixupInstanceFields(Object* orig, Object* copy) {
107 uint32_t ref_offsets = orig->GetClass()->GetReferenceOffsets();
108 if (ref_offsets != CLASS_WALK_SUPER) {
109 // Found a reference offset bitmap. Fixup the specified offsets.
110 while (ref_offsets != 0) {
111 size_t right_shift = CLZ(ref_offsets);
112 size_t byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
113 const Object* ref = orig->GetFieldObject(byte_offset);
114 copy->SetFieldObject(byte_offset, GetImageAddress(ref));
115 ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
116 }
117 } else {
118 // There is no reference offset bitmap for this class. Walk up
119 // the class inheritance hierarchy and find reference offsets the
120 // hard way.
121 for (Class *klass = orig->GetClass();
122 klass != NULL;
123 klass = klass->GetSuperClass()) {
124 for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
125 size_t field_offset = klass->GetInstanceField(i)->GetOffset();
126 const Object* ref = orig->GetFieldObject(field_offset);
127 copy->SetFieldObject(field_offset, GetImageAddress(ref));
128 }
129 }
130 }
131}
132
133} // namespace art