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

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

Issue 1190863003: Oilpan: Allocation should be allowed in pre-finalizers (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 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 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 // TODO(Oilpan): Avoid calling weak callbacks for dead objects. 510 // TODO(Oilpan): Avoid calling weak callbacks for dead objects.
511 // We can do that by checking isHeapObjectAlive(object) before 511 // We can do that by checking isHeapObjectAlive(object) before
512 // calling the weak callback, but in that case Callback::Item 512 // calling the weak callback, but in that case Callback::Item
513 // needs to understand T*. 513 // needs to understand T*.
514 item->call(visitor); 514 item->call(visitor);
515 return true; 515 return true;
516 } 516 }
517 return false; 517 return false;
518 } 518 }
519 519
520 void ThreadState::threadLocalWeakProcessing()
521 {
522 ASSERT(!sweepForbidden());
523 TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing");
524 SweepForbiddenScope forbiddenScope(this);
525 if (isMainThread())
526 ScriptForbiddenScope::enter();
527
528 // Disallow allocation during weak processing.
529 // It would be technically safe to allow allocations, but it is unsafe
530 // to mutate an object graph in a way in which a dead object gets
531 // resurrected or mutate a HashTable (because HashTable's weak processing
532 // assumes that the HashTable hasn't been mutated since the latest marking).
533 // Due to the complexity, we just forbid allocations.
534 NoAllocationScope noAllocationScope(this);
535
536 MarkingVisitor<Visitor::WeakProcessing> weakProcessingVisitor;
537
538 // Perform thread-specific weak processing.
539 while (popAndInvokeThreadLocalWeakCallback(&weakProcessingVisitor)) { }
540
541 if (isMainThread())
542 ScriptForbiddenScope::exit();
543 }
544
520 PersistentAnchor& ThreadState::globalRoots() 545 PersistentAnchor& ThreadState::globalRoots()
521 { 546 {
522 AtomicallyInitializedStaticReference(PersistentAnchor, anchor, new Persisten tAnchor); 547 AtomicallyInitializedStaticReference(PersistentAnchor, anchor, new Persisten tAnchor);
523 return anchor; 548 return anchor;
524 } 549 }
525 550
526 Mutex& ThreadState::globalRootsMutex() 551 Mutex& ThreadState::globalRootsMutex()
527 { 552 {
528 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex); 553 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
529 return mutex; 554 return mutex;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 if (!isSweepingInProgress()) 697 if (!isSweepingInProgress())
673 return; 698 return;
674 699
675 // This check is here to prevent performIdleLazySweep() from being called 700 // This check is here to prevent performIdleLazySweep() from being called
676 // recursively. I'm not sure if it can happen but it would be safer to have 701 // recursively. I'm not sure if it can happen but it would be safer to have
677 // the check just in case. 702 // the check just in case.
678 if (sweepForbidden()) 703 if (sweepForbidden())
679 return; 704 return;
680 705
681 bool sweepCompleted = true; 706 bool sweepCompleted = true;
682 ThreadState::SweepForbiddenScope scope(this); 707 SweepForbiddenScope scope(this);
683 { 708 {
684 if (isMainThread()) 709 if (isMainThread())
685 ScriptForbiddenScope::enter(); 710 ScriptForbiddenScope::enter();
686 711
687 for (int i = 0; i < NumberOfHeaps; i++) { 712 for (int i = 0; i < NumberOfHeaps; i++) {
688 // lazySweepWithDeadline() won't check the deadline until it sweeps 713 // lazySweepWithDeadline() won't check the deadline until it sweeps
689 // 10 pages. So we give a small slack for safety. 714 // 10 pages. So we give a small slack for safety.
690 double slack = 0.001; 715 double slack = 0.001;
691 double remainingBudget = deadlineSeconds - slack - Platform::current ()->monotonicallyIncreasingTime(); 716 double remainingBudget = deadlineSeconds - slack - Platform::current ()->monotonicallyIncreasingTime();
692 if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadl ineSeconds)) { 717 if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadl ineSeconds)) {
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 m_gcState = NoGCScheduled; 968 m_gcState = NoGCScheduled;
944 } 969 }
945 } 970 }
946 971
947 void ThreadState::preSweep() 972 void ThreadState::preSweep()
948 { 973 {
949 checkThread(); 974 checkThread();
950 if (gcState() != EagerSweepScheduled && gcState() != LazySweepScheduled) 975 if (gcState() != EagerSweepScheduled && gcState() != LazySweepScheduled)
951 return; 976 return;
952 977
953 { 978 threadLocalWeakProcessing();
954 if (isMainThread())
955 ScriptForbiddenScope::enter();
956 979
957 SweepForbiddenScope forbiddenScope(this); 980 GCState previousGCState = gcState();
sof 2015/06/18 12:18:03 This runs the risk of triggering an unused variabl
haraken 2015/06/18 16:30:13 Done.
958 { 981 setGCState(Sweeping);
sof 2015/06/18 12:18:03 Moving this up before running the prefinalizers ma
haraken 2015/06/18 16:30:13 Moving setGCState(Sweeping) up here is necessary t
959 MarkingVisitor<Visitor::WeakProcessing> weakProcessingVisitor;
960 982
961 // Disallow allocation during weak processing. 983 // Allocation is allowed during the pre-finalizers and destructors.
962 NoAllocationScope noAllocationScope(this); 984 // However, they must not mutate an object graph in a way in which
963 { 985 // a dead object gets resurrected.
964 // Perform thread-specific weak processing. 986 invokePreFinalizers();
965 TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing ");
966 while (popAndInvokeThreadLocalWeakCallback(&weakProcessingVisito r)) { }
967 }
968 {
969 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers");
970 invokePreFinalizers();
971 }
972 }
973
974 if (isMainThread())
975 ScriptForbiddenScope::exit();
976 }
977 987
978 #if defined(ADDRESS_SANITIZER) 988 #if defined(ADDRESS_SANITIZER)
979 poisonEagerHeap(SetPoison); 989 poisonEagerHeap(SetPoison);
980 #endif 990 #endif
981 991
982 #if ENABLE(LAZY_SWEEPING) 992 #if ENABLE(LAZY_SWEEPING)
983 if (gcState() == EagerSweepScheduled) { 993 if (previousGCState == EagerSweepScheduled) {
984 // Eager sweeping should happen only in testing. 994 // Eager sweeping should happen only in testing.
985 setGCState(Sweeping);
986 eagerSweep(); 995 eagerSweep();
987 #if defined(ADDRESS_SANITIZER) 996 #if defined(ADDRESS_SANITIZER)
988 poisonAllHeaps(); 997 poisonAllHeaps();
989 #endif 998 #endif
990 completeSweep(); 999 completeSweep();
991 } else { 1000 } else {
992 // The default behavior is lazy sweeping. 1001 // The default behavior is lazy sweeping.
993 setGCState(Sweeping);
994 eagerSweep(); 1002 eagerSweep();
995 #if defined(ADDRESS_SANITIZER) 1003 #if defined(ADDRESS_SANITIZER)
996 poisonAllHeaps(); 1004 poisonAllHeaps();
997 #endif 1005 #endif
998 scheduleIdleLazySweep(); 1006 scheduleIdleLazySweep();
999 } 1007 }
1000 #else 1008 #else
1001 setGCState(Sweeping);
1002 completeSweep(); 1009 completeSweep();
1003 #endif 1010 #endif
1004 1011
1005 #if ENABLE(GC_PROFILING) 1012 #if ENABLE(GC_PROFILING)
1006 snapshotFreeListIfNecessary(); 1013 snapshotFreeListIfNecessary();
1007 #endif 1014 #endif
1008 } 1015 }
1009 1016
1010 #if defined(ADDRESS_SANITIZER) 1017 #if defined(ADDRESS_SANITIZER)
1011 void ThreadState::poisonAllHeaps() 1018 void ThreadState::poisonAllHeaps()
(...skipping 21 matching lines...) Expand all
1033 { 1040 {
1034 // Some objects need to be finalized promptly and cannot be handled 1041 // Some objects need to be finalized promptly and cannot be handled
1035 // by lazy sweeping. Keep those in a designated heap and sweep it 1042 // by lazy sweeping. Keep those in a designated heap and sweep it
1036 // eagerly. 1043 // eagerly.
1037 ASSERT(isSweepingInProgress()); 1044 ASSERT(isSweepingInProgress());
1038 1045
1039 // Mirroring the completeSweep() condition; see its comment. 1046 // Mirroring the completeSweep() condition; see its comment.
1040 if (sweepForbidden()) 1047 if (sweepForbidden())
1041 return; 1048 return;
1042 1049
1043 ThreadState::SweepForbiddenScope scope(this); 1050 SweepForbiddenScope scope(this);
1044 { 1051 {
1045 if (isMainThread()) 1052 if (isMainThread())
1046 ScriptForbiddenScope::enter(); 1053 ScriptForbiddenScope::enter();
1047 1054
1048 m_heaps[EagerSweepHeapIndex]->completeSweep(); 1055 m_heaps[EagerSweepHeapIndex]->completeSweep();
1049 1056
1050 if (isMainThread()) 1057 if (isMainThread())
1051 ScriptForbiddenScope::exit(); 1058 ScriptForbiddenScope::exit();
1052 } 1059 }
1053 } 1060 }
1054 1061
1055 void ThreadState::completeSweep() 1062 void ThreadState::completeSweep()
1056 { 1063 {
1057 // If we are not in a sweeping phase, there is nothing to do here. 1064 // If we are not in a sweeping phase, there is nothing to do here.
1058 if (!isSweepingInProgress()) 1065 if (!isSweepingInProgress())
1059 return; 1066 return;
1060 1067
1061 // completeSweep() can be called recursively if finalizers can allocate 1068 // completeSweep() can be called recursively if finalizers can allocate
1062 // memory and the allocation triggers completeSweep(). This check prevents 1069 // memory and the allocation triggers completeSweep(). This check prevents
1063 // the sweeping from being executed recursively. 1070 // the sweeping from being executed recursively.
1064 if (sweepForbidden()) 1071 if (sweepForbidden())
1065 return; 1072 return;
1066 1073
1067 ThreadState::SweepForbiddenScope scope(this); 1074 SweepForbiddenScope scope(this);
1068 { 1075 {
1069 if (isMainThread()) 1076 if (isMainThread())
1070 ScriptForbiddenScope::enter(); 1077 ScriptForbiddenScope::enter();
1071 1078
1072 TRACE_EVENT0("blink_gc", "ThreadState::completeSweep"); 1079 TRACE_EVENT0("blink_gc", "ThreadState::completeSweep");
1073 double timeStamp = WTF::currentTimeMS(); 1080 double timeStamp = WTF::currentTimeMS();
1074 1081
1075 static_assert(EagerSweepHeapIndex == 0, "Eagerly swept heaps must be pro cessed first."); 1082 static_assert(EagerSweepHeapIndex == 0, "Eagerly swept heaps must be pro cessed first.");
1076 for (int i = 0; i < NumberOfHeaps; i++) 1083 for (int i = 0; i < NumberOfHeaps; i++)
1077 m_heaps[i]->completeSweep(); 1084 m_heaps[i]->completeSweep();
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 if (sweepForbidden()) 1297 if (sweepForbidden())
1291 return; 1298 return;
1292 auto it = m_preFinalizers.find(target); 1299 auto it = m_preFinalizers.find(target);
1293 ASSERT(it != m_preFinalizers.end()); 1300 ASSERT(it != m_preFinalizers.end());
1294 m_preFinalizers.remove(it); 1301 m_preFinalizers.remove(it);
1295 } 1302 }
1296 1303
1297 void ThreadState::invokePreFinalizers() 1304 void ThreadState::invokePreFinalizers()
1298 { 1305 {
1299 checkThread(); 1306 checkThread();
1307 ASSERT(!sweepForbidden());
1308 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers");
1309
1310 if (isMainThread())
1311 ScriptForbiddenScope::enter();
1312
1313 SweepForbiddenScope forbiddenScope(this);
1300 Vector<void*> deadObjects; 1314 Vector<void*> deadObjects;
1301 for (auto& entry : m_preFinalizers) { 1315 for (auto& entry : m_preFinalizers) {
1302 if (entry.value(entry.key)) 1316 if (entry.value(entry.key))
1303 deadObjects.append(entry.key); 1317 deadObjects.append(entry.key);
1304 } 1318 }
1305 // FIXME: removeAll is inefficient. It can shrink repeatedly. 1319 // FIXME: removeAll is inefficient. It can shrink repeatedly.
1306 m_preFinalizers.removeAll(deadObjects); 1320 m_preFinalizers.removeAll(deadObjects);
1321
1322 if (isMainThread())
1323 ScriptForbiddenScope::exit();
1307 } 1324 }
1308 1325
1309 void ThreadState::clearHeapAges() 1326 void ThreadState::clearHeapAges()
1310 { 1327 {
1311 memset(m_heapAges, 0, sizeof(size_t) * NumberOfHeaps); 1328 memset(m_heapAges, 0, sizeof(size_t) * NumberOfHeaps);
1312 memset(m_likelyToBePromptlyFreed.get(), 0, sizeof(int) * likelyToBePromptlyF reedArraySize); 1329 memset(m_likelyToBePromptlyFreed.get(), 0, sizeof(int) * likelyToBePromptlyF reedArraySize);
1313 m_currentHeapAges = 0; 1330 m_currentHeapAges = 0;
1314 } 1331 }
1315 1332
1316 int ThreadState::heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex, int endHeapIndex) 1333 int ThreadState::heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex, int endHeapIndex)
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 json->beginArray(it->key.ascii().data()); 1464 json->beginArray(it->key.ascii().data());
1448 for (size_t age = 0; age <= maxHeapObjectAge; ++age) 1465 for (size_t age = 0; age <= maxHeapObjectAge; ++age)
1449 json->pushInteger(it->value.ages[age]); 1466 json->pushInteger(it->value.ages[age]);
1450 json->endArray(); 1467 json->endArray();
1451 } 1468 }
1452 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); 1469 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release());
1453 } 1470 }
1454 #endif 1471 #endif
1455 1472
1456 } // namespace blink 1473 } // namespace blink
OLDNEW
« Source/platform/heap/ThreadState.h ('K') | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698