Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: Source/platform/heap/HeapTest.cpp

Issue 260723003: [oilpan]: Make parking threads for GC timeout in the case parking exceeds 100 MS (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 18 matching lines...) Expand all
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 32
33 #include "platform/heap/Handle.h" 33 #include "platform/heap/Handle.h"
34 #include "platform/heap/Heap.h" 34 #include "platform/heap/Heap.h"
35 #include "platform/heap/HeapLinkedStack.h" 35 #include "platform/heap/HeapLinkedStack.h"
36 #include "platform/heap/HeapTerminatedArrayBuilder.h" 36 #include "platform/heap/HeapTerminatedArrayBuilder.h"
37 #include "platform/heap/ThreadState.h" 37 #include "platform/heap/ThreadState.h"
38 #include "platform/heap/Visitor.h" 38 #include "platform/heap/Visitor.h"
39 #include "public/platform/Platform.h"
39 #include "wtf/HashTraits.h" 40 #include "wtf/HashTraits.h"
40 #include "wtf/LinkedHashSet.h" 41 #include "wtf/LinkedHashSet.h"
41 42
42 #include <gtest/gtest.h> 43 #include <gtest/gtest.h>
43 44
44 namespace WebCore { 45 namespace WebCore {
45 46
46 class ThreadMarker { 47 class ThreadMarker {
47 public: 48 public:
48 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num( 0) { } 49 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num( 0) { }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 93
93 } 94 }
94 95
95 namespace WebCore { 96 namespace WebCore {
96 97
97 class TestGCScope { 98 class TestGCScope {
98 public: 99 public:
99 explicit TestGCScope(ThreadState::StackState state) 100 explicit TestGCScope(ThreadState::StackState state)
100 : m_state(ThreadState::current()) 101 : m_state(ThreadState::current())
101 , m_safePointScope(state) 102 , m_safePointScope(state)
103 , m_parkedAllThreads(false)
102 { 104 {
103 m_state->checkThread(); 105 m_state->checkThread();
104 ASSERT(!m_state->isInGC()); 106 ASSERT(!m_state->isInGC());
105 ThreadState::stopThreads(); 107 if (LIKELY(ThreadState::stopThreads())) {
106 m_state->enterGC(); 108 m_state->enterGC();
109 m_parkedAllThreads = true;
110 }
107 } 111 }
108 112
113 bool allThreadsParked() { return m_parkedAllThreads; }
114
109 ~TestGCScope() 115 ~TestGCScope()
110 { 116 {
111 m_state->leaveGC(); 117 // Only cleanup if we parked all threads in which case the GC happened
112 ASSERT(!m_state->isInGC()); 118 // and we need to resume the other threads.
113 ThreadState::resumeThreads(); 119 if (LIKELY(m_parkedAllThreads)) {
120 m_state->leaveGC();
121 ASSERT(!m_state->isInGC());
122 ThreadState::resumeThreads();
123 }
114 } 124 }
115 125
116 private: 126 private:
117 ThreadState* m_state; 127 ThreadState* m_state;
118 ThreadState::SafePointScope m_safePointScope; 128 ThreadState::SafePointScope m_safePointScope;
129 bool m_parkedAllThreads; // False if we fail to park all threads
119 }; 130 };
120 131
121 static void getHeapStats(HeapStats* stats) 132 static void getHeapStats(HeapStats* stats)
122 { 133 {
123 TestGCScope scope(ThreadState::NoHeapPointersOnStack); 134 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
135 EXPECT_TRUE(scope.allThreadsParked());
124 Heap::getStats(stats); 136 Heap::getStats(stats);
125 } 137 }
126 138
127 #define DEFINE_VISITOR_METHODS(Type) \ 139 #define DEFINE_VISITOR_METHODS(Type) \
128 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \ 140 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
129 { \ 141 { \
130 if (object) \ 142 if (object) \
131 m_count++; \ 143 m_count++; \
132 } \ 144 } \
133 virtual bool isMarked(const Type*) OVERRIDE { return false; } 145 virtual bool isMarked(const Type*) OVERRIDE { return false; }
(...skipping 3029 matching lines...) Expand 10 before | Expand all | Expand 10 after
3163 3175
3164 // This is a low-level test where we call checkAndMarkPointer. This method 3176 // This is a low-level test where we call checkAndMarkPointer. This method
3165 // causes the object start bitmap to be computed which requires the heap 3177 // causes the object start bitmap to be computed which requires the heap
3166 // to be in a consistent state (e.g. the free allocation area must be put 3178 // to be in a consistent state (e.g. the free allocation area must be put
3167 // into a free list header). However when we call makeConsistentForGC it 3179 // into a free list header). However when we call makeConsistentForGC it
3168 // also clears out the freelists so we have to rebuild those before trying 3180 // also clears out the freelists so we have to rebuild those before trying
3169 // to allocate anything again. We do this by forcing a GC after doing the 3181 // to allocate anything again. We do this by forcing a GC after doing the
3170 // checkAndMarkPointer tests. 3182 // checkAndMarkPointer tests.
3171 { 3183 {
3172 TestGCScope scope(ThreadState::HeapPointersOnStack); 3184 TestGCScope scope(ThreadState::HeapPointersOnStack);
3185 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads.
3173 Heap::makeConsistentForGC(); 3186 Heap::makeConsistentForGC();
3174 for (size_t i = 0; i < objectAddresses.size(); i++) { 3187 for (size_t i = 0; i < objectAddresses.size(); i++) {
3175 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i])) ; 3188 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i])) ;
3176 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])); 3189 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3177 } 3190 }
3178 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); 3191 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
3179 visitor.reset(); 3192 visitor.reset();
3180 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress)); 3193 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3181 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress)); 3194 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3182 EXPECT_EQ(2ul, visitor.count()); 3195 EXPECT_EQ(2ul, visitor.count());
3183 visitor.reset(); 3196 visitor.reset();
3184 } 3197 }
3185 // This forces a GC without stack scanning which results in the objects 3198 // This forces a GC without stack scanning which results in the objects
3186 // being collected. This will also rebuild the above mentioned freelists, 3199 // being collected. This will also rebuild the above mentioned freelists,
3187 // however we don't rely on that below since we don't have any allocations. 3200 // however we don't rely on that below since we don't have any allocations.
3188 clearOutOldGarbage(&initialHeapStats); 3201 clearOutOldGarbage(&initialHeapStats);
3189 { 3202 {
3190 TestGCScope scope(ThreadState::HeapPointersOnStack); 3203 TestGCScope scope(ThreadState::HeapPointersOnStack);
3204 EXPECT_TRUE(scope.allThreadsParked());
3191 Heap::makeConsistentForGC(); 3205 Heap::makeConsistentForGC();
3192 for (size_t i = 0; i < objectAddresses.size(); i++) { 3206 for (size_t i = 0; i < objectAddresses.size(); i++) {
3193 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]) ); 3207 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]) );
3194 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])); 3208 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3195 } 3209 }
3196 EXPECT_EQ(0ul, visitor.count()); 3210 EXPECT_EQ(0ul, visitor.count());
3197 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress)); 3211 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3198 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress)) ; 3212 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress)) ;
3199 EXPECT_EQ(0ul, visitor.count()); 3213 EXPECT_EQ(0ul, visitor.count());
3200 } 3214 }
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
3616 TEST(HeapTest, DestructorsCalledOnMapClear) 3630 TEST(HeapTest, DestructorsCalledOnMapClear)
3617 { 3631 {
3618 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map; 3632 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3619 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor(); 3633 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3620 map.add(hasDestructor, adoptPtr(hasDestructor)); 3634 map.add(hasDestructor, adoptPtr(hasDestructor));
3621 SimpleClassWithDestructor::s_wasDestructed = false; 3635 SimpleClassWithDestructor::s_wasDestructed = false;
3622 map.clear(); 3636 map.clear();
3623 ASSERT(SimpleClassWithDestructor::s_wasDestructed); 3637 ASSERT(SimpleClassWithDestructor::s_wasDestructed);
3624 } 3638 }
3625 3639
3640
3641 class GCParkingThreadTester {
3642 public:
3643 static void test()
3644 {
3645 createThread(&sleeperMainFunc, 0, "SleepingThread");
3646
3647 // Wait for the sleeper to run.
3648 while (!s_sleeperRunning) {
3649 yield();
3650 }
3651
3652 {
3653 // Expect the first attempt to park the sleeping thread to fail
3654 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3655 EXPECT_FALSE(scope.allThreadsParked());
3656 }
3657
3658 s_sleeperDone = true;
3659
3660 // Wait for the sleeper to finish.
3661 while (s_sleeperRunning) {
3662 yield();
3663 }
3664 {
3665 // Since the sleeper thread has detached this is the only thread.
3666 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3667 EXPECT_TRUE(scope.allThreadsParked());
3668 }
3669 }
3670
3671 private:
3672 static void sleeperMainFunc(void* data)
3673 {
3674 ThreadState::attach();
3675 s_sleeperRunning = true;
3676
3677 // Simulate a long running op that is not entering a safepoint.
3678 while (!s_sleeperDone) {
3679 yield();
3680 }
3681
3682 ThreadState::detach();
3683 s_sleeperRunning = false;
3684 }
3685
3686 static volatile bool s_sleeperRunning;
3687 static volatile bool s_sleeperDone;
3688 };
3689
3690 volatile bool GCParkingThreadTester::s_sleeperRunning = false;
3691 volatile bool GCParkingThreadTester::s_sleeperDone = false;
3692
3693 TEST(HeapTest, GCParkingTimeout)
3694 {
3695 GCParkingThreadTester::test();
3696 }
3697
3626 } // WebCore namespace 3698 } // WebCore namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698