JITServer.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  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 CheckModuleAddress(HANDLE process, LPCVOID remoteImageBase, LPCVOID localImageBase)
  104. {
  105. byte remoteImageHeader[0x1000];
  106. MEMORY_BASIC_INFORMATION remoteImageInfo;
  107. SIZE_T resultBytes = VirtualQueryEx(process, (LPCVOID)remoteImageBase, &remoteImageInfo, sizeof(remoteImageInfo));
  108. if (resultBytes != sizeof(remoteImageInfo))
  109. {
  110. return E_ACCESSDENIED;
  111. }
  112. if (remoteImageInfo.BaseAddress != (PVOID)remoteImageBase)
  113. {
  114. return E_ACCESSDENIED;
  115. }
  116. if (remoteImageInfo.Type != MEM_IMAGE)
  117. {
  118. return E_ACCESSDENIED;
  119. }
  120. if (remoteImageInfo.State != MEM_COMMIT)
  121. {
  122. return E_ACCESSDENIED;
  123. }
  124. if (remoteImageInfo.RegionSize < sizeof(remoteImageHeader))
  125. {
  126. return E_ACCESSDENIED;
  127. }
  128. if (!ReadProcessMemory(process, remoteImageBase, remoteImageHeader, sizeof(remoteImageHeader), &resultBytes))
  129. {
  130. return HRESULT_FROM_WIN32(GetLastError());
  131. }
  132. if (resultBytes < sizeof(remoteImageHeader))
  133. {
  134. return E_ACCESSDENIED;
  135. }
  136. PIMAGE_DOS_HEADER localDosHeader = (PIMAGE_DOS_HEADER)localImageBase;
  137. PIMAGE_NT_HEADERS localNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)localDosHeader + localDosHeader->e_lfanew);
  138. PIMAGE_DOS_HEADER remoteDosHeader = (PIMAGE_DOS_HEADER)remoteImageHeader;
  139. PIMAGE_NT_HEADERS remoteNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)remoteDosHeader + remoteDosHeader->e_lfanew);
  140. uintptr_t remoteHeaderMax = (uintptr_t)remoteImageHeader + sizeof(remoteImageHeader);
  141. uintptr_t remoteMaxRead = (uintptr_t)remoteNtHeader + sizeof(IMAGE_NT_HEADERS);
  142. if (remoteMaxRead >= remoteHeaderMax || remoteMaxRead < (uintptr_t)remoteImageHeader)
  143. {
  144. return E_ACCESSDENIED;
  145. }
  146. if (localNtHeader->FileHeader.NumberOfSections != remoteNtHeader->FileHeader.NumberOfSections)
  147. {
  148. return E_ACCESSDENIED;
  149. }
  150. if (localNtHeader->FileHeader.NumberOfSymbols != remoteNtHeader->FileHeader.NumberOfSymbols)
  151. {
  152. return E_ACCESSDENIED;
  153. }
  154. if (localNtHeader->OptionalHeader.CheckSum != remoteNtHeader->OptionalHeader.CheckSum)
  155. {
  156. return E_ACCESSDENIED;
  157. }
  158. if (localNtHeader->OptionalHeader.SizeOfImage != remoteNtHeader->OptionalHeader.SizeOfImage)
  159. {
  160. return E_ACCESSDENIED;
  161. }
  162. return S_OK;
  163. }
  164. #pragma warning(push)
  165. #pragma warning(disable:6387 28196) // PREFast does not understand the out context can be null here
  166. HRESULT
  167. ServerInitializeThreadContext(
  168. /* [in] */ handle_t binding,
  169. /* [in] */ __RPC__in ThreadContextDataIDL * threadContextData,
  170. /* [out] */ __RPC__deref_out_opt PPTHREADCONTEXT_HANDLE threadContextInfoAddress,
  171. /* [out] */ __RPC__out intptr_t *prereservedRegionAddr,
  172. /* [out] */ __RPC__out intptr_t *jitThunkAddr)
  173. {
  174. if (threadContextInfoAddress == nullptr || prereservedRegionAddr == nullptr)
  175. {
  176. Assert(false);
  177. return RPC_S_INVALID_ARG;
  178. }
  179. *threadContextInfoAddress = nullptr;
  180. *prereservedRegionAddr = 0;
  181. *jitThunkAddr = 0;
  182. ServerThreadContext * contextInfo = nullptr;
  183. try
  184. {
  185. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory));
  186. contextInfo = HeapNew(ServerThreadContext, threadContextData);
  187. ServerContextManager::RegisterThreadContext(contextInfo);
  188. }
  189. catch (Js::OutOfMemoryException)
  190. {
  191. CloseHandle((HANDLE)threadContextData->processHandle);
  192. return E_OUTOFMEMORY;
  193. }
  194. return ServerCallWrapper(contextInfo, [&]()->HRESULT
  195. {
  196. RPC_CALL_ATTRIBUTES CallAttributes = { 0 };
  197. CallAttributes.Version = RPC_CALL_ATTRIBUTES_VERSION;
  198. CallAttributes.Flags = RPC_QUERY_CLIENT_PID;
  199. HRESULT hr = HRESULT_FROM_WIN32(RpcServerInqCallAttributes(binding, &CallAttributes));
  200. if (FAILED(hr))
  201. {
  202. return hr;
  203. }
  204. if (CallAttributes.ClientPID != (HANDLE)contextInfo->GetRuntimePid())
  205. {
  206. return E_ACCESSDENIED;
  207. }
  208. hr = CheckModuleAddress(contextInfo->GetProcessHandle(), (LPCVOID)contextInfo->GetRuntimeChakraBaseAddress(), (LPCVOID)AutoSystemInfo::Data.dllLoadAddress);
  209. if (FAILED(hr))
  210. {
  211. return hr;
  212. }
  213. if (contextInfo->GetUCrtC99MathApis()->IsAvailable())
  214. {
  215. hr = CheckModuleAddress(contextInfo->GetProcessHandle(), (LPCVOID)contextInfo->GetRuntimeCRTBaseAddress(), (LPCVOID)contextInfo->GetJITCRTBaseAddress());
  216. if (FAILED(hr))
  217. {
  218. return hr;
  219. }
  220. }
  221. *threadContextInfoAddress = (PTHREADCONTEXT_HANDLE)EncodePointer(contextInfo);
  222. #if defined(_CONTROL_FLOW_GUARD)
  223. if (contextInfo->IsCFGEnabled())
  224. {
  225. if (!PHASE_OFF1(Js::PreReservedHeapAllocPhase))
  226. {
  227. *prereservedRegionAddr = (intptr_t)contextInfo->GetPreReservedSectionAllocator()->EnsurePreReservedRegion();
  228. }
  229. #if _M_IX86 || _M_X64
  230. *jitThunkAddr = (intptr_t)contextInfo->GetJITThunkEmitter()->EnsureInitialized();
  231. #endif
  232. }
  233. #endif
  234. return hr;
  235. });
  236. }
  237. HRESULT
  238. ServerInitializeScriptContext(
  239. /* [in] */ handle_t binding,
  240. /* [in] */ __RPC__in ScriptContextDataIDL * scriptContextData,
  241. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  242. /* [out] */ __RPC__deref_out_opt PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  243. {
  244. if (scriptContextInfoAddress == nullptr || threadContextInfoAddress == nullptr)
  245. {
  246. Assert(false);
  247. return RPC_S_INVALID_ARG;
  248. }
  249. *scriptContextInfoAddress = nullptr;
  250. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  251. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  252. {
  253. ServerScriptContext * contextInfo = HeapNew(ServerScriptContext, scriptContextData, threadContextInfo);
  254. ServerContextManager::RegisterScriptContext(contextInfo);
  255. *scriptContextInfoAddress = (PSCRIPTCONTEXT_HANDLE)EncodePointer(contextInfo);
  256. #if !FLOATVAR
  257. // TODO: should move this to ServerInitializeThreadContext, also for the fields in IDL
  258. XProcNumberPageSegmentImpl::Initialize(contextInfo->IsRecyclerVerifyEnabled(), contextInfo->GetRecyclerVerifyPad());
  259. #endif
  260. return S_OK;
  261. });
  262. }
  263. #pragma warning(pop)
  264. HRESULT
  265. ServerCleanupThreadContext(
  266. /* [in] */ handle_t binding,
  267. /* [in] */ __RPC__deref_inout_opt PPTHREADCONTEXT_HANDLE threadContextInfoAddress)
  268. {
  269. if (threadContextInfoAddress == nullptr)
  270. {
  271. Assert(false);
  272. return RPC_S_INVALID_ARG;
  273. }
  274. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(*threadContextInfoAddress);
  275. if (threadContextInfo == nullptr)
  276. {
  277. Assert(false);
  278. return RPC_S_INVALID_ARG;
  279. }
  280. // This tells the run-time, when it is marshalling the out
  281. // parameters, that the context handle has been closed normally.
  282. *threadContextInfoAddress = nullptr;
  283. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  284. {
  285. threadContextInfo->Close();
  286. ServerContextManager::UnRegisterThreadContext(threadContextInfo);
  287. return S_OK;
  288. });
  289. }
  290. HRESULT
  291. ServerUpdatePropertyRecordMap(
  292. /* [in] */ handle_t binding,
  293. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  294. /* [in] */ __RPC__in_opt BVSparseNodeIDL * updatedPropsBVHead)
  295. {
  296. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  297. if (threadContextInfo == nullptr)
  298. {
  299. Assert(false);
  300. return RPC_S_INVALID_ARG;
  301. }
  302. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  303. {
  304. typedef ServerThreadContext::BVSparseNode BVSparseNode;
  305. CompileAssert(sizeof(BVSparseNode) == sizeof(BVSparseNodeIDL));
  306. threadContextInfo->UpdateNumericPropertyBV((BVSparseNode*)updatedPropsBVHead);
  307. return S_OK;
  308. });
  309. }
  310. HRESULT
  311. ServerAddDOMFastPathHelper(
  312. /* [in] */ handle_t binding,
  313. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  314. /* [in] */ intptr_t funcInfoAddr,
  315. /* [in] */ int helper)
  316. {
  317. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  318. if (scriptContextInfo == nullptr)
  319. {
  320. Assert(false);
  321. return RPC_S_INVALID_ARG;
  322. }
  323. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  324. {
  325. scriptContextInfo->AddToDOMFastPathHelperMap(funcInfoAddr, (IR::JnHelperMethod)helper);
  326. return S_OK;
  327. });
  328. }
  329. HRESULT
  330. ServerAddModuleRecordInfo(
  331. /* [in] */ handle_t binding,
  332. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  333. /* [in] */ unsigned int moduleId,
  334. /* [in] */ intptr_t localExportSlotsAddr)
  335. {
  336. ServerScriptContext * serverScriptContext = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  337. if (serverScriptContext == nullptr)
  338. {
  339. Assert(false);
  340. return RPC_S_INVALID_ARG;
  341. }
  342. return ServerCallWrapper(serverScriptContext, [&]()->HRESULT
  343. {
  344. serverScriptContext->AddModuleRecordInfo(moduleId, localExportSlotsAddr);
  345. return S_OK;
  346. });
  347. }
  348. HRESULT
  349. ServerSetWellKnownHostTypeId(
  350. /* [in] */ handle_t binding,
  351. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  352. /* [in] */ int typeId)
  353. {
  354. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  355. if (threadContextInfo == nullptr)
  356. {
  357. Assert(false);
  358. return RPC_S_INVALID_ARG;
  359. }
  360. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  361. {
  362. threadContextInfo->SetWellKnownHostTypeId((Js::TypeId)typeId);
  363. return S_OK;
  364. });
  365. }
  366. HRESULT
  367. ServerCleanupScriptContext(
  368. /* [in] */ handle_t binding,
  369. /* [in] */ __RPC__deref_inout_opt PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  370. {
  371. if (scriptContextInfoAddress == nullptr)
  372. {
  373. Assert(false);
  374. return RPC_S_INVALID_ARG;
  375. }
  376. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(*scriptContextInfoAddress);
  377. if (scriptContextInfo == nullptr)
  378. {
  379. Assert(false);
  380. return RPC_S_INVALID_ARG;
  381. }
  382. if (!scriptContextInfo->IsClosed())
  383. {
  384. scriptContextInfo->Close();
  385. ServerContextManager::UnRegisterScriptContext(scriptContextInfo);
  386. }
  387. // This tells the run-time, when it is marshalling the out
  388. // parameters, that the context handle has been closed normally.
  389. *scriptContextInfoAddress = nullptr;
  390. HeapDelete(scriptContextInfo);
  391. return S_OK;
  392. }
  393. HRESULT
  394. ServerCloseScriptContext(
  395. /* [in] */ handle_t binding,
  396. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  397. {
  398. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  399. if (scriptContextInfo == nullptr)
  400. {
  401. Assert(false);
  402. return RPC_S_INVALID_ARG;
  403. }
  404. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  405. {
  406. #ifdef PROFILE_EXEC
  407. auto profiler = scriptContextInfo->GetCodeGenProfiler();
  408. if (profiler && profiler->IsInitialized())
  409. {
  410. profiler->ProfilePrint(Js::Configuration::Global.flags.Profile.GetFirstPhase());
  411. }
  412. #endif
  413. scriptContextInfo->Close();
  414. ServerContextManager::UnRegisterScriptContext(scriptContextInfo);
  415. return S_OK;
  416. });
  417. }
  418. HRESULT
  419. ServerDecommitInterpreterBufferManager(
  420. /* [in] */ handle_t binding,
  421. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  422. /* [in] */ boolean asmJsManager)
  423. {
  424. ServerScriptContext * scriptContext = (ServerScriptContext *)DecodePointer((void*)scriptContextInfoAddress);
  425. if (scriptContext == nullptr)
  426. {
  427. Assert(false);
  428. return RPC_S_INVALID_ARG;
  429. }
  430. return ServerCallWrapper(scriptContext, [&]()->HRESULT
  431. {
  432. scriptContext->DecommitEmitBufferManager(asmJsManager != FALSE);
  433. return S_OK;
  434. });
  435. }
  436. HRESULT
  437. ServerNewInterpreterThunkBlock(
  438. /* [in] */ handle_t binding,
  439. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfo,
  440. /* [in] */ __RPC__in InterpreterThunkInputIDL * thunkInput,
  441. /* [out] */ __RPC__out InterpreterThunkOutputIDL * thunkOutput)
  442. {
  443. memset(thunkOutput, 0, sizeof(InterpreterThunkOutputIDL));
  444. ServerScriptContext * scriptContext = (ServerScriptContext *)DecodePointer(scriptContextInfo);
  445. if (scriptContext == nullptr)
  446. {
  447. Assert(false);
  448. return RPC_S_INVALID_ARG;
  449. }
  450. return ServerCallWrapper(scriptContext, [&]()->HRESULT
  451. {
  452. ServerThreadContext * threadContext = scriptContext->GetThreadContext();
  453. class AutoLocalAlloc
  454. {
  455. public:
  456. AutoLocalAlloc(ServerThreadContext * threadContext) : localAddress(nullptr), threadContext(threadContext) { }
  457. ~AutoLocalAlloc()
  458. {
  459. if (localAddress)
  460. {
  461. threadContext->GetCodePageAllocators()->FreeLocal(this->localAddress, this->segment);
  462. }
  463. }
  464. char * localAddress;
  465. void * segment;
  466. ServerThreadContext * threadContext;
  467. } localAlloc(threadContext);
  468. OOPEmitBufferManager * emitBufferManager = scriptContext->GetEmitBufferManager(thunkInput->asmJsThunk != FALSE);
  469. BYTE* runtimeAddress;
  470. EmitBufferAllocation<SectionAllocWrapper, PreReservedSectionAllocWrapper> * alloc = emitBufferManager->AllocateBuffer(InterpreterThunkEmitter::BlockSize, &runtimeAddress);
  471. CompileAssert(InterpreterThunkEmitter::BlockSize <= CustomHeap::Page::MaxAllocationSize);
  472. localAlloc.segment = alloc->allocation->page->segment;
  473. localAlloc.localAddress = threadContext->GetCodePageAllocators()->AllocLocal((char*)runtimeAddress, InterpreterThunkEmitter::BlockSize, localAlloc.segment);
  474. if (!localAlloc.localAddress)
  475. {
  476. Js::Throw::OutOfMemory();
  477. }
  478. #if PDATA_ENABLED
  479. PRUNTIME_FUNCTION pdataStart = {0};
  480. intptr_t epilogEnd = 0;
  481. #endif
  482. DWORD thunkCount = 0;
  483. InterpreterThunkEmitter::FillBuffer(
  484. threadContext,
  485. thunkInput->asmJsThunk != FALSE,
  486. (intptr_t)runtimeAddress,
  487. InterpreterThunkEmitter::BlockSize,
  488. (BYTE*)localAlloc.localAddress,
  489. #if PDATA_ENABLED
  490. &pdataStart,
  491. &epilogEnd,
  492. #endif
  493. &thunkCount
  494. );
  495. emitBufferManager->CommitBufferForInterpreter(alloc, runtimeAddress, InterpreterThunkEmitter::BlockSize);
  496. // Call to set VALID flag for CFG check
  497. if (CONFIG_FLAG(OOPCFGRegistration))
  498. {
  499. threadContext->SetValidCallTargetForCFG(runtimeAddress);
  500. }
  501. thunkOutput->thunkCount = thunkCount;
  502. thunkOutput->mappedBaseAddr = (intptr_t)runtimeAddress;
  503. #if PDATA_ENABLED
  504. thunkOutput->pdataTableStart = (intptr_t)pdataStart;
  505. thunkOutput->epilogEndAddr = epilogEnd;
  506. #endif
  507. return S_OK;
  508. });
  509. }
  510. #if DBG
  511. HRESULT
  512. ServerIsInterpreterThunkAddr(
  513. /* [in] */ handle_t binding,
  514. /* [in] */ PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  515. /* [in] */ intptr_t address,
  516. /* [in] */ boolean asmjsThunk,
  517. /* [out] */ __RPC__out boolean * result)
  518. {
  519. ServerScriptContext * context = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress);
  520. if (context == nullptr)
  521. {
  522. *result = false;
  523. return RPC_S_INVALID_ARG;
  524. }
  525. OOPEmitBufferManager * manager = context->GetEmitBufferManager(asmjsThunk != FALSE);
  526. if (manager == nullptr)
  527. {
  528. *result = false;
  529. return S_OK;
  530. }
  531. *result = manager->IsInHeap((void*)address);
  532. return S_OK;
  533. }
  534. #endif
  535. HRESULT
  536. ServerFreeAllocation(
  537. /* [in] */ handle_t binding,
  538. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfo,
  539. /* [in] */ intptr_t codeAddress,
  540. /* [in] */ intptr_t thunkAddress)
  541. {
  542. ServerThreadContext * context = (ServerThreadContext*)DecodePointer(threadContextInfo);
  543. if (context == nullptr)
  544. {
  545. Assert(false);
  546. return RPC_S_INVALID_ARG;
  547. }
  548. return ServerCallWrapper(context, [&]()->HRESULT
  549. {
  550. if (CONFIG_FLAG(OOPCFGRegistration) && !thunkAddress)
  551. {
  552. context->SetValidCallTargetForCFG((PVOID)codeAddress, false);
  553. }
  554. context->GetCodeGenAllocators()->emitBufferManager.FreeAllocation((void*)codeAddress);
  555. #if defined(_CONTROL_FLOW_GUARD) && (_M_IX86 || _M_X64)
  556. if (thunkAddress)
  557. {
  558. context->GetJITThunkEmitter()->FreeThunk(thunkAddress);
  559. }
  560. #endif
  561. return S_OK;
  562. });
  563. }
  564. HRESULT
  565. ServerIsNativeAddr(
  566. /* [in] */ handle_t binding,
  567. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfo,
  568. /* [in] */ intptr_t address,
  569. /* [out] */ __RPC__out boolean * result)
  570. {
  571. if (result == nullptr)
  572. {
  573. Assert(false);
  574. return RPC_S_INVALID_ARG;
  575. }
  576. *result = false;
  577. ServerThreadContext * context = (ServerThreadContext*)DecodePointer(threadContextInfo);
  578. if (context == nullptr)
  579. {
  580. Assert(false);
  581. return RPC_S_INVALID_ARG;
  582. }
  583. return ServerCallWrapper(context, [&]()->HRESULT
  584. {
  585. PreReservedSectionAllocWrapper *preReservedAllocWrapper = context->GetPreReservedSectionAllocator();
  586. if (preReservedAllocWrapper->IsInRange((void*)address))
  587. {
  588. *result = true;
  589. }
  590. else if (!context->IsAllJITCodeInPreReservedRegion())
  591. {
  592. AutoCriticalSection autoLock(&context->GetCodePageAllocators()->cs);
  593. *result = context->GetCodePageAllocators()->IsInNonPreReservedPageAllocator((void*)address);
  594. }
  595. else
  596. {
  597. *result = false;
  598. }
  599. return S_OK;
  600. });
  601. }
  602. HRESULT
  603. ServerSetIsPRNGSeeded(
  604. /* [in] */ handle_t binding,
  605. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  606. /* [in] */ boolean value)
  607. {
  608. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  609. if (scriptContextInfo == nullptr)
  610. {
  611. Assert(false);
  612. return RPC_S_INVALID_ARG;
  613. }
  614. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  615. {
  616. scriptContextInfo->SetIsPRNGSeeded(value != FALSE);
  617. return S_OK;
  618. });
  619. }
  620. HRESULT
  621. ServerRemoteCodeGen(
  622. /* [in] */ handle_t binding,
  623. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  624. /* [in] */ __RPC__in CodeGenWorkItemIDL *workItemData,
  625. /* [out] */ __RPC__out JITOutputIDL *jitData)
  626. {
  627. memset(jitData, 0, sizeof(JITOutputIDL));
  628. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  629. if (scriptContextInfo == nullptr)
  630. {
  631. Assert(false);
  632. return RPC_S_INVALID_ARG;
  633. }
  634. return ServerCallWrapper(scriptContextInfo, [&]() ->HRESULT
  635. {
  636. LARGE_INTEGER start_time = { 0 };
  637. if (PHASE_TRACE1(Js::BackEndPhase))
  638. {
  639. QueryPerformanceCounter(&start_time);
  640. }
  641. scriptContextInfo->UpdateGlobalObjectThisAddr(workItemData->globalThisAddr);
  642. ServerThreadContext * threadContextInfo = scriptContextInfo->GetThreadContext();
  643. AutoReturnPageAllocator autoReturnPageAllocator;
  644. PageAllocator* pageAllocator = autoReturnPageAllocator.GetPageAllocator();
  645. NoRecoverMemoryJitArenaAllocator jitArena(L"JITArena", pageAllocator, Js::Throw::OutOfMemory);
  646. #if DBG
  647. jitArena.SetNeedsDelayFreeList();
  648. #endif
  649. JITTimeWorkItem * jitWorkItem = Anew(&jitArena, JITTimeWorkItem, workItemData);
  650. if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId()))
  651. {
  652. LARGE_INTEGER freq;
  653. LARGE_INTEGER end_time;
  654. QueryPerformanceCounter(&end_time);
  655. QueryPerformanceFrequency(&freq);
  656. Output::Print(
  657. L"BackendMarshalIn - function: %s time:%8.6f mSec\r\n",
  658. jitWorkItem->GetJITFunctionBody()->GetDisplayName(),
  659. (((double)((end_time.QuadPart - workItemData->startTime)* (double)1000.0 / (double)freq.QuadPart))) / (1));
  660. Output::Flush();
  661. }
  662. auto profiler = scriptContextInfo->GetCodeGenProfiler();
  663. #ifdef PROFILE_EXEC
  664. if (profiler && !profiler->IsInitialized())
  665. {
  666. profiler->Initialize(pageAllocator, nullptr);
  667. }
  668. #endif
  669. if (jitWorkItem->GetWorkItemData()->xProcNumberPageSegment)
  670. {
  671. jitData->numberPageSegments = (XProcNumberPageSegment*)midl_user_allocate(sizeof(XProcNumberPageSegment));
  672. if (!jitData->numberPageSegments)
  673. {
  674. return E_OUTOFMEMORY;
  675. }
  676. __analysis_assume(jitData->numberPageSegments);
  677. memcpy_s(jitData->numberPageSegments, sizeof(XProcNumberPageSegment), jitWorkItem->GetWorkItemData()->xProcNumberPageSegment, sizeof(XProcNumberPageSegment));
  678. }
  679. Func::Codegen(
  680. &jitArena,
  681. jitWorkItem,
  682. threadContextInfo,
  683. scriptContextInfo,
  684. jitData,
  685. nullptr,
  686. nullptr,
  687. jitWorkItem->GetPolymorphicInlineCacheInfo(),
  688. threadContextInfo->GetCodeGenAllocators(),
  689. #if !FLOATVAR
  690. nullptr, // number allocator
  691. #endif
  692. profiler,
  693. true);
  694. #ifdef PROFILE_EXEC
  695. if (profiler && profiler->IsInitialized())
  696. {
  697. profiler->ProfilePrint(Js::Configuration::Global.flags.Profile.GetFirstPhase());
  698. }
  699. #endif
  700. if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId()))
  701. {
  702. LARGE_INTEGER freq;
  703. LARGE_INTEGER end_time;
  704. QueryPerformanceCounter(&end_time);
  705. QueryPerformanceFrequency(&freq);
  706. Output::Print(
  707. L"EndBackEndInner - function: %s time:%8.6f mSec\r\n",
  708. jitWorkItem->GetJITFunctionBody()->GetDisplayName(),
  709. (((double)((end_time.QuadPart - start_time.QuadPart)* (double)1000.0 / (double)freq.QuadPart))) / (1));
  710. Output::Flush();
  711. }
  712. LARGE_INTEGER out_time = { 0 };
  713. if (PHASE_TRACE1(Js::BackEndPhase))
  714. {
  715. QueryPerformanceCounter(&out_time);
  716. jitData->startTime = out_time.QuadPart;
  717. }
  718. Assert(jitData->codeAddress);
  719. Assert(jitData->codeSize);
  720. return S_OK;
  721. });
  722. }
  723. JsUtil::BaseHashSet<ServerThreadContext*, HeapAllocator> ServerContextManager::threadContexts(&HeapAllocator::Instance);
  724. JsUtil::BaseHashSet<ServerScriptContext*, HeapAllocator> ServerContextManager::scriptContexts(&HeapAllocator::Instance);
  725. CriticalSection ServerContextManager::cs;
  726. #ifdef STACK_BACK_TRACE
  727. SList<ServerContextManager::ClosedContextEntry<ServerThreadContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedThreadContextList(&NoThrowHeapAllocator::Instance);
  728. SList<ServerContextManager::ClosedContextEntry<ServerScriptContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedScriptContextList(&NoThrowHeapAllocator::Instance);
  729. #endif
  730. void ServerContextManager::RegisterThreadContext(ServerThreadContext* threadContext)
  731. {
  732. AutoCriticalSection autoCS(&cs);
  733. threadContexts.Add(threadContext);
  734. }
  735. void ServerContextManager::UnRegisterThreadContext(ServerThreadContext* threadContext)
  736. {
  737. AutoCriticalSection autoCS(&cs);
  738. threadContexts.Remove(threadContext);
  739. auto iter = scriptContexts.GetIteratorWithRemovalSupport();
  740. while (iter.IsValid())
  741. {
  742. ServerScriptContext* scriptContext = iter.Current().Key();
  743. if (scriptContext->GetThreadContext() == threadContext)
  744. {
  745. if (!scriptContext->IsClosed())
  746. {
  747. scriptContext->Close();
  748. }
  749. iter.RemoveCurrent();
  750. }
  751. iter.MoveNext();
  752. }
  753. }
  754. void ServerContextManager::RegisterScriptContext(ServerScriptContext* scriptContext)
  755. {
  756. AutoCriticalSection autoCS(&cs);
  757. scriptContexts.Add(scriptContext);
  758. }
  759. void ServerContextManager::UnRegisterScriptContext(ServerScriptContext* scriptContext)
  760. {
  761. AutoCriticalSection autoCS(&cs);
  762. scriptContexts.Remove(scriptContext);
  763. }
  764. bool ServerContextManager::CheckLivenessAndAddref(ServerScriptContext* context)
  765. {
  766. AutoCriticalSection autoCS(&cs);
  767. if (scriptContexts.LookupWithKey(context))
  768. {
  769. if (!context->IsClosed() && !context->GetThreadContext()->IsClosed())
  770. {
  771. context->AddRef();
  772. context->GetThreadContext()->AddRef();
  773. return true;
  774. }
  775. }
  776. return false;
  777. }
  778. bool ServerContextManager::CheckLivenessAndAddref(ServerThreadContext* context)
  779. {
  780. AutoCriticalSection autoCS(&cs);
  781. if (threadContexts.LookupWithKey(context))
  782. {
  783. if (!context->IsClosed())
  784. {
  785. context->AddRef();
  786. return true;
  787. }
  788. }
  789. return false;
  790. }
  791. template<typename Fn>
  792. HRESULT ServerCallWrapper(ServerThreadContext* threadContextInfo, Fn fn)
  793. {
  794. MemoryOperationLastError::ClearLastError();
  795. HRESULT hr = S_OK;
  796. try
  797. {
  798. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow));
  799. AutoReleaseThreadContext autoThreadContext(threadContextInfo);
  800. hr = fn();
  801. }
  802. catch (ContextClosedException&)
  803. {
  804. hr = E_ACCESSDENIED;
  805. }
  806. catch (Js::OutOfMemoryException)
  807. {
  808. hr = E_OUTOFMEMORY;
  809. }
  810. catch (Js::StackOverflowException)
  811. {
  812. hr = VBSERR_OutOfStack;
  813. }
  814. catch (Js::OperationAbortedException)
  815. {
  816. hr = E_ABORT;
  817. }
  818. catch (...)
  819. {
  820. AssertOrFailFastMsg(false, "Unknown exception caught in JIT server call.");
  821. }
  822. if (hr == S_OK)
  823. {
  824. return MemoryOperationLastError::GetLastError();
  825. }
  826. return hr;
  827. }
  828. template<typename Fn>
  829. HRESULT ServerCallWrapper(ServerScriptContext* scriptContextInfo, Fn fn)
  830. {
  831. try
  832. {
  833. AutoReleaseScriptContext autoScriptContext(scriptContextInfo);
  834. ServerThreadContext* threadContextInfo = scriptContextInfo->GetThreadContext();
  835. return ServerCallWrapper(threadContextInfo, fn);
  836. }
  837. catch (ContextClosedException&)
  838. {
  839. return E_ACCESSDENIED;
  840. }
  841. }