diff options
Diffstat (limited to 'src')
43 files changed, 418 insertions, 238 deletions
diff --git a/src/check_jni.cc b/src/check_jni.cc index e7590d3b0b..7c5186adc1 100644 --- a/src/check_jni.cc +++ b/src/check_jni.cc @@ -208,6 +208,7 @@ class ScopedCheck { // 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 @@ class ScopedCheck { 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 @@ class ScopedCheck { 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 @@ class ScopedCheck { 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 @@ class ScopedCheck { } 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 @@ class ScopedCheck { } 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 @@ class ScopedCheck { 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 83661cbafc..a76c9c85d3 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -222,6 +222,7 @@ ClassLinker::ClassLinker(InternTable* intern_table) 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 @@ OatFile* ClassLinker::OpenOat(const ImageSpace* space) { 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 @@ static const DexFile* FindDexFileInOatLocation(const std::string& dex_location, } 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 @@ bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file, 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 @@ bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file, } 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 @@ bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file, 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 @@ void ClassLinker::InitFromImage() { 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 @@ void ClassLinker::InitFromImageCallback(Object* obj, void* arg) { // 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 @@ void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { } visitor(array_iftable_, arg); + is_dirty_ = false; } void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) const { @@ -1746,6 +1756,7 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<DexCach 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 @@ Class* ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass, boo return existing; } classes.insert(std::make_pair(hash, klass)); + Dirty(); return NULL; } @@ -2803,7 +2815,8 @@ bool ClassLinker::InitializeStaticFields(Class* klass) { 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 096d602558..f1530f3ec8 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -262,7 +262,7 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { IfTable* array_iftable_; bool init_done_; + bool is_dirty_; InternTable* intern_table_; diff --git a/src/compiler.cc b/src/compiler.cc index 1be7b75b3f..8d7f5b660d 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -839,9 +839,15 @@ void Compiler::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_t // 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 c1d46611a5..21f824dfd6 100644 --- a/src/compiler/codegen/GenCommon.cc +++ b/src/compiler/codegen/GenCommon.cc @@ -1321,6 +1321,10 @@ void genInstanceof(CompilationUnit* cUnit, uint32_t type_idx, RegLocation rlDest } } /* 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 @@ void genInstanceof(CompilationUnit* cUnit, uint32_t type_idx, RegLocation rlDest 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 @@ void genInstanceof(CompilationUnit* cUnit, uint32_t type_idx, RegLocation rlDest 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 @@ bool genArithOpInt(CompilationUnit* cUnit, Instruction::Code opcode, RegLocation 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 @@ bool genArithOpInt(CompilationUnit* cUnit, Instruction::Code opcode, RegLocation 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 f121a5434f..437f1ed2d8 100644 --- a/src/compiler/codegen/mips/FP/MipsFP.cc +++ b/src/compiler/codegen/mips/FP/MipsFP.cc @@ -197,11 +197,11 @@ static bool genCmpFP(CompilationUnit *cUnit, Instruction::Code opcode, RegLocati 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 5e5147a96b..5077c9fa40 100644 --- a/src/compiler/codegen/mips/MipsLIR.h +++ b/src/compiler/codegen/mips/MipsLIR.h @@ -141,6 +141,8 @@ namespace art { /* 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 8750c0bed2..484dd77e3a 100644 --- a/src/compiler_llvm/gbc_expander.cc +++ b/src/compiler_llvm/gbc_expander.cc @@ -60,7 +60,7 @@ class GBCExpanderPass : public llvm::FunctionPass { 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 @@ class GBCExpanderPass : public llvm::FunctionPass { 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 @@ class GBCExpanderPass : public llvm::FunctionPass { 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 @@ bool GBCExpanderPass::runOnFunction(llvm::Function& func) { // 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 @@ llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst, 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 @@ void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) { 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 872701d054..e118646a82 100644 --- a/src/compiler_llvm/generated/art_module.cc +++ b/src/compiler_llvm/generated/art_module.cc @@ -93,7 +93,8 @@ std::vector<Type*>FuncTy_7_args; 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 1737b70282..f91694efc8 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -3823,7 +3823,7 @@ void MethodCompiler::EmitPushShadowFrame(bool is_inline) { } 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 2effdddfa1..dbcbe89034 100644 --- a/src/compiler_llvm/runtime_support_builder.cc +++ b/src/compiler_llvm/runtime_support_builder.cc @@ -124,10 +124,16 @@ llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_ 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 b8123a55ca..ba512af66a 100644 --- a/src/compiler_llvm/runtime_support_builder.h +++ b/src/compiler_llvm/runtime_support_builder.h @@ -53,7 +53,7 @@ class RuntimeSupportBuilder { 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 d20d7ab1c5..20872e1aa4 100644 --- a/src/dex2oat.cc +++ b/src/dex2oat.cc @@ -253,11 +253,13 @@ class Dex2Oat { 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 @@ class Dex2Oat { 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 d918152dd4..c433f3dc48 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -901,10 +901,11 @@ static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right 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 @@ void EncodedStaticFieldValueIterator::Next() { 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 @@ void EncodedStaticFieldValueIterator::Next() { 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 @@ void EncodedStaticFieldValueIterator::ReadValueToField(Field* field) const { 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 cca3935722..58a0b3f2f7 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -347,7 +347,8 @@ class DexFile { // 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 @@ class DexFile { 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 ClassDataItemIterator { }; 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 @@ class EncodedStaticFieldValueIterator { void Next(); - private: enum ValueType { kByte = 0x00, kShort = 0x02, @@ -1151,19 +1153,22 @@ class EncodedStaticFieldValueIterator { 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 72c6c733dc..b066dd593d 100644 --- a/src/gc/large_object_space.cc +++ b/src/gc/large_object_space.cc @@ -267,4 +267,10 @@ Object* FreeListSpace::Alloc(Thread* self, size_t num_bytes) { 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 2bf6abf95a..979fce6078 100644 --- a/src/gc/large_object_space.h +++ b/src/gc/large_object_space.h @@ -131,6 +131,9 @@ class FreeListSpace : public LargeObjectSpace { 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 03bbb6abcb..980eed1d67 100644 --- a/src/gc/mark_sweep.cc +++ b/src/gc/mark_sweep.cc @@ -79,6 +79,8 @@ void MarkSweep::Init() { 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::VerifyRootCallback(const Object* root, void* arg, size_t vreg, 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 @@ void MarkSweep::VerifyRoots() { // 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 76c5428299..ed74f993fc 100644 --- a/src/gc/mark_sweep.h +++ b/src/gc/mark_sweep.h @@ -52,6 +52,9 @@ class MarkSweep { 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 4d5ce933ae..a7a5942804 100644 --- a/src/gc/space.cc +++ b/src/gc/space.cc @@ -434,7 +434,6 @@ void DlMallocSpace::SetFootprintLimit(size_t new_size) { 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 98845d8b92..584c5b2e69 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -517,8 +517,7 @@ bool Heap::IsLiveObjectLocked(const Object* obj) { #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 @@ void Heap::DumpSpaces() { << 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 @@ void Heap::CollectGarbageMarkSweepPlan(Thread* self, GcType gc_type, GcCause gc_ 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 @@ void Heap::SwapBitmaps(GcType gc_type) { 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 @@ void Heap::CollectGarbageConcurrentMarkSweepPlan(Thread* self, GcType gc_type, G 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 @@ void Heap::CollectGarbageConcurrentMarkSweepPlan(Thread* self, GcType gc_type, G 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::ConcurrentGC(Thread* self) { } } -void Heap::Trim(Thread* self) { - WaitForConcurrentGcToComplete(self); +void Heap::Trim() { alloc_space_->Trim(); } diff --git a/src/heap.h b/src/heap.h index 14d8382226..984a3296b2 100644 --- a/src/heap.h +++ b/src/heap.h @@ -278,7 +278,7 @@ class Heap { 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 399b1439d2..852367d1b6 100644 --- a/src/image.h +++ b/src/image.h @@ -71,6 +71,10 @@ class PACKED ImageHeader { 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 05ddc54193..afccb4acc0 100644 --- a/src/image_test.cc +++ b/src/image_test.cc @@ -36,7 +36,7 @@ TEST_F(ImageTest, WriteRead) { 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 56dfa5eeb7..497ca2200e 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -676,6 +676,10 @@ void ImageWriter::PatchOatCodeAndMethods(const Compiler& compiler) { 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 @@ void ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint 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 @@ void ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint << "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 5ad39582b8..817ce1e5e1 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 @@ void InternTable::DumpForSigQuit(std::ostream& os) const { << 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 @@ String* InternTable::Insert(String* s, bool is_strong) { 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 6f5677385f..93d20b2e2b 100644 --- a/src/intern_table.h +++ b/src/intern_table.h @@ -65,10 +65,15 @@ class InternTable { 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 @@ class InternTable { 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 3ef5e5c540..a55d7f1793 100644 --- a/src/native/dalvik_system_DexFile.cc +++ b/src/native/dalvik_system_DexFile.cc @@ -244,10 +244,18 @@ static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename 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 b98f974f12..9c400418db 100644 --- a/src/native/dalvik_system_VMRuntime.cc +++ b/src/native/dalvik_system_VMRuntime.cc @@ -156,15 +156,14 @@ static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVe } } -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 68ae7db76d..8b14117e83 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 @@ static void MountExternalStorage(uid_t uid, jint mount_external) { #if defined(__linux__) static bool NeedsNoRandomizeWorkaround() { +#if !defined(__arm__) + return false; +#else int major; int minor; struct utsname uts; @@ -353,6 +354,7 @@ static bool NeedsNoRandomizeWorkaround() { // Kernels before 3.4.* need the workaround. return (major < 3) || ((major == 3) && (minor < 4)); +#endif } #endif @@ -416,17 +418,27 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra 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/oat.cc b/src/oat.cc index 4df4543f3f..a328a1149b 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() { 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 @@ OatHeader::OatHeader(InstructionSet instruction_set, } 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 @@ uint32_t OatHeader::GetExecutableOffset() const { return executable_offset_; } -uint32_t OatHeader::GetImageFileLocationChecksum() const { +uint32_t OatHeader::GetImageFileLocationOatChecksum() const { + CHECK(IsValid()); + return image_file_location_oat_checksum_; +} + +uint32_t OatHeader::GetImageFileLocationOatBegin() const { CHECK(IsValid()); - return image_file_location_checksum_; + return image_file_location_oat_begin_; } uint32_t OatHeader::GetImageFileLocationSize() const { @@ -30,7 +30,8 @@ class PACKED OatHeader { 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 @@ class PACKED OatHeader { 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 @@ class PACKED OatHeader { 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 334ca9585d..458933fc3e 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 CmpgDouble(double a, double b); 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 @@ void InitEntryPoints(EntryPoints* points) { 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 cbf895a641..eafd380996 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_array_bounds_from_code: 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 @@ art_handle_fill_data_from_code: 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_initialize_type_and_verify_access_from_code: 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_get32_static_from_code: 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_get64_static_from_code: 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_get_obj_static_from_code: 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_get32_instance_from_code: 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_get64_instance_from_code: 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_get_obj_instance_from_code: 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_set32_static_from_code: 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_set64_static_from_code: 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_set_obj_static_from_code: 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_set32_instance_from_code: 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_set64_instance_from_code: 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 @@ art_alloc_array_from_code: .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 @@ art_alloc_array_from_code_with_access_check: .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 @@ art_check_and_alloc_array_from_code: .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 @@ art_check_and_alloc_array_from_code_with_access_check: .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 @@ art_check_and_alloc_array_from_code_with_access_check: */ 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 @@ art_shl_long: 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 @@ art_shr_long: /* 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 @@ art_ushr_long: 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 9fd65c89a4..b04979b2db 100644 --- a/src/oat/runtime/mips/stub_mips.cc +++ b/src/oat/runtime/mips/stub_mips.cc @@ -126,15 +126,17 @@ ByteArray* CreateAbstractMethodErrorStub() { 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 @@ ByteArray* CreateJniDlsymLookupStub() { 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 93ff7a65b7..1e9d820716 100644 --- a/src/oat_file.cc +++ b/src/oat_file.cc @@ -49,7 +49,7 @@ OatFile* OatFile::Open(File& file, 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 @@ bool OatFile::Map(File& file, 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 @@ bool OatFile::Map(File& file, << "+" << 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 @@ OatFile::OatDexFile::~OatDexFile() {} 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 ae4aae2a0f..64c502d39a 100644 --- a/src/oat_test.cc +++ b/src/oat_test.cc @@ -75,6 +75,7 @@ TEST_F(OatTest, WriteRead) { class_loader, class_linker->GetBootClassPath(), 42U, + 4096U, "lue.art", *compiler_.get()); ASSERT_TRUE(success); @@ -88,8 +89,10 @@ TEST_F(OatTest, WriteRead) { 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, WriteRead) { 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 5e12299afc..e26e3cc6ff 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -33,11 +33,13 @@ namespace art { 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 @@ bool OatWriter::Create(File* file, } 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 @@ size_t OatWriter::InitOatHeader() { // 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 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, } #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 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla } #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 fd8e2b2533..09db96b6c5 100644 --- a/src/oat_writer.h +++ b/src/oat_writer.h @@ -66,14 +66,16 @@ class OatWriter { 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 @@ class OatWriter { // 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 b4ba3dfbe4..6c7e2ef07c 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -48,7 +48,7 @@ static void usage() { "\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 @@ class OatDumper { 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 f93d687399..3a5c41ca08 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -993,10 +993,17 @@ void Runtime::DetachCurrentThread() { 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::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { } } +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 @@ AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, 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 a6c662cb45..44823a0d1b 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -224,9 +224,20 @@ class Runtime { 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 6daeadf602..cea919fb47 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -2013,9 +2013,9 @@ static void VerifyObject(const Object* obj, void* arg) { 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 |