JITServer.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  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 "JITServerPch.h"
  6. __declspec(dllexport)
  7. HRESULT JsInitializeJITServer(
  8. __in UUID* connectionUuid,
  9. __in_opt void* securityDescriptor,
  10. __in_opt void* alpcSecurityDescriptor)
  11. {
  12. RPC_STATUS status;
  13. RPC_BINDING_VECTOR* bindingVector = NULL;
  14. UUID_VECTOR uuidVector;
  15. uuidVector.Count = 1;
  16. uuidVector.Uuid[0] = connectionUuid;
  17. status = RpcServerUseProtseqW(
  18. (RPC_WSTR)L"ncalrpc",
  19. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  20. alpcSecurityDescriptor);
  21. if (status != RPC_S_OK)
  22. {
  23. return status;
  24. }
  25. if (AutoSystemInfo::Data.IsWin8OrLater())
  26. {
  27. status = RPCLibrary::Instance->RpcServerRegisterIf3(
  28. ServerIChakraJIT_v0_0_s_ifspec,
  29. NULL,
  30. NULL,
  31. RPC_IF_AUTOLISTEN,
  32. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  33. (ULONG)-1,
  34. NULL,
  35. securityDescriptor);
  36. }
  37. else
  38. {
  39. status = RpcServerRegisterIf2(
  40. ServerIChakraJIT_v0_0_s_ifspec,
  41. NULL,
  42. NULL,
  43. RPC_IF_AUTOLISTEN,
  44. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  45. (ULONG)-1,
  46. NULL);
  47. }
  48. if (status != RPC_S_OK)
  49. {
  50. return status;
  51. }
  52. status = RpcServerInqBindings(&bindingVector);
  53. if (status != RPC_S_OK)
  54. {
  55. return status;
  56. }
  57. JITManager::GetJITManager()->SetIsJITServer();
  58. PageAllocatorPool::Initialize();
  59. status = RpcEpRegister(
  60. ServerIChakraJIT_v0_0_s_ifspec,
  61. bindingVector,
  62. &uuidVector,
  63. NULL);
  64. if (status != RPC_S_OK)
  65. {
  66. return status;
  67. }
  68. status = RpcBindingVectorFree(&bindingVector);
  69. if (status != RPC_S_OK)
  70. {
  71. return status;
  72. }
  73. status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
  74. return status;
  75. }
  76. HRESULT
  77. ShutdownCommon()
  78. {
  79. HRESULT status = RpcMgmtStopServerListening(NULL);
  80. if (status != RPC_S_OK)
  81. {
  82. return status;
  83. }
  84. status = RpcServerUnregisterIf(ServerIChakraJIT_v0_0_s_ifspec, NULL, FALSE);
  85. ServerContextManager::Shutdown();
  86. PageAllocatorPool::Shutdown();
  87. return status;
  88. }
  89. HRESULT
  90. ServerShutdown(
  91. /* [in] */ handle_t binding)
  92. {
  93. return ShutdownCommon();
  94. }
  95. void
  96. __RPC_USER PTHREADCONTEXT_HANDLE_rundown(__RPC__in PTHREADCONTEXT_HANDLE phContext)
  97. {
  98. ServerCleanupThreadContext(nullptr, &phContext);
  99. }
  100. void
  101. __RPC_USER PSCRIPTCONTEXT_HANDLE_rundown(__RPC__in PSCRIPTCONTEXT_HANDLE phContext)
  102. {
  103. ServerCloseScriptContext(nullptr, phContext);
  104. ServerCleanupScriptContext(nullptr, &phContext);
  105. }
  106. HRESULT
  107. ServerConnectProcess(
  108. handle_t binding,
  109. #ifdef USE_RPC_HANDLE_MARSHALLING
  110. HANDLE processHandle,
  111. #endif
  112. intptr_t chakraBaseAddress,
  113. intptr_t crtBaseAddress
  114. )
  115. {
  116. DWORD clientPid;
  117. HRESULT hr = HRESULT_FROM_WIN32(I_RpcBindingInqLocalClientPID(binding, &clientPid));
  118. if (FAILED(hr))
  119. {
  120. return hr;
  121. }
  122. #ifdef USE_RPC_HANDLE_MARSHALLING
  123. HANDLE targetHandle;
  124. if (!DuplicateHandle(GetCurrentProcess(), processHandle, GetCurrentProcess(), &targetHandle, 0, false, DUPLICATE_SAME_ACCESS))
  125. {
  126. Assert(UNREACHED);
  127. return E_ACCESSDENIED;
  128. }
  129. #else
  130. HANDLE targetHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_LIMITED_INFORMATION, false, clientPid);
  131. if (!targetHandle)
  132. {
  133. Assert(UNREACHED);
  134. return E_ACCESSDENIED;
  135. }
  136. #endif
  137. return ProcessContextManager::RegisterNewProcess(clientPid, targetHandle, chakraBaseAddress, crtBaseAddress);
  138. }
  139. #pragma warning(push)
  140. #pragma warning(disable:6387 28196) // PREFast does not understand the out context can be null here
  141. HRESULT
  142. ServerInitializeThreadContext(
  143. /* [in] */ handle_t binding,
  144. /* [in] */ __RPC__in ThreadContextDataIDL * threadContextData,
  145. /* [out] */ __RPC__deref_out_opt PPTHREADCONTEXT_HANDLE threadContextInfoAddress,
  146. /* [out] */ __RPC__out intptr_t *prereservedRegionAddr,
  147. /* [out] */ __RPC__out intptr_t *jitThunkAddr)
  148. {
  149. if (threadContextInfoAddress == nullptr || prereservedRegionAddr == nullptr)
  150. {
  151. Assert(false);
  152. return RPC_S_INVALID_ARG;
  153. }
  154. *threadContextInfoAddress = nullptr;
  155. *prereservedRegionAddr = 0;
  156. *jitThunkAddr = 0;
  157. ServerThreadContext * contextInfo = nullptr;
  158. DWORD clientPid;
  159. HRESULT hr = HRESULT_FROM_WIN32(I_RpcBindingInqLocalClientPID(binding, &clientPid));
  160. if (FAILED(hr))
  161. {
  162. return hr;
  163. }
  164. ProcessContext* processContext = ProcessContextManager::GetProcessContext(clientPid);
  165. if (processContext == nullptr)
  166. {
  167. return E_ACCESSDENIED;
  168. }
  169. try
  170. {
  171. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory));
  172. contextInfo = HeapNew(ServerThreadContext, threadContextData, processContext);
  173. ServerContextManager::RegisterThreadContext(contextInfo);
  174. }
  175. catch (Js::OutOfMemoryException)
  176. {
  177. if (contextInfo)
  178. {
  179. // If we OOM while registering the ThreadContext, we need to free it
  180. HeapDelete(contextInfo);
  181. }
  182. else
  183. {
  184. // If we OOM while creating the ThreadContext, then we haven't transfered ownership
  185. // of the ProcessContext reference, so we must release it here
  186. processContext->Release();
  187. }
  188. return E_OUTOFMEMORY;
  189. }
  190. return ServerCallWrapper(contextInfo, [&]()->HRESULT
  191. {
  192. if (clientPid != contextInfo->GetRuntimePid())
  193. {
  194. return E_ACCESSDENIED;
  195. }
  196. *threadContextInfoAddress = (PTHREADCONTEXT_HANDLE)EncodePointer(contextInfo);
  197. #if defined(_CONTROL_FLOW_GUARD)
  198. if (!PHASE_OFF1(Js::PreReservedHeapAllocPhase))
  199. {
  200. *prereservedRegionAddr = (intptr_t)contextInfo->GetPreReservedSectionAllocator()->EnsurePreReservedRegion();
  201. contextInfo->SetCanCreatePreReservedSegment(*prereservedRegionAddr != 0);
  202. }
  203. #if !defined(_M_ARM)
  204. *jitThunkAddr = (intptr_t)contextInfo->GetJITThunkEmitter()->EnsureInitialized();
  205. #endif
  206. #endif
  207. return hr;
  208. });
  209. }
  210. HRESULT
  211. ServerInitializeScriptContext(
  212. /* [in] */ handle_t binding,
  213. /* [in] */ __RPC__in ScriptContextDataIDL * scriptContextData,
  214. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  215. /* [out] */ __RPC__deref_out_opt PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  216. {
  217. if (scriptContextInfoAddress == nullptr || threadContextInfoAddress == nullptr)
  218. {
  219. Assert(false);
  220. return RPC_S_INVALID_ARG;
  221. }
  222. *scriptContextInfoAddress = nullptr;
  223. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  224. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  225. {
  226. ServerScriptContext * contextInfo = HeapNew(ServerScriptContext, scriptContextData, threadContextInfo);
  227. ServerContextManager::RegisterScriptContext(contextInfo);
  228. *scriptContextInfoAddress = (PSCRIPTCONTEXT_HANDLE)EncodePointer(contextInfo);
  229. #if !FLOATVAR
  230. // TODO: should move this to ServerInitializeThreadContext, also for the fields in IDL
  231. XProcNumberPageSegmentImpl::Initialize(contextInfo->IsRecyclerVerifyEnabled(), contextInfo->GetRecyclerVerifyPad());
  232. #endif
  233. return S_OK;
  234. });
  235. }
  236. #pragma warning(pop)
  237. HRESULT
  238. ServerCleanupThreadContext(
  239. /* [in] */ handle_t binding,
  240. /* [in] */ __RPC__deref_inout_opt PPTHREADCONTEXT_HANDLE threadContextInfoAddress)
  241. {
  242. if (threadContextInfoAddress == nullptr)
  243. {
  244. Assert(false);
  245. return RPC_S_INVALID_ARG;
  246. }
  247. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(*threadContextInfoAddress);
  248. if (threadContextInfo == nullptr)
  249. {
  250. Assert(false);
  251. return RPC_S_INVALID_ARG;
  252. }
  253. // This tells the run-time, when it is marshalling the out
  254. // parameters, that the context handle has been closed normally.
  255. *threadContextInfoAddress = nullptr;
  256. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  257. {
  258. threadContextInfo->Close();
  259. ServerContextManager::UnRegisterThreadContext(threadContextInfo);
  260. return S_OK;
  261. });
  262. }
  263. HRESULT
  264. ServerUpdatePropertyRecordMap(
  265. /* [in] */ handle_t binding,
  266. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  267. /* [in] */ __RPC__in_opt BVSparseNodeIDL * updatedPropsBVHead)
  268. {
  269. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  270. if (threadContextInfo == nullptr)
  271. {
  272. Assert(false);
  273. return RPC_S_INVALID_ARG;
  274. }
  275. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  276. {
  277. typedef ServerThreadContext::BVSparseNode BVSparseNode;
  278. CompileAssert(sizeof(BVSparseNode) == sizeof(BVSparseNodeIDL));
  279. threadContextInfo->UpdateNumericPropertyBV((BVSparseNode*)updatedPropsBVHead);
  280. return S_OK;
  281. });
  282. }
  283. HRESULT
  284. ServerAddDOMFastPathHelper(
  285. /* [in] */ handle_t binding,
  286. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  287. /* [in] */ intptr_t funcInfoAddr,
  288. /* [in] */ int helper)
  289. {
  290. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  291. if (scriptContextInfo == nullptr)
  292. {
  293. Assert(false);
  294. return RPC_S_INVALID_ARG;
  295. }
  296. if (helper < 0 || helper >= IR::JnHelperMethodCount)
  297. {
  298. Assert(UNREACHED);
  299. return E_ACCESSDENIED;
  300. }
  301. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  302. {
  303. scriptContextInfo->AddToDOMFastPathHelperMap(funcInfoAddr, (IR::JnHelperMethod)helper);
  304. return S_OK;
  305. });
  306. }
  307. HRESULT
  308. ServerAddModuleRecordInfo(
  309. /* [in] */ handle_t binding,
  310. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  311. /* [in] */ unsigned int moduleId,
  312. /* [in] */ intptr_t localExportSlotsAddr)
  313. {
  314. ServerScriptContext * serverScriptContext = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  315. if (serverScriptContext == nullptr)
  316. {
  317. Assert(false);
  318. return RPC_S_INVALID_ARG;
  319. }
  320. return ServerCallWrapper(serverScriptContext, [&]()->HRESULT
  321. {
  322. serverScriptContext->AddModuleRecordInfo(moduleId, localExportSlotsAddr);
  323. return S_OK;
  324. });
  325. }
  326. HRESULT
  327. ServerSetWellKnownHostTypeId(
  328. /* [in] */ handle_t binding,
  329. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  330. /* [in] */ int typeId)
  331. {
  332. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  333. if (threadContextInfo == nullptr)
  334. {
  335. Assert(false);
  336. return RPC_S_INVALID_ARG;
  337. }
  338. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  339. {
  340. threadContextInfo->SetWellKnownHostTypeId((Js::TypeId)typeId);
  341. return S_OK;
  342. });
  343. }
  344. HRESULT
  345. ServerCleanupScriptContext(
  346. /* [in] */ handle_t binding,
  347. /* [in] */ __RPC__deref_inout_opt PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  348. {
  349. if (scriptContextInfoAddress == nullptr)
  350. {
  351. Assert(false);
  352. return RPC_S_INVALID_ARG;
  353. }
  354. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(*scriptContextInfoAddress);
  355. if (scriptContextInfo == nullptr)
  356. {
  357. Assert(false);
  358. return RPC_S_INVALID_ARG;
  359. }
  360. if (!scriptContextInfo->IsClosed())
  361. {
  362. scriptContextInfo->Close();
  363. ServerContextManager::UnRegisterScriptContext(scriptContextInfo);
  364. }
  365. // This tells the run-time, when it is marshalling the out
  366. // parameters, that the context handle has been closed normally.
  367. *scriptContextInfoAddress = nullptr;
  368. HeapDelete(scriptContextInfo);
  369. return S_OK;
  370. }
  371. HRESULT
  372. ServerCloseScriptContext(
  373. /* [in] */ handle_t binding,
  374. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  375. {
  376. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  377. if (scriptContextInfo == nullptr)
  378. {
  379. Assert(false);
  380. return RPC_S_INVALID_ARG;
  381. }
  382. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  383. {
  384. #ifdef PROFILE_EXEC
  385. scriptContextInfo->GetFirstCodeGenProfiler()->ProfilePrint();
  386. #endif
  387. scriptContextInfo->Close();
  388. ServerContextManager::UnRegisterScriptContext(scriptContextInfo);
  389. return S_OK;
  390. });
  391. }
  392. HRESULT
  393. ServerDecommitInterpreterBufferManager(
  394. /* [in] */ handle_t binding,
  395. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  396. /* [in] */ boolean asmJsManager)
  397. {
  398. ServerScriptContext * scriptContext = (ServerScriptContext *)DecodePointer((void*)scriptContextInfoAddress);
  399. if (scriptContext == nullptr)
  400. {
  401. Assert(false);
  402. return RPC_S_INVALID_ARG;
  403. }
  404. return ServerCallWrapper(scriptContext, [&]()->HRESULT
  405. {
  406. scriptContext->DecommitEmitBufferManager(asmJsManager != FALSE);
  407. return S_OK;
  408. });
  409. }
  410. HRESULT
  411. ServerNewInterpreterThunkBlock(
  412. /* [in] */ handle_t binding,
  413. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfo,
  414. /* [in] */ __RPC__in InterpreterThunkInputIDL * thunkInput,
  415. /* [out] */ __RPC__out InterpreterThunkOutputIDL * thunkOutput)
  416. {
  417. memset(thunkOutput, 0, sizeof(InterpreterThunkOutputIDL));
  418. ServerScriptContext * scriptContext = (ServerScriptContext *)DecodePointer(scriptContextInfo);
  419. if (scriptContext == nullptr)
  420. {
  421. Assert(false);
  422. return RPC_S_INVALID_ARG;
  423. }
  424. return ServerCallWrapper(scriptContext, [&]()->HRESULT
  425. {
  426. ServerThreadContext * threadContext = scriptContext->GetThreadContext();
  427. class AutoLocalAlloc
  428. {
  429. public:
  430. AutoLocalAlloc(ServerThreadContext * threadContext) : localAddress(nullptr), threadContext(threadContext) { }
  431. ~AutoLocalAlloc()
  432. {
  433. if (localAddress)
  434. {
  435. threadContext->GetCodePageAllocators()->FreeLocal(this->localAddress, this->segment);
  436. }
  437. }
  438. char * localAddress;
  439. void * segment;
  440. ServerThreadContext * threadContext;
  441. } localAlloc(threadContext);
  442. OOPEmitBufferManagerWithLock * emitBufferManager = scriptContext->GetEmitBufferManager(thunkInput->asmJsThunk != FALSE);
  443. BYTE* runtimeAddress;
  444. EmitBufferAllocation<SectionAllocWrapper, PreReservedSectionAllocWrapper> * alloc = emitBufferManager->AllocateBuffer(InterpreterThunkEmitter::BlockSize, &runtimeAddress);
  445. CompileAssert(InterpreterThunkEmitter::BlockSize <= CustomHeap::Page::MaxAllocationSize);
  446. localAlloc.segment = alloc->allocation->page->segment;
  447. localAlloc.localAddress = threadContext->GetCodePageAllocators()->AllocLocal((char*)runtimeAddress, InterpreterThunkEmitter::BlockSize, localAlloc.segment);
  448. if (!localAlloc.localAddress)
  449. {
  450. Js::Throw::OutOfMemory();
  451. }
  452. #if PDATA_ENABLED
  453. PRUNTIME_FUNCTION pdataStart = {0};
  454. intptr_t epilogEnd = 0;
  455. #endif
  456. DWORD thunkCount = 0;
  457. InterpreterThunkEmitter::FillBuffer(
  458. threadContext,
  459. thunkInput->asmJsThunk != FALSE,
  460. (intptr_t)runtimeAddress,
  461. InterpreterThunkEmitter::BlockSize,
  462. (BYTE*)localAlloc.localAddress,
  463. #if PDATA_ENABLED
  464. &pdataStart,
  465. &epilogEnd,
  466. #endif
  467. &thunkCount
  468. );
  469. if (!emitBufferManager->CommitBufferForInterpreter(alloc, runtimeAddress, InterpreterThunkEmitter::BlockSize))
  470. {
  471. Js::Throw::OutOfMemory();
  472. }
  473. // Call to set VALID flag for CFG check
  474. if (CONFIG_FLAG(OOPCFGRegistration))
  475. {
  476. emitBufferManager->SetValidCallTarget(alloc, runtimeAddress, true);
  477. }
  478. thunkOutput->thunkCount = thunkCount;
  479. thunkOutput->mappedBaseAddr = (intptr_t)runtimeAddress;
  480. #if PDATA_ENABLED
  481. thunkOutput->pdataTableStart = (intptr_t)pdataStart;
  482. thunkOutput->epilogEndAddr = epilogEnd;
  483. #endif
  484. return S_OK;
  485. });
  486. }
  487. #if DBG
  488. HRESULT
  489. ServerIsInterpreterThunkAddr(
  490. /* [in] */ handle_t binding,
  491. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  492. /* [in] */ intptr_t address,
  493. /* [in] */ boolean asmjsThunk,
  494. /* [out] */ __RPC__out boolean * result)
  495. {
  496. ServerScriptContext * context = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress);
  497. if (context == nullptr)
  498. {
  499. *result = false;
  500. return RPC_S_INVALID_ARG;
  501. }
  502. OOPEmitBufferManagerWithLock * manager = context->GetEmitBufferManager(asmjsThunk != FALSE);
  503. if (manager == nullptr)
  504. {
  505. *result = false;
  506. return S_OK;
  507. }
  508. *result = manager->IsInHeap((void*)address);
  509. return S_OK;
  510. }
  511. #endif
  512. HRESULT
  513. ServerFreeAllocation(
  514. /* [in] */ handle_t binding,
  515. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfo,
  516. /* [in] */ intptr_t codeAddress)
  517. {
  518. ServerScriptContext* context = (ServerScriptContext*)DecodePointer(scriptContextInfo);
  519. if (context == nullptr)
  520. {
  521. Assert(false);
  522. return RPC_S_INVALID_ARG;
  523. }
  524. return ServerCallWrapper(context, [&]()->HRESULT
  525. {
  526. context->GetCodeGenAllocators()->emitBufferManager.FreeAllocation((void*)codeAddress);
  527. return S_OK;
  528. });
  529. }
  530. HRESULT
  531. ServerIsNativeAddr(
  532. /* [in] */ handle_t binding,
  533. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfo,
  534. /* [in] */ intptr_t address,
  535. /* [out] */ __RPC__out boolean * result)
  536. {
  537. if (result == nullptr)
  538. {
  539. Assert(false);
  540. return RPC_S_INVALID_ARG;
  541. }
  542. *result = false;
  543. ServerThreadContext* context = (ServerThreadContext*)DecodePointer(threadContextInfo);
  544. if (context == nullptr)
  545. {
  546. Assert(false);
  547. return RPC_S_INVALID_ARG;
  548. }
  549. return ServerCallWrapper(context, [&]()->HRESULT
  550. {
  551. PreReservedSectionAllocWrapper *preReservedAllocWrapper = context->GetPreReservedSectionAllocator();
  552. if (preReservedAllocWrapper->IsInRange((void*)address))
  553. {
  554. *result = true;
  555. }
  556. else if (!context->IsAllJITCodeInPreReservedRegion())
  557. {
  558. AutoCriticalSection autoLock(&context->GetCodePageAllocators()->cs);
  559. *result = context->GetCodePageAllocators()->IsInNonPreReservedPageAllocator((void*)address);
  560. }
  561. else
  562. {
  563. *result = false;
  564. }
  565. return S_OK;
  566. });
  567. }
  568. HRESULT
  569. ServerSetIsPRNGSeeded(
  570. /* [in] */ handle_t binding,
  571. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  572. /* [in] */ boolean value)
  573. {
  574. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  575. if (scriptContextInfo == nullptr)
  576. {
  577. Assert(false);
  578. return RPC_S_INVALID_ARG;
  579. }
  580. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  581. {
  582. scriptContextInfo->SetIsPRNGSeeded(value != FALSE);
  583. return S_OK;
  584. });
  585. }
  586. HRESULT
  587. ServerRemoteCodeGen(
  588. /* [in] */ handle_t binding,
  589. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  590. /* [in] */ __RPC__in CodeGenWorkItemIDL *workItemData,
  591. /* [out] */ __RPC__out JITOutputIDL *jitData)
  592. {
  593. memset(jitData, 0, sizeof(JITOutputIDL));
  594. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  595. if (scriptContextInfo == nullptr)
  596. {
  597. Assert(false);
  598. return RPC_S_INVALID_ARG;
  599. }
  600. #if DBG
  601. size_t serializedRpcDataSize = 0;
  602. const unsigned char* serializedRpcData = nullptr;
  603. JITManager::SerializeRPCData(workItemData, &serializedRpcDataSize, &serializedRpcData);
  604. struct AutoFreeArray
  605. {
  606. const byte* arr = nullptr;
  607. size_t bufferSize = 0;
  608. ~AutoFreeArray() { HeapDeleteArray(bufferSize, arr); }
  609. } autoFreeArray;
  610. autoFreeArray.arr = serializedRpcData;
  611. autoFreeArray.bufferSize = serializedRpcDataSize;
  612. #endif
  613. return ServerCallWrapper(scriptContextInfo, [&]() ->HRESULT
  614. {
  615. LARGE_INTEGER start_time = { 0 };
  616. if (PHASE_TRACE1(Js::BackEndPhase))
  617. {
  618. QueryPerformanceCounter(&start_time);
  619. }
  620. scriptContextInfo->UpdateGlobalObjectThisAddr(workItemData->globalThisAddr);
  621. ServerThreadContext * threadContextInfo = scriptContextInfo->GetThreadContext();
  622. AutoReturnPageAllocator autoReturnPageAllocator;
  623. PageAllocator* pageAllocator = autoReturnPageAllocator.GetPageAllocator();
  624. NoRecoverMemoryJitArenaAllocator jitArena(L"JITArena", pageAllocator, Js::Throw::OutOfMemory);
  625. #if DBG
  626. jitArena.SetNeedsDelayFreeList();
  627. #endif
  628. JITTimeWorkItem * jitWorkItem = Anew(&jitArena, JITTimeWorkItem, workItemData);
  629. if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId()))
  630. {
  631. LARGE_INTEGER freq;
  632. LARGE_INTEGER end_time;
  633. QueryPerformanceCounter(&end_time);
  634. QueryPerformanceFrequency(&freq);
  635. Output::Print(
  636. L"BackendMarshalIn - function: %s time:%8.6f mSec\r\n",
  637. jitWorkItem->GetJITFunctionBody()->GetDisplayName(),
  638. (((double)((end_time.QuadPart - workItemData->startTime)* (double)1000.0 / (double)freq.QuadPart))) / (1));
  639. Output::Flush();
  640. }
  641. #ifdef PROFILE_EXEC
  642. Js::ScriptContextProfiler* profiler = scriptContextInfo->GetCodeGenProfiler(pageAllocator);
  643. #else
  644. Js::ScriptContextProfiler* profiler = nullptr;
  645. #endif
  646. #if !FLOATVAR
  647. if (jitWorkItem->GetWorkItemData()->xProcNumberPageSegment)
  648. {
  649. jitData->numberPageSegments = (XProcNumberPageSegment*)midl_user_allocate(sizeof(XProcNumberPageSegment));
  650. if (!jitData->numberPageSegments)
  651. {
  652. return E_OUTOFMEMORY;
  653. }
  654. __analysis_assume(jitData->numberPageSegments);
  655. memcpy_s(jitData->numberPageSegments, sizeof(XProcNumberPageSegment), jitWorkItem->GetWorkItemData()->xProcNumberPageSegment, sizeof(XProcNumberPageSegment));
  656. }
  657. #endif
  658. Func::Codegen(
  659. &jitArena,
  660. jitWorkItem,
  661. threadContextInfo,
  662. scriptContextInfo,
  663. jitData,
  664. nullptr,
  665. nullptr,
  666. jitWorkItem->GetPolymorphicInlineCacheInfo(),
  667. scriptContextInfo->GetCodeGenAllocators(),
  668. #if !FLOATVAR
  669. nullptr, // number allocator
  670. #endif
  671. profiler,
  672. true);
  673. #ifdef PROFILE_EXEC
  674. if (profiler && profiler->IsInitialized())
  675. {
  676. profiler->ProfilePrint(Js::Configuration::Global.flags.Profile.GetFirstPhase());
  677. }
  678. #endif
  679. if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId()))
  680. {
  681. LARGE_INTEGER freq;
  682. LARGE_INTEGER end_time;
  683. QueryPerformanceCounter(&end_time);
  684. QueryPerformanceFrequency(&freq);
  685. Output::Print(
  686. L"EndBackEndInner - function: %s time:%8.6f mSec\r\n",
  687. jitWorkItem->GetJITFunctionBody()->GetDisplayName(),
  688. (((double)((end_time.QuadPart - start_time.QuadPart)* (double)1000.0 / (double)freq.QuadPart))) / (1));
  689. Output::Flush();
  690. }
  691. LARGE_INTEGER out_time = { 0 };
  692. if (PHASE_TRACE1(Js::BackEndPhase))
  693. {
  694. QueryPerformanceCounter(&out_time);
  695. jitData->startTime = out_time.QuadPart;
  696. }
  697. Assert(jitData->codeAddress);
  698. Assert(jitData->codeSize);
  699. return S_OK;
  700. });
  701. }
  702. JsUtil::BaseHashSet<ServerThreadContext*, HeapAllocator> ServerContextManager::threadContexts(&HeapAllocator::Instance);
  703. JsUtil::BaseHashSet<ServerScriptContext*, HeapAllocator> ServerContextManager::scriptContexts(&HeapAllocator::Instance);
  704. CriticalSection ServerContextManager::cs;
  705. BaseDictionary<DWORD, ProcessContext*, HeapAllocator> ProcessContextManager::ProcessContexts(&HeapAllocator::Instance);
  706. CriticalSection ProcessContextManager::cs;
  707. HRESULT
  708. ProcessContextManager::RegisterNewProcess(DWORD pid, HANDLE processHandle, intptr_t chakraBaseAddress, intptr_t crtBaseAddress)
  709. {
  710. AutoCriticalSection autoCS(&cs);
  711. for (auto iter = ProcessContexts.GetIteratorWithRemovalSupport(); iter.IsValid(); iter.MoveNext())
  712. {
  713. ProcessContext* context = iter.CurrentValue();
  714. // We can delete a ProcessContext if no ThreadContexts refer to it and the process is terminated
  715. if (!context->HasRef() && WaitForSingleObject(context->processHandle, 0) == WAIT_OBJECT_0)
  716. {
  717. iter.RemoveCurrent();
  718. HeapDelete(context);
  719. }
  720. }
  721. // We cannot register multiple ProcessContexts for a single process
  722. if (ProcessContexts.ContainsKey(pid))
  723. {
  724. Assert(UNREACHED);
  725. return E_ACCESSDENIED;
  726. }
  727. ProcessContext* context = nullptr;
  728. try
  729. {
  730. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory));
  731. context = HeapNew(ProcessContext, processHandle, chakraBaseAddress, crtBaseAddress);
  732. ProcessContexts.Add(pid, context);
  733. }
  734. catch (Js::OutOfMemoryException)
  735. {
  736. if (context != nullptr)
  737. {
  738. // If we OOM while registering the ProcessContext, we should free it
  739. HeapDelete(context);
  740. }
  741. return E_OUTOFMEMORY;
  742. }
  743. return S_OK;
  744. }
  745. ProcessContext*
  746. ProcessContextManager::GetProcessContext(DWORD pid)
  747. {
  748. AutoCriticalSection autoCS(&cs);
  749. ProcessContext* context = nullptr;
  750. // It is possible that we don't have a ProcessContext for a pid in case ProcessContext initialization failed,
  751. // or if the calling process terminated and the ProcessContext was already cleaned up before we got here
  752. if (ProcessContexts.ContainsKey(pid))
  753. {
  754. context = ProcessContexts.Item(pid);
  755. context->AddRef();
  756. }
  757. return context;
  758. }
  759. #ifdef STACK_BACK_TRACE
  760. SList<ServerContextManager::ClosedContextEntry<ServerThreadContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedThreadContextList(&NoThrowHeapAllocator::Instance);
  761. SList<ServerContextManager::ClosedContextEntry<ServerScriptContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedScriptContextList(&NoThrowHeapAllocator::Instance);
  762. #endif
  763. void ServerContextManager::RegisterThreadContext(ServerThreadContext* threadContext)
  764. {
  765. AutoCriticalSection autoCS(&cs);
  766. threadContexts.Add(threadContext);
  767. }
  768. void ServerContextManager::UnRegisterThreadContext(ServerThreadContext* threadContext)
  769. {
  770. AutoCriticalSection autoCS(&cs);
  771. threadContexts.Remove(threadContext);
  772. auto iter = scriptContexts.GetIteratorWithRemovalSupport();
  773. while (iter.IsValid())
  774. {
  775. ServerScriptContext* scriptContext = iter.Current().Key();
  776. if (scriptContext->GetThreadContext() == threadContext)
  777. {
  778. if (!scriptContext->IsClosed())
  779. {
  780. scriptContext->Close();
  781. }
  782. iter.RemoveCurrent();
  783. }
  784. iter.MoveNext();
  785. }
  786. }
  787. void ServerContextManager::RegisterScriptContext(ServerScriptContext* scriptContext)
  788. {
  789. AutoCriticalSection autoCS(&cs);
  790. scriptContexts.Add(scriptContext);
  791. }
  792. void ServerContextManager::UnRegisterScriptContext(ServerScriptContext* scriptContext)
  793. {
  794. AutoCriticalSection autoCS(&cs);
  795. scriptContexts.Remove(scriptContext);
  796. }
  797. bool ServerContextManager::CheckLivenessAndAddref(ServerScriptContext* context)
  798. {
  799. AutoCriticalSection autoCS(&cs);
  800. if (scriptContexts.LookupWithKey(context))
  801. {
  802. if (!context->IsClosed() && !context->GetThreadContext()->IsClosed())
  803. {
  804. context->AddRef();
  805. context->GetThreadContext()->AddRef();
  806. return true;
  807. }
  808. }
  809. return false;
  810. }
  811. bool ServerContextManager::CheckLivenessAndAddref(ServerThreadContext* context)
  812. {
  813. AutoCriticalSection autoCS(&cs);
  814. if (threadContexts.LookupWithKey(context))
  815. {
  816. if (!context->IsClosed())
  817. {
  818. context->AddRef();
  819. return true;
  820. }
  821. }
  822. return false;
  823. }
  824. template<typename Fn>
  825. HRESULT ServerCallWrapper(ServerThreadContext* threadContextInfo, Fn fn)
  826. {
  827. MemoryOperationLastError::ClearLastError();
  828. HRESULT hr = S_OK;
  829. try
  830. {
  831. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow));
  832. AutoReleaseThreadContext autoThreadContext(threadContextInfo);
  833. hr = fn();
  834. }
  835. catch (ContextClosedException&)
  836. {
  837. hr = E_ACCESSDENIED;
  838. }
  839. catch (Js::OutOfMemoryException)
  840. {
  841. hr = E_OUTOFMEMORY;
  842. }
  843. catch (Js::StackOverflowException)
  844. {
  845. hr = VBSERR_OutOfStack;
  846. }
  847. catch (Js::OperationAbortedException)
  848. {
  849. hr = E_ABORT;
  850. }
  851. catch (...)
  852. {
  853. AssertOrFailFastMsg(false, "Unknown exception caught in JIT server call.");
  854. }
  855. if (hr == S_OK)
  856. {
  857. return MemoryOperationLastError::GetLastError();
  858. }
  859. return hr;
  860. }
  861. template<typename Fn>
  862. HRESULT ServerCallWrapper(ServerScriptContext* scriptContextInfo, Fn fn)
  863. {
  864. try
  865. {
  866. AutoReleaseScriptContext autoScriptContext(scriptContextInfo);
  867. ServerThreadContext* threadContextInfo = scriptContextInfo->GetThreadContext();
  868. return ServerCallWrapper(threadContextInfo, fn);
  869. }
  870. catch (ContextClosedException&)
  871. {
  872. return E_ACCESSDENIED;
  873. }
  874. }