diff options
| -rw-r--r-- | runtime/arch/arm/entrypoints_init_arm.cc | 2 | ||||
| -rw-r--r-- | runtime/arch/arm/quick_entrypoints_arm.S | 110 | ||||
| -rw-r--r-- | runtime/arch/arm64/entrypoints_init_arm64.cc | 2 | ||||
| -rw-r--r-- | runtime/arch/arm64/quick_entrypoints_arm64.S | 2 | ||||
| -rw-r--r-- | runtime/dex2oat_environment_test.h | 15 | ||||
| -rw-r--r-- | runtime/gc/space/image_space_fs.h | 9 | ||||
| -rw-r--r-- | runtime/oat_file_assistant.cc | 16 | ||||
| -rw-r--r-- | runtime/utils.cc | 46 | ||||
| -rw-r--r-- | runtime/utils.h | 7 | ||||
| -rw-r--r-- | runtime/utils_test.cc | 6 |
10 files changed, 89 insertions, 126 deletions
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc index 0e2a6720ae..492a12d02b 100644 --- a/runtime/arch/arm/entrypoints_init_arm.cc +++ b/runtime/arch/arm/entrypoints_init_arm.cc @@ -133,7 +133,7 @@ void InitEntryPoints(JniEntryPoints* jpoints, QuickEntryPoints* qpoints) { qpoints->pReadBarrierMarkReg09 = art_quick_read_barrier_mark_reg09; qpoints->pReadBarrierMarkReg10 = art_quick_read_barrier_mark_reg10; qpoints->pReadBarrierMarkReg11 = art_quick_read_barrier_mark_reg11; - qpoints->pReadBarrierMarkReg12 = art_quick_read_barrier_mark_reg12; + qpoints->pReadBarrierMarkReg12 = nullptr; // Cannot use register 12 (IP) to pass arguments. qpoints->pReadBarrierMarkReg13 = nullptr; // Cannot use register 13 (SP) to pass arguments. qpoints->pReadBarrierMarkReg14 = nullptr; // Cannot use register 14 (LR) to pass arguments. qpoints->pReadBarrierMarkReg15 = nullptr; // Cannot use register 15 (PC) to pass arguments. diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S index 3d0da8075d..c4ec72685f 100644 --- a/runtime/arch/arm/quick_entrypoints_arm.S +++ b/runtime/arch/arm/quick_entrypoints_arm.S @@ -1246,9 +1246,15 @@ ENTRY art_quick_alloc_object_region_tlab ldr r2, [r2, r0, lsl #COMPRESSED_REFERENCE_SIZE_SHIFT] // Read barrier for class load. ldr r3, [r9, #THREAD_IS_GC_MARKING_OFFSET] - cbnz r3, .Lart_quick_alloc_object_region_tlab_class_load_read_barrier_slow_path + cbnz r3, .Lart_quick_alloc_object_region_tlab_class_load_read_barrier_marking .Lart_quick_alloc_object_region_tlab_class_load_read_barrier_slow_path_exit: ALLOC_OBJECT_TLAB_FAST_PATH .Lart_quick_alloc_object_region_tlab_slow_path +.Lart_quick_alloc_object_region_tlab_class_load_read_barrier_marking: + cbz r2, .Lart_quick_alloc_object_region_tlab_slow_path // Null check for loading lock word. + // Check lock word for mark bit, if marked do the allocation. + ldr r3, [r2, MIRROR_OBJECT_LOCK_WORD_OFFSET] + ands r3, #LOCK_WORD_MARK_BIT_MASK_SHIFTED + bne .Lart_quick_alloc_object_region_tlab_class_load_read_barrier_slow_path_exit .Lart_quick_alloc_object_region_tlab_class_load_read_barrier_slow_path: // The read barrier slow path. Mark // the class. @@ -1817,6 +1823,39 @@ ENTRY art_quick_l2f pop {pc} END art_quick_l2f +.macro CONDITIONAL_CBZ reg, reg_if, dest +.ifc \reg, \reg_if + cbz \reg, \dest +.endif +.endm + +.macro CONDITIONAL_CMPBZ reg, reg_if, dest +.ifc \reg, \reg_if + cmp \reg, #0 + beq \dest +.endif +.endm + +// Use CBZ if the register is in {r0, r7} otherwise compare and branch. +.macro SMART_CBZ reg, dest + CONDITIONAL_CBZ \reg, r0, \dest + CONDITIONAL_CBZ \reg, r1, \dest + CONDITIONAL_CBZ \reg, r2, \dest + CONDITIONAL_CBZ \reg, r3, \dest + CONDITIONAL_CBZ \reg, r4, \dest + CONDITIONAL_CBZ \reg, r5, \dest + CONDITIONAL_CBZ \reg, r6, \dest + CONDITIONAL_CBZ \reg, r7, \dest + CONDITIONAL_CMPBZ \reg, r8, \dest + CONDITIONAL_CMPBZ \reg, r9, \dest + CONDITIONAL_CMPBZ \reg, r10, \dest + CONDITIONAL_CMPBZ \reg, r11, \dest + CONDITIONAL_CMPBZ \reg, r12, \dest + CONDITIONAL_CMPBZ \reg, r13, \dest + CONDITIONAL_CMPBZ \reg, r14, \dest + CONDITIONAL_CMPBZ \reg, r15, \dest +.endm + /* * Create a function `name` calling the ReadBarrier::Mark routine, * getting its argument and returning its result through register @@ -1835,28 +1874,25 @@ END art_quick_l2f .macro READ_BARRIER_MARK_REG name, reg ENTRY \name // Null check so that we can load the lock word. - cmp \reg, #0 - beq .Lret_rb_\name - // Check lock word for mark bit, if marked return. - push {r0} - ldr r0, [\reg, MIRROR_OBJECT_LOCK_WORD_OFFSET] - and r0, #LOCK_WORD_MARK_BIT_MASK_SHIFTED - cbz r0, .Lslow_rb_\name - // Restore LR and return. - pop {r0} - bx lr + SMART_CBZ \reg, .Lret_rb_\name + // Check lock word for mark bit, if marked return. Use IP for scratch since it is blocked. + ldr ip, [\reg, MIRROR_OBJECT_LOCK_WORD_OFFSET] + ands ip, #LOCK_WORD_MARK_BIT_MASK_SHIFTED + beq .Lslow_rb_\name + // Already marked, return right away. + bx lr .Lslow_rb_\name: - pop {r0} - push {r0-r4, r9, r12, lr} @ save return address and core caller-save registers + push {r0-r5, r9, lr} @ save return address and core caller-save registers + @ also save callee save r5 for 16 byte alignment .cfi_adjust_cfa_offset 32 .cfi_rel_offset r0, 0 .cfi_rel_offset r1, 4 .cfi_rel_offset r2, 8 .cfi_rel_offset r3, 12 .cfi_rel_offset r4, 16 - .cfi_rel_offset r9, 20 - .cfi_rel_offset r12, 24 + .cfi_rel_offset r5, 20 + .cfi_rel_offset r9, 24 .cfi_rel_offset lr, 28 vpush {s0-s15} @ save floating-point caller-save registers .cfi_adjust_cfa_offset 64 @@ -1865,48 +1901,11 @@ ENTRY \name mov r0, \reg @ pass arg1 - obj from `reg` .endif bl artReadBarrierMark @ r0 <- artReadBarrierMark(obj) - + mov ip, r0 @ Save result in IP vpop {s0-s15} @ restore floating-point registers .cfi_adjust_cfa_offset -64 - @ If `reg` is a caller-save register, save the result to its - @ corresponding stack slot; it will be restored by the "pop" - @ instruction below. Otherwise, move result into `reg`. - @ - @ (Note that saving `reg` to its stack slot will overwrite the value - @ previously stored by the "push" instruction above. That is - @ alright, as in that case we know that `reg` is not a live - @ register, as it is used to pass the argument and return the result - @ of this function.) - .ifc \reg, r0 - PUSH_REG r0, 0 @ copy result to r0's stack location - .else - .ifc \reg, r1 - PUSH_REG r0, 4 @ copy result to r1's stack location - .else - .ifc \reg, r2 - PUSH_REG r0, 8 @ copy result to r2's stack location - .else - .ifc \reg, r3 - PUSH_REG r0, 12 @ copy result to r3's stack location - .else - .ifc \reg, r4 - PUSH_REG r0, 16 @ copy result to r4's stack location - .else - .ifc \reg, r9 - PUSH_REG r0, 20 @ copy result to r9's stack location - .else - .ifc \reg, r12 - PUSH_REG r0, 24 @ copy result to r12's stack location - .else - mov \reg, r0 @ return result into `reg` - .endif - .endif - .endif - .endif - .endif - .endif - .endif - pop {r0-r4, r9, r12, pc} @ restore caller-save registers and return + pop {r0-r5, r9, lr} @ restore caller-save registers + mov \reg, ip @ copy result to reg .Lret_rb_\name: bx lr END \name @@ -1924,4 +1923,3 @@ READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg08, r8 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg09, r9 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg10, r10 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg11, r11 -READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg12, r12 diff --git a/runtime/arch/arm64/entrypoints_init_arm64.cc b/runtime/arch/arm64/entrypoints_init_arm64.cc index cc5bf29609..55b09c318c 100644 --- a/runtime/arch/arm64/entrypoints_init_arm64.cc +++ b/runtime/arch/arm64/entrypoints_init_arm64.cc @@ -149,7 +149,7 @@ void InitEntryPoints(JniEntryPoints* jpoints, QuickEntryPoints* qpoints) { qpoints->pReadBarrierMarkReg13 = art_quick_read_barrier_mark_reg13; qpoints->pReadBarrierMarkReg14 = art_quick_read_barrier_mark_reg14; qpoints->pReadBarrierMarkReg15 = art_quick_read_barrier_mark_reg15; - qpoints->pReadBarrierMarkReg16 = art_quick_read_barrier_mark_reg16; + qpoints->pReadBarrierMarkReg16 = nullptr; // IP0 is used as a temp by the asm stub. qpoints->pReadBarrierMarkReg17 = art_quick_read_barrier_mark_reg17; qpoints->pReadBarrierMarkReg18 = art_quick_read_barrier_mark_reg18; qpoints->pReadBarrierMarkReg19 = art_quick_read_barrier_mark_reg19; diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S index 35f5c56282..4289cabbc6 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -2751,7 +2751,7 @@ READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg12, w12, x12 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg13, w13, x13 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg14, w14, x14 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg15, w15, x15 -READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg16, w16, x16 +// READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg16, w16, x16 ip0 is blocked READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg17, w17, x17 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg18, w18, x18 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg19, w19, x19 diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h index 743fbb9c68..d717ec0fcb 100644 --- a/runtime/dex2oat_environment_test.h +++ b/runtime/dex2oat_environment_test.h @@ -137,7 +137,20 @@ class Dex2oatEnvironmentTest : public CommonRuntimeTest { } bool GetCachedImageFile(/*out*/std::string* image, std::string* error_msg) const { - std::string cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA), true); + std::string cache; + bool have_android_data; + bool dalvik_cache_exists; + bool is_global_cache; + GetDalvikCache(GetInstructionSetString(kRuntimeISA), + true, + &cache, + &have_android_data, + &dalvik_cache_exists, + &is_global_cache); + if (!dalvik_cache_exists) { + *error_msg = "Failed to create dalvik cache"; + return false; + } return GetDalvikCacheFilename(GetImageLocation().c_str(), cache.c_str(), image, error_msg); } diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h index fc9a3cfed5..fa941c0376 100644 --- a/runtime/gc/space/image_space_fs.h +++ b/runtime/gc/space/image_space_fs.h @@ -89,9 +89,11 @@ static void DeleteDirectoryContents(const std::string& dir, bool recurse) { static void PruneDalvikCache(InstructionSet isa) { CHECK_NE(isa, kNone); // Prune the base /data/dalvik-cache. - impl::DeleteDirectoryContents(GetDalvikCacheOrDie(".", false), false); + // Note: GetDalvikCache may return the empty string if the directory doesn't + // exist. It is safe to pass "" to DeleteDirectoryContents, so this is okay. + impl::DeleteDirectoryContents(GetDalvikCache("."), false); // Prune /data/dalvik-cache/<isa>. - impl::DeleteDirectoryContents(GetDalvikCacheOrDie(GetInstructionSetString(isa), false), false); + impl::DeleteDirectoryContents(GetDalvikCache(GetInstructionSetString(isa)), false); // Be defensive. There should be a runtime created here, but this may be called in a test. if (Runtime::Current() != nullptr) { @@ -104,7 +106,8 @@ static void PruneDalvikCache(InstructionSet isa) { // present, it usually means the boot didn't complete. We wipe the entire dalvik // cache if that's the case. static void MarkZygoteStart(const InstructionSet isa, const uint32_t max_failed_boots) { - const std::string isa_subdir = GetDalvikCacheOrDie(GetInstructionSetString(isa), false); + const std::string isa_subdir = GetDalvikCache(GetInstructionSetString(isa)); + CHECK(!isa_subdir.empty()) << "Dalvik cache not found"; const std::string boot_marker = isa_subdir + "/.booting"; const char* file_name = boot_marker.c_str(); diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index c1901587df..fe6332dee2 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -713,21 +713,15 @@ bool OatFileAssistant::DexLocationToOatFilename(const std::string& location, CHECK(oat_filename != nullptr); CHECK(error_msg != nullptr); - // TODO: The work done in GetDalvikCache is overkill for what we need. - // Ideally a new API for getting the DalvikCacheDirectory the way we want - // (without existence testing, creation, or death) is provided with the rest - // of the GetDalvikCache family of functions. Until such an API is in place, - // we use GetDalvikCache to avoid duplicating the logic for determining the - // dalvik cache directory. - std::string dalvik_cache_dir; - bool ignored; - GetDalvikCache("", false, &dalvik_cache_dir, &ignored, &ignored, &ignored); + std::string cache_dir = GetDalvikCache(GetInstructionSetString(isa)); + if (cache_dir.empty()) { + *error_msg = "Dalvik cache directory does not exist"; + return false; + } // TODO: The oat file assistant should be the definitive place for // determining the oat file name from the dex location, not // GetDalvikCacheFilename. - std::string cache_dir = StringPrintf("%s%s", - dalvik_cache_dir.c_str(), GetInstructionSetString(isa)); return GetDalvikCacheFilename(location.c_str(), cache_dir.c_str(), oat_filename, error_msg); } diff --git a/runtime/utils.cc b/runtime/utils.cc index 515ba9f9e3..8ab8cd2814 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -1087,58 +1087,18 @@ void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string } } -static std::string GetDalvikCacheImpl(const char* subdir, - const bool create_if_absent, - const bool abort_on_error) { +std::string GetDalvikCache(const char* subdir) { CHECK(subdir != nullptr); const char* android_data = GetAndroidData(); const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data)); const std::string dalvik_cache = dalvik_cache_root + subdir; if (!OS::DirectoryExists(dalvik_cache.c_str())) { - if (!create_if_absent) { - // TODO: Check callers. Traditional behavior is to not to abort, even when abort_on_error. - return ""; - } - - // Don't create the system's /data/dalvik-cache/... because it needs special permissions. - if (strcmp(android_data, "/data") == 0) { - if (abort_on_error) { - LOG(FATAL) << "Failed to find dalvik-cache directory " << dalvik_cache - << ", cannot create /data dalvik-cache."; - UNREACHABLE(); - } - return ""; - } - - int result = mkdir(dalvik_cache_root.c_str(), 0700); - if (result != 0 && errno != EEXIST) { - if (abort_on_error) { - PLOG(FATAL) << "Failed to create dalvik-cache root directory " << dalvik_cache_root; - UNREACHABLE(); - } - return ""; - } - - result = mkdir(dalvik_cache.c_str(), 0700); - if (result != 0) { - if (abort_on_error) { - PLOG(FATAL) << "Failed to create dalvik-cache directory " << dalvik_cache; - UNREACHABLE(); - } - return ""; - } + // TODO: Check callers. Traditional behavior is to not abort. + return ""; } return dalvik_cache; } -std::string GetDalvikCache(const char* subdir, const bool create_if_absent) { - return GetDalvikCacheImpl(subdir, create_if_absent, false); -} - -std::string GetDalvikCacheOrDie(const char* subdir, const bool create_if_absent) { - return GetDalvikCacheImpl(subdir, create_if_absent, true); -} - bool GetDalvikCacheFilename(const char* location, const char* cache_location, std::string* filename, std::string* error_msg) { if (location[0] != '/') { diff --git a/runtime/utils.h b/runtime/utils.h index 699b732522..fd1ba23573 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -251,11 +251,8 @@ const char* GetAndroidData(); const char* GetAndroidDataSafe(std::string* error_msg); // Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache -// could not be found (or created). -std::string GetDalvikCache(const char* subdir, bool create_if_absent = true); -// Returns the dalvik-cache location, or dies trying. subdir will be -// appended to the cache location. -std::string GetDalvikCacheOrDie(const char* subdir, bool create_if_absent = true); +// could not be found. +std::string GetDalvikCache(const char* subdir); // Return true if we found the dalvik cache and stored it in the dalvik_cache argument. // have_android_data will be set to true if we have an ANDROID_DATA that exists, // dalvik_cache_exists will be true if there is a dalvik-cache directory that is present. diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index 55b6e01f99..d2100d16d4 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -337,11 +337,9 @@ TEST_F(UtilsTest, GetDalvikCacheFilenameOrDie) { } TEST_F(UtilsTest, GetDalvikCache) { - EXPECT_STREQ("", GetDalvikCache("should-not-exist123", false).c_str()); + EXPECT_STREQ("", GetDalvikCache("should-not-exist123").c_str()); - EXPECT_STREQ((android_data_ + "/dalvik-cache/.").c_str(), GetDalvikCache(".", false).c_str()); - EXPECT_STREQ((android_data_ + "/dalvik-cache/should-not-be-there").c_str(), - GetDalvikCache("should-not-be-there", true).c_str()); + EXPECT_STREQ((android_data_ + "/dalvik-cache/.").c_str(), GetDalvikCache(".").c_str()); } |