blob: a5d3d6a73fc30f3ca9e510cd4fcd751d00198474 [file] [log] [blame]
// Copyright 2011 Google Inc. All Rights Reserved.
#ifndef ART_SRC_IMAGE_WRITER_H_
#define ART_SRC_IMAGE_WRITER_H_
#include <stdint.h>
#include <cstddef>
#include "UniquePtr.h"
#include "dex_cache.h"
#include "mem_map.h"
#include "object.h"
#include "os.h"
#include "space.h"
namespace art {
// Write a Space built during compilation for use during execution.
class ImageWriter {
public:
ImageWriter() : source_space_(NULL), image_top_(0), image_base_(NULL) {};
bool Write(const char* filename, uintptr_t image_base);
~ImageWriter() {};
private:
bool Init();
// we use the lock word to store the offset of the object in the image
void AssignImageOffset(Object* object) {
DCHECK(object != NULL);
DCHECK(object->GetMonitor() == NULL); // should be no lock
SetImageOffset(object, image_top_);
image_top_ += RoundUp(object->SizeOf(), 8); // 64-bit alignment
DCHECK_LT(image_top_, image_->GetLength());
}
static void SetImageOffset(Object* object, size_t offset) {
DCHECK(object != NULL);
// should be no lock (but it might be forward referenced interned string)
DCHECK(object->GetMonitor() == NULL || object->IsString());
DCHECK_NE(0U, offset);
object->SetMonitor(reinterpret_cast<Monitor*>(offset));
}
static size_t IsImageOffsetAssigned(const Object* object) {
DCHECK(object != NULL);
size_t offset = reinterpret_cast<size_t>(object->GetMonitor());
return offset != 0U;
}
static size_t GetImageOffset(const Object* object) {
DCHECK(object != NULL);
size_t offset = reinterpret_cast<size_t>(object->GetMonitor());
DCHECK_NE(0U, offset);
return offset;
}
static void ResetImageOffset(Object* object) {
DCHECK(object != NULL);
DCHECK(object->GetMonitor() != NULL); // should be an offset
object->SetMonitor(reinterpret_cast<Monitor*>(0));
}
bool InSourceSpace(const Object* object) {
DCHECK(source_space_ != NULL);
const byte* o = reinterpret_cast<const byte*>(object);
return (o >= source_space_->GetBase() && o < source_space_->GetLimit());
}
Object* GetImageAddress(const Object* object) {
if (object == NULL) {
return NULL;
}
// if object outside the relocating source_space_, assume unchanged
if (!InSourceSpace(object)) {
return const_cast<Object*>(object);
}
return reinterpret_cast<Object*>(image_base_ + GetImageOffset(object));
}
Object* GetLocalAddress(const Object* object) {
size_t offset = GetImageOffset(object);
byte* dst = image_->GetAddress() + offset;
return reinterpret_cast<Object*>(dst);
}
void CalculateNewObjectOffsets();
static void CalculateNewObjectOffsetsCallback(Object* obj, void *arg);
void CopyAndFixupObjects();
static void CopyAndFixupObjectsCallback(Object* obj, void *arg);
void FixupClass(const Class* orig, Class* copy);
void FixupMethod(const Method* orig, Method* copy);
void FixupObject(const Object* orig, Object* copy);
void FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy);
void FixupInstanceFields(const Object* orig, Object* copy);
void FixupStaticFields(const Class* orig, Class* copy);
void FixupFields(const Object* orig, Object* copy, uint32_t ref_offsets, bool is_static);
void FixupDexCaches();
void FixupDexCache(const DexCache* orig, DexCache* copy);
// Space we are writing objects from
const Space* source_space_;
// memory mapped for generating the image
UniquePtr<MemMap> image_;
// Offset to the free space in image_
size_t image_top_;
// Target base address for the output image
byte* image_base_;
// DexCaches seen while scanning for fixing up CodeAndDirectMethods
typedef std::tr1::unordered_set<DexCache*, DexCacheHash> Set;
Set dex_caches_;
};
} // namespace art
#endif // ART_SRC_IMAGE_WRITER_H_