Merge "Fix for Mac build." into dalvik-dev
diff --git a/Android.mk b/Android.mk
index 097dd08..3e17072 100644
--- a/Android.mk
+++ b/Android.mk
@@ -274,7 +274,7 @@
# oatdump targets
.PHONY: dump-oat
-dump-oat: dump-oat-core dump-oat-boot
+dump-oat: dump-oat-core dump-oat-boot dump-oat-Calculator
.PHONY: dump-oat-core
dump-oat-core: dump-oat-core-host dump-oat-core-target
@@ -294,6 +294,12 @@
$(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=/tmp/boot.oatdump.txt
@echo Output in /tmp/boot.oatdump.txt
+.PHONY: dump-oat-Calculator
+dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.apk.oat $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
+ $(OATDUMP) --oat-file=$< --output=/tmp/Calculator.oatdump.txt
+ @echo Output in /tmp/Calculator.oatdump.txt
+
+
########################################################################
# cpplint target
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 0373b58..5d89c40 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -373,6 +373,7 @@
LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \
+ src/dex_file.h \
src/dex_instruction.h \
src/gc/space.h \
src/heap.h \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 6eaa778..43ce31a 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -104,7 +104,7 @@
LOCAL_SHARED_LIBRARIES := liblog libnativehelper
LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
ifeq ($$(art_target_or_host),target)
- LOCAL_SHARED_LIBRARIES += libcutils libstlport libz libdl
+ LOCAL_SHARED_LIBRARIES += libcutils libstlport libz libdl libselinux
LOCAL_SHARED_LIBRARIES += libdynamic_annotations # tsan support
else # host
LOCAL_STATIC_LIBRARIES += libcutils
diff --git a/src/check_jni.cc b/src/check_jni.cc
index e7590d3..7c5186a 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -208,6 +208,7 @@
// obj will be NULL. Otherwise, obj should always be non-NULL
// and valid.
if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
+ Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "field operation on invalid %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
return;
@@ -244,6 +245,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Object* o = soa_.Decode<Object*>(java_object);
if (o == NULL || !Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
+ Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "field operation on invalid %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
return;
@@ -623,6 +625,7 @@
Object* obj = soa_.Decode<Object*>(java_object);
if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
+ Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
return false;
@@ -676,6 +679,7 @@
Array* a = soa_.Decode<Array*>(java_array);
if (!Runtime::Current()->GetHeap()->IsHeapAddress(a)) {
+ Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
} else if (!a->IsArrayInstance()) {
@@ -696,6 +700,7 @@
}
Field* f = soa_.DecodeField(fid);
if (!Runtime::Current()->GetHeap()->IsHeapAddress(f) || !f->IsField()) {
+ Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "invalid jfieldID: %p", fid);
return NULL;
}
@@ -709,6 +714,7 @@
}
AbstractMethod* m = soa_.DecodeMethod(mid);
if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsMethod()) {
+ Runtime::Current()->GetHeap()->DumpSpaces();
JniAbortF(function_name_, "invalid jmethodID: %p", mid);
return NULL;
}
@@ -729,6 +735,7 @@
Object* o = soa_.Decode<Object*>(java_object);
if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
+ Runtime::Current()->GetHeap()->DumpSpaces();
// TODO: when we remove work_around_app_jni_bugs, this should be impossible.
JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 83661cb..a76c9c8 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -222,6 +222,7 @@
class_roots_(NULL),
array_iftable_(NULL),
init_done_(false),
+ is_dirty_(false),
intern_table_(intern_table) {
CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
}
@@ -706,7 +707,7 @@
uint32_t image_oat_checksum = image_header.GetOatChecksum();
if (oat_checksum != image_oat_checksum) {
LOG(ERROR) << "Failed to match oat file checksum " << std::hex << oat_checksum
- << " to expected oat checksum " << std::hex << oat_checksum
+ << " to expected oat checksum " << std::hex << image_oat_checksum
<< " in image";
return NULL;
}
@@ -742,7 +743,11 @@
}
Runtime* runtime = Runtime::Current();
const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
- if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+ if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
+ return NULL;
+ }
+ if (oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+ != reinterpret_cast<uint32_t>(image_header.GetOatBegin())) {
return NULL;
}
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
@@ -813,8 +818,10 @@
uint32_t dex_location_checksum) {
Runtime* runtime = Runtime::Current();
const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
- uint32_t image_checksum = image_header.GetOatChecksum();
- bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
+ uint32_t image_oat_checksum = image_header.GetOatChecksum();
+ uint32_t image_oat_begin = reinterpret_cast<uint32_t>(image_header.GetOatBegin());
+ bool image_check = ((oat_file->GetOatHeader().GetImageFileLocationOatChecksum() == image_oat_checksum)
+ && (oat_file->GetOatHeader().GetImageFileLocationOatBegin() == image_oat_begin));
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
if (oat_dex_file == NULL) {
@@ -828,7 +835,7 @@
}
return false;
}
- bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
+ bool dex_check = dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum();
if (image_check && dex_check) {
return true;
@@ -838,14 +845,15 @@
std::string image_file(image_header.GetImageRoot(
ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
LOG(WARNING) << ".oat file " << oat_file->GetLocation()
- << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
- << ") mismatch with " << image_file
- << " (" << std::hex << image_checksum << ")";
+ << " mismatch ( " << std::hex << oat_file->GetOatHeader().GetImageFileLocationOatChecksum()
+ << ", " << oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+ << ") with " << image_file
+ << " (" << image_oat_checksum << ", " << std::hex << image_oat_begin << ")";
}
if (!dex_check) {
LOG(WARNING) << ".oat file " << oat_file->GetLocation()
- << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
- << ") mismatch with " << dex_location
+ << " mismatch ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+ << ") with " << dex_location
<< " (" << std::hex << dex_location_checksum << ")";
}
return false;
@@ -957,7 +965,8 @@
ImageSpace* space = heap->GetImageSpace();
OatFile* oat_file = OpenOat(space);
CHECK(oat_file != NULL) << "Failed to open oat file for image";
- CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationChecksum(), 0U);
+ CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0U);
+ CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatBegin(), 0U);
CHECK(oat_file->GetOatHeader().GetImageFileLocation().empty());
Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
@@ -1043,7 +1052,7 @@
// Keep in sync with InitCallback. Anything we visit, we need to
// reinit references to when reinitializing a ClassLinker from a
// mapped image.
-void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
+void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
visitor(class_roots_, arg);
Thread* self = Thread::Current();
{
@@ -1065,6 +1074,7 @@
}
visitor(array_iftable_, arg);
+ is_dirty_ = false;
}
void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) const {
@@ -1746,6 +1756,7 @@
CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()));
dex_caches_.push_back(dex_cache.get());
dex_cache->SetDexFile(&dex_file);
+ Dirty();
}
void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
@@ -1990,6 +2001,7 @@
return existing;
}
classes.insert(std::make_pair(hash, klass));
+ Dirty();
return NULL;
}
@@ -2803,7 +2815,8 @@
const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
CHECK(dex_class_def != NULL);
const DexFile& dex_file = kh.GetDexFile();
- EncodedStaticFieldValueIterator it(dex_file, dex_cache, this, *dex_class_def);
+ EncodedStaticFieldValueIterator it(dex_file, dex_cache, klass->GetClassLoader(),
+ this, *dex_class_def);
if (it.HasNext()) {
// We reordered the fields, so we need to be able to map the field indexes to the right fields.
diff --git a/src/class_linker.h b/src/class_linker.h
index 096d602..f1530f3 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -262,7 +262,7 @@
void VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* arg) const
LOCKS_EXCLUDED(Locks::classlinker_classes_lock_);
- void VisitRoots(Heap::RootVisitor* visitor, void* arg) const
+ void VisitRoots(Heap::RootVisitor* visitor, void* arg)
LOCKS_EXCLUDED(Locks::classlinker_classes_lock_, dex_lock_);
DexCache* FindDexCache(const DexFile& dex_file) const
@@ -302,7 +302,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Returns true if oat file contains the dex file with the given location and checksum
+ // Returns true if oat file contains the dex file with the given location and checksum.
static bool VerifyOatFileChecksums(const OatFile* oat_file,
const std::string& dex_location,
uint32_t dex_location_checksum)
@@ -378,6 +378,14 @@
pid_t GetClassesLockOwner(); // For SignalCatcher.
pid_t GetDexLockOwner(); // For SignalCatcher.
+ bool IsDirty() const {
+ return is_dirty_;
+ }
+
+ void Dirty() {
+ is_dirty_ = true;
+ }
+
private:
explicit ClassLinker(InternTable*);
@@ -636,6 +644,7 @@
IfTable* array_iftable_;
bool init_done_;
+ bool is_dirty_;
InternTable* intern_table_;
diff --git a/src/compiler.cc b/src/compiler.cc
index 1be7b75..8d7f5b6 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -839,9 +839,15 @@
// invoked, so this can be passed to the out-of-line runtime support code.
direct_code = 0;
direct_method = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
if (sharp_type != kStatic && sharp_type != kDirect && sharp_type != kInterface) {
return;
}
+#else
+ if (sharp_type != kStatic && sharp_type != kDirect) {
+ return;
+ }
+#endif
bool method_code_in_boot = method->GetDeclaringClass()->GetClassLoader() == NULL;
if (!method_code_in_boot) {
return;
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index c1d4661..21f824d 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -1321,6 +1321,10 @@
}
}
/* rARG0 is ref, rARG2 is class. If ref==null, use directly as bool result */
+ RegLocation rlResult = oatGetReturn(cUnit, false);
+#if defined(TARGET_MIPS)
+ opRegCopy(cUnit, rlResult.lowReg, r_ZERO); // store false result for if branch is taken
+#endif
LIR* branch1 = opCmpImmBranch(cUnit, kCondEq, rARG0, 0, NULL);
/* load object->klass_ */
DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
@@ -1339,7 +1343,7 @@
oatFreeTemp(cUnit, rTgt);
#else
/* Uses branchovers */
- loadConstant(cUnit, rARG0, 1); // assume true
+ loadConstant(cUnit, rlResult.lowReg, 1); // assume true
LIR* branchover = opCmpBranch(cUnit, kCondEq, rARG1, rARG2, NULL);
#if !defined(TARGET_X86)
int rTgt = loadHelper(cUnit,
@@ -1356,7 +1360,6 @@
oatClobberCalleeSave(cUnit);
/* branch targets here */
LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
- RegLocation rlResult = oatGetReturn(cUnit, false);
storeValue(cUnit, rlDest, rlResult);
branch1->target = target;
#if !defined(TARGET_ARM)
@@ -1884,9 +1887,10 @@
storeValue(cUnit, rlDest, rlResult);
} else {
#if defined(TARGET_MIPS)
+ rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
if (checkZero) {
- genNullCheck(cUnit, rlSrc2.sRegLow, rlSrc2.lowReg, 0);
+ genImmedCheck(cUnit, kCondEq, rlSrc2.lowReg, 0, kThrowDivZero);
}
newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc1.lowReg, rlSrc2.lowReg);
rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
@@ -1918,8 +1922,8 @@
rlResult = oatGetReturn(cUnit, false);
else
rlResult = oatGetReturnAlt(cUnit);
- storeValue(cUnit, rlDest, rlResult);
#endif
+ storeValue(cUnit, rlDest, rlResult);
}
return false;
}
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index f121a54..437f1ed 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -197,11 +197,11 @@
oatFlushAllRegs(cUnit);
oatLockCallTemps(cUnit);
if (wide) {
- loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
- loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+ loadValueDirectWideFixed(cUnit, rlSrc1, r_FARG0, r_FARG1);
+ loadValueDirectWideFixed(cUnit, rlSrc2, r_FARG2, r_FARG3);
} else {
- loadValueDirectFixed(cUnit, rlSrc1, rARG0);
- loadValueDirectFixed(cUnit, rlSrc2, rARG1);
+ loadValueDirectFixed(cUnit, rlSrc1, r_FARG0);
+ loadValueDirectFixed(cUnit, rlSrc2, r_FARG2);
}
int rTgt = loadHelper(cUnit, offset);
// NOTE: not a safepoint
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 5e5147a..5077c9f 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -141,6 +141,8 @@
/* These are the same for both big and little endian. */
#define r_FARG0 r_F12
#define r_FARG1 r_F13
+#define r_FARG2 r_F14
+#define r_FARG3 r_F15
#define r_FRESULT0 r_F0
#define r_FRESULT1 r_F1
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 8750c0b..484dd77 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -60,7 +60,7 @@
private:
llvm::AllocaInst* shadow_frame_;
llvm::Value* old_shadow_frame_;
- uint32_t shadow_frame_size_;
+ uint16_t num_shadow_frame_refs_;
private:
art::Compiler* compiler_;
@@ -326,7 +326,7 @@
GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
: llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
context_(irb.getContext()), rtb_(irb.Runtime()),
- shadow_frame_(NULL), old_shadow_frame_(NULL), shadow_frame_size_(0),
+ shadow_frame_(NULL), old_shadow_frame_(NULL), num_shadow_frame_refs_(0),
compiler_(NULL), dex_file_(NULL), code_item_(NULL),
oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
changed_(false)
@@ -336,7 +336,7 @@
art::Compiler* compiler, art::OatCompilationUnit* oat_compilation_unit)
: llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
context_(irb.getContext()), rtb_(irb.Runtime()),
- shadow_frame_(NULL), old_shadow_frame_(NULL), shadow_frame_size_(0),
+ shadow_frame_(NULL), old_shadow_frame_(NULL), num_shadow_frame_refs_(0),
compiler_(compiler),
dex_file_(oat_compilation_unit->GetDexFile()),
code_item_(oat_compilation_unit->GetCodeItem()),
@@ -366,7 +366,7 @@
// Setup rewrite context
shadow_frame_ = NULL;
old_shadow_frame_ = NULL;
- shadow_frame_size_ = 0;
+ num_shadow_frame_refs_ = 0;
func_ = &func;
changed_ = false; // Assume unchanged
@@ -1095,11 +1095,11 @@
void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
// Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
// MethodCompiler::EmitPushShadowFrame
- shadow_frame_size_ =
+ num_shadow_frame_refs_ =
llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
llvm::StructType* shadow_frame_type =
- irb_.getShadowFrameTy(shadow_frame_size_);
+ irb_.getShadowFrameTy(num_shadow_frame_refs_);
shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
@@ -1126,7 +1126,8 @@
llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
method_object_addr,
- shadow_frame_size_);
+ num_shadow_frame_refs_,
+ 0);
irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 872701d..e118646 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -93,7 +93,8 @@
FuncTy_7_args.push_back(PointerTy_1);
FuncTy_7_args.push_back(PointerTy_2);
FuncTy_7_args.push_back(PointerTy_1);
-FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
+FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
FunctionType* FuncTy_7 = FunctionType::get(
/*Result=*/PointerTy_2,
/*Params=*/FuncTy_7_args,
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 1737b70..f91694e 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -3823,7 +3823,7 @@
} else {
DCHECK(num_shadow_frame_refs_ == 0);
result = irb_.Runtime().EmitPushShadowFrameNoInline(shadow_frame_upcast, method_object_addr,
- num_shadow_frame_refs_);
+ num_shadow_frame_refs_, 0);
}
irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
}
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index 2effddd..dbcbe89 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -124,10 +124,16 @@
llvm::Value*
RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
- llvm::Value* method, uint32_t size) {
+ llvm::Value* method, uint16_t num_refs,
+ uint16_t num_vregs) {
Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
llvm::CallInst* call_inst =
- irb_.CreateCall4(func, EmitGetCurrentThread(), new_shadow_frame, method, irb_.getInt32(size));
+ irb_.CreateCall5(func,
+ EmitGetCurrentThread(),
+ new_shadow_frame,
+ method,
+ irb_.getInt16(num_refs),
+ irb_.getInt16(num_vregs));
irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
return call_inst;
}
diff --git a/src/compiler_llvm/runtime_support_builder.h b/src/compiler_llvm/runtime_support_builder.h
index b8123a5..ba512af 100644
--- a/src/compiler_llvm/runtime_support_builder.h
+++ b/src/compiler_llvm/runtime_support_builder.h
@@ -53,7 +53,7 @@
virtual llvm::Value* EmitPushShadowFrame(llvm::Value* new_shadow_frame,
llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
virtual llvm::Value* EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
- llvm::Value* method, uint32_t size);
+ llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
virtual void EmitPopShadowFrame(llvm::Value* old_shadow_frame);
/* Exception */
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index d20d7ab..20872e1 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -253,11 +253,13 @@
Thread::Current()->TransitionFromSuspendedToRunnable();
std::string image_file_location;
- uint32_t image_file_location_checksum = 0;
+ uint32_t image_file_location_oat_checksum = 0;
+ uint32_t image_file_location_oat_begin = 0;
Heap* heap = Runtime::Current()->GetHeap();
if (heap->GetSpaces().size() > 1) {
ImageSpace* image_space = heap->GetImageSpace();
- image_file_location_checksum = image_space->GetImageHeader().GetOatChecksum();
+ image_file_location_oat_checksum = image_space->GetImageHeader().GetOatChecksum();
+ image_file_location_oat_begin = reinterpret_cast<uint32_t>(image_space->GetImageHeader().GetOatBegin());
image_file_location = image_space->GetImageFilename();
if (host_prefix != NULL && StartsWith(image_file_location, host_prefix->c_str())) {
image_file_location = image_file_location.substr(host_prefix->size());
@@ -267,7 +269,8 @@
if (!OatWriter::Create(oat_file,
class_loader,
dex_files,
- image_file_location_checksum,
+ image_file_location_oat_checksum,
+ image_file_location_oat_begin,
image_file_location,
*compiler.get())) {
LOG(ERROR) << "Failed to create oat file " << oat_file->name();
diff --git a/src/dex_file.cc b/src/dex_file.cc
index d918152..c433f3d 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -901,10 +901,11 @@
EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
DexCache* dex_cache,
+ ClassLoader* class_loader,
ClassLinker* linker,
const DexFile::ClassDef& class_def)
- : dex_file_(dex_file), dex_cache_(dex_cache), linker_(linker), array_size_(), pos_(-1),
- type_(0) {
+ : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker),
+ array_size_(), pos_(-1), type_(kByte) {
ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
if (ptr_ == NULL) {
array_size_ = 0;
@@ -924,7 +925,7 @@
byte value_type = *ptr_++;
byte value_arg = value_type >> kEncodedValueArgShift;
size_t width = value_arg + 1; // assume and correct later
- type_ = value_type & kEncodedValueTypeMask;
+ type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
switch (type_) {
case kBoolean:
jval_.i = (value_arg != 0) ? 1 : 0;
@@ -956,11 +957,11 @@
break;
case kString:
case kType:
- case kMethod:
- case kEnum:
jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
break;
case kField:
+ case kMethod:
+ case kEnum:
case kArray:
case kAnnotation:
UNIMPLEMENTED(FATAL) << ": type " << type_;
@@ -991,6 +992,11 @@
field->SetObject(NULL, resolved);
break;
}
+ case kType: {
+ Class* resolved = linker_->ResolveType(dex_file_, jval_.i, dex_cache_, class_loader_);
+ field->SetObject(NULL, resolved);
+ break;
+ }
default: UNIMPLEMENTED(FATAL) << ": type " << type_;
}
}
diff --git a/src/dex_file.h b/src/dex_file.h
index cca3935..58a0b3f 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -347,7 +347,8 @@
// Opens .dex file, backed by existing memory
static const DexFile* Open(const uint8_t* base, size_t size,
- const std::string& location, uint32_t location_checksum) {
+ const std::string& location,
+ uint32_t location_checksum) {
return OpenMemory(base, size, location, location_checksum, NULL);
}
@@ -826,7 +827,8 @@
MemMap* mem_map);
DexFile(const byte* base, size_t size,
- const std::string& location, uint32_t location_checksum,
+ const std::string& location,
+ uint32_t location_checksum,
MemMap* mem_map)
: begin_(base),
size_(size),
@@ -1115,12 +1117,13 @@
};
class ClassLinker;
+class ClassLoader;
class DexCache;
class Field;
class EncodedStaticFieldValueIterator {
public:
- EncodedStaticFieldValueIterator(const DexFile& dex_file, DexCache* dex_cache,
+ EncodedStaticFieldValueIterator(const DexFile& dex_file, DexCache* dex_cache, ClassLoader* class_loader,
ClassLinker* linker, const DexFile::ClassDef& class_def)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -1131,7 +1134,6 @@
void Next();
- private:
enum ValueType {
kByte = 0x00,
kShort = 0x02,
@@ -1151,19 +1153,22 @@
kBoolean = 0x1f
};
+ private:
static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
static const byte kEncodedValueArgShift = 5;
const DexFile& dex_file_;
DexCache* dex_cache_; // dex cache to resolve literal objects
+ ClassLoader* class_loader_; // ClassLoader to resolve types
ClassLinker* linker_; // linker to resolve literal objects
size_t array_size_; // size of array
size_t pos_; // current position
const byte* ptr_; // pointer into encoded data array
- byte type_; // type of current encoded value
+ ValueType type_; // type of current encoded value
jvalue jval_; // value of current encoded value
DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator);
};
+std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code);
class CatchHandlerIterator {
public:
diff --git a/src/gc/large_object_space.cc b/src/gc/large_object_space.cc
index 72c6c73..b066dd5 100644
--- a/src/gc/large_object_space.cc
+++ b/src/gc/large_object_space.cc
@@ -267,4 +267,10 @@
return reinterpret_cast<Object*>(addr);
}
+void FreeListSpace::Dump(std::ostream& os) const{
+ os << GetName() << " -"
+ << " begin: " << reinterpret_cast<void*>(Begin())
+ << " end: " << reinterpret_cast<void*>(End());
+}
+
}
diff --git a/src/gc/large_object_space.h b/src/gc/large_object_space.h
index 2bf6abf..979fce6 100644
--- a/src/gc/large_object_space.h
+++ b/src/gc/large_object_space.h
@@ -131,6 +131,9 @@
size_t Size() const {
return End() - Begin();
}
+
+ virtual void Dump(std::ostream& os) const;
+
private:
static const size_t kAlignment = kPageSize;
diff --git a/src/gc/mark_sweep.cc b/src/gc/mark_sweep.cc
index 03bbb6a..980eed1 100644
--- a/src/gc/mark_sweep.cc
+++ b/src/gc/mark_sweep.cc
@@ -79,6 +79,8 @@
FindDefaultMarkBitmap();
// TODO: if concurrent, enable card marking in compiler
// TODO: check that the mark bitmap is entirely clear.
+ // Mark any concurrent roots as dirty since we need to scan them at least once during this GC.
+ Runtime::Current()->DirtyRoots();
}
void MarkSweep::FindDefaultMarkBitmap() {
@@ -177,9 +179,9 @@
void MarkSweep::VerifyRoot(const Object* root, size_t vreg, const AbstractMethod* method) {
// See if the root is on any space bitmap.
- if (heap_->FindSpaceFromObject(root) == NULL) {
+ if (GetHeap()->GetLiveBitmap()->GetSpaceBitmap(root) == NULL) {
LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
- if (large_object_space->Contains(root)) {
+ if (!large_object_space->Contains(root)) {
LOG(ERROR) << "Found invalid root: " << root;
LOG(ERROR) << "VReg / Shadow frame offset: " << vreg;
if (method != NULL) {
@@ -195,7 +197,11 @@
// Marks all objects in the root set.
void MarkSweep::MarkRoots() {
- Runtime::Current()->VisitRoots(MarkObjectVisitor, this);
+ Runtime::Current()->VisitNonConcurrentRoots(MarkObjectVisitor, this);
+}
+
+void MarkSweep::MarkConcurrentRoots() {
+ Runtime::Current()->VisitConcurrentRoots(MarkObjectVisitor, this);
}
class CheckObjectVisitor {
diff --git a/src/gc/mark_sweep.h b/src/gc/mark_sweep.h
index 76c5428..ed74f99 100644
--- a/src/gc/mark_sweep.h
+++ b/src/gc/mark_sweep.h
@@ -52,6 +52,9 @@
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void MarkConcurrentRoots();
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+
// Verify that image roots point to only marked objects within the alloc space.
void VerifyImageRoots() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
diff --git a/src/gc/space.cc b/src/gc/space.cc
index 4d5ce93..a7a5942 100644
--- a/src/gc/space.cc
+++ b/src/gc/space.cc
@@ -434,7 +434,6 @@
new_size = current_space_size;
}
mspace_set_footprint_limit(mspace_, new_size);
- LOG(INFO) << "Setting footprint limit to " << new_size;
}
size_t ImageSpace::bitmap_index_ = 0;
diff --git a/src/heap.cc b/src/heap.cc
index 98845d8..584c5b2 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -517,8 +517,7 @@
#if VERIFY_OBJECT_ENABLED
void Heap::VerifyObject(const Object* obj) {
- if (obj == NULL || this == NULL || !verify_objects_ || Runtime::Current()->IsShuttingDown() ||
- Thread::Current() == NULL ||
+ if (obj == NULL || this == NULL || !verify_objects_ || Thread::Current() == NULL ||
Runtime::Current()->GetThreadList()->GetLockOwner() == Thread::Current()->GetTid()) {
return;
}
@@ -536,7 +535,9 @@
<< live_bitmap << " " << *live_bitmap << "\n"
<< mark_bitmap << " " << *mark_bitmap;
}
- // TODO: Dump large object space?
+ if (large_object_space_.get() != NULL) {
+ large_object_space_->Dump(LOG(INFO));
+ }
}
void Heap::VerifyObjectBody(const Object* obj) {
@@ -1045,6 +1046,7 @@
mark_sweep.FindDefaultMarkBitmap();
mark_sweep.MarkRoots();
+ mark_sweep.MarkConcurrentRoots();
timings.AddSplit("MarkRoots");
// Roots are marked on the bitmap and the mark_stack is empty.
@@ -1458,9 +1460,13 @@
if (space->GetGcRetentionPolicy() == kGcRetentionPolicyAlwaysCollect ||
(gc_type == kGcTypeFull &&
space->GetGcRetentionPolicy() == kGcRetentionPolicyFullCollect)) {
- live_bitmap_->ReplaceBitmap(space->GetLiveBitmap(), space->GetMarkBitmap());
- mark_bitmap_->ReplaceBitmap(space->GetMarkBitmap(), space->GetLiveBitmap());
- space->AsAllocSpace()->SwapBitmaps();
+ SpaceBitmap* live_bitmap = space->GetLiveBitmap();
+ SpaceBitmap* mark_bitmap = space->GetMarkBitmap();
+ if (live_bitmap != mark_bitmap) {
+ live_bitmap_->ReplaceBitmap(live_bitmap, mark_bitmap);
+ mark_bitmap_->ReplaceBitmap(mark_bitmap, live_bitmap);
+ space->AsAllocSpace()->SwapBitmaps();
+ }
}
}
SwapLargeObjects();
@@ -1615,6 +1621,10 @@
root_end = NanoTime();
timings.AddSplit("RootEnd");
+ // Mark the roots which we can do concurrently.
+ mark_sweep.MarkConcurrentRoots();
+ timings.AddSplit("MarkConcurrentRoots");
+
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
UpdateAndMarkModUnion(&mark_sweep, timings, gc_type);
@@ -1695,11 +1705,12 @@
if (verify_post_gc_heap_) {
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
- SwapBitmaps(gc_type);
+ // Swapping bound bitmaps does nothing.
+ SwapBitmaps(kGcTypeFull);
if (!VerifyHeapReferences()) {
LOG(FATAL) << "Post " << gc_type_str.str() << "Gc verification failed";
}
- SwapBitmaps(gc_type);
+ SwapBitmaps(kGcTypeFull);
timings.AddSplit("VerifyHeapReferencesPostGC");
}
@@ -2029,8 +2040,7 @@
}
}
-void Heap::Trim(Thread* self) {
- WaitForConcurrentGcToComplete(self);
+void Heap::Trim() {
alloc_space_->Trim();
}
diff --git a/src/heap.h b/src/heap.h
index 14d8382..984a329 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -278,7 +278,7 @@
void DumpForSigQuit(std::ostream& os);
- void Trim(Thread* self);
+ void Trim();
HeapBitmap* GetLiveBitmap() SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
return live_bitmap_.get();
diff --git a/src/image.h b/src/image.h
index 399b143..852367d 100644
--- a/src/image.h
+++ b/src/image.h
@@ -71,6 +71,10 @@
return oat_checksum_;
}
+ void SetOatChecksum(uint32_t oat_checksum) {
+ oat_checksum_ = oat_checksum;
+ }
+
byte* GetOatBegin() const {
return reinterpret_cast<byte*>(oat_begin_);
}
diff --git a/src/image_test.cc b/src/image_test.cc
index 05ddc54..afccb4a 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -36,7 +36,7 @@
ScopedObjectAccess soa(Thread::Current());
std::vector<const DexFile*> dex_files;
dex_files.push_back(java_lang_dex_file_);
- bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, 0, "", *compiler_.get());
+ bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, 0, 0, "", *compiler_.get());
ASSERT_TRUE(success_oat);
// Force all system classes into memory
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 56dfa5e..497ca22 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -676,6 +676,10 @@
AbstractMethod* target = GetTargetMethod(patch);
SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target)));
}
+
+ // Update the image header with the new checksum after patching
+ ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
+ image_header->SetOatChecksum(oat_file_->GetOatHeader().GetChecksum());
}
void ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value) {
@@ -683,6 +687,7 @@
AbstractMethod* method = GetReferrerMethod(patch);
// Goodbye const, we are about to modify some code.
void* code = const_cast<void*>(class_linker->GetOatCodeFor(method));
+ OatHeader& oat_header = const_cast<OatHeader&>(oat_file_->GetOatHeader());
// TODO: make this Thumb2 specific
uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(code) & ~0x1);
uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset());
@@ -696,6 +701,7 @@
<< "value=" << value;
#endif
*patch_location = value;
+ oat_header.UpdateChecksum(patch_location, sizeof(value));
}
} // namespace art
diff --git a/src/intern_table.cc b/src/intern_table.cc
index 5ad3958..817ce1e 100644
--- a/src/intern_table.cc
+++ b/src/intern_table.cc
@@ -21,7 +21,7 @@
namespace art {
-InternTable::InternTable() : intern_table_lock_("InternTable lock") {
+InternTable::InternTable() : intern_table_lock_("InternTable lock"), is_dirty_(false) {
}
size_t InternTable::Size() const {
@@ -36,12 +36,13 @@
<< image_strong_interns_.size() << " image strong\n";
}
-void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
+void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
MutexLock mu(Thread::Current(), intern_table_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) {
visitor(it->second, arg);
}
+ is_dirty_ = false;
// Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
}
@@ -97,6 +98,9 @@
return image;
}
+ // Mark as dirty so that we rescan the roots.
+ Dirty();
+
// There is no match in the strong table, check the weak table.
String* weak = Lookup(weak_interns_, s, hash_code);
if (weak != NULL) {
diff --git a/src/intern_table.h b/src/intern_table.h
index 6f56773..93d20b2 100644
--- a/src/intern_table.h
+++ b/src/intern_table.h
@@ -65,10 +65,15 @@
size_t Size() const;
- void VisitRoots(Heap::RootVisitor* visitor, void* arg) const;
+ void VisitRoots(Heap::RootVisitor* visitor, void* arg);
void DumpForSigQuit(std::ostream& os) const;
+ bool IsDirty() const { return is_dirty_; }
+ void Dirty() {
+ is_dirty_ = true;
+ }
+
private:
typedef std::multimap<int32_t, String*> Table;
@@ -81,6 +86,7 @@
void Remove(Table& table, const String* s, uint32_t hash_code);
mutable Mutex intern_table_lock_;
+ bool is_dirty_;
Table image_strong_interns_ GUARDED_BY(intern_table_lock_);
Table strong_interns_ GUARDED_BY(intern_table_lock_);
Table weak_interns_ GUARDED_BY(intern_table_lock_);
diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index 3ef5e5c..a55d7f1 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -244,10 +244,18 @@
if ((*cur)->IsImageSpace()) {
// TODO: Ensure this works with multiple image spaces.
const ImageHeader& image_header = (*cur)->AsImageSpace()->GetImageHeader();
- if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+ if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
ScopedObjectAccess soa(env);
LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
- << " has out-of-date checksum compared to "
+ << " has out-of-date oat checksum compared to "
+ << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8();
+ return JNI_TRUE;
+ }
+ if (oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+ != reinterpret_cast<uint32_t>(image_header.GetOatBegin())) {
+ ScopedObjectAccess soa(env);
+ LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
+ << " has out-of-date oat begin compared to "
<< image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8();
return JNI_TRUE;
}
diff --git a/src/native/dalvik_system_VMRuntime.cc b/src/native/dalvik_system_VMRuntime.cc
index b98f974..9c40041 100644
--- a/src/native/dalvik_system_VMRuntime.cc
+++ b/src/native/dalvik_system_VMRuntime.cc
@@ -156,15 +156,14 @@
}
}
-static void VMRuntime_trimHeap(JNIEnv* env, jobject) {
+static void VMRuntime_trimHeap(JNIEnv*, jobject) {
// Trim the managed heap.
Heap* heap = Runtime::Current()->GetHeap();
uint64_t start_ns = NanoTime();
DlMallocSpace* alloc_space = heap->GetAllocSpace();
size_t alloc_space_size = alloc_space->Size();
float utilization = static_cast<float>(alloc_space->GetNumBytesAllocated()) / alloc_space_size;
- Thread* self = static_cast<JNIEnvExt*>(env)->self;
- heap->Trim(self);
+ heap->Trim();
// Trim the native heap.
dlmalloc_trim(0);
dlmalloc_inspect_all(MspaceMadviseCallback, NULL);
diff --git a/src/native/dalvik_system_Zygote.cc b/src/native/dalvik_system_Zygote.cc
index 68ae7db..8b14117e 100644
--- a/src/native/dalvik_system_Zygote.cc
+++ b/src/native/dalvik_system_Zygote.cc
@@ -36,9 +36,7 @@
#include <sys/prctl.h>
#endif
-#if defined(HAVE_SELINUX)
#include <selinux/android.h>
-#endif
#if defined(__linux__)
#include <sys/personality.h>
@@ -340,6 +338,9 @@
#if defined(__linux__)
static bool NeedsNoRandomizeWorkaround() {
+#if !defined(__arm__)
+ return false;
+#else
int major;
int minor;
struct utsname uts;
@@ -353,6 +354,7 @@
// Kernels before 3.4.* need the workaround.
return (major < 3) || ((major == 3) && (minor < 4));
+#endif
}
#endif
@@ -416,17 +418,27 @@
SetSchedulerPolicy();
-#if defined(HAVE_SELINUX) && defined(HAVE_ANDROID_OS)
+#if defined(HAVE_ANDROID_OS)
{
- ScopedUtfChars se_info(env, java_se_info);
- CHECK(se_info != NULL);
- ScopedUtfChars se_name(env, java_se_name);
- CHECK(se_name != NULL);
- rc = selinux_android_setcontext(uid, is_system_server, se_info, se_name);
+ const char* se_info_c_str = NULL;
+ UniquePtr<ScopedUtfChars> se_info;
+ if (java_se_info != NULL) {
+ se_info.reset(new ScopedUtfChars(env, java_se_info));
+ se_info_c_str = se_info->c_str();
+ CHECK(se_info_c_str != NULL);
+ }
+ const char* se_name_c_str = NULL;
+ UniquePtr<ScopedUtfChars> se_name;
+ if (java_se_name != NULL) {
+ se_name.reset(new ScopedUtfChars(env, java_se_name));
+ se_name_c_str = se_name->c_str();
+ CHECK(se_name_c_str != NULL);
+ }
+ rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
if (rc == -1) {
PLOG(FATAL) << "selinux_android_setcontext(" << uid << ", "
<< (is_system_server ? "true" : "false") << ", "
- << "\"" << se_info << "\", \"" << se_name << "\") failed";
+ << "\"" << se_info_c_str << "\", \"" << se_name_c_str << "\") failed";
}
}
#else
diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc
index a6ae49d..bcea373 100644
--- a/src/native/java_lang_Object.cc
+++ b/src/native/java_lang_Object.cc
@@ -45,7 +45,7 @@
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Object, internalClone, "(Ljava/lang/Cloneable;)Ljava/lang/Object;"),
+ NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;"),
NATIVE_METHOD(Object, notify, "()V"),
NATIVE_METHOD(Object, notifyAll, "()V"),
NATIVE_METHOD(Object, wait, "(JI)V"),
diff --git a/src/oat.cc b/src/oat.cc
index 4df4543..a328a11 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -21,7 +21,7 @@
namespace art {
const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '0', '2', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '0', '3', '\0' };
OatHeader::OatHeader() {
memset(this, 0, sizeof(*this));
@@ -29,21 +29,27 @@
OatHeader::OatHeader(InstructionSet instruction_set,
const std::vector<const DexFile*>* dex_files,
- uint32_t image_file_location_checksum,
+ uint32_t image_file_location_oat_checksum,
+ uint32_t image_file_location_oat_begin,
const std::string& image_file_location) {
memcpy(magic_, kOatMagic, sizeof(kOatMagic));
memcpy(version_, kOatVersion, sizeof(kOatVersion));
adler32_checksum_ = adler32(0L, Z_NULL, 0);
+ CHECK_NE(instruction_set, kNone);
instruction_set_ = instruction_set;
UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
dex_file_count_ = dex_files->size();
UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
- image_file_location_checksum_ = image_file_location_checksum;
- UpdateChecksum(&image_file_location_checksum_, sizeof(image_file_location_checksum_));
+ image_file_location_oat_checksum_ = image_file_location_oat_checksum;
+ UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
+
+ CHECK(IsAligned<kPageSize>(image_file_location_oat_begin));
+ image_file_location_oat_begin_ = image_file_location_oat_begin;
+ UpdateChecksum(&image_file_location_oat_begin_, sizeof(image_file_location_oat_begin_));
image_file_location_size_ = image_file_location.size();
UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_));
@@ -53,10 +59,10 @@
}
bool OatHeader::IsValid() const {
- if (memcmp(magic_, kOatMagic, sizeof(kOatMagic) != 0)) {
+ if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
return false;
}
- if (memcmp(version_, kOatVersion, sizeof(kOatVersion) != 0)) {
+ if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
return false;
}
return true;
@@ -95,9 +101,14 @@
return executable_offset_;
}
-uint32_t OatHeader::GetImageFileLocationChecksum() const {
+uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
CHECK(IsValid());
- return image_file_location_checksum_;
+ return image_file_location_oat_checksum_;
+}
+
+uint32_t OatHeader::GetImageFileLocationOatBegin() const {
+ CHECK(IsValid());
+ return image_file_location_oat_begin_;
}
uint32_t OatHeader::GetImageFileLocationSize() const {
diff --git a/src/oat.h b/src/oat.h
index cd3330b..96ed4c4 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -30,7 +30,8 @@
OatHeader();
OatHeader(InstructionSet instruction_set,
const std::vector<const DexFile*>* dex_files,
- uint32_t image_file_location_checksum,
+ uint32_t image_file_location_oat_checksum,
+ uint32_t image_file_location_oat_begin,
const std::string& image_file_location);
bool IsValid() const;
@@ -41,7 +42,8 @@
uint32_t GetExecutableOffset() const;
InstructionSet GetInstructionSet() const;
void SetExecutableOffset(uint32_t executable_offset);
- uint32_t GetImageFileLocationChecksum() const;
+ uint32_t GetImageFileLocationOatChecksum() const;
+ uint32_t GetImageFileLocationOatBegin() const;
uint32_t GetImageFileLocationSize() const;
const uint8_t* GetImageFileLocationData() const;
std::string GetImageFileLocation() const;
@@ -58,7 +60,8 @@
uint32_t dex_file_count_;
uint32_t executable_offset_;
- uint32_t image_file_location_checksum_;
+ uint32_t image_file_location_oat_checksum_;
+ uint32_t image_file_location_oat_begin_;
uint32_t image_file_location_size_;
uint8_t image_file_location_data_[0]; // note variable width data at end
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 334ca95..458933f 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -84,6 +84,9 @@
extern int32_t CmplDouble(double a, double b);
extern int32_t CmpgFloat(float a, float b);
extern int32_t CmplFloat(float a, float b);
+extern "C" int64_t artLmulFromCode(int64_t a, int64_t b);
+extern "C" int64_t artLdivFromCode(int64_t a, int64_t b);
+extern "C" int64_t artLdivmodFromCode(int64_t a, int64_t b);
// Math conversions.
extern "C" float __floatsisf(int op1); // INT_TO_FLOAT
@@ -233,9 +236,9 @@
points->pIdivmod = NULL;
points->pD2l = art_d2l;
points->pF2l = art_f2l;
- points->pLdiv = NULL;
- points->pLdivmod = NULL;
- points->pLmul = NULL;
+ points->pLdiv = artLdivFromCode;
+ points->pLdivmod = artLdivmodFromCode;
+ points->pLmul = artLmulFromCode;
points->pShlLong = art_shl_long;
points->pShrLong = art_shr_long;
points->pUshrLong = art_ushr_long;
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index cbf895a..eafd380 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -53,30 +53,32 @@
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kRefsOnly). Restoration assumes non-moving GC.
* Does not include rSUSPEND or rSELF
- * callee-save: $s2-$s8 + $ra, 8 total + 4 words
+ * callee-save: $s2-$s8 + $ra, 8 total + 4 words + extra args + gp
*/
.macro SETUP_REF_ONLY_CALLEE_SAVE_FRAME
- addiu $sp, $sp, -48
- sw $ra, 44($sp)
- sw $s8, 40($sp)
- sw $s7, 36($sp)
- sw $s6, 32($sp)
- sw $s5, 28($sp)
- sw $s4, 24($sp)
- sw $s3, 20($sp)
- sw $s2, 16($sp)
- # 4 open words for args $a0-$a3, bottom will hold Method*
+ addiu $sp, $sp, -64
+ sw $ra, 60($sp)
+ sw $s8, 56($sp)
+ sw $s7, 52($sp)
+ sw $s6, 48($sp)
+ sw $s5, 44($sp)
+ sw $s4, 40($sp)
+ sw $s3, 36($sp)
+ sw $s2, 32($sp)
+ sw $gp, 28($sp)
+ # 3 words for alignment and extra args, 4 open words for args $a0-$a3, bottom will hold Method*
.endm
.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
- lw $ra, 44($sp)
- addiu $sp, $sp, 48
+ lw $gp, 28($sp)
+ lw $ra, 60($sp)
+ addiu $sp, $sp, 64
.endm
.macro RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
- lw $ra, 44($sp)
+ lw $ra, 60($sp)
jr $ra
- addiu $sp, $sp, 48
+ addiu $sp, $sp, 64
.endm
/*
@@ -304,9 +306,9 @@
art_throw_stack_overflow_from_code:
.cpload $25
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
- move $a1, rSELF # pass Thread::Current
- jal artThrowStackOverflowFromCode # artThrowStackOverflowFromCode(method, Thread*, $sp)
- move $a2, $sp # pass $sp
+ move $a0, rSELF # pass Thread::Current
+ jal artThrowStackOverflowFromCode # artThrowStackOverflowFromCode(Thread*, $sp)
+ move $a1, $sp # pass $sp
.global art_throw_no_such_method_from_code
.extern artThrowNoSuchMethodFromCode
@@ -409,13 +411,7 @@
move $a2, rSELF # pass Thread::Current
jal artHandleFillArrayDataFromCode # (Array*, const DexFile::Payload*, Thread*, $sp)
move $a3, $sp # pass $sp
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
- bnez $v0, 1f # success?
- nop
- jr $ra # return on success
- nop
-1:
- DELIVER_PENDING_EXCEPTION
+ RETURN_IF_ZERO
.global art_lock_object_from_code
.extern artLockObjectFromCode
@@ -531,7 +527,7 @@
art_get32_static_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a1, 48($sp) # pass referrer's Method*
+ lw $a1, 64($sp) # pass referrer's Method*
move $a2, rSELF # pass Thread::Current
jal artGet32StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
move $a3, $sp # pass $sp
@@ -546,7 +542,7 @@
art_get64_static_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a1, 48($sp) # pass referrer's Method*
+ lw $a1, 64($sp) # pass referrer's Method*
move $a2, rSELF # pass Thread::Current
jal artGet64StaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
move $a3, $sp # pass $sp
@@ -561,7 +557,7 @@
art_get_obj_static_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a1, 48($sp) # pass referrer's Method*
+ lw $a1, 64($sp) # pass referrer's Method*
move $a2, rSELF # pass Thread::Current
jal artGetObjStaticFromCode # (uint32_t field_idx, const Method* referrer, Thread*, $sp)
move $a3, $sp # pass $sp
@@ -576,13 +572,10 @@
art_get32_instance_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a2, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a2, 64($sp) # pass referrer's Method*
move $a3, rSELF # pass Thread::Current
jal artGet32InstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp)
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_NO_EXCEPTION
.global art_get64_instance_from_code
@@ -594,13 +587,10 @@
art_get64_instance_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a2, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a2, 64($sp) # pass referrer's Method*
move $a3, rSELF # pass Thread::Current
jal artGet64InstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp)
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_NO_EXCEPTION
.global art_get_obj_instance_from_code
@@ -612,13 +602,10 @@
art_get_obj_instance_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a2, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a2, 64($sp) # pass referrer's Method*
move $a3, rSELF # pass Thread::Current
jal artGetObjInstanceFromCode # (field_idx, Object*, referrer, Thread*, $sp)
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_NO_EXCEPTION
.global art_set32_static_from_code
@@ -630,13 +617,10 @@
art_set32_static_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a2, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a2, 64($sp) # pass referrer's Method*
move $a3, rSELF # pass Thread::Current
jal artSet32StaticFromCode # (field_idx, new_val, referrer, Thread*, $sp)
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_ZERO
.global art_set64_static_from_code
@@ -648,13 +632,10 @@
art_set64_static_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a1, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a1, 64($sp) # pass referrer's Method*
sw rSELF, 16($sp) # pass Thread::Current
jal artSet64StaticFromCode # (field_idx, referrer, new_val, Thread*, $sp)
- sw $t0, 20($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
.global art_set_obj_static_from_code
@@ -666,13 +647,10 @@
art_set_obj_static_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a2, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a2, 64($sp) # pass referrer's Method*
move $a3, rSELF # pass Thread::Current
jal artSetObjStaticFromCode # (field_idx, new_val, referrer, Thread*, $sp)
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_ZERO
.global art_set32_instance_from_code
@@ -684,13 +662,10 @@
art_set32_instance_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a3, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a3, 64($sp) # pass referrer's Method*
sw rSELF, 16($sp) # pass Thread::Current
jal artSet32InstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*, $sp)
- sw $t0, 20($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
.global art_set64_instance_from_code
@@ -702,12 +677,9 @@
art_set64_instance_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
sw rSELF, 16($sp) # pass Thread::Current
jal artSet64InstanceFromCode # (field_idx, Object*, new_val, Thread*, $sp)
- sw $t0, 20($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
.global art_set_obj_instance_from_code
@@ -719,13 +691,10 @@
art_set_obj_instance_from_code:
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
- lw $a3, 48($sp) # pass referrer's Method*
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
+ lw $a3, 64($sp) # pass referrer's Method*
sw rSELF, 16($sp) # pass Thread::Current
jal artSetObjInstanceFromCode # (field_idx, Object*, new_val, referrer, Thread*, $sp)
- sw $t0, 20($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 20($sp) # pass $sp
RETURN_IF_ZERO
.global art_resolve_string_from_code
@@ -785,12 +754,9 @@
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
# artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, Thread*, $sp)
jal artAllocArrayFromCode
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
.global art_alloc_array_from_code_with_access_check
@@ -804,12 +770,9 @@
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
# artAllocArrayFromCodeWithAccessCheck(type_idx, method, component_count, Thread*, $sp)
jal artAllocArrayFromCodeWithAccessCheck
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
.global art_check_and_alloc_array_from_code
@@ -822,12 +785,9 @@
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
# artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t count, Thread* , $sp)
jal artCheckAndAllocArrayFromCode
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
.global art_check_and_alloc_array_from_code_with_access_check
@@ -840,12 +800,9 @@
.cpload $25
SETUP_REF_ONLY_CALLEE_SAVE_FRAME # save callee saves in case of GC
move $a3, rSELF # pass Thread::Current
- move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
# artCheckAndAllocArrayFromCodeWithAccessCheck(type_idx, method, count, Thread* , $sp)
jal artCheckAndAllocArrayFromCodeWithAccessCheck
- sw $t0, 16($sp) # pass $sp
- addiu $sp, $sp, 16 # release out args
+ sw $sp, 16($sp) # pass $sp
RETURN_IF_NONZERO
.global art_test_suspend
@@ -855,6 +812,7 @@
*/
ALIGN_FUNCTION_ENTRY
art_test_suspend:
+ .cpload $25
lh $a0, THREAD_FLAGS_OFFSET(rSELF)
bnez $a0, 1f
addi rSUSPEND, $zero, SUSPEND_CHECK_INTERVAL # reset rSUSPEND to SUSPEND_CHECK_INTERVAL
@@ -958,7 +916,7 @@
andi $a2, 0x20 # shift< shift & 0x20
movn $v1, $v0, $a2 # rhi<- rlo (if shift&0x20)
jr $ra
- movn $v0, $zero, $a2 # rlo<- 0 (if shift&0x20)
+ movn $v0, $zero, $a2 # rlo<- 0 (if shift&0x20)
.global art_shr_long
/*
@@ -999,9 +957,8 @@
/* ushr-long vAA, vBB, vCC */
ALIGN_FUNCTION_ENTRY
art_ushr_long:
- sra $v1, $a1, $a2 # rhi<- ahi >> (shift&31)
+ srl $v1, $a1, $a2 # rhi<- ahi >> (shift&31)
srl $v0, $a0, $a2 # rlo<- alo >> (shift&31)
- sra $a3, $a1, 31 # $a3<- sign(ah)
not $a0, $a2 # alo<- 31-shift (shift is 5b)
sll $a1, 1
sll $a1, $a0 # ahi<- ahi << (32-(shift&31))
@@ -1009,7 +966,7 @@
andi $a2, 0x20 # shift & 0x20
movn $v0, $v1, $a2 # rlo<- rhi (if shift&0x20)
jr $ra
- movn $v1, $a3, $a2 # rhi<- sign(ahi) (if shift&0x20)
+ movn $v1, $zero, $a2 # rhi<- 0 (if shift&0x20)
.global art_indexof
ALIGN_FUNCTION_ENTRY
diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc
index 9fd65c8..b04979b 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -126,15 +126,17 @@
UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
#if !defined(ART_USE_LLVM_COMPILER)
// Save callee saves and ready frame for exception delivery
- __ AddConstant(SP, SP, -48);
- __ StoreToOffset(kStoreWord, RA, SP, 44);
- __ StoreToOffset(kStoreWord, FP, SP, 40);
- __ StoreToOffset(kStoreWord, S7, SP, 36);
- __ StoreToOffset(kStoreWord, S6, SP, 32);
- __ StoreToOffset(kStoreWord, S5, SP, 28);
- __ StoreToOffset(kStoreWord, S4, SP, 24);
- __ StoreToOffset(kStoreWord, S3, SP, 20);
- __ StoreToOffset(kStoreWord, S2, SP, 16);
+ __ AddConstant(SP, SP, -64);
+ __ StoreToOffset(kStoreWord, RA, SP, 60);
+ __ StoreToOffset(kStoreWord, FP, SP, 56);
+ __ StoreToOffset(kStoreWord, S7, SP, 52);
+ __ StoreToOffset(kStoreWord, S6, SP, 48);
+ __ StoreToOffset(kStoreWord, S5, SP, 44);
+ __ StoreToOffset(kStoreWord, S4, SP, 40);
+ __ StoreToOffset(kStoreWord, S3, SP, 36);
+ __ StoreToOffset(kStoreWord, S2, SP, 32);
+ __ StoreToOffset(kStoreWord, S1, SP, 28);
+ __ StoreToOffset(kStoreWord, S0, SP, 24);
// A0 is the Method* already
__ Move(A1, S1); // Pass Thread::Current() in A1
@@ -191,7 +193,8 @@
Label no_native_code_found;
__ EmitBranch(V0, ZERO, &no_native_code_found, true);
- __ Jr(V0); // If V0 != 0 tail call method's code
+ __ Move(T9, V0); // Move result into T9
+ __ Jr(T9); // If result != 0, tail call method's code
__ Bind(&no_native_code_found, false);
__ Jr(RA); // Return to caller to handle exception
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 93ff7a6..1e9d820 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -49,7 +49,7 @@
bool writable) {
CHECK(!location.empty());
if (!IsValidOatFilename(location)) {
- LOG(WARNING) << "Attempting to open dex file with unknown extension '" << location << "'";
+ LOG(WARNING) << "Attempting to open oat file with unknown extension '" << location << "'";
}
UniquePtr<OatFile> oat_file(new OatFile(location));
bool success = oat_file->Map(file, requested_base, reloc, writable);
@@ -102,24 +102,27 @@
file.Fd(),
0));
if (map.get() == NULL) {
- LOG(WARNING) << "Failed to map oat file " << GetLocation();
+ LOG(WARNING) << "Failed to map oat file from " << file.name() << " for " << GetLocation();
return false;
}
CHECK(requested_base == 0 || requested_base == map->Begin())
- << GetLocation() << " " << reinterpret_cast<void*>(map->Begin());
- DCHECK_EQ(0, memcmp(&oat_header, map->Begin(), sizeof(OatHeader))) << GetLocation();
+ << file.name() << " for " << GetLocation() << " " << reinterpret_cast<void*>(map->Begin());
+ DCHECK_EQ(0, memcmp(&oat_header, map->Begin(), sizeof(OatHeader)))
+ << file.name() << " for " << GetLocation();
off_t code_offset = oat_header.GetExecutableOffset();
if (code_offset < file.Length()) {
byte* code_address = map->Begin() + code_offset;
size_t code_length = file.Length() - code_offset;
if (mprotect(code_address, code_length, prot | PROT_EXEC) != 0) {
- PLOG(ERROR) << "Failed to make oat code executable in " << GetLocation();
+ PLOG(ERROR) << "Failed to make oat code executable in "
+ << file.name() << " for " << GetLocation();
return false;
}
} else {
// its possible to have no code if all the methods were abstract, native, etc
- DCHECK_EQ(code_offset, RoundUp(file.Length(), kPageSize)) << GetLocation();
+ DCHECK_EQ(code_offset, RoundUp(file.Length(), kPageSize))
+ << file.name() << " for " << GetLocation();
}
const byte* oat = map->Begin();
@@ -132,37 +135,40 @@
<< "+" << sizeof(OatHeader)
<< "+" << oat_header.GetImageFileLocationSize()
<< "<=" << reinterpret_cast<void*>(map->End())
- << " " << GetLocation();
+ << " " << file.name() << " for " << GetLocation();
for (size_t i = 0; i < oat_header.GetDexFileCount(); i++) {
size_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
- CHECK_GT(dex_file_location_size, 0U) << GetLocation();
+ CHECK_GT(dex_file_location_size, 0U) << file.name() << " for " << GetLocation();
oat += sizeof(dex_file_location_size);
- CHECK_LT(oat, map->End()) << GetLocation();
+ CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
oat += dex_file_location_size;
- CHECK_LT(oat, map->End()) << GetLocation();
+ CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
std::string dex_file_location(dex_file_location_data, dex_file_location_size);
uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
oat += sizeof(dex_file_checksum);
- CHECK_LT(oat, map->End()) << GetLocation();
+ CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat);
- CHECK_GT(dex_file_offset, 0U) << GetLocation();
- CHECK_LT(dex_file_offset, static_cast<uint32_t>(file.Length())) << GetLocation();
+ CHECK_GT(dex_file_offset, 0U) << file.name() << " for " << GetLocation();
+ CHECK_LT(dex_file_offset, static_cast<uint32_t>(file.Length()))
+ << file.name() << " for " << GetLocation();
oat += sizeof(dex_file_offset);
- CHECK_LT(oat, map->End()) << GetLocation();
+ CHECK_LT(oat, map->End()) << file.name() << " for " << GetLocation();
uint8_t* dex_file_pointer = map->Begin() + dex_file_offset;
- CHECK(DexFile::IsMagicValid(dex_file_pointer)) << GetLocation() << " " << dex_file_pointer;
- CHECK(DexFile::IsVersionValid(dex_file_pointer)) << GetLocation() << " " << dex_file_pointer;
+ CHECK(DexFile::IsMagicValid(dex_file_pointer))
+ << file.name() << " for " << GetLocation() << " " << dex_file_pointer;
+ CHECK(DexFile::IsVersionValid(dex_file_pointer))
+ << file.name() << " for " << GetLocation() << " " << dex_file_pointer;
const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat);
oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
- CHECK_LE(oat, map->End()) << GetLocation();
+ CHECK_LE(oat, map->End()) << file.name() << " for " << GetLocation();
oat_dex_files_.Put(dex_file_location, new OatDexFile(this,
dex_file_location,
@@ -230,7 +236,8 @@
const DexFile* OatFile::OatDexFile::OpenDexFile() const {
size_t length = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
- return DexFile::Open(dex_file_pointer_, length, dex_file_location_, dex_file_location_checksum_);
+ return DexFile::Open(dex_file_pointer_, length, dex_file_location_,
+ dex_file_location_checksum_);
}
const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const {
diff --git a/src/oat_test.cc b/src/oat_test.cc
index ae4aae2..64c502d 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -75,6 +75,7 @@
class_loader,
class_linker->GetBootClassPath(),
42U,
+ 4096U,
"lue.art",
*compiler_.get());
ASSERT_TRUE(success);
@@ -88,8 +89,10 @@
OatFile::kRelocNone));
ASSERT_TRUE(oat_file.get() != NULL);
const OatHeader& oat_header = oat_file->GetOatHeader();
+ ASSERT_TRUE(oat_header.IsValid());
ASSERT_EQ(1U, oat_header.GetDexFileCount());
- ASSERT_EQ(42U, oat_header.GetImageFileLocationChecksum());
+ ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
+ ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatBegin());
ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());
const DexFile* dex_file = java_lang_dex_file_;
@@ -124,8 +127,33 @@
TEST_F(OatTest, OatHeaderSizeCheck) {
// If this test is failing and you have to update these constants,
// it is time to update OatHeader::kOatVersion
- EXPECT_EQ(32U, sizeof(OatHeader));
+ EXPECT_EQ(36U, sizeof(OatHeader));
+#if !defined(ART_USE_LLVM_COMPILER)
EXPECT_EQ(32U, sizeof(OatMethodOffsets));
+#else
+ // ART-LLVM has a extra 4 bytes field: proxy_stub_offset_
+ EXPECT_EQ(36U, sizeof(OatMethodOffsets));
+#endif
+}
+
+TEST_F(OatTest, OatHeaderIsValid) {
+ InstructionSet instruction_set = kX86;
+ std::vector<const DexFile*> dex_files;
+ uint32_t image_file_location_oat_checksum = 0;
+ uint32_t image_file_location_oat_begin = 0;
+ const std::string image_file_location;
+ OatHeader oat_header(instruction_set,
+ &dex_files,
+ image_file_location_oat_checksum,
+ image_file_location_oat_begin,
+ image_file_location);
+ ASSERT_TRUE(oat_header.IsValid());
+
+ char* magic = const_cast<char*>(oat_header.GetMagic());
+ strcpy(magic, ""); // bad magic
+ ASSERT_FALSE(oat_header.IsValid());
+ strcpy(magic, "oat\n000"); // bad version
+ ASSERT_FALSE(oat_header.IsValid());
}
} // namespace art
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 5e12299..e26e3cc 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -33,11 +33,13 @@
bool OatWriter::Create(File* file,
jobject class_loader,
const std::vector<const DexFile*>& dex_files,
- uint32_t image_file_location_checksum,
+ uint32_t image_file_location_oat_checksum,
+ uint32_t image_file_location_oat_begin,
const std::string& image_file_location,
const Compiler& compiler) {
OatWriter oat_writer(dex_files,
- image_file_location_checksum,
+ image_file_location_oat_checksum,
+ image_file_location_oat_begin,
image_file_location,
class_loader,
compiler);
@@ -45,13 +47,15 @@
}
OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
- uint32_t image_file_location_checksum,
+ uint32_t image_file_location_oat_checksum,
+ uint32_t image_file_location_oat_begin,
const std::string& image_file_location,
jobject class_loader,
const Compiler& compiler) {
compiler_ = &compiler;
class_loader_ = class_loader;
- image_file_location_checksum_ = image_file_location_checksum;
+ image_file_location_oat_checksum_ = image_file_location_oat_checksum;
+ image_file_location_oat_begin_ = image_file_location_oat_begin;
image_file_location_ = image_file_location;
dex_files_ = &dex_files;
oat_header_ = NULL;
@@ -77,7 +81,8 @@
// create the OatHeader
oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
dex_files_,
- image_file_location_checksum_,
+ image_file_location_oat_checksum_,
+ image_file_location_oat_begin_,
image_file_location_);
size_t offset = sizeof(*oat_header_);
offset += image_file_location_.size();
@@ -353,7 +358,7 @@
}
#if defined(ART_USE_LLVM_COMPILER)
- if (type == kStatic) {
+ if (type != kStatic) {
const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
if (compiled_proxy_stub != NULL) {
offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
@@ -733,7 +738,7 @@
}
#if defined(ART_USE_LLVM_COMPILER)
- if (is_static) {
+ if (!is_static) {
const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
if (compiled_proxy_stub != NULL) {
uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
diff --git a/src/oat_writer.h b/src/oat_writer.h
index fd8e2b2..09db96b 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -66,14 +66,16 @@
static bool Create(File* file,
jobject class_loader,
const std::vector<const DexFile*>& dex_files,
- uint32_t image_file_location_checksum,
+ uint32_t image_file_location_oat_checksum,
+ uint32_t image_file_location_oat_begin,
const std::string& image_file_location,
const Compiler& compiler)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
OatWriter(const std::vector<const DexFile*>& dex_files,
- uint32_t image_file_location_checksum,
+ uint32_t image_file_location_oat_checksum,
+ uint32_t image_file_location_oat_begin,
const std::string& image_file_location,
jobject class_loader,
const Compiler& compiler) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -156,8 +158,9 @@
// note OatFile does not take ownership of the DexFiles
const std::vector<const DexFile*>* dex_files_;
- // dependency on the image
- uint32_t image_file_location_checksum_;
+ // dependencies on the image.
+ uint32_t image_file_location_oat_checksum_;
+ uint32_t image_file_location_oat_begin_;
std::string image_file_location_;
// data to write
diff --git a/src/oatdump.cc b/src/oatdump.cc
index b4ba3df..6c7e2ef 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -48,7 +48,7 @@
"\n");
fprintf(stderr,
" --oat-file=<file.oat>: specifies an input oat filename.\n"
- " Example: --image=/system/framework/boot.oat\n"
+ " Example: --oat-file=/system/framework/boot.oat\n"
"\n");
fprintf(stderr,
" --image=<file.art>: specifies an input image filename.\n"
@@ -113,8 +113,11 @@
os << "EXECUTABLE OFFSET:\n";
os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
- os << "IMAGE FILE LOCATION CHECKSUM:\n";
- os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationChecksum());
+ os << "IMAGE FILE LOCATION OAT CHECKSUM:\n";
+ os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum());
+
+ os << "IMAGE FILE LOCATION OAT BEGIN:\n";
+ os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatBegin());
os << "IMAGE FILE LOCATION:\n";
const std::string image_file_location(oat_header.GetImageFileLocation());
diff --git a/src/runtime.cc b/src/runtime.cc
index f93d687..3a5c41c 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -993,10 +993,17 @@
thread_list_->Unregister(self);
}
-void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
+void Runtime::VisitConcurrentRoots(Heap::RootVisitor* visitor, void* arg) {
+ if (intern_table_->IsDirty()) {
+ intern_table_->VisitRoots(visitor, arg);
+ }
+ if (class_linker_->IsDirty()) {
+ class_linker_->VisitRoots(visitor, arg);
+ }
+}
+
+void Runtime::VisitNonConcurrentRoots(Heap::RootVisitor* visitor, void* arg) {
Dbg::VisitRoots(visitor, arg);
- class_linker_->VisitRoots(visitor, arg);
- intern_table_->VisitRoots(visitor, arg);
java_vm_->VisitRoots(visitor, arg);
thread_list_->VisitRoots(visitor, arg);
if (pre_allocated_OutOfMemoryError_ != NULL) {
@@ -1013,6 +1020,16 @@
}
}
+void Runtime::DirtyRoots() {
+ intern_table_->Dirty();
+ class_linker_->Dirty();
+}
+
+void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
+ VisitConcurrentRoots(visitor, arg);
+ VisitNonConcurrentRoots(visitor, arg);
+}
+
void Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) {
CHECK(jni_stub_array != NULL) << " jni_stub_array=" << jni_stub_array;
CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array)
@@ -1088,7 +1105,7 @@
uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
(type == kSaveAll ? all_spills : 0) | (1 << art::mips::RA);
size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
- (type == kRefsAndArgs ? 0 : 3) /* always reserve arg space */ +
+ (type == kRefsAndArgs ? 0 : 5) /* reserve arg space */ +
1 /* Method* */) * kPointerSize, kStackAlignment);
method->SetFrameSizeInBytes(frame_size);
method->SetCoreSpillMask(core_spills);
diff --git a/src/runtime.h b/src/runtime.h
index a6c662c..44823a0 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -224,9 +224,20 @@
return "2.0.0";
}
- void VisitRoots(Heap::RootVisitor* visitor, void* arg) const
+ // Force all the roots which can be marked concurrently to be dirty.
+ void DirtyRoots();
+
+ // Visit all the roots.
+ void VisitRoots(Heap::RootVisitor* visitor, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Visit all of the roots we can do safely do concurrently.
+ void VisitConcurrentRoots(Heap::RootVisitor* visitor, void* arg);
+
+ // Visit all other roots which must be done with mutators suspended.
+ void VisitNonConcurrentRoots(Heap::RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
bool HasJniDlsymLookupStub() const {
return jni_stub_array_ != NULL;
}
diff --git a/src/thread.cc b/src/thread.cc
index 6daeadf..cea919f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -2013,9 +2013,9 @@
void Thread::VerifyStack() {
UniquePtr<Context> context(Context::Create());
- RootCallbackVisitor visitorToCallback(visitor, arg);
+ RootCallbackVisitor visitorToCallback(VerifyObject, Runtime::Current()->GetHeap());
ReferenceMapVisitor<RootCallbackVisitor> mapper(GetManagedStack(), GetTraceStack(), context.get(),
- VerifyObject, Runtime::Current()->GetHeap());
+ visitorToCallback);
mapper.WalkStack();
}
#endif