JsrtRuntime.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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 <JsrtPch.h>
  6. #include "JsrtRuntime.h"
  7. #include "jsrtHelper.h"
  8. #include "Base/ThreadContextTlsEntry.h"
  9. #include "Base/ThreadBoundThreadContextManager.h"
  10. JsrtRuntime::JsrtRuntime(ThreadContext * threadContext, bool useIdle, bool dispatchExceptions)
  11. {
  12. Assert(threadContext != NULL);
  13. this->threadContext = threadContext;
  14. this->contextList = NULL;
  15. this->collectCallback = NULL;
  16. this->beforeCollectCallback = NULL;
  17. this->beforeCollectCallbackContext = NULL;
  18. #ifdef _CHAKRACOREBUILD
  19. this->beforeSweepCallback = NULL;
  20. this->beforeSweepCallbackContext = NULL;
  21. #endif
  22. this->allocationPolicyManager = threadContext->GetAllocationPolicyManager();
  23. this->useIdle = useIdle;
  24. this->dispatchExceptions = dispatchExceptions;
  25. if (useIdle)
  26. {
  27. this->threadService.Initialize(threadContext);
  28. }
  29. threadContext->SetJSRTRuntime(this);
  30. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  31. serializeByteCodeForLibrary = false;
  32. #endif
  33. #ifdef ENABLE_SCRIPT_DEBUGGING
  34. this->jsrtDebugManager = nullptr;
  35. #endif
  36. }
  37. JsrtRuntime::~JsrtRuntime()
  38. {
  39. HeapDelete(allocationPolicyManager);
  40. #ifdef ENABLE_SCRIPT_DEBUGGING
  41. if (this->jsrtDebugManager != nullptr)
  42. {
  43. HeapDelete(this->jsrtDebugManager);
  44. this->jsrtDebugManager = nullptr;
  45. }
  46. #endif
  47. }
  48. // This is called at process detach.
  49. // threadcontext created from runtime should not be destroyed in ThreadBoundThreadContext
  50. // we should clean them up at process detach only as runtime can be used in other threads
  51. // even after the current physical thread was destroyed.
  52. // This is called after ThreadBoundThreadContext are cleaned up, so the remaining items
  53. // in the globalthreadContext linklist should be for jsrt only.
  54. void JsrtRuntime::Uninitialize()
  55. {
  56. ThreadContext* currentThreadContext = ThreadContext::GetThreadContextList();
  57. ThreadContext* tmpThreadContext;
  58. while (currentThreadContext)
  59. {
  60. Assert(!currentThreadContext->IsScriptActive());
  61. JsrtRuntime* currentRuntime = static_cast<JsrtRuntime*>(currentThreadContext->GetJSRTRuntime());
  62. tmpThreadContext = currentThreadContext;
  63. currentThreadContext = currentThreadContext->Next();
  64. #ifdef CHAKRA_STATIC_LIBRARY
  65. // xplat-todo: Cleanup staticlib shutdown. This only shuts down threads.
  66. // Other closing contexts / finalizers having trouble with current
  67. // runtime/context.
  68. RentalThreadContextManager::DestroyThreadContext(tmpThreadContext);
  69. #else
  70. currentRuntime->CloseContexts();
  71. RentalThreadContextManager::DestroyThreadContext(tmpThreadContext);
  72. HeapDelete(currentRuntime);
  73. #endif
  74. }
  75. }
  76. void JsrtRuntime::CloseContexts()
  77. {
  78. while (this->contextList != NULL)
  79. {
  80. this->contextList->Dispose(false);
  81. // This will remove it from the list
  82. }
  83. }
  84. void JsrtRuntime::SetBeforeCollectCallback(JsBeforeCollectCallback beforeCollectCallback, void * callbackContext)
  85. {
  86. if (beforeCollectCallback != nullptr)
  87. {
  88. if (this->collectCallback == nullptr)
  89. {
  90. this->collectCallback = this->threadContext->AddRecyclerCollectCallBack(RecyclerCollectCallbackStatic, this);
  91. }
  92. this->beforeCollectCallback = beforeCollectCallback;
  93. this->beforeCollectCallbackContext = callbackContext;
  94. }
  95. else
  96. {
  97. if (this->collectCallback != nullptr
  98. #ifdef _CHAKRACOREBUILD
  99. && this->beforeSweepCallback == nullptr
  100. #endif
  101. )
  102. {
  103. this->threadContext->RemoveRecyclerCollectCallBack(this->collectCallback);
  104. this->collectCallback = nullptr;
  105. }
  106. this->beforeCollectCallback = nullptr;
  107. this->beforeCollectCallbackContext = nullptr;
  108. }
  109. }
  110. #ifdef _CHAKRACOREBUILD
  111. void JsrtRuntime::SetBeforeSweepCallback(JsBeforeSweepCallback afterCollectCallback, void * callbackContext)
  112. {
  113. if (afterCollectCallback != nullptr)
  114. {
  115. if (this->collectCallback == nullptr)
  116. {
  117. this->collectCallback = this->threadContext->AddRecyclerCollectCallBack(RecyclerCollectCallbackStatic, this);
  118. }
  119. this->beforeSweepCallback = afterCollectCallback;
  120. this->beforeSweepCallbackContext = callbackContext;
  121. }
  122. else
  123. {
  124. if (this->collectCallback != nullptr && this->beforeCollectCallback == nullptr)
  125. {
  126. this->threadContext->RemoveRecyclerCollectCallBack(this->collectCallback);
  127. this->collectCallback = nullptr;
  128. }
  129. this->beforeSweepCallback = nullptr;
  130. this->beforeSweepCallbackContext = nullptr;
  131. }
  132. }
  133. #endif
  134. void JsrtRuntime::RecyclerCollectCallbackStatic(void * context, RecyclerCollectCallBackFlags flags)
  135. {
  136. if (flags & Collect_Begin)
  137. {
  138. JsrtRuntime * _this = reinterpret_cast<JsrtRuntime *>(context);
  139. if (_this->beforeCollectCallback == nullptr)
  140. {
  141. return;
  142. }
  143. try
  144. {
  145. JsrtCallbackState scope(reinterpret_cast<ThreadContext*>(_this->GetThreadContext()));
  146. _this->beforeCollectCallback(_this->beforeCollectCallbackContext);
  147. }
  148. catch (...)
  149. {
  150. AssertMsg(false, "Unexpected non-engine exception.");
  151. }
  152. }
  153. #ifdef _CHAKRACOREBUILD
  154. else if (flags & Collect_Begin_Sweep)
  155. {
  156. JsrtRuntime * _this = reinterpret_cast<JsrtRuntime *>(context);
  157. if (_this->beforeSweepCallback == nullptr)
  158. {
  159. return;
  160. }
  161. try
  162. {
  163. JsrtCallbackState scope(reinterpret_cast<ThreadContext*>(_this->GetThreadContext()));
  164. _this->beforeSweepCallback(_this->beforeSweepCallbackContext);
  165. }
  166. catch (...)
  167. {
  168. AssertMsg(false, "Unexpected non-engine exception.");
  169. }
  170. }
  171. #endif
  172. }
  173. unsigned int JsrtRuntime::Idle()
  174. {
  175. return this->threadService.Idle();
  176. }
  177. #ifdef ENABLE_SCRIPT_DEBUGGING
  178. void JsrtRuntime::EnsureJsrtDebugManager()
  179. {
  180. if (this->jsrtDebugManager == nullptr)
  181. {
  182. this->jsrtDebugManager = HeapNew(JsrtDebugManager, this->threadContext);
  183. }
  184. Assert(this->jsrtDebugManager != nullptr);
  185. }
  186. void JsrtRuntime::DeleteJsrtDebugManager()
  187. {
  188. if (this->jsrtDebugManager != nullptr)
  189. {
  190. HeapDelete(this->jsrtDebugManager);
  191. this->jsrtDebugManager = nullptr;
  192. }
  193. }
  194. JsrtDebugManager * JsrtRuntime::GetJsrtDebugManager()
  195. {
  196. return this->jsrtDebugManager;
  197. }
  198. #if ENABLE_TTD
  199. uint32 JsrtRuntime::BPRegister_TTD(int64 bpID, Js::ScriptContext* scriptContext, Js::Utf8SourceInfo* utf8SourceInfo, uint32 line, uint32 column, BOOL* isNewBP)
  200. {
  201. TTDAssert(this->jsrtDebugManager != nullptr, "This needs to be setup before registering any breakpoints.");
  202. Js::BreakpointProbe* probe = this->jsrtDebugManager->SetBreakpointHelper_TTD(bpID, scriptContext, utf8SourceInfo, line, column, isNewBP);
  203. return probe->GetId();
  204. }
  205. void JsrtRuntime::BPDelete_TTD(uint32 bpID)
  206. {
  207. TTDAssert(this->jsrtDebugManager != nullptr, "This needs to be setup before deleting any breakpoints.");
  208. this->jsrtDebugManager->GetDebugDocumentManager()->RemoveBreakpoint(bpID);
  209. }
  210. void JsrtRuntime::BPClearDocument_TTD()
  211. {
  212. TTDAssert(this->jsrtDebugManager != nullptr, "This needs to be setup before deleting any breakpoints.");
  213. this->jsrtDebugManager->ClearBreakpointDebugDocumentDictionary();
  214. }
  215. #endif
  216. #endif