summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/entrypoints/jni/jni_entrypoints.cc75
-rw-r--r--runtime/gc/collector/garbage_collector.cc1
-rw-r--r--runtime/gc/collector/mark_sweep.cc1
-rw-r--r--runtime/gc/collector/semi_space.cc1
-rw-r--r--runtime/gc/heap.cc57
-rw-r--r--test/ThreadStress/ThreadStress.java6
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) {
}
}