JITManager.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  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 "JITClientPch.h"
  6. _Must_inspect_result_
  7. _Ret_maybenull_ _Post_writable_byte_size_(size)
  8. void * __RPC_USER midl_user_allocate(
  9. #if defined(NTBUILD) || defined(_M_ARM)
  10. _In_ // starting win8, _In_ is in the signature
  11. #endif
  12. size_t size)
  13. {
  14. return (HeapAlloc(GetProcessHeap(), 0, size));
  15. }
  16. void __RPC_USER midl_user_free(_Pre_maybenull_ _Post_invalid_ void * ptr)
  17. {
  18. if (ptr != NULL)
  19. {
  20. HeapFree(GetProcessHeap(), NULL, ptr);
  21. }
  22. }
  23. JITManager JITManager::s_jitManager = JITManager();
  24. JITManager::JITManager() :
  25. m_rpcBindingHandle(nullptr),
  26. m_oopJitEnabled(false),
  27. m_isJITServer(false),
  28. m_serverHandle(nullptr),
  29. m_jitConnectionId()
  30. {
  31. }
  32. JITManager::~JITManager()
  33. {
  34. if (m_rpcBindingHandle)
  35. {
  36. RpcBindingFree(&m_rpcBindingHandle);
  37. }
  38. if (m_serverHandle)
  39. {
  40. CloseHandle(m_serverHandle);
  41. }
  42. }
  43. /* static */
  44. JITManager *
  45. JITManager::GetJITManager()
  46. {
  47. return &s_jitManager;
  48. }
  49. // This routine creates a binding with the server.
  50. HRESULT
  51. JITManager::CreateBinding(
  52. __in HANDLE serverProcessHandle,
  53. __in_opt void * serverSecurityDescriptor,
  54. __in UUID * connectionUuid,
  55. __out RPC_BINDING_HANDLE * bindingHandle)
  56. {
  57. Assert(IsOOPJITEnabled());
  58. RPC_STATUS status;
  59. DWORD attemptCount = 0;
  60. DWORD sleepInterval = 100; // in milliseconds
  61. RPC_BINDING_HANDLE localBindingHandle;
  62. RPC_BINDING_HANDLE_TEMPLATE_V1 bindingTemplate;
  63. RPC_BINDING_HANDLE_SECURITY_V1_W bindingSecurity;
  64. #ifndef NTBUILD
  65. RPC_SECURITY_QOS_V4 securityQOS;
  66. ZeroMemory(&securityQOS, sizeof(RPC_SECURITY_QOS_V4));
  67. securityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
  68. securityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
  69. securityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
  70. securityQOS.Version = 4;
  71. #else
  72. RPC_SECURITY_QOS_V5 securityQOS;
  73. ZeroMemory(&securityQOS, sizeof(RPC_SECURITY_QOS_V5));
  74. securityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
  75. securityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
  76. securityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
  77. securityQOS.Version = 5;
  78. securityQOS.ServerSecurityDescriptor = serverSecurityDescriptor;
  79. #endif // NTBUILD
  80. ZeroMemory(&bindingTemplate, sizeof(bindingTemplate));
  81. bindingTemplate.Version = 1;
  82. bindingTemplate.ProtocolSequence = RPC_PROTSEQ_LRPC;
  83. bindingTemplate.StringEndpoint = NULL;
  84. memcpy_s(&bindingTemplate.ObjectUuid, sizeof(UUID), connectionUuid, sizeof(UUID));
  85. bindingTemplate.Flags |= RPC_BHT_OBJECT_UUID_VALID;
  86. ZeroMemory(&bindingSecurity, sizeof(bindingSecurity));
  87. bindingSecurity.Version = 1;
  88. bindingSecurity.AuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  89. bindingSecurity.AuthnSvc = RPC_C_AUTHN_KERNEL;
  90. bindingSecurity.SecurityQos = (RPC_SECURITY_QOS*)&securityQOS;
  91. status = RpcBindingCreate(&bindingTemplate, &bindingSecurity, NULL, &localBindingHandle);
  92. if (status != RPC_S_OK)
  93. {
  94. return HRESULT_FROM_WIN32(status);
  95. }
  96. // We keep attempting to connect to the server with increasing wait intervals in between.
  97. // This will wait close to 5 minutes before it finally gives up.
  98. do
  99. {
  100. DWORD waitStatus;
  101. status = RpcBindingBind(NULL, localBindingHandle, ClientIChakraJIT_v0_0_c_ifspec);
  102. if (status == RPC_S_OK)
  103. {
  104. break;
  105. }
  106. else if (status == EPT_S_NOT_REGISTERED)
  107. {
  108. // The Server side has not finished registering the RPC Server yet.
  109. // We should only breakout if we have reached the max attempt count.
  110. if (attemptCount > 600)
  111. {
  112. break;
  113. }
  114. }
  115. else
  116. {
  117. // Some unknown error occurred. We are not going to retry for arbitrary errors.
  118. break;
  119. }
  120. // When we come to this point, it means the server has not finished registration yet.
  121. // We should wait for a while and then reattempt to bind.
  122. waitStatus = WaitForSingleObject(serverProcessHandle, sleepInterval);
  123. if (waitStatus == WAIT_OBJECT_0)
  124. {
  125. DWORD exitCode = (DWORD)-1;
  126. // The server process died for some reason. No need to reattempt.
  127. // We use -1 as the exit code if GetExitCodeProcess fails.
  128. Assert(GetExitCodeProcess(serverProcessHandle, &exitCode));
  129. status = RPC_S_SERVER_UNAVAILABLE;
  130. break;
  131. }
  132. else if (waitStatus == WAIT_TIMEOUT)
  133. {
  134. // Not an error. the server is still alive and we should reattempt.
  135. }
  136. else
  137. {
  138. // wait operation failed for an unknown reason.
  139. Assert(false);
  140. status = HRESULT_FROM_WIN32(waitStatus);
  141. break;
  142. }
  143. attemptCount++;
  144. if (sleepInterval < 500)
  145. {
  146. sleepInterval += 100;
  147. }
  148. } while (status != RPC_S_OK); // redundant check, but compiler would not allow true here.
  149. *bindingHandle = localBindingHandle;
  150. return HRESULT_FROM_WIN32(status);
  151. }
  152. bool
  153. JITManager::IsJITServer() const
  154. {
  155. return m_isJITServer;
  156. }
  157. void
  158. JITManager::SetIsJITServer()
  159. {
  160. m_isJITServer = true;
  161. m_oopJitEnabled = true;
  162. }
  163. bool
  164. JITManager::IsConnected() const
  165. {
  166. Assert(IsOOPJITEnabled());
  167. return m_rpcBindingHandle != nullptr;
  168. }
  169. HANDLE
  170. JITManager::GetServerHandle() const
  171. {
  172. return m_serverHandle;
  173. }
  174. void
  175. JITManager::EnableOOPJIT()
  176. {
  177. m_oopJitEnabled = true;
  178. }
  179. bool
  180. JITManager::IsOOPJITEnabled() const
  181. {
  182. return m_oopJitEnabled;
  183. }
  184. HRESULT
  185. JITManager::ConnectRpcServer(__in HANDLE jitProcessHandle, __in_opt void* serverSecurityDescriptor, __in UUID connectionUuid)
  186. {
  187. Assert(IsOOPJITEnabled());
  188. Assert(m_rpcBindingHandle == nullptr);
  189. Assert(m_serverHandle == nullptr);
  190. HRESULT hr = E_FAIL;
  191. if (IsConnected())
  192. {
  193. Assert(UNREACHED);
  194. return E_FAIL;
  195. }
  196. if (!DuplicateHandle(GetCurrentProcess(), jitProcessHandle, GetCurrentProcess(), &m_serverHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
  197. {
  198. hr = HRESULT_FROM_WIN32(GetLastError());
  199. goto FailureCleanup;
  200. }
  201. hr = CreateBinding(jitProcessHandle, serverSecurityDescriptor, &connectionUuid, &m_rpcBindingHandle);
  202. if (FAILED(hr))
  203. {
  204. goto FailureCleanup;
  205. }
  206. m_jitConnectionId = connectionUuid;
  207. return hr;
  208. FailureCleanup:
  209. if (m_serverHandle)
  210. {
  211. CloseHandle(m_serverHandle);
  212. m_serverHandle = nullptr;
  213. }
  214. if (m_rpcBindingHandle)
  215. {
  216. RpcBindingFree(&m_rpcBindingHandle);
  217. m_rpcBindingHandle = nullptr;
  218. }
  219. return hr;
  220. }
  221. HRESULT
  222. JITManager::Shutdown()
  223. {
  224. // this is special case of shutdown called when runtime process is a parent of the server process
  225. // used for console host type scenarios
  226. HRESULT hr = S_OK;
  227. Assert(IsOOPJITEnabled());
  228. Assert(m_rpcBindingHandle != nullptr);
  229. RpcTryExcept
  230. {
  231. ClientShutdown(m_rpcBindingHandle);
  232. }
  233. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  234. {
  235. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  236. }
  237. RpcEndExcept;
  238. m_rpcBindingHandle = nullptr;
  239. return hr;
  240. }
  241. HRESULT
  242. JITManager::InitializeThreadContext(
  243. __in ThreadContextDataIDL * data,
  244. __out PPTHREADCONTEXT_HANDLE threadContextInfoAddress,
  245. __out intptr_t * prereservedRegionAddr)
  246. {
  247. Assert(IsOOPJITEnabled());
  248. HRESULT hr = E_FAIL;
  249. RpcTryExcept
  250. {
  251. hr = ClientInitializeThreadContext(m_rpcBindingHandle, data, threadContextInfoAddress, prereservedRegionAddr);
  252. }
  253. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  254. {
  255. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  256. }
  257. RpcEndExcept;
  258. return hr;
  259. }
  260. HRESULT
  261. JITManager::CleanupThreadContext(
  262. __inout PPTHREADCONTEXT_HANDLE threadContextInfoAddress)
  263. {
  264. Assert(IsOOPJITEnabled());
  265. HRESULT hr = E_FAIL;
  266. RpcTryExcept
  267. {
  268. hr = ClientCleanupThreadContext(m_rpcBindingHandle, threadContextInfoAddress);
  269. }
  270. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  271. {
  272. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  273. }
  274. RpcEndExcept;
  275. return hr;
  276. }
  277. HRESULT
  278. JITManager::AddDOMFastPathHelper(
  279. __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  280. __in intptr_t funcInfoAddr,
  281. __in int helper)
  282. {
  283. Assert(IsOOPJITEnabled());
  284. HRESULT hr = E_FAIL;
  285. RpcTryExcept
  286. {
  287. hr = ClientAddDOMFastPathHelper(m_rpcBindingHandle, scriptContextInfoAddress, funcInfoAddr, helper);
  288. }
  289. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  290. {
  291. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  292. }
  293. RpcEndExcept;
  294. return hr;
  295. }
  296. HRESULT
  297. JITManager::SetIsPRNGSeeded(
  298. __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  299. __in boolean value)
  300. {
  301. HRESULT hr = E_FAIL;
  302. RpcTryExcept
  303. {
  304. hr = ClientSetIsPRNGSeeded(m_rpcBindingHandle, scriptContextInfoAddress, value);
  305. }
  306. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  307. {
  308. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  309. }
  310. RpcEndExcept;
  311. return hr;
  312. }
  313. HRESULT
  314. JITManager::DecommitInterpreterBufferManager(
  315. __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  316. __in boolean asmJsThunk)
  317. {
  318. Assert(IsOOPJITEnabled());
  319. HRESULT hr = E_FAIL;
  320. RpcTryExcept
  321. {
  322. hr = ClientDecommitInterpreterBufferManager(m_rpcBindingHandle, scriptContextInfoAddress, asmJsThunk);
  323. }
  324. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  325. {
  326. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  327. }
  328. RpcEndExcept;
  329. return hr;
  330. }
  331. HRESULT
  332. JITManager::NewInterpreterThunkBlock(
  333. __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  334. __in InterpreterThunkInputIDL * thunkInput,
  335. __out InterpreterThunkOutputIDL * thunkOutput)
  336. {
  337. Assert(IsOOPJITEnabled());
  338. HRESULT hr = E_FAIL;
  339. RpcTryExcept
  340. {
  341. hr = ClientNewInterpreterThunkBlock(m_rpcBindingHandle, scriptContextInfoAddress, thunkInput, thunkOutput);
  342. }
  343. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  344. {
  345. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  346. }
  347. RpcEndExcept;
  348. return hr;
  349. }
  350. HRESULT
  351. JITManager::AddModuleRecordInfo(
  352. /* [in] */ PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  353. /* [in] */ unsigned int moduleId,
  354. /* [in] */ intptr_t localExportSlotsAddr)
  355. {
  356. Assert(IsOOPJITEnabled());
  357. HRESULT hr = E_FAIL;
  358. RpcTryExcept
  359. {
  360. hr = ClientAddModuleRecordInfo(m_rpcBindingHandle, scriptContextInfoAddress, moduleId, localExportSlotsAddr);
  361. }
  362. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  363. {
  364. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  365. }
  366. RpcEndExcept;
  367. return hr;
  368. }
  369. HRESULT
  370. JITManager::SetWellKnownHostTypeId(
  371. __in PTHREADCONTEXT_HANDLE threadContextRoot,
  372. __in int typeId)
  373. {
  374. Assert(IsOOPJITEnabled());
  375. HRESULT hr = E_FAIL;
  376. RpcTryExcept
  377. {
  378. hr = ClientSetWellKnownHostTypeId(m_rpcBindingHandle, threadContextRoot, typeId);
  379. }
  380. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  381. {
  382. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  383. }
  384. RpcEndExcept;
  385. return hr;
  386. }
  387. HRESULT
  388. JITManager::UpdatePropertyRecordMap(
  389. __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  390. __in_opt BVSparseNodeIDL * updatedPropsBVHead)
  391. {
  392. Assert(IsOOPJITEnabled());
  393. HRESULT hr = E_FAIL;
  394. RpcTryExcept
  395. {
  396. hr = ClientUpdatePropertyRecordMap(m_rpcBindingHandle, threadContextInfoAddress, updatedPropsBVHead);
  397. }
  398. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  399. {
  400. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  401. }
  402. RpcEndExcept;
  403. return hr;
  404. }
  405. HRESULT
  406. JITManager::InitializeScriptContext(
  407. __in ScriptContextDataIDL * data,
  408. __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  409. __out PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  410. {
  411. Assert(IsOOPJITEnabled());
  412. HRESULT hr = E_FAIL;
  413. RpcTryExcept
  414. {
  415. hr = ClientInitializeScriptContext(m_rpcBindingHandle, data, threadContextInfoAddress, scriptContextInfoAddress);
  416. }
  417. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  418. {
  419. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  420. }
  421. RpcEndExcept;
  422. return hr;
  423. }
  424. HRESULT
  425. JITManager::CleanupScriptContext(
  426. __inout PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  427. {
  428. Assert(IsOOPJITEnabled());
  429. HRESULT hr = E_FAIL;
  430. RpcTryExcept
  431. {
  432. hr = ClientCleanupScriptContext(m_rpcBindingHandle, scriptContextInfoAddress);
  433. }
  434. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  435. {
  436. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  437. }
  438. RpcEndExcept;
  439. return hr;
  440. }
  441. HRESULT
  442. JITManager::CloseScriptContext(
  443. __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  444. {
  445. Assert(IsOOPJITEnabled());
  446. HRESULT hr = E_FAIL;
  447. RpcTryExcept
  448. {
  449. hr = ClientCloseScriptContext(m_rpcBindingHandle, scriptContextInfoAddress);
  450. }
  451. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  452. {
  453. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  454. }
  455. RpcEndExcept;
  456. return hr;
  457. }
  458. HRESULT
  459. JITManager::FreeAllocation(
  460. __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  461. __in intptr_t address)
  462. {
  463. Assert(IsOOPJITEnabled());
  464. HRESULT hr = E_FAIL;
  465. RpcTryExcept
  466. {
  467. hr = ClientFreeAllocation(m_rpcBindingHandle, threadContextInfoAddress, address);
  468. }
  469. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  470. {
  471. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  472. }
  473. RpcEndExcept;
  474. return hr;
  475. }
  476. HRESULT
  477. JITManager::IsNativeAddr(
  478. __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  479. __in intptr_t address,
  480. __out boolean * result)
  481. {
  482. Assert(IsOOPJITEnabled());
  483. HRESULT hr = E_FAIL;
  484. RpcTryExcept
  485. {
  486. hr = ClientIsNativeAddr(m_rpcBindingHandle, threadContextInfoAddress, address, result);
  487. }
  488. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  489. {
  490. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  491. }
  492. RpcEndExcept;
  493. return hr;
  494. }
  495. HRESULT
  496. JITManager::RemoteCodeGenCall(
  497. __in CodeGenWorkItemIDL *workItemData,
  498. __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  499. __out JITOutputIDL *jitData)
  500. {
  501. Assert(IsOOPJITEnabled());
  502. HRESULT hr = E_FAIL;
  503. RpcTryExcept
  504. {
  505. hr = ClientRemoteCodeGen(m_rpcBindingHandle, scriptContextInfoAddress, workItemData, jitData);
  506. }
  507. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  508. {
  509. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  510. }
  511. RpcEndExcept;
  512. return hr;
  513. }
  514. #if DBG
  515. HRESULT
  516. JITManager::IsInterpreterThunkAddr(
  517. __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  518. __in intptr_t address,
  519. __in boolean asmjsThunk,
  520. __out boolean * result)
  521. {
  522. Assert(IsOOPJITEnabled());
  523. HRESULT hr = E_FAIL;
  524. RpcTryExcept
  525. {
  526. hr = ClientIsInterpreterThunkAddr(m_rpcBindingHandle, scriptContextInfoAddress, address, asmjsThunk, result);
  527. }
  528. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  529. {
  530. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  531. }
  532. RpcEndExcept;
  533. return hr;
  534. }
  535. #endif