PageAllocatorPool.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "Backend.h"
  6. #if ENABLE_OOP_NATIVE_CODEGEN
  7. #include "JITServer/JITServer.h"
  8. #include "PageAllocatorPool.h"
  9. CriticalSection PageAllocatorPool::cs;
  10. PageAllocatorPool* PageAllocatorPool::Instance = nullptr;
  11. PageAllocatorPool::PageAllocatorPool()
  12. :pageAllocators(&NoThrowHeapAllocator::Instance),
  13. idleCleanupTimer(NULL),
  14. activePageAllocatorCount(0)
  15. {
  16. idleCleanupTimer = CreateThreadpoolTimer(IdleCleanupRoutine, NULL, NULL);
  17. }
  18. PageAllocatorPool::~PageAllocatorPool()
  19. {
  20. AutoCriticalSection autoCS(&cs);
  21. RemoveAll();
  22. }
  23. void PageAllocatorPool::Initialize()
  24. {
  25. Instance = HeapNewNoThrow(PageAllocatorPool);
  26. if (Instance == nullptr)
  27. {
  28. Js::Throw::FatalInternalError();
  29. }
  30. }
  31. void PageAllocatorPool::Shutdown()
  32. {
  33. AutoCriticalSection autoCS(&cs);
  34. Assert(Instance);
  35. if (Instance)
  36. {
  37. PageAllocatorPool* localInstance = Instance;
  38. Instance = nullptr;
  39. if (localInstance->idleCleanupTimer)
  40. {
  41. CloseThreadpoolTimer(localInstance->idleCleanupTimer);
  42. }
  43. HeapDelete(localInstance);
  44. }
  45. }
  46. void PageAllocatorPool::RemoveAll()
  47. {
  48. Assert(cs.IsLocked());
  49. while (!pageAllocators.Empty())
  50. {
  51. HeapDelete(pageAllocators.Pop());
  52. }
  53. }
  54. unsigned int PageAllocatorPool::GetInactivePageAllocatorCount()
  55. {
  56. AutoCriticalSection autoCS(&cs);
  57. return pageAllocators.Count();
  58. }
  59. PageAllocator* PageAllocatorPool::GetPageAllocator()
  60. {
  61. AutoCriticalSection autoCS(&cs);
  62. PageAllocator* pageAllocator = nullptr;
  63. if (pageAllocators.Count() > 0)
  64. {
  65. // TODO: OOP JIT, select the page allocator with right count of free pages
  66. // base on some heuristic
  67. pageAllocator = this->pageAllocators.Pop();
  68. }
  69. else
  70. {
  71. pageAllocator = HeapNew(PageAllocator, nullptr, Js::Configuration::Global.flags, PageAllocatorType_BGJIT,
  72. AutoSystemInfo::Data.IsLowMemoryProcess() ? PageAllocator::DefaultLowMaxFreePageCount : PageAllocator::DefaultMaxFreePageCount);
  73. }
  74. activePageAllocatorCount++;
  75. return pageAllocator;
  76. }
  77. void PageAllocatorPool::ReturnPageAllocator(PageAllocator* pageAllocator)
  78. {
  79. AutoCriticalSection autoCS(&cs);
  80. if (!this->pageAllocators.PrependNoThrow(&NoThrowHeapAllocator::Instance, pageAllocator))
  81. {
  82. HeapDelete(pageAllocator);
  83. }
  84. activePageAllocatorCount--;
  85. if (activePageAllocatorCount == 0 || GetInactivePageAllocatorCount() > (uint)Js::Configuration::Global.flags.JITServerMaxInactivePageAllocatorCount)
  86. {
  87. PageAllocatorPool::IdleCleanup();
  88. }
  89. }
  90. void PageAllocatorPool::IdleCleanup()
  91. {
  92. AutoCriticalSection autoCS(&cs);
  93. if (Instance
  94. #ifdef PROFILE_EXEC
  95. // profiler keeps persistent reference to page allocators, so we can't cleanup on idle even if the allocators aren't currently being used for JIT
  96. && !Js::Configuration::Global.flags.IsEnabled(Js::ProfileFlag)
  97. #endif
  98. )
  99. {
  100. LARGE_INTEGER liDueTime;
  101. liDueTime.QuadPart = Js::Configuration::Global.flags.JITServerIdleTimeout * -10000LL; // wait for JITServerIdleTimeout milliseconds to do the cleanup
  102. if (Instance->idleCleanupTimer)
  103. {
  104. // Setting the timer cancels the previous timer, if any.
  105. SetThreadpoolTimer(Instance->idleCleanupTimer, (PFILETIME)&liDueTime, 0, 0);
  106. }
  107. else
  108. {
  109. Instance->RemoveAll();
  110. }
  111. }
  112. }
  113. VOID CALLBACK PageAllocatorPool::IdleCleanupRoutine(
  114. _Inout_ PTP_CALLBACK_INSTANCE,
  115. _Inout_opt_ PVOID,
  116. _Inout_ PTP_TIMER)
  117. {
  118. AutoCriticalSection autoCS(&cs);
  119. if (Instance)
  120. {
  121. // TODO: OOP JIT, use better stragtegy to do the cleanup, like do not remove all,
  122. // instead keep couple inactivate page allocator for next calls
  123. Instance->RemoveAll();
  124. }
  125. }
  126. #endif