diff options
author | 2024-07-05 09:08:25 +0000 | |
---|---|---|
committer | 2024-07-11 14:00:00 +0000 | |
commit | b67495b6aa3f1253383938f2699da6eada1a0ead (patch) | |
tree | 902d6c0e3f61e399b0c2fad7f75c5e63a1f9740c | |
parent | 3b92bd7e571e3efc0d9afc37f5262cdb16fc6733 (diff) |
Use a current entry pointer instead of index for the method trace buffer
For the thread local method trace buffers we used to store the pointer
to the buffer and the current index of the next free space. We compute
the address of the location to store the entry in the generated JITed
code when storing the method trace entry. Instead we could use a pointer
to the entry to avoid computing the address in the generated code. This
doesn't have a noticeable impact for the regular method tracing but is
better for the upcoming changes that will introduce an experimental
feature for on-demand method tracing.
Bug: 259258187
Test: art/test.py
Change-Id: I7e39e686bee62ee91c651a1cb3ff242470010cb6
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 27 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 25 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_riscv64.cc | 22 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 30 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 35 | ||||
-rw-r--r-- | runtime/entrypoints_order_test.cc | 4 | ||||
-rw-r--r-- | runtime/thread.h | 27 | ||||
-rw-r--r-- | runtime/trace.cc | 50 |
8 files changed, 108 insertions, 112 deletions
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index e3a76e807e..3ec67afce9 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -1212,8 +1212,8 @@ void InstructionCodeGeneratorARM64::GenerateMethodEntryExitHook(HInstruction* in MacroAssembler* masm = GetVIXLAssembler(); UseScratchRegisterScope temps(masm); Register addr = temps.AcquireX(); - Register index = temps.AcquireX(); - Register value = index.W(); + Register curr_entry = temps.AcquireX(); + Register value = curr_entry.W(); SlowPathCodeARM64* slow_path = new (codegen_->GetScopedAllocator()) MethodEntryExitHooksSlowPathARM64(instruction); @@ -1242,21 +1242,20 @@ void InstructionCodeGeneratorARM64::GenerateMethodEntryExitHook(HInstruction* in // If yes, just take the slow path. __ B(gt, slow_path->GetEntryLabel()); + Register init_entry = addr; // Check if there is place in the buffer to store a new entry, if no, take slow path. - uint32_t trace_buffer_index_offset = - Thread::TraceBufferIndexOffset<kArm64PointerSize>().Int32Value(); - __ Ldr(index, MemOperand(tr, trace_buffer_index_offset)); - __ Subs(index, index, kNumEntriesForWallClock); + uint32_t trace_buffer_curr_entry_offset = + Thread::TraceBufferCurrPtrOffset<kArm64PointerSize>().Int32Value(); + __ Ldr(curr_entry, MemOperand(tr, trace_buffer_curr_entry_offset)); + __ Sub(curr_entry, curr_entry, kNumEntriesForWallClock * sizeof(void*)); + __ Ldr(init_entry, MemOperand(tr, Thread::TraceBufferPtrOffset<kArm64PointerSize>().SizeValue())); + __ Cmp(curr_entry, init_entry); __ B(lt, slow_path->GetEntryLabel()); // Update the index in the `Thread`. - __ Str(index, MemOperand(tr, trace_buffer_index_offset)); - // Calculate the entry address in the buffer. - // addr = base_addr + sizeof(void*) * index; - __ Ldr(addr, MemOperand(tr, Thread::TraceBufferPtrOffset<kArm64PointerSize>().SizeValue())); - __ ComputeAddress(addr, MemOperand(addr, index, LSL, TIMES_8)); + __ Str(curr_entry, MemOperand(tr, trace_buffer_curr_entry_offset)); - Register tmp = index; + Register tmp = init_entry; // Record method pointer and trace action. __ Ldr(tmp, MemOperand(sp, 0)); // Use last two bits to encode trace method action. For MethodEntry it is 0 @@ -1267,10 +1266,10 @@ void InstructionCodeGeneratorARM64::GenerateMethodEntryExitHook(HInstruction* in static_assert(enum_cast<int32_t>(TraceAction::kTraceMethodExit) == 1); __ Orr(tmp, tmp, Operand(enum_cast<int32_t>(TraceAction::kTraceMethodExit))); } - __ Str(tmp, MemOperand(addr, kMethodOffsetInBytes)); + __ Str(tmp, MemOperand(curr_entry, kMethodOffsetInBytes)); // Record the timestamp. __ Mrs(tmp, (SystemRegister)SYS_CNTVCT_EL0); - __ Str(tmp, MemOperand(addr, kTimestampOffsetInBytes)); + __ Str(tmp, MemOperand(curr_entry, kTimestampOffsetInBytes)); __ Bind(slow_path->GetExitLabel()); } diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index fc2fc34dde..34227a5480 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -2220,19 +2220,18 @@ void InstructionCodeGeneratorARMVIXL::GenerateMethodEntryExitHook(HInstruction* __ B(gt, slow_path->GetEntryLabel()); // Check if there is place in the buffer to store a new entry, if no, take slow path. - uint32_t trace_buffer_index_offset = - Thread::TraceBufferIndexOffset<kArmPointerSize>().Int32Value(); - vixl32::Register index = value; - __ Ldr(index, MemOperand(tr, trace_buffer_index_offset)); - __ Subs(index, index, kNumEntriesForWallClock); + uint32_t trace_buffer_curr_entry_offset = + Thread::TraceBufferCurrPtrOffset<kArmPointerSize>().Int32Value(); + vixl32::Register curr_entry = value; + vixl32::Register init_entry = addr; + __ Ldr(curr_entry, MemOperand(tr, trace_buffer_curr_entry_offset)); + __ Subs(curr_entry, curr_entry, static_cast<uint32_t>(kNumEntriesForWallClock * sizeof(void*))); + __ Ldr(init_entry, MemOperand(tr, Thread::TraceBufferPtrOffset<kArmPointerSize>().SizeValue())); + __ Cmp(curr_entry, init_entry); __ B(lt, slow_path->GetEntryLabel()); // Update the index in the `Thread`. - __ Str(index, MemOperand(tr, trace_buffer_index_offset)); - // Calculate the entry address in the buffer. - // addr = base_addr + sizeof(void*) * index - __ Ldr(addr, MemOperand(tr, Thread::TraceBufferPtrOffset<kArmPointerSize>().SizeValue())); - __ Add(addr, addr, Operand(index, LSL, TIMES_4)); + __ Str(curr_entry, MemOperand(tr, trace_buffer_curr_entry_offset)); // Record method pointer and trace action. __ Ldr(tmp, MemOperand(sp, 0)); @@ -2244,9 +2243,9 @@ void InstructionCodeGeneratorARMVIXL::GenerateMethodEntryExitHook(HInstruction* static_assert(enum_cast<int32_t>(TraceAction::kTraceMethodExit) == 1); __ Orr(tmp, tmp, Operand(enum_cast<int32_t>(TraceAction::kTraceMethodExit))); } - __ Str(tmp, MemOperand(addr, kMethodOffsetInBytes)); + __ Str(tmp, MemOperand(curr_entry, kMethodOffsetInBytes)); - vixl32::Register tmp1 = index; + vixl32::Register tmp1 = init_entry; // See Architecture Reference Manual ARMv7-A and ARMv7-R edition section B4.1.34. __ Mrrc(/* lower 32-bit */ tmp, /* higher 32-bit */ tmp1, @@ -2255,7 +2254,7 @@ void InstructionCodeGeneratorARMVIXL::GenerateMethodEntryExitHook(HInstruction* /* crm= */ 14); static_assert(kHighTimestampOffsetInBytes == kTimestampOffsetInBytes + static_cast<uint32_t>(kRuntimePointerSize)); - __ Strd(tmp, tmp1, MemOperand(addr, kTimestampOffsetInBytes)); + __ Strd(tmp, tmp1, MemOperand(curr_entry, kTimestampOffsetInBytes)); __ Bind(slow_path->GetExitLabel()); } diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc index 8581c38895..f6067a5468 100644 --- a/compiler/optimizing/code_generator_riscv64.cc +++ b/compiler/optimizing/code_generator_riscv64.cc @@ -2640,24 +2640,20 @@ void InstructionCodeGeneratorRISCV64::GenerateMethodEntryExitHook(HInstruction* __ Addi(tmp, tmp, -1); __ Bnez(tmp, slow_path->GetEntryLabel()); - // Check if there is place in the buffer to store a new entry, if no, take the slow path. - int32_t trace_buffer_index_offset = - Thread::TraceBufferIndexOffset<kRiscv64PointerSize>().Int32Value(); - __ Loadd(tmp, TR, trace_buffer_index_offset); - __ Addi(tmp, tmp, -dchecked_integral_cast<int32_t>(kNumEntriesForWallClock)); - __ Bltz(tmp, slow_path->GetEntryLabel()); - - // Update the index in the `Thread`. - __ Stored(tmp, TR, trace_buffer_index_offset); - // Allocate second core scratch register. We can no longer use `Stored()` // and similar macro instructions because there is no core scratch register left. XRegister tmp2 = temps.AllocateXRegister(); - // Calculate the entry address in the buffer. - // /*addr*/ tmp = TR->GetMethodTraceBuffer() + sizeof(void*) * /*index*/ tmp; + // Check if there is place in the buffer to store a new entry, if no, take the slow path. + int32_t trace_buffer_curr_entry_offset = + Thread::TraceBufferCurrPtrOffset<kRiscv64PointerSize>().Int32Value(); + __ Loadd(tmp, TR, trace_buffer_curr_entry_offset); __ Loadd(tmp2, TR, Thread::TraceBufferPtrOffset<kRiscv64PointerSize>().SizeValue()); - __ Sh3Add(tmp, tmp, tmp2); + __ Addi(tmp, tmp, -dchecked_integral_cast<int32_t>(kNumEntriesForWallClock * sizeof(void*))); + __ Blt(tmp, tmp2, slow_path->GetEntryLabel()); + + // Update the index in the `Thread`. + __ Sd(tmp, TR, trace_buffer_curr_entry_offset); // Record method pointer and trace action. __ Ld(tmp2, SP, 0); diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index f549da189f..91f4a89ced 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1274,29 +1274,27 @@ void InstructionCodeGeneratorX86::GenerateMethodEntryExitHook(HInstruction* inst // If yes, just take the slow path. __ j(kGreater, slow_path->GetEntryLabel()); - // For entry_addr use the first temp that isn't EAX or EDX. We need this after + // For curr_entry use the register that isn't EAX or EDX. We need this after // rdtsc which returns values in EAX + EDX. - Register entry_addr = locations->GetTemp(2).AsRegister<Register>(); - Register index = locations->GetTemp(1).AsRegister<Register>(); + Register curr_entry = locations->GetTemp(2).AsRegister<Register>(); + Register init_entry = locations->GetTemp(1).AsRegister<Register>(); // Check if there is place in the buffer for a new entry, if no, take slow path. uint32_t trace_buffer_ptr = Thread::TraceBufferPtrOffset<kX86PointerSize>().Int32Value(); - uint64_t trace_buffer_index_offset = - Thread::TraceBufferIndexOffset<kX86PointerSize>().Int32Value(); + uint64_t trace_buffer_curr_entry_offset = + Thread::TraceBufferCurrPtrOffset<kX86PointerSize>().Int32Value(); - __ fs()->movl(index, Address::Absolute(trace_buffer_index_offset)); - __ subl(index, Immediate(kNumEntriesForWallClock)); + __ fs()->movl(curr_entry, Address::Absolute(trace_buffer_curr_entry_offset)); + __ subl(curr_entry, Immediate(kNumEntriesForWallClock * sizeof(void*))); + __ fs()->movl(init_entry, Address::Absolute(trace_buffer_ptr)); + __ cmpl(curr_entry, init_entry); __ j(kLess, slow_path->GetEntryLabel()); // Update the index in the `Thread`. - __ fs()->movl(Address::Absolute(trace_buffer_index_offset), index); - // Calculate the entry address in the buffer. - // entry_addr = base_addr + sizeof(void*) * index - __ fs()->movl(entry_addr, Address::Absolute(trace_buffer_ptr)); - __ leal(entry_addr, Address(entry_addr, index, TIMES_4, 0)); + __ fs()->movl(Address::Absolute(trace_buffer_curr_entry_offset), curr_entry); // Record method pointer and trace action. - Register method = index; + Register method = init_entry; __ movl(method, Address(ESP, kCurrentMethodStackOffset)); // Use last two bits to encode trace method action. For MethodEntry it is 0 // so no need to set the bits since they are 0 already. @@ -1306,11 +1304,11 @@ void InstructionCodeGeneratorX86::GenerateMethodEntryExitHook(HInstruction* inst static_assert(enum_cast<int32_t>(TraceAction::kTraceMethodExit) == 1); __ orl(method, Immediate(enum_cast<int32_t>(TraceAction::kTraceMethodExit))); } - __ movl(Address(entry_addr, kMethodOffsetInBytes), method); + __ movl(Address(curr_entry, kMethodOffsetInBytes), method); // Get the timestamp. rdtsc returns timestamp in EAX + EDX. __ rdtsc(); - __ movl(Address(entry_addr, kTimestampOffsetInBytes), EAX); - __ movl(Address(entry_addr, kHighTimestampOffsetInBytes), EDX); + __ movl(Address(curr_entry, kTimestampOffsetInBytes), EAX); + __ movl(Address(curr_entry, kHighTimestampOffsetInBytes), EDX); __ Bind(slow_path->GetExitLabel()); } diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index f61bb39ccc..5e213e38e0 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1695,28 +1695,25 @@ void InstructionCodeGeneratorX86_64::GenerateMethodEntryExitHook(HInstruction* i __ j(kGreater, slow_path->GetEntryLabel()); // Check if there is place in the buffer for a new entry, if no, take slow path. - CpuRegister index = locations->GetTemp(0).AsRegister<CpuRegister>(); - CpuRegister entry_addr = CpuRegister(TMP); - uint64_t trace_buffer_index_offset = - Thread::TraceBufferIndexOffset<kX86_64PointerSize>().SizeValue(); - __ gs()->movq(CpuRegister(index), - Address::Absolute(trace_buffer_index_offset, /* no_rip= */ true)); - __ subq(CpuRegister(index), Immediate(kNumEntriesForWallClock)); + CpuRegister curr_entry = locations->GetTemp(0).AsRegister<CpuRegister>(); + CpuRegister init_entry = CpuRegister(TMP); + uint64_t trace_buffer_curr_entry_offset = + Thread::TraceBufferCurrPtrOffset<kX86_64PointerSize>().SizeValue(); + __ gs()->movq(CpuRegister(curr_entry), + Address::Absolute(trace_buffer_curr_entry_offset, /* no_rip= */ true)); + __ subq(CpuRegister(curr_entry), Immediate(kNumEntriesForWallClock * sizeof(void*))); + __ gs()->movq(init_entry, + Address::Absolute(Thread::TraceBufferPtrOffset<kX86_64PointerSize>().SizeValue(), + /* no_rip= */ true)); + __ cmpq(curr_entry, init_entry); __ j(kLess, slow_path->GetEntryLabel()); // Update the index in the `Thread`. - __ gs()->movq(Address::Absolute(trace_buffer_index_offset, /* no_rip= */ true), - CpuRegister(index)); - // Calculate the entry address in the buffer. - // entry_addr = base_addr + sizeof(void*) * index - __ gs()->movq(entry_addr, - Address::Absolute(Thread::TraceBufferPtrOffset<kX86_64PointerSize>().SizeValue(), - /* no_rip= */ true)); - __ leaq(CpuRegister(entry_addr), - Address(CpuRegister(entry_addr), CpuRegister(index), TIMES_8, 0)); + __ gs()->movq(Address::Absolute(trace_buffer_curr_entry_offset, /* no_rip= */ true), + CpuRegister(curr_entry)); // Record method pointer and action. - CpuRegister method = index; + CpuRegister method = init_entry; __ movq(CpuRegister(method), Address(CpuRegister(RSP), kCurrentMethodStackOffset)); // Use last two bits to encode trace method action. For MethodEntry it is 0 // so no need to set the bits since they are 0 already. @@ -1726,12 +1723,12 @@ void InstructionCodeGeneratorX86_64::GenerateMethodEntryExitHook(HInstruction* i static_assert(enum_cast<int32_t>(TraceAction::kTraceMethodExit) == 1); __ orq(method, Immediate(enum_cast<int32_t>(TraceAction::kTraceMethodExit))); } - __ movq(Address(entry_addr, kMethodOffsetInBytes), CpuRegister(method)); + __ movq(Address(curr_entry, kMethodOffsetInBytes), CpuRegister(method)); // Get the timestamp. rdtsc returns timestamp in RAX + RDX even in 64-bit architectures. __ rdtsc(); __ shlq(CpuRegister(RDX), Immediate(32)); __ orq(CpuRegister(RAX), CpuRegister(RDX)); - __ movq(Address(entry_addr, kTimestampOffsetInBytes), CpuRegister(RAX)); + __ movq(Address(curr_entry, kTimestampOffsetInBytes), CpuRegister(RAX)); __ Bind(slow_path->GetExitLabel()); } diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc index b25e01067b..090484eabb 100644 --- a/runtime/entrypoints_order_test.cc +++ b/runtime/entrypoints_order_test.cc @@ -134,9 +134,9 @@ class EntrypointsOrderTest : public CommonArtTest { EXPECT_OFFSET_DIFFP( Thread, tlsPtr_, top_reflective_handle_scope, method_trace_buffer, sizeof(void*)); EXPECT_OFFSET_DIFFP( - Thread, tlsPtr_, method_trace_buffer, method_trace_buffer_index, sizeof(void*)); + Thread, tlsPtr_, method_trace_buffer, method_trace_buffer_curr_entry, sizeof(void*)); EXPECT_OFFSET_DIFFP( - Thread, tlsPtr_, method_trace_buffer_index, thread_exit_flags, sizeof(void*)); + Thread, tlsPtr_, method_trace_buffer_curr_entry, thread_exit_flags, sizeof(void*)); EXPECT_OFFSET_DIFFP( Thread, tlsPtr_, thread_exit_flags, last_no_thread_suspension_cause, sizeof(void*)); EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, last_no_thread_suspension_cause, diff --git a/runtime/thread.h b/runtime/thread.h index 464b343b1e..fda086adf0 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -1099,9 +1099,9 @@ class EXPORT Thread { } template <PointerSize pointer_size> - static constexpr ThreadOffset<pointer_size> TraceBufferIndexOffset() { + static constexpr ThreadOffset<pointer_size> TraceBufferCurrPtrOffset() { return ThreadOffsetFromTlsPtr<pointer_size>( - OFFSETOF_MEMBER(tls_ptr_sized_values, method_trace_buffer_index)); + OFFSETOF_MEMBER(tls_ptr_sized_values, method_trace_buffer_curr_entry)); } template <PointerSize pointer_size> @@ -1364,10 +1364,21 @@ class EXPORT Thread { uintptr_t* GetMethodTraceBuffer() { return tlsPtr_.method_trace_buffer; } - size_t* GetMethodTraceIndexPtr() { return &tlsPtr_.method_trace_buffer_index; } + uintptr_t** GetTraceBufferCurrEntryPtr() { return &tlsPtr_.method_trace_buffer_curr_entry; } - uintptr_t* SetMethodTraceBuffer(uintptr_t* buffer) { - return tlsPtr_.method_trace_buffer = buffer; + void SetMethodTraceBuffer(uintptr_t* buffer, int init_index) { + tlsPtr_.method_trace_buffer = buffer; + SetTraceBufferCurrentEntry(init_index); + } + + void SetTraceBufferCurrentEntry(int index) { + uintptr_t* buffer = tlsPtr_.method_trace_buffer; + if (buffer == nullptr) { + tlsPtr_.method_trace_buffer_curr_entry = nullptr; + } else { + DCHECK(buffer != nullptr); + tlsPtr_.method_trace_buffer_curr_entry = buffer + index; + } } uint64_t GetTraceClockBase() const { @@ -2152,7 +2163,7 @@ class EXPORT Thread { async_exception(nullptr), top_reflective_handle_scope(nullptr), method_trace_buffer(nullptr), - method_trace_buffer_index(0), + method_trace_buffer_curr_entry(nullptr), thread_exit_flags(nullptr), last_no_thread_suspension_cause(nullptr), last_no_transaction_checks_cause(nullptr) { @@ -2327,8 +2338,8 @@ class EXPORT Thread { // Pointer to a thread-local buffer for method tracing. uintptr_t* method_trace_buffer; - // The index of the next free entry in method_trace_buffer. - size_t method_trace_buffer_index; + // Pointer to the current entry in the buffer. + uintptr_t* method_trace_buffer_curr_entry; // Pointer to the first node of an intrusively doubly-linked list of ThreadExitFlags. ThreadExitFlag* thread_exit_flags GUARDED_BY(Locks::thread_list_lock_); diff --git a/runtime/trace.cc b/runtime/trace.cc index 8e3d8b926d..af2a6befd7 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -1018,7 +1018,7 @@ void Trace::ReleaseThreadBuffer(Thread* self) { return; } the_trace_->trace_writer_->ReleaseBufferForThread(self); - self->SetMethodTraceBuffer(nullptr); + self->SetMethodTraceBuffer(nullptr, 0); } void Trace::Abort() { @@ -1661,25 +1661,25 @@ int TraceWriter::GetMethodTraceIndex(uintptr_t* current_buffer) { void TraceWriter::FlushBuffer(Thread* thread, bool is_sync, bool release) { uintptr_t* method_trace_entries = thread->GetMethodTraceBuffer(); - size_t* current_offset = thread->GetMethodTraceIndexPtr(); + uintptr_t** current_entry_ptr = thread->GetTraceBufferCurrEntryPtr(); + size_t current_offset = *current_entry_ptr - method_trace_entries; size_t tid = thread->GetTid(); DCHECK(method_trace_entries != nullptr); if (is_sync || thread_pool_ == nullptr) { std::unordered_map<ArtMethod*, std::string> method_infos; if (trace_format_version_ == Trace::kFormatV1) { - PreProcessTraceForMethodInfos(method_trace_entries, *current_offset, method_infos); + PreProcessTraceForMethodInfos(method_trace_entries, current_offset, method_infos); } - FlushBuffer(method_trace_entries, *current_offset, tid, method_infos); + FlushBuffer(method_trace_entries, current_offset, tid, method_infos); // This is a synchronous flush, so no need to allocate a new buffer. This is used either // when the tracing has finished or in non-streaming mode. // Just reset the buffer pointer to the initial value, so we can reuse the same buffer. if (release) { - thread->SetMethodTraceBuffer(nullptr); - *current_offset = 0; + thread->SetMethodTraceBuffer(nullptr, 0); } else { - *current_offset = kPerThreadBufSize; + thread->SetTraceBufferCurrentEntry(kPerThreadBufSize); } } else { int old_index = GetMethodTraceIndex(method_trace_entries); @@ -1687,13 +1687,11 @@ void TraceWriter::FlushBuffer(Thread* thread, bool is_sync, bool release) { // entries are flushed. thread_pool_->AddTask( Thread::Current(), - new TraceEntriesWriterTask(this, old_index, method_trace_entries, *current_offset, tid)); + new TraceEntriesWriterTask(this, old_index, method_trace_entries, current_offset, tid)); if (release) { - thread->SetMethodTraceBuffer(nullptr); - *current_offset = 0; + thread->SetMethodTraceBuffer(nullptr, 0); } else { - thread->SetMethodTraceBuffer(AcquireTraceBuffer(tid)); - *current_offset = kPerThreadBufSize; + thread->SetMethodTraceBuffer(AcquireTraceBuffer(tid), kPerThreadBufSize); } } @@ -1882,53 +1880,51 @@ void Trace::LogMethodTraceEvent(Thread* thread, // concurrently. uintptr_t* method_trace_buffer = thread->GetMethodTraceBuffer(); - size_t* current_index = thread->GetMethodTraceIndexPtr(); + uintptr_t** current_entry_ptr = thread->GetTraceBufferCurrEntryPtr(); // Initialize the buffer lazily. It's just simpler to keep the creation at one place. if (method_trace_buffer == nullptr) { method_trace_buffer = trace_writer_->AcquireTraceBuffer(thread->GetTid()); DCHECK(method_trace_buffer != nullptr); - thread->SetMethodTraceBuffer(method_trace_buffer); - *current_index = kPerThreadBufSize; + thread->SetMethodTraceBuffer(method_trace_buffer, kPerThreadBufSize); trace_writer_->RecordThreadInfo(thread); } if (trace_writer_->HasOverflow()) { // In non-streaming modes, we stop recoding events once the buffer is full. Just reset the // index, so we don't go to runtime for each method. - *current_index = kPerThreadBufSize; + thread->SetTraceBufferCurrentEntry(kPerThreadBufSize); return; } size_t required_entries = GetNumEntries(clock_source_); - if (*current_index < required_entries) { + if (*current_entry_ptr - required_entries < method_trace_buffer) { // This returns nullptr in non-streaming mode if there's an overflow and we cannot record any // more entries. In streaming mode, it returns nullptr if it fails to allocate a new buffer. method_trace_buffer = trace_writer_->PrepareBufferForNewEntries(thread); if (method_trace_buffer == nullptr) { - *current_index = kPerThreadBufSize; + thread->SetTraceBufferCurrentEntry(kPerThreadBufSize); return; } } + *current_entry_ptr = *current_entry_ptr - required_entries; // Record entry in per-thread trace buffer. - // Update the offset - int new_entry_index = *current_index - required_entries; - *current_index = new_entry_index; - + int entry_index = 0; + uintptr_t* current_entry = *current_entry_ptr; // Ensure we always use the non-obsolete version of the method so that entry/exit events have the // same pointer value. method = method->GetNonObsoleteMethod(); - method_trace_buffer[new_entry_index++] = reinterpret_cast<uintptr_t>(method) | action; + current_entry[entry_index++] = reinterpret_cast<uintptr_t>(method) | action; if (UseThreadCpuClock(clock_source_)) { - method_trace_buffer[new_entry_index++] = thread_clock_diff; + current_entry[entry_index++] = thread_clock_diff; } if (UseWallClock(clock_source_)) { if (art::kRuntimePointerSize == PointerSize::k32) { // On 32-bit architectures store timestamp counter as two 32-bit values. - method_trace_buffer[new_entry_index++] = static_cast<uint32_t>(timestamp_counter); - method_trace_buffer[new_entry_index++] = timestamp_counter >> 32; + current_entry[entry_index++] = static_cast<uint32_t>(timestamp_counter); + current_entry[entry_index++] = timestamp_counter >> 32; } else { - method_trace_buffer[new_entry_index++] = timestamp_counter; + current_entry[entry_index++] = timestamp_counter; } } } |