GCThread.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (C) 2012 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  14. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  15. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  17. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  23. * THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "GCThread.h"
  27. #include "CopyVisitor.h"
  28. #include "CopyVisitorInlines.h"
  29. #include "GCThreadSharedData.h"
  30. #include "SlotVisitor.h"
  31. #include <wtf/MainThread.h>
  32. #include <wtf/PassOwnPtr.h>
  33. namespace JSC {
  34. GCThread::GCThread(GCThreadSharedData& shared, SlotVisitor* slotVisitor, CopyVisitor* copyVisitor)
  35. : m_threadID(0)
  36. , m_shared(shared)
  37. , m_slotVisitor(WTF::adoptPtr(slotVisitor))
  38. , m_copyVisitor(WTF::adoptPtr(copyVisitor))
  39. {
  40. }
  41. ThreadIdentifier GCThread::threadID()
  42. {
  43. ASSERT(m_threadID);
  44. return m_threadID;
  45. }
  46. void GCThread::initializeThreadID(ThreadIdentifier threadID)
  47. {
  48. ASSERT(!m_threadID);
  49. m_threadID = threadID;
  50. }
  51. SlotVisitor* GCThread::slotVisitor()
  52. {
  53. ASSERT(m_slotVisitor);
  54. return m_slotVisitor.get();
  55. }
  56. CopyVisitor* GCThread::copyVisitor()
  57. {
  58. ASSERT(m_copyVisitor);
  59. return m_copyVisitor.get();
  60. }
  61. GCPhase GCThread::waitForNextPhase()
  62. {
  63. MutexLocker locker(m_shared.m_phaseLock);
  64. while (m_shared.m_gcThreadsShouldWait)
  65. m_shared.m_phaseCondition.wait(m_shared.m_phaseLock);
  66. m_shared.m_numberOfActiveGCThreads--;
  67. if (!m_shared.m_numberOfActiveGCThreads)
  68. m_shared.m_activityCondition.signal();
  69. while (m_shared.m_currentPhase == NoPhase)
  70. m_shared.m_phaseCondition.wait(m_shared.m_phaseLock);
  71. m_shared.m_numberOfActiveGCThreads++;
  72. return m_shared.m_currentPhase;
  73. }
  74. void GCThread::gcThreadMain()
  75. {
  76. GCPhase currentPhase;
  77. #if ENABLE(PARALLEL_GC)
  78. WTF::registerGCThread();
  79. #endif
  80. // Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before
  81. // creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
  82. {
  83. MutexLocker locker(m_shared.m_phaseLock);
  84. }
  85. {
  86. ParallelModeEnabler enabler(*m_slotVisitor);
  87. while ((currentPhase = waitForNextPhase()) != Exit) {
  88. // Note: Each phase is responsible for its own termination conditions. The comments below describe
  89. // how each phase reaches termination.
  90. switch (currentPhase) {
  91. case Mark:
  92. m_slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
  93. // GCThreads only return from drainFromShared() if the main thread sets the m_parallelMarkersShouldExit
  94. // flag in the GCThreadSharedData. The only way the main thread sets that flag is if it realizes
  95. // that all of the various subphases in Heap::markRoots() have been fully finished and there is
  96. // no more marking work to do and all of the GCThreads are idle, meaning no more work can be generated.
  97. break;
  98. case Copy:
  99. // We don't have to call startCopying() because it's called for us on the main thread to avoid a
  100. // race condition.
  101. m_copyVisitor->copyFromShared();
  102. // We know we're done copying when we return from copyFromShared() because we would
  103. // only do so if there were no more chunks of copying work left to do. When there is no
  104. // more copying work to do, the main thread will wait in CopiedSpace::doneCopying() until
  105. // all of the blocks that the GCThreads borrowed have been returned. doneCopying()
  106. // returns our borrowed CopiedBlock, allowing the copying phase to finish.
  107. m_copyVisitor->doneCopying();
  108. break;
  109. case NoPhase:
  110. RELEASE_ASSERT_NOT_REACHED();
  111. break;
  112. case Exit:
  113. RELEASE_ASSERT_NOT_REACHED();
  114. break;
  115. }
  116. }
  117. }
  118. }
  119. void GCThread::gcThreadStartFunc(void* data)
  120. {
  121. GCThread* thread = static_cast<GCThread*>(data);
  122. thread->gcThreadMain();
  123. }
  124. } // namespace JSC