Working dex2oat and oatexec
adb shell dex2oatd --dex-file=/system/framework/core.jar --image=/system/framework/boot.oat --base=0x50000000 "'--method=Ljava/lang/System;logI(Ljava/lang/String;)V'" "'--method=Ljava/lang/System;log(CLjava/lang/String;Ljava/lang/Throwable;)V'"
adb shell dex2oatd --boot-dex-file=/system/framework/core.jar --boot=/system/framework/boot.oat --dex-file=/system/framework/art-test-dex-HelloWorld.jar --image=/system/framework/art-test-dex-HelloWorld.oat
adb shell oatexecd -Xbootclasspath:/system/framework/core.jar -Xbootimage:/system/framework/boot.oat -classpath /system/framework/art-test-dex-HelloWorld.jar -Ximage:/system/framework/art-test-dex-HelloWorld.oat HelloWorld
09-05 17:58:18.912 2385 2385 I System : Hello, world!
Change-Id: I53e534068584f0c3a837313e4d517a0e4a7154fc
diff --git a/src/image_writer.cc b/src/image_writer.cc
index e0e77c7..a49b261 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -23,9 +23,16 @@
namespace art {
-bool ImageWriter::Write(Space* space, const char* filename, byte* image_base) {
- image_base_ = image_base;
- if (!Init(space)) {
+bool ImageWriter::Write(const char* filename, uintptr_t image_base) {
+ CHECK_NE(image_base, 0U);
+ image_base_ = reinterpret_cast<byte*>(image_base);
+
+ const std::vector<Space*>& spaces = Heap::GetSpaces();
+ // currently just write the last space, assuming it is the space that was being used for allocation
+ CHECK_GE(spaces.size(), 1U);
+ source_space_ = spaces[spaces.size()-1];
+
+ if (!Init()) {
return false;
}
CalculateNewObjectOffsets();
@@ -38,8 +45,8 @@
return file->WriteFully(image_->GetAddress(), image_top_);
}
-bool ImageWriter::Init(Space* space) {
- size_t size = space->Size();
+bool ImageWriter::Init() {
+ size_t size = source_space_->Size();
int prot = PROT_READ | PROT_WRITE;
size_t length = RoundUp(size, kPageSize);
image_.reset(MemMap::Map(length, prot));
@@ -88,9 +95,23 @@
DCHECK(obj != NULL);
DCHECK(arg != NULL);
ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
+ if (!image_writer->InSourceSpace(obj)) {
+ return;
+ }
image_writer->SetImageOffset(obj, image_writer->image_top_);
image_writer->image_top_ += RoundUp(obj->SizeOf(), 8); // 64-bit alignment
DCHECK_LT(image_writer->image_top_, image_writer->image_->GetLength());
+
+ // sniff out the DexCaches on this pass for use on the next pass
+ if (obj->IsClass()) {
+ Class* klass = obj->AsClass();
+ DexCache* dex_cache = klass->GetDexCache();
+ if (dex_cache != NULL) {
+ image_writer->dex_caches_.insert(dex_cache);
+ } else {
+ DCHECK(klass->IsArrayClass() || klass->IsPrimitive());
+ }
+ }
}
void ImageWriter::CalculateNewObjectOffsets() {
@@ -104,7 +125,7 @@
// know where interned_array is going to end up
image_top_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment
- heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this);
+ heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this); // TODO: add Space-limited Walk
DCHECK_LT(image_top_, image_->GetLength());
// return to write header at start of image with future location of interned_array
@@ -120,7 +141,8 @@
DCHECK(heap_bitmap != NULL);
// TODO: heap validation can't handle this fix up pass
Heap::DisableObjectValidation();
- heap_bitmap->Walk(CopyAndFixupObjectsCallback, this);
+ heap_bitmap->Walk(CopyAndFixupObjectsCallback, this); // TODO: add Space-limited Walk
+ FixupDexCaches();
}
void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void *arg) {
@@ -128,7 +150,11 @@
DCHECK(arg != NULL);
const Object* obj = object;
ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
+ if (!image_writer->InSourceSpace(object)) {
+ return;
+ }
+ // see GetLocalAddress for similar computation
size_t offset = image_writer->GetImageOffset(obj);
byte* dst = image_writer->image_->GetAddress() + offset;
const byte* src = reinterpret_cast<const byte*>(obj);
@@ -136,6 +162,7 @@
DCHECK_LT(offset + n, image_writer->image_->GetLength());
memcpy(dst, src, n);
Object* copy = reinterpret_cast<Object*>(dst);
+ ResetImageOffset(copy);
image_writer->FixupObject(obj, copy);
}
@@ -178,20 +205,36 @@
FixupStaticFields(orig, copy);
}
+const void* FixupCode(const ByteArray* copy_code_array, const void* orig_code) {
+ // TODO: change to DCHECK when all code compiling
+ if (copy_code_array == NULL) {
+ return NULL;
+ }
+ const void* copy_code = copy_code_array->GetData();
+ // TODO: remember InstructionSet with each code array so we know if we need to do thumb fixup?
+ if ((reinterpret_cast<uintptr_t>(orig_code) % 2) == 1) {
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(copy_code) + 1);
+ }
+ return copy_code;
+}
+
// TODO: remove this slow path
void ImageWriter::FixupMethod(const Method* orig, Method* copy) {
FixupInstanceFields(orig, copy);
// TODO: remove need for this by adding "signature" to java.lang.reflect.Method
copy->signature_ = down_cast<String*>(GetImageAddress(orig->signature_));
DCHECK(copy->signature_ != NULL);
+ // TODO: convert shorty_ to heap allocated storage
copy->dex_cache_strings_ = down_cast<ObjectArray<String>*>(GetImageAddress(orig->dex_cache_strings_));
copy->dex_cache_resolved_types_ = down_cast<ObjectArray<Class>*>(GetImageAddress(orig->dex_cache_resolved_types_));
copy->dex_cache_resolved_methods_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->dex_cache_resolved_methods_));
copy->dex_cache_resolved_fields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->dex_cache_resolved_fields_));
copy->dex_cache_code_and_direct_methods_ = down_cast<CodeAndDirectMethods*>(GetImageAddress(orig->dex_cache_code_and_direct_methods_));
copy->dex_cache_initialized_static_storage_ = down_cast<ObjectArray<StaticStorageBase>*>(GetImageAddress(orig->dex_cache_initialized_static_storage_));
-
- // TODO: convert shorty_ to heap allocated storage
+ copy->code_array_ = down_cast<ByteArray*>(GetImageAddress(orig->code_array_));
+ copy->code_ = FixupCode(copy->code_array_, orig->code_);
+ copy->invoke_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig->invoke_stub_array_));
+ copy->invoke_stub_ = reinterpret_cast<Method::InvokeStub*>(FixupCode(copy->invoke_stub_array_, reinterpret_cast<void*>(orig->invoke_stub_)));
}
void ImageWriter::FixupField(const Field* orig, Field* copy) {
@@ -262,4 +305,34 @@
}
}
+void ImageWriter::FixupDexCaches() {
+ typedef Set::const_iterator It; // TODO: C++0x auto
+ for (It it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) {
+ DexCache* orig = *it;
+ DexCache* copy = down_cast<DexCache*>(GetLocalAddress(orig));
+ FixupDexCache(orig, copy);
+ }
+}
+
+void ImageWriter::FixupDexCache(const DexCache* orig, DexCache* copy) {
+ CHECK(orig != NULL);
+ CHECK(copy != NULL);
+
+ CodeAndDirectMethods* orig_cadms = orig->GetCodeAndDirectMethods();
+ CodeAndDirectMethods* copy_cadms = down_cast<CodeAndDirectMethods*>(GetLocalAddress(orig_cadms));
+ for (size_t i = 0; i < orig->NumResolvedMethods(); i++) {
+ Method* orig_method = orig->GetResolvedMethod(i);
+ // if it was resolved in the original, resolve it in the copy
+ if (orig_method != NULL
+ && InSourceSpace(orig_method)
+ && orig_method == orig_cadms->GetResolvedMethod(i)) {
+ Method* copy_method = down_cast<Method*>(GetLocalAddress(orig_method));
+ copy_cadms->Set(CodeAndDirectMethods::CodeIndex(i),
+ reinterpret_cast<int32_t>(copy_method->code_));
+ copy_cadms->Set(CodeAndDirectMethods::MethodIndex(i),
+ reinterpret_cast<int32_t>(GetImageAddress(orig_method)));
+ }
+ }
+}
+
} // namespace art