diff options
-rw-r--r-- | runtime/entrypoints/jni/jni_entrypoints.cc | 75 | ||||
-rw-r--r-- | runtime/gc/collector/garbage_collector.cc | 1 | ||||
-rw-r--r-- | runtime/gc/collector/mark_sweep.cc | 1 | ||||
-rw-r--r-- | runtime/gc/collector/semi_space.cc | 1 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 57 | ||||
-rw-r--r-- | test/ThreadStress/ThreadStress.java | 6 |
6 files changed, 34 insertions, 107 deletions
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc index c0304eb..bea7d96 100644 --- a/runtime/entrypoints/jni/jni_entrypoints.cc +++ b/runtime/entrypoints/jni/jni_entrypoints.cc @@ -46,79 +46,4 @@ extern "C" void* artFindNativeMethod() { } } -static void WorkAroundJniBugsForJobject(intptr_t* arg_ptr) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - intptr_t value = *arg_ptr; - mirror::Object** value_as_jni_rep = reinterpret_cast<mirror::Object**>(value); - mirror::Object* value_as_work_around_rep = value_as_jni_rep != NULL ? *value_as_jni_rep : NULL; - CHECK(Runtime::Current()->GetHeap()->IsValidObjectAddress(value_as_work_around_rep)) - << value_as_work_around_rep; - *arg_ptr = reinterpret_cast<intptr_t>(value_as_work_around_rep); -} - -extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(Thread::Current() == self); - // TODO: this code is specific to ARM - // On entry the stack pointed by sp is: - // | arg3 | <- Calling JNI method's frame (and extra bit for out args) - // | LR | - // | R3 | arg2 - // | R2 | arg1 - // | R1 | jclass/jobject - // | R0 | JNIEnv - // | unused | - // | unused | - // | unused | <- sp - mirror::ArtMethod* jni_method = self->GetCurrentMethod(NULL); - DCHECK(jni_method->IsNative()) << PrettyMethod(jni_method); - intptr_t* arg_ptr = sp + 4; // pointer to r1 on stack - // Fix up this/jclass argument - WorkAroundJniBugsForJobject(arg_ptr); - arg_ptr++; - // Fix up jobject arguments - MethodHelper mh(jni_method); - int reg_num = 2; // Current register being processed, -1 for stack arguments. - for (uint32_t i = 1; i < mh.GetShortyLength(); i++) { - char shorty_char = mh.GetShorty()[i]; - if (shorty_char == 'L') { - WorkAroundJniBugsForJobject(arg_ptr); - } - if (shorty_char == 'J' || shorty_char == 'D') { - if (reg_num == 2) { - arg_ptr = sp + 8; // skip to out arguments - reg_num = -1; - } else if (reg_num == 3) { - arg_ptr = sp + 10; // skip to out arguments plus 2 slots as long must be aligned - reg_num = -1; - } else { - DCHECK_EQ(reg_num, -1); - if ((reinterpret_cast<intptr_t>(arg_ptr) & 7) == 4) { - arg_ptr += 3; // unaligned, pad and move through stack arguments - } else { - arg_ptr += 2; // aligned, move through stack arguments - } - } - } else { - if (reg_num == 2) { - arg_ptr++; // move through register arguments - reg_num++; - } else if (reg_num == 3) { - arg_ptr = sp + 8; // skip to outgoing stack arguments - reg_num = -1; - } else { - DCHECK_EQ(reg_num, -1); - arg_ptr++; // move through stack arguments - } - } - } - // Load expected destination, see Method::RegisterNative - const void* code = reinterpret_cast<const void*>(jni_method->GetNativeGcMap()); - if (UNLIKELY(code == NULL)) { - code = GetJniDlsymLookupStub(); - jni_method->RegisterNative(self, code, false); - } - return code; -} - } // namespace art diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc index 6380cba..615ec98 100644 --- a/runtime/gc/collector/garbage_collector.cc +++ b/runtime/gc/collector/garbage_collector.cc @@ -65,6 +65,7 @@ void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) { ThreadList* thread_list = Runtime::Current()->GetThreadList(); Thread* self = Thread::Current(); uint64_t start_time = NanoTime(); + timings_.Reset(); pause_times_.clear(); duration_ns_ = 0; clear_soft_references_ = clear_soft_references; diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 8af4fd8..007eb23 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -104,7 +104,6 @@ MarkSweep::MarkSweep(Heap* heap, bool is_concurrent, const std::string& name_pre } void MarkSweep::InitializePhase() { - timings_.Reset(); TimingLogger::ScopedSplit split("InitializePhase", &timings_); mark_stack_ = heap_->mark_stack_.get(); DCHECK(mark_stack_ != nullptr); diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc index 0413439..3b9e853 100644 --- a/runtime/gc/collector/semi_space.cc +++ b/runtime/gc/collector/semi_space.cc @@ -110,7 +110,6 @@ SemiSpace::SemiSpace(Heap* heap, bool generational, const std::string& name_pref } void SemiSpace::InitializePhase() { - timings_.Reset(); TimingLogger::ScopedSplit split("InitializePhase", &timings_); mark_stack_ = heap_->mark_stack_.get(); DCHECK(mark_stack_ != nullptr); diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 5d72bc1..a9799b9 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -1910,36 +1910,37 @@ collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type, GcCaus EnqueueClearedReferences(); // Grow the heap so that we know when to perform the next GC. GrowForUtilization(collector); - if (CareAboutPauseTimes()) { - const size_t duration = collector->GetDurationNs(); - std::vector<uint64_t> pauses = collector->GetPauseTimes(); + const size_t duration = collector->GetDurationNs(); + const std::vector<uint64_t>& pause_times = collector->GetPauseTimes(); + // Print the GC if it is an explicit GC (e.g. Runtime.gc()) or a slow GC + // (mutator time blocked >= long_pause_log_threshold_). + bool log_gc = gc_cause == kGcCauseExplicit; + if (!log_gc && CareAboutPauseTimes()) { // GC for alloc pauses the allocating thread, so consider it as a pause. - bool was_slow = duration > long_gc_log_threshold_ || + log_gc = duration > long_gc_log_threshold_ || (gc_cause == kGcCauseForAlloc && duration > long_pause_log_threshold_); - if (!was_slow) { - for (uint64_t pause : pauses) { - was_slow = was_slow || pause > long_pause_log_threshold_; - } - } - if (was_slow) { - const size_t percent_free = GetPercentFree(); - const size_t current_heap_size = GetBytesAllocated(); - const size_t total_memory = GetTotalMemory(); - std::ostringstream pause_string; - for (size_t i = 0; i < pauses.size(); ++i) { - pause_string << PrettyDuration((pauses[i] / 1000) * 1000) - << ((i != pauses.size() - 1) ? ", " : ""); - } - LOG(INFO) << gc_cause << " " << collector->GetName() - << " GC freed " << collector->GetFreedObjects() << "(" - << PrettySize(collector->GetFreedBytes()) << ") AllocSpace objects, " - << collector->GetFreedLargeObjects() << "(" - << PrettySize(collector->GetFreedLargeObjectBytes()) << ") LOS objects, " - << percent_free << "% free, " << PrettySize(current_heap_size) << "/" - << PrettySize(total_memory) << ", " << "paused " << pause_string.str() - << " total " << PrettyDuration((duration / 1000) * 1000); - VLOG(heap) << ConstDumpable<TimingLogger>(collector->GetTimings()); - } + for (uint64_t pause : pause_times) { + log_gc = log_gc || pause >= long_pause_log_threshold_; + } + } + if (log_gc) { + const size_t percent_free = GetPercentFree(); + const size_t current_heap_size = GetBytesAllocated(); + const size_t total_memory = GetTotalMemory(); + std::ostringstream pause_string; + for (size_t i = 0; i < pause_times.size(); ++i) { + pause_string << PrettyDuration((pause_times[i] / 1000) * 1000) + << ((i != pause_times.size() - 1) ? ", " : ""); + } + LOG(INFO) << gc_cause << " " << collector->GetName() + << " GC freed " << collector->GetFreedObjects() << "(" + << PrettySize(collector->GetFreedBytes()) << ") AllocSpace objects, " + << collector->GetFreedLargeObjects() << "(" + << PrettySize(collector->GetFreedLargeObjectBytes()) << ") LOS objects, " + << percent_free << "% free, " << PrettySize(current_heap_size) << "/" + << PrettySize(total_memory) << ", " << "paused " << pause_string.str() + << " total " << PrettyDuration((duration / 1000) * 1000); + VLOG(heap) << ConstDumpable<TimingLogger>(collector->GetTimings()); } FinishGC(self, gc_type); ATRACE_END(); diff --git a/test/ThreadStress/ThreadStress.java b/test/ThreadStress/ThreadStress.java index 795c790..5dccc68 100644 --- a/test/ThreadStress/ThreadStress.java +++ b/test/ThreadStress/ThreadStress.java @@ -14,13 +14,15 @@ * limitations under the License. */ +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import libcore.io.*; // Run on host with: // javac ThreadTest.java && java ThreadStress && rm *.class @@ -202,7 +204,7 @@ class ThreadStress implements Runnable { } case SIGQUIT: { try { - Libcore.os.kill(Libcore.os.getpid(), OsConstants.SIGQUIT); + Os.kill(Os.getpid(), OsConstants.SIGQUIT); } catch (ErrnoException ex) { } } |