JITManager.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  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_targetHandle(nullptr),
  29. m_jitConnectionId()
  30. {
  31. }
  32. JITManager::~JITManager()
  33. {
  34. if(m_targetHandle)
  35. {
  36. CleanupProcess();
  37. }
  38. if (m_rpcBindingHandle)
  39. {
  40. RpcBindingFree(&m_rpcBindingHandle);
  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. if (status != RPC_S_OK)
  150. {
  151. RpcBindingFree(&localBindingHandle);
  152. return HRESULT_FROM_WIN32(status);
  153. }
  154. *bindingHandle = localBindingHandle;
  155. return S_OK;
  156. }
  157. bool
  158. JITManager::IsJITServer() const
  159. {
  160. return m_isJITServer;
  161. }
  162. void
  163. JITManager::SetIsJITServer()
  164. {
  165. m_isJITServer = true;
  166. m_oopJitEnabled = true;
  167. }
  168. bool
  169. JITManager::IsConnected() const
  170. {
  171. Assert(IsOOPJITEnabled());
  172. return m_rpcBindingHandle != nullptr && m_targetHandle != nullptr;
  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. HANDLE
  185. JITManager::GetJITTargetHandle() const
  186. {
  187. if (!IsOOPJITEnabled())
  188. {
  189. return GetCurrentProcess();
  190. }
  191. Assert(m_targetHandle != nullptr);
  192. return m_targetHandle;
  193. }
  194. HRESULT
  195. JITManager::ConnectRpcServer(__in HANDLE jitProcessHandle, __in_opt void* serverSecurityDescriptor, __in UUID connectionUuid)
  196. {
  197. Assert(IsOOPJITEnabled());
  198. HRESULT hr;
  199. RPC_BINDING_HANDLE localBindingHandle;
  200. if (IsConnected() && (connectionUuid != m_jitConnectionId))
  201. {
  202. return E_FAIL;
  203. }
  204. hr = CreateBinding(jitProcessHandle, serverSecurityDescriptor, &connectionUuid, &localBindingHandle);
  205. HANDLE targetHandle;
  206. BOOL succeeded = DuplicateHandle(
  207. GetCurrentProcess(), GetCurrentProcess(),
  208. jitProcessHandle, &targetHandle,
  209. NULL, FALSE, DUPLICATE_SAME_ACCESS);
  210. if (!succeeded)
  211. {
  212. return HRESULT_FROM_WIN32(GetLastError());
  213. }
  214. m_targetHandle = targetHandle;
  215. m_rpcBindingHandle = localBindingHandle;
  216. m_jitConnectionId = connectionUuid;
  217. return hr;
  218. }
  219. HRESULT
  220. JITManager::CleanupProcess()
  221. {
  222. Assert(JITManager::IsOOPJITEnabled());
  223. HRESULT hr = E_FAIL;
  224. RpcTryExcept
  225. {
  226. hr = ClientCleanupProcess(m_rpcBindingHandle, (intptr_t)m_targetHandle);
  227. }
  228. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  229. {
  230. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  231. }
  232. RpcEndExcept;
  233. return hr;
  234. }
  235. HRESULT
  236. JITManager::Shutdown()
  237. {
  238. HRESULT hr = S_OK;
  239. Assert(IsOOPJITEnabled());
  240. RpcTryExcept
  241. {
  242. ClientShutdown(m_rpcBindingHandle);
  243. }
  244. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  245. {
  246. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  247. }
  248. RpcEndExcept;
  249. return hr;
  250. }
  251. HRESULT
  252. JITManager::InitializeThreadContext(
  253. __in ThreadContextDataIDL * data,
  254. __out intptr_t * threadContextInfoAddress,
  255. __out intptr_t * prereservedRegionAddr)
  256. {
  257. Assert(IsOOPJITEnabled());
  258. HRESULT hr = E_FAIL;
  259. RpcTryExcept
  260. {
  261. hr = ClientInitializeThreadContext(m_rpcBindingHandle, data, threadContextInfoAddress, prereservedRegionAddr);
  262. }
  263. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  264. {
  265. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  266. }
  267. RpcEndExcept;
  268. return hr;
  269. }
  270. HRESULT
  271. JITManager::CleanupThreadContext(
  272. __in intptr_t threadContextInfoAddress)
  273. {
  274. Assert(IsOOPJITEnabled());
  275. HRESULT hr = E_FAIL;
  276. RpcTryExcept
  277. {
  278. hr = ClientCleanupThreadContext(m_rpcBindingHandle, threadContextInfoAddress);
  279. }
  280. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  281. {
  282. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  283. }
  284. RpcEndExcept;
  285. return hr;
  286. }
  287. HRESULT
  288. JITManager::AddDOMFastPathHelper(
  289. __in intptr_t scriptContextInfoAddress,
  290. __in intptr_t funcInfoAddr,
  291. __in int helper)
  292. {
  293. Assert(IsOOPJITEnabled());
  294. HRESULT hr = E_FAIL;
  295. RpcTryExcept
  296. {
  297. hr = ClientAddDOMFastPathHelper(m_rpcBindingHandle, scriptContextInfoAddress, funcInfoAddr, helper);
  298. }
  299. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  300. {
  301. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  302. }
  303. RpcEndExcept;
  304. return hr;
  305. }
  306. HRESULT
  307. JITManager::SetIsPRNGSeeded(
  308. __in intptr_t scriptContextInfoAddress,
  309. __in boolean value)
  310. {
  311. HRESULT hr = E_FAIL;
  312. RpcTryExcept
  313. {
  314. hr = ClientSetIsPRNGSeeded(m_rpcBindingHandle, scriptContextInfoAddress, value);
  315. }
  316. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  317. {
  318. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  319. }
  320. RpcEndExcept;
  321. return hr;
  322. }
  323. HRESULT
  324. JITManager::DecommitInterpreterBufferManager(
  325. __in intptr_t scriptContextInfoAddress,
  326. __in boolean asmJsThunk)
  327. {
  328. Assert(IsOOPJITEnabled());
  329. HRESULT hr = E_FAIL;
  330. RpcTryExcept
  331. {
  332. hr = ClientDecommitInterpreterBufferManager(m_rpcBindingHandle, scriptContextInfoAddress, asmJsThunk);
  333. }
  334. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  335. {
  336. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  337. }
  338. RpcEndExcept;
  339. return hr;
  340. }
  341. HRESULT
  342. JITManager::NewInterpreterThunkBlock(
  343. __in intptr_t scriptContextInfoAddress,
  344. __in boolean asmJsThunk,
  345. __out InterpreterThunkInfoIDL * thunkInfo)
  346. {
  347. Assert(IsOOPJITEnabled());
  348. HRESULT hr = E_FAIL;
  349. RpcTryExcept
  350. {
  351. hr = ClientNewInterpreterThunkBlock(m_rpcBindingHandle, scriptContextInfoAddress, asmJsThunk, thunkInfo);
  352. }
  353. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  354. {
  355. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  356. }
  357. RpcEndExcept;
  358. return hr;
  359. }
  360. HRESULT
  361. JITManager::AddModuleRecordInfo(
  362. /* [in] */ intptr_t scriptContextInfoAddress,
  363. /* [in] */ unsigned int moduleId,
  364. /* [in] */ intptr_t localExportSlotsAddr)
  365. {
  366. Assert(IsOOPJITEnabled());
  367. HRESULT hr = E_FAIL;
  368. RpcTryExcept
  369. {
  370. hr = ClientAddModuleRecordInfo(m_rpcBindingHandle, scriptContextInfoAddress, moduleId, localExportSlotsAddr);
  371. }
  372. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  373. {
  374. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  375. }
  376. RpcEndExcept;
  377. return hr;
  378. }
  379. HRESULT
  380. JITManager::SetWellKnownHostTypeId(
  381. __in intptr_t threadContextRoot,
  382. __in int typeId)
  383. {
  384. Assert(IsOOPJITEnabled());
  385. HRESULT hr = E_FAIL;
  386. RpcTryExcept
  387. {
  388. hr = ClientSetWellKnownHostTypeId(m_rpcBindingHandle, threadContextRoot, typeId);
  389. }
  390. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  391. {
  392. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  393. }
  394. RpcEndExcept;
  395. return hr;
  396. }
  397. HRESULT
  398. JITManager::UpdatePropertyRecordMap(
  399. __in intptr_t threadContextInfoAddress,
  400. __in UpdatedPropertysIDL * updatedProps)
  401. {
  402. Assert(IsOOPJITEnabled());
  403. HRESULT hr = E_FAIL;
  404. RpcTryExcept
  405. {
  406. hr = ClientUpdatePropertyRecordMap(m_rpcBindingHandle, threadContextInfoAddress, updatedProps);
  407. }
  408. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  409. {
  410. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  411. }
  412. RpcEndExcept;
  413. return hr;
  414. }
  415. HRESULT
  416. JITManager::InitializeScriptContext(
  417. __in ScriptContextDataIDL * data,
  418. __in intptr_t threadContextInfoAddress,
  419. __out intptr_t * scriptContextInfoAddress)
  420. {
  421. Assert(IsOOPJITEnabled());
  422. HRESULT hr = E_FAIL;
  423. RpcTryExcept
  424. {
  425. hr = ClientInitializeScriptContext(m_rpcBindingHandle, data, threadContextInfoAddress, scriptContextInfoAddress);
  426. }
  427. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  428. {
  429. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  430. }
  431. RpcEndExcept;
  432. return hr;
  433. }
  434. HRESULT
  435. JITManager::CleanupScriptContext(
  436. __in intptr_t scriptContextInfoAddress)
  437. {
  438. Assert(IsOOPJITEnabled());
  439. HRESULT hr = E_FAIL;
  440. RpcTryExcept
  441. {
  442. hr = ClientCleanupScriptContext(m_rpcBindingHandle, scriptContextInfoAddress);
  443. }
  444. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  445. {
  446. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  447. }
  448. RpcEndExcept;
  449. return hr;
  450. }
  451. HRESULT
  452. JITManager::CloseScriptContext(
  453. __in intptr_t scriptContextInfoAddress)
  454. {
  455. Assert(IsOOPJITEnabled());
  456. HRESULT hr = E_FAIL;
  457. RpcTryExcept
  458. {
  459. hr = ClientCloseScriptContext(m_rpcBindingHandle, scriptContextInfoAddress);
  460. }
  461. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  462. {
  463. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  464. }
  465. RpcEndExcept;
  466. return hr;
  467. }
  468. HRESULT
  469. JITManager::FreeAllocation(
  470. __in intptr_t threadContextInfoAddress,
  471. __in intptr_t address)
  472. {
  473. Assert(IsOOPJITEnabled());
  474. HRESULT hr = E_FAIL;
  475. RpcTryExcept
  476. {
  477. hr = ClientFreeAllocation(m_rpcBindingHandle, threadContextInfoAddress, address);
  478. }
  479. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  480. {
  481. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  482. }
  483. RpcEndExcept;
  484. return hr;
  485. }
  486. #if DBG
  487. HRESULT
  488. JITManager::IsInterpreterThunkAddr(
  489. __in intptr_t scriptContextInfoAddress,
  490. __in intptr_t address,
  491. __in boolean asmjsThunk,
  492. __out boolean * result)
  493. {
  494. Assert(IsOOPJITEnabled());
  495. HRESULT hr = E_FAIL;
  496. RpcTryExcept
  497. {
  498. hr = ClientIsInterpreterThunkAddr(m_rpcBindingHandle, scriptContextInfoAddress, address, asmjsThunk, result);
  499. }
  500. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  501. {
  502. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  503. }
  504. RpcEndExcept;
  505. return hr;
  506. }
  507. #endif
  508. HRESULT
  509. JITManager::IsNativeAddr(
  510. __in intptr_t threadContextInfoAddress,
  511. __in intptr_t address,
  512. __out boolean * result)
  513. {
  514. Assert(IsOOPJITEnabled());
  515. HRESULT hr = E_FAIL;
  516. RpcTryExcept
  517. {
  518. hr = ClientIsNativeAddr(m_rpcBindingHandle, threadContextInfoAddress, address, result);
  519. }
  520. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  521. {
  522. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  523. }
  524. RpcEndExcept;
  525. return hr;
  526. }
  527. HRESULT
  528. JITManager::RemoteCodeGenCall(
  529. __in CodeGenWorkItemIDL *workItemData,
  530. __in intptr_t scriptContextInfoAddress,
  531. __out JITOutputIDL *jitData)
  532. {
  533. Assert(IsOOPJITEnabled());
  534. HRESULT hr = E_FAIL;
  535. RpcTryExcept
  536. {
  537. hr = ClientRemoteCodeGen(m_rpcBindingHandle, scriptContextInfoAddress, workItemData, jitData);
  538. }
  539. RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
  540. {
  541. hr = HRESULT_FROM_WIN32(RpcExceptionCode());
  542. }
  543. RpcEndExcept;
  544. return hr;
  545. }