JITServer.cpp 29 KB

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