diff options
| -rw-r--r-- | compiler/Android.bp | 3 | ||||
| l--------- | compiler/generate-operator-out.py | 1 | ||||
| -rw-r--r-- | runtime/Android.bp | 3 | ||||
| -rw-r--r-- | runtime/arch/arm/quick_entrypoints_arm.S | 14 | ||||
| -rw-r--r-- | runtime/arch/arm64/quick_entrypoints_arm64.S | 15 | ||||
| -rw-r--r-- | runtime/arch/x86/quick_entrypoints_x86.S | 15 | ||||
| -rw-r--r-- | runtime/arch/x86_64/quick_entrypoints_x86_64.S | 7 | ||||
| -rw-r--r-- | runtime/base/unix_file/fd_file.cc | 53 | ||||
| -rw-r--r-- | runtime/base/unix_file/fd_file.h | 9 | ||||
| -rw-r--r-- | runtime/base/unix_file/fd_file_test.cc | 20 | ||||
| -rw-r--r-- | runtime/gc/collector/concurrent_copying-inl.h | 2 | ||||
| l--------- | runtime/generate-operator-out.py | 1 | ||||
| -rw-r--r-- | runtime/generated/asm_support_gen.h | 2 | ||||
| -rw-r--r-- | runtime/lock_word.h | 3 | ||||
| -rw-r--r-- | test/115-native-bridge/nativebridge.cc | 2 | ||||
| -rw-r--r-- | tools/cpp-define-generator/constant_lockword.def | 1 |
16 files changed, 131 insertions, 20 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp index b2ed074fa7..f1bf27ece7 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -204,7 +204,8 @@ art_cc_defaults { gensrcs { name: "art_compiler_operator_srcs", - cmd: "art/tools/generate-operator-out.py art/compiler $in > $out", + cmd: "$(location generate-operator-out.py) art/compiler $(in) > $(out)", + tool_files: ["generate-operator-out.py"], srcs: [ "compiled_method.h", "dex/dex_to_dex_compiler.h", diff --git a/compiler/generate-operator-out.py b/compiler/generate-operator-out.py new file mode 120000 index 0000000000..cc291d20c1 --- /dev/null +++ b/compiler/generate-operator-out.py @@ -0,0 +1 @@ +../tools/generate-operator-out.py
\ No newline at end of file diff --git a/runtime/Android.bp b/runtime/Android.bp index 9157907cee..57413dcaab 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -405,7 +405,8 @@ cc_defaults { gensrcs { name: "art_operator_srcs", - cmd: "art/tools/generate-operator-out.py art/runtime $in > $out", + cmd: "$(location generate-operator-out.py) art/runtime $(in) > $(out)", + tool_files: ["generate-operator-out.py"], srcs: [ "arch/instruction_set.h", "base/allocator.h", diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S index bf70c554b1..0135260de8 100644 --- a/runtime/arch/arm/quick_entrypoints_arm.S +++ b/runtime/arch/arm/quick_entrypoints_arm.S @@ -1999,11 +1999,17 @@ ENTRY \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] tst ip, #LOCK_WORD_MARK_BIT_MASK_SHIFTED - beq .Lslow_rb_\name + beq .Lnot_marked_rb_\name // Already marked, return right away. .Lret_rb_\name: bx lr +.Lnot_marked_rb_\name: + // Test that both the forwarding state bits are 1. + mvn ip, ip + tst ip, #(LOCK_WORD_STATE_FORWARDING_ADDRESS << LOCK_WORD_STATE_SHIFT) + beq .Lret_forwarding_address\name + .Lslow_rb_\name: // Save IP: the kSaveEverything entrypoint art_quick_resolve_string makes a tail call here. push {r0-r4, r9, ip, lr} @ save return address, core caller-save registers and ip @@ -2064,6 +2070,12 @@ ENTRY \name .cfi_restore ip .cfi_restore lr bx lr +.Lret_forwarding_address\name: + // Shift left by the forwarding address shift. This clears out the state bits since they are + // in the top 2 bits of the lock word. + mvn ip, ip + lsl \reg, ip, #LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT + bx lr END \name .endm diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S index 483cee3100..d806715ec9 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -2539,10 +2539,17 @@ ENTRY \name */ // Use wIP0 as temp and check the mark bit of the reference. wIP0 is not used by the compiler. ldr wIP0, [\xreg, #MIRROR_OBJECT_LOCK_WORD_OFFSET] - tbz wIP0, #LOCK_WORD_MARK_BIT_SHIFT, .Lslow_rb_\name + tbz wIP0, #LOCK_WORD_MARK_BIT_SHIFT, .Lnot_marked_rb_\name .Lret_rb_\name: ret +.Lnot_marked_rb_\name: + // Check if the top two bits are one, if this is the case it is a forwarding address. + mvn wIP0, wIP0 + cmp wzr, wIP0, lsr #30 + beq .Lret_forwarding_address\name .Lslow_rb_\name: + // We must not clobber IP0 since art_quick_resolve_string makes a tail call here and relies on + // IP0 being restored. // Save all potentially live caller-save core registers. SAVE_TWO_REGS_INCREASE_FRAME x0, x1, 368 SAVE_TWO_REGS x2, x3, 16 @@ -2608,6 +2615,12 @@ ENTRY \name RESTORE_REG xLR, 360 DECREASE_FRAME 368 ret +.Lret_forwarding_address\name: + mvn wIP0, wIP0 + // Shift left by the forwarding address shift. This clears out the state bits since they are + // in the top 2 bits of the lock word. + lsl \wreg, wIP0, #LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT + ret END \name .endm diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S index f4f9a68e30..98739d3cc8 100644 --- a/runtime/arch/x86/quick_entrypoints_x86.S +++ b/runtime/arch/x86/quick_entrypoints_x86.S @@ -2155,8 +2155,15 @@ MACRO2(READ_BARRIER_MARK_REG, name, reg) jz .Lslow_rb_\name ret .Lslow_rb_\name: - // Save all potentially live caller-save core registers. PUSH eax + mov MIRROR_OBJECT_LOCK_WORD_OFFSET(REG_VAR(reg)), %eax + add LITERAL(LOCK_WORD_STATE_FORWARDING_ADDRESS_OVERFLOW), %eax + // Jump if overflow, the only case where it overflows should be the forwarding address one. + // Taken ~25% of the time. + jnae .Lret_forwarding_address\name + + // Save all potentially live caller-save core registers. + mov 0(%esp), %eax PUSH ecx PUSH edx PUSH ebx @@ -2204,6 +2211,12 @@ MACRO2(READ_BARRIER_MARK_REG, name, reg) POP_REG_NE eax, RAW_VAR(reg) .Lret_rb_\name: ret +.Lret_forwarding_address\name: + // The overflow cleared the top bits. + sall LITERAL(LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT), %eax + mov %eax, REG_VAR(reg) + POP_REG_NE eax, RAW_VAR(reg) + ret END_FUNCTION VAR(name) END_MACRO diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S index fc549ecb04..185e55e114 100644 --- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S @@ -2279,9 +2279,10 @@ MACRO2(READ_BARRIER_MARK_REG, name, reg) PUSH rax movl MIRROR_OBJECT_LOCK_WORD_OFFSET(REG_VAR(reg)), %eax addl LITERAL(LOCK_WORD_STATE_FORWARDING_ADDRESS_OVERFLOW), %eax - // Jump if overflow, the only case where it overflows should be the forwarding address one. + // Jump if the addl caused eax to unsigned overflow. The only case where it overflows is the + // forwarding address one. // Taken ~25% of the time. - jnae .Lret_overflow\name + jnae .Lret_forwarding_address\name // Save all potentially live caller-save core registers. movq 0(%rsp), %rax @@ -2349,7 +2350,7 @@ MACRO2(READ_BARRIER_MARK_REG, name, reg) POP_REG_NE rax, RAW_VAR(reg) .Lret_rb_\name: ret -.Lret_overflow\name: +.Lret_forwarding_address\name: // The overflow cleared the top bits. sall LITERAL(LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT), %eax movq %rax, REG_VAR(reg) diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc index 4498198b34..ff2dd1b399 100644 --- a/runtime/base/unix_file/fd_file.cc +++ b/runtime/base/unix_file/fd_file.cc @@ -339,22 +339,59 @@ bool FdFile::Copy(FdFile* input_file, int64_t offset, int64_t size) { return true; } -void FdFile::Erase() { +bool FdFile::Unlink() { + if (file_path_.empty()) { + return false; + } + + // Try to figure out whether this file is still referring to the one on disk. + bool is_current = false; + { + struct stat this_stat, current_stat; + int cur_fd = TEMP_FAILURE_RETRY(open(file_path_.c_str(), O_RDONLY)); + if (cur_fd > 0) { + // File still exists. + if (fstat(fd_, &this_stat) == 0 && fstat(cur_fd, ¤t_stat) == 0) { + is_current = (this_stat.st_dev == current_stat.st_dev) && + (this_stat.st_ino == current_stat.st_ino); + } + close(cur_fd); + } + } + + if (is_current) { + unlink(file_path_.c_str()); + } + + return is_current; +} + +bool FdFile::Erase(bool unlink) { DCHECK(!read_only_mode_); - TEMP_FAILURE_RETRY(SetLength(0)); - TEMP_FAILURE_RETRY(Flush()); - TEMP_FAILURE_RETRY(Close()); + + bool ret_result = true; + if (unlink) { + ret_result = Unlink(); + } + + int result; + result = SetLength(0); + result = Flush(); + result = Close(); + // Ignore the errors. + + return ret_result; } int FdFile::FlushCloseOrErase() { DCHECK(!read_only_mode_); - int flush_result = TEMP_FAILURE_RETRY(Flush()); + int flush_result = Flush(); if (flush_result != 0) { LOG(ERROR) << "CloseOrErase failed while flushing a file."; Erase(); return flush_result; } - int close_result = TEMP_FAILURE_RETRY(Close()); + int close_result = Close(); if (close_result != 0) { LOG(ERROR) << "CloseOrErase failed while closing a file."; Erase(); @@ -365,11 +402,11 @@ int FdFile::FlushCloseOrErase() { int FdFile::FlushClose() { DCHECK(!read_only_mode_); - int flush_result = TEMP_FAILURE_RETRY(Flush()); + int flush_result = Flush(); if (flush_result != 0) { LOG(ERROR) << "FlushClose failed while flushing a file."; } - int close_result = TEMP_FAILURE_RETRY(Close()); + int close_result = Close(); if (close_result != 0) { LOG(ERROR) << "FlushClose failed while closing a file."; } diff --git a/runtime/base/unix_file/fd_file.h b/runtime/base/unix_file/fd_file.h index d896ee9ecb..eb85c4f097 100644 --- a/runtime/base/unix_file/fd_file.h +++ b/runtime/base/unix_file/fd_file.h @@ -97,7 +97,14 @@ class FdFile : public RandomAccessFile { int Flush() OVERRIDE WARN_UNUSED; // Short for SetLength(0); Flush(); Close(); - void Erase(); + // If the file was opened with a path name and unlink = true, also calls Unlink() on the path. + // Note that it is the the caller's responsibility to avoid races. + bool Erase(bool unlink = false); + + // Call unlink() if the file was opened with a path, and if open() with the name shows that + // the file descriptor of this file is still up-to-date. This is still racy, though, and it + // is up to the caller to ensure correctness in a multi-process setup. + bool Unlink(); // Try to Flush(), then try to Close(); If either fails, call Erase(). int FlushCloseOrErase() WARN_UNUSED; diff --git a/runtime/base/unix_file/fd_file_test.cc b/runtime/base/unix_file/fd_file_test.cc index 99ef6f73ba..7657a38cec 100644 --- a/runtime/base/unix_file/fd_file_test.cc +++ b/runtime/base/unix_file/fd_file_test.cc @@ -186,4 +186,24 @@ TEST_F(FdFileTest, MoveConstructor) { ASSERT_EQ(file2.Close(), 0); } +TEST_F(FdFileTest, EraseWithPathUnlinks) { + // New scratch file, zero-length. + art::ScratchFile tmp; + std::string filename = tmp.GetFilename(); + tmp.Close(); // This is required because of the unlink race between the scratch file and the + // FdFile, which leads to close-guard breakage. + FdFile file(filename, O_RDWR, false); + ASSERT_TRUE(file.IsOpened()); + EXPECT_GE(file.Fd(), 0); + uint8_t buffer[16] = { 0 }; + EXPECT_TRUE(file.WriteFully(&buffer, sizeof(buffer))); + EXPECT_EQ(file.Flush(), 0); + + EXPECT_TRUE(file.Erase(true)); + + EXPECT_FALSE(file.IsOpened()); + + EXPECT_FALSE(art::OS::FileExists(filename.c_str())) << filename; +} + } // namespace unix_file diff --git a/runtime/gc/collector/concurrent_copying-inl.h b/runtime/gc/collector/concurrent_copying-inl.h index 6b6a12defb..7c649525e4 100644 --- a/runtime/gc/collector/concurrent_copying-inl.h +++ b/runtime/gc/collector/concurrent_copying-inl.h @@ -149,8 +149,6 @@ inline mirror::Object* ConcurrentCopying::Mark(mirror::Object* from_ref) { inline mirror::Object* ConcurrentCopying::MarkFromReadBarrier(mirror::Object* from_ref) { mirror::Object* ret; - // TODO: Delete GetMarkBit check when all of the callers properly check the bit. Remaining caller - // is array allocations. if (from_ref == nullptr) { return from_ref; } diff --git a/runtime/generate-operator-out.py b/runtime/generate-operator-out.py new file mode 120000 index 0000000000..cc291d20c1 --- /dev/null +++ b/runtime/generate-operator-out.py @@ -0,0 +1 @@ +../tools/generate-operator-out.py
\ No newline at end of file diff --git a/runtime/generated/asm_support_gen.h b/runtime/generated/asm_support_gen.h index f938c9f08a..2c95fe942e 100644 --- a/runtime/generated/asm_support_gen.h +++ b/runtime/generated/asm_support_gen.h @@ -98,6 +98,8 @@ DEFINE_CHECK_EQ(static_cast<uint32_t>(LOCK_WORD_READ_BARRIER_STATE_MASK), (stati DEFINE_CHECK_EQ(static_cast<uint32_t>(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED), (static_cast<uint32_t>(art::LockWord::kReadBarrierStateMaskShiftedToggled))) #define LOCK_WORD_THIN_LOCK_COUNT_ONE 65536 DEFINE_CHECK_EQ(static_cast<int32_t>(LOCK_WORD_THIN_LOCK_COUNT_ONE), (static_cast<int32_t>(art::LockWord::kThinLockCountOne))) +#define LOCK_WORD_STATE_FORWARDING_ADDRESS 0x3 +DEFINE_CHECK_EQ(static_cast<uint32_t>(LOCK_WORD_STATE_FORWARDING_ADDRESS), (static_cast<uint32_t>(art::LockWord::kStateForwardingAddress))) #define LOCK_WORD_STATE_FORWARDING_ADDRESS_OVERFLOW 0x40000000 DEFINE_CHECK_EQ(static_cast<uint32_t>(LOCK_WORD_STATE_FORWARDING_ADDRESS_OVERFLOW), (static_cast<uint32_t>(art::LockWord::kStateForwardingAddressOverflow))) #define LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT 0x3 diff --git a/runtime/lock_word.h b/runtime/lock_word.h index dea301c451..2f2565b9d0 100644 --- a/runtime/lock_word.h +++ b/runtime/lock_word.h @@ -265,6 +265,9 @@ class LockWord { static_cast<uint64_t>(kStateForwardingAddressOverflow); constexpr bool is_larger = overflow > static_cast<uint64_t>(0xFFFFFFFF); static_assert(is_larger, "should have overflowed"); + static_assert( + (~kStateForwardingAddress & kStateMask) == 0, + "READ_BARRIER_MARK_REG relies on the forwarding address state being only one bits"); CheckReadBarrierState(); } diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc index 56d737f4ee..41329af138 100644 --- a/test/115-native-bridge/nativebridge.cc +++ b/test/115-native-bridge/nativebridge.cc @@ -466,7 +466,7 @@ extern "C" int native_bridge_unloadLibrary(void* handle ATTRIBUTE_UNUSED) { return 0; } -extern "C" char* native_bridge_getError() { +extern "C" const char* native_bridge_getError() { printf("dlerror() in native bridge.\n"); return nullptr; } diff --git a/tools/cpp-define-generator/constant_lockword.def b/tools/cpp-define-generator/constant_lockword.def index f9b6b19655..08d588505d 100644 --- a/tools/cpp-define-generator/constant_lockword.def +++ b/tools/cpp-define-generator/constant_lockword.def @@ -30,6 +30,7 @@ DEFINE_LOCK_WORD_EXPR(READ_BARRIER_STATE_MASK, uint32_t, kReadBarrierStateMas DEFINE_LOCK_WORD_EXPR(READ_BARRIER_STATE_MASK_TOGGLED, uint32_t, kReadBarrierStateMaskShiftedToggled) DEFINE_LOCK_WORD_EXPR(THIN_LOCK_COUNT_ONE, int32_t, kThinLockCountOne) +DEFINE_LOCK_WORD_EXPR(STATE_FORWARDING_ADDRESS, uint32_t, kStateForwardingAddress) DEFINE_LOCK_WORD_EXPR(STATE_FORWARDING_ADDRESS_OVERFLOW, uint32_t, kStateForwardingAddressOverflow) DEFINE_LOCK_WORD_EXPR(STATE_FORWARDING_ADDRESS_SHIFT, uint32_t, kForwardingAddressShift) |