diff options
| -rw-r--r-- | runtime/monitor.cc | 6 | ||||
| -rw-r--r-- | runtime/monitor.h | 1 | ||||
| -rw-r--r-- | test/596-monitor-inflation/expected.txt | 6 | ||||
| -rw-r--r-- | test/596-monitor-inflation/info.txt | 5 | ||||
| -rw-r--r-- | test/596-monitor-inflation/monitor_inflation.cc | 35 | ||||
| -rw-r--r-- | test/596-monitor-inflation/src/Main.java | 79 | ||||
| -rw-r--r-- | test/Android.bp | 1 |
7 files changed, 133 insertions, 0 deletions
diff --git a/runtime/monitor.cc b/runtime/monitor.cc index 9c0927584e..071b0e2c75 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -1394,6 +1394,12 @@ void MonitorList::SweepMonitorList(IsMarkedVisitor* visitor) { } } +size_t MonitorList::Size() { + Thread* self = Thread::Current(); + MutexLock mu(self, monitor_list_lock_); + return list_.size(); +} + class MonitorDeflateVisitor : public IsMarkedVisitor { public: MonitorDeflateVisitor() : self_(Thread::Current()), deflate_count_(0) {} diff --git a/runtime/monitor.h b/runtime/monitor.h index c3da5636ad..1fa46826eb 100644 --- a/runtime/monitor.h +++ b/runtime/monitor.h @@ -331,6 +331,7 @@ class MonitorList { void BroadcastForNewMonitors() REQUIRES(!monitor_list_lock_); // Returns how many monitors were deflated. size_t DeflateMonitors() REQUIRES(!monitor_list_lock_) REQUIRES(Locks::mutator_lock_); + size_t Size() REQUIRES(!monitor_list_lock_); typedef std::list<Monitor*, TrackingAllocator<Monitor*, kAllocatorTagMonitorList>> Monitors; diff --git a/test/596-monitor-inflation/expected.txt b/test/596-monitor-inflation/expected.txt new file mode 100644 index 0000000000..2add6966a0 --- /dev/null +++ b/test/596-monitor-inflation/expected.txt @@ -0,0 +1,6 @@ +JNI_OnLoad called +Monitor list grew by at least 4000 monitors +Monitor list shrank correctly +Finished first check +Finished second check +Total checks: 10000 diff --git a/test/596-monitor-inflation/info.txt b/test/596-monitor-inflation/info.txt new file mode 100644 index 0000000000..81dedb60aa --- /dev/null +++ b/test/596-monitor-inflation/info.txt @@ -0,0 +1,5 @@ +A simple test that forces many monitors to be inflated, while checking +that hashcodes are consistently maintained. + +This allocates more monitors and hence may exercise the monitor pool +differently, and with more context, than the monitor_pool_test gtest. diff --git a/test/596-monitor-inflation/monitor_inflation.cc b/test/596-monitor-inflation/monitor_inflation.cc new file mode 100644 index 0000000000..fb4275b711 --- /dev/null +++ b/test/596-monitor-inflation/monitor_inflation.cc @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gc/heap.h" +#include "jni.h" +#include "monitor.h" +#include "runtime.h" +#include "thread-inl.h" + +namespace art { +namespace { + +extern "C" JNIEXPORT void JNICALL Java_Main_trim(JNIEnv*, jclass) { + Runtime::Current()->GetHeap()->Trim(Thread::Current()); +} + +extern "C" JNIEXPORT jint JNICALL Java_Main_monitorListSize(JNIEnv*, jclass) { + return Runtime::Current()->GetMonitorList()->Size(); +} + +} // namespace +} // namespace art diff --git a/test/596-monitor-inflation/src/Main.java b/test/596-monitor-inflation/src/Main.java new file mode 100644 index 0000000000..d97c7667e9 --- /dev/null +++ b/test/596-monitor-inflation/src/Main.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.util.IdentityHashMap; +import dalvik.system.VMRuntime; + +public class Main { + public static void main(String[] args) { + System.loadLibrary(args[0]); + int initialSize = monitorListSize(); + IdentityHashMap<Object, Integer> all = new IdentityHashMap(); + for (int i = 0; i < 5000; ++i) { + Object obj = new Object(); + synchronized(obj) { + // Should force inflation. + all.put(obj, obj.hashCode()); + } + } + // Since monitor deflation is delayed significantly, we believe that even with an intervening + // GC, monitors should remain inflated. We allow some slop for unrelated concurrent runtime + // actions. + int inflatedSize = monitorListSize(); + if (inflatedSize >= initialSize + 4000) { + System.out.println("Monitor list grew by at least 4000 monitors"); + } else { + System.out.println("Monitor list did not grow as expected"); + } + // Encourage monitor deflation. + // trim() (Heap::Trim()) deflates only in JANK_IMPERCEPTIBLE state. + // Some of this mirrors code in ActivityThread.java. + final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0; + final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1; + VMRuntime.getRuntime().updateProcessState(DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE); + System.gc(); + System.runFinalization(); + trim(); + VMRuntime.getRuntime().updateProcessState(DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE); + int finalSize = monitorListSize(); + if (finalSize > initialSize + 1000) { + System.out.println("Monitor list failed to shrink properly"); + } else { + System.out.println("Monitor list shrank correctly"); + } + int j = 0; + for (Object obj: all.keySet()) { + ++j; + if (obj.hashCode() != all.get(obj)) { + throw new AssertionError("Failed hashcode test!"); + } + } + System.out.println("Finished first check"); + for (Object obj: all.keySet()) { + ++j; + synchronized(obj) { + if (obj.hashCode() != all.get(obj)) { + throw new AssertionError("Failed hashcode test!"); + } + } + } + System.out.println("Finished second check"); + System.out.println("Total checks: " + j); + } + + private static native void trim(); + + private static native int monitorListSize(); +} diff --git a/test/Android.bp b/test/Android.bp index 965d07aa43..e820d28fa1 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -325,6 +325,7 @@ cc_defaults { "570-checker-osr/osr.cc", "595-profile-saving/profile-saving.cc", "596-app-images/app_images.cc", + "596-monitor-inflation/monitor_inflation.cc", "597-deopt-new-string/deopt.cc", "626-const-class-linking/clear_dex_cache_types.cc", ], |