JITServer.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  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. {
  173. if (threadContextInfoAddress == nullptr || prereservedRegionAddr == nullptr)
  174. {
  175. Assert(false);
  176. return RPC_S_INVALID_ARG;
  177. }
  178. *threadContextInfoAddress = nullptr;
  179. *prereservedRegionAddr = 0;
  180. ServerThreadContext * contextInfo = nullptr;
  181. try
  182. {
  183. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory));
  184. contextInfo = HeapNew(ServerThreadContext, threadContextData);
  185. ServerContextManager::RegisterThreadContext(contextInfo);
  186. }
  187. catch (Js::OutOfMemoryException)
  188. {
  189. CloseHandle((HANDLE)threadContextData->processHandle);
  190. return E_OUTOFMEMORY;
  191. }
  192. return ServerCallWrapper(contextInfo, [&]()->HRESULT
  193. {
  194. RPC_CALL_ATTRIBUTES CallAttributes = {0};
  195. CallAttributes.Version = RPC_CALL_ATTRIBUTES_VERSION;
  196. CallAttributes.Flags = RPC_QUERY_CLIENT_PID;
  197. HRESULT hr = HRESULT_FROM_WIN32(RpcServerInqCallAttributes(binding, &CallAttributes));
  198. if (FAILED(hr))
  199. {
  200. return hr;
  201. }
  202. if (CallAttributes.ClientPID != (HANDLE)contextInfo->GetRuntimePid())
  203. {
  204. return E_ACCESSDENIED;
  205. }
  206. hr = CheckModuleAddress(contextInfo->GetProcessHandle(), (LPCVOID)contextInfo->GetRuntimeChakraBaseAddress(), (LPCVOID)AutoSystemInfo::Data.dllLoadAddress);
  207. if (FAILED(hr))
  208. {
  209. return hr;
  210. }
  211. if (contextInfo->GetUCrtC99MathApis()->IsAvailable())
  212. {
  213. hr = CheckModuleAddress(contextInfo->GetProcessHandle(), (LPCVOID)contextInfo->GetRuntimeCRTBaseAddress(), (LPCVOID)contextInfo->GetJITCRTBaseAddress());
  214. if (FAILED(hr))
  215. {
  216. return hr;
  217. }
  218. }
  219. *threadContextInfoAddress = (PTHREADCONTEXT_HANDLE)EncodePointer(contextInfo);
  220. *prereservedRegionAddr = (intptr_t)contextInfo->GetPreReservedSectionAllocator()->EnsurePreReservedRegion();
  221. return hr;
  222. });
  223. }
  224. HRESULT
  225. ServerInitializeScriptContext(
  226. /* [in] */ handle_t binding,
  227. /* [in] */ __RPC__in ScriptContextDataIDL * scriptContextData,
  228. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  229. /* [out] */ __RPC__deref_out_opt PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  230. {
  231. if (scriptContextInfoAddress == nullptr || threadContextInfoAddress == nullptr)
  232. {
  233. Assert(false);
  234. return RPC_S_INVALID_ARG;
  235. }
  236. *scriptContextInfoAddress = nullptr;
  237. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  238. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  239. {
  240. ServerScriptContext * contextInfo = HeapNew(ServerScriptContext, scriptContextData, threadContextInfo);
  241. ServerContextManager::RegisterScriptContext(contextInfo);
  242. *scriptContextInfoAddress = (PSCRIPTCONTEXT_HANDLE)EncodePointer(contextInfo);
  243. #if !FLOATVAR
  244. // TODO: should move this to ServerInitializeThreadContext, also for the fields in IDL
  245. XProcNumberPageSegmentImpl::Initialize(contextInfo->IsRecyclerVerifyEnabled(), contextInfo->GetRecyclerVerifyPad());
  246. #endif
  247. return S_OK;
  248. });
  249. }
  250. #pragma warning(pop)
  251. HRESULT
  252. ServerCleanupThreadContext(
  253. /* [in] */ handle_t binding,
  254. /* [in] */ __RPC__deref_inout_opt PPTHREADCONTEXT_HANDLE threadContextInfoAddress)
  255. {
  256. if (threadContextInfoAddress == nullptr)
  257. {
  258. Assert(false);
  259. return RPC_S_INVALID_ARG;
  260. }
  261. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(*threadContextInfoAddress);
  262. if (threadContextInfo == nullptr)
  263. {
  264. Assert(false);
  265. return RPC_S_INVALID_ARG;
  266. }
  267. // This tells the run-time, when it is marshalling the out
  268. // parameters, that the context handle has been closed normally.
  269. *threadContextInfoAddress = nullptr;
  270. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  271. {
  272. threadContextInfo->Close();
  273. ServerContextManager::UnRegisterThreadContext(threadContextInfo);
  274. return S_OK;
  275. });
  276. }
  277. HRESULT
  278. ServerUpdatePropertyRecordMap(
  279. /* [in] */ handle_t binding,
  280. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  281. /* [in] */ __RPC__in_opt BVSparseNodeIDL * updatedPropsBVHead)
  282. {
  283. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  284. if (threadContextInfo == nullptr)
  285. {
  286. Assert(false);
  287. return RPC_S_INVALID_ARG;
  288. }
  289. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  290. {
  291. typedef ServerThreadContext::BVSparseNode BVSparseNode;
  292. CompileAssert(sizeof(BVSparseNode) == sizeof(BVSparseNodeIDL));
  293. threadContextInfo->UpdateNumericPropertyBV((BVSparseNode*)updatedPropsBVHead);
  294. return S_OK;
  295. });
  296. }
  297. HRESULT
  298. ServerAddDOMFastPathHelper(
  299. /* [in] */ handle_t binding,
  300. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  301. /* [in] */ intptr_t funcInfoAddr,
  302. /* [in] */ int helper)
  303. {
  304. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  305. if (scriptContextInfo == nullptr)
  306. {
  307. Assert(false);
  308. return RPC_S_INVALID_ARG;
  309. }
  310. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  311. {
  312. scriptContextInfo->AddToDOMFastPathHelperMap(funcInfoAddr, (IR::JnHelperMethod)helper);
  313. return S_OK;
  314. });
  315. }
  316. HRESULT
  317. ServerAddModuleRecordInfo(
  318. /* [in] */ handle_t binding,
  319. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  320. /* [in] */ unsigned int moduleId,
  321. /* [in] */ intptr_t localExportSlotsAddr)
  322. {
  323. ServerScriptContext * serverScriptContext = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  324. if (serverScriptContext == nullptr)
  325. {
  326. Assert(false);
  327. return RPC_S_INVALID_ARG;
  328. }
  329. return ServerCallWrapper(serverScriptContext, [&]()->HRESULT
  330. {
  331. serverScriptContext->AddModuleRecordInfo(moduleId, localExportSlotsAddr);
  332. return S_OK;
  333. });
  334. }
  335. HRESULT
  336. ServerSetWellKnownHostTypeId(
  337. /* [in] */ handle_t binding,
  338. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
  339. /* [in] */ int typeId)
  340. {
  341. ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer(threadContextInfoAddress);
  342. if (threadContextInfo == nullptr)
  343. {
  344. Assert(false);
  345. return RPC_S_INVALID_ARG;
  346. }
  347. return ServerCallWrapper(threadContextInfo, [&]()->HRESULT
  348. {
  349. threadContextInfo->SetWellKnownHostTypeId((Js::TypeId)typeId);
  350. return S_OK;
  351. });
  352. }
  353. HRESULT
  354. ServerCleanupScriptContext(
  355. /* [in] */ handle_t binding,
  356. /* [in] */ __RPC__deref_inout_opt PPSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  357. {
  358. if (scriptContextInfoAddress == nullptr)
  359. {
  360. Assert(false);
  361. return RPC_S_INVALID_ARG;
  362. }
  363. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(*scriptContextInfoAddress);
  364. if (scriptContextInfo == nullptr)
  365. {
  366. Assert(false);
  367. return RPC_S_INVALID_ARG;
  368. }
  369. // This tells the run-time, when it is marshalling the out
  370. // parameters, that the context handle has been closed normally.
  371. *scriptContextInfoAddress = nullptr;
  372. Assert(scriptContextInfo->IsClosed());
  373. HeapDelete(scriptContextInfo);
  374. return S_OK;
  375. }
  376. HRESULT
  377. ServerCloseScriptContext(
  378. /* [in] */ handle_t binding,
  379. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress)
  380. {
  381. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  382. if (scriptContextInfo == nullptr)
  383. {
  384. Assert(false);
  385. return RPC_S_INVALID_ARG;
  386. }
  387. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  388. {
  389. #ifdef PROFILE_EXEC
  390. auto profiler = scriptContextInfo->GetCodeGenProfiler();
  391. if (profiler && profiler->IsInitialized())
  392. {
  393. profiler->ProfilePrint(Js::Configuration::Global.flags.Profile.GetFirstPhase());
  394. }
  395. #endif
  396. scriptContextInfo->Close();
  397. ServerContextManager::UnRegisterScriptContext(scriptContextInfo);
  398. return S_OK;
  399. });
  400. }
  401. HRESULT
  402. ServerDecommitInterpreterBufferManager(
  403. /* [in] */ handle_t binding,
  404. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  405. /* [in] */ boolean asmJsManager)
  406. {
  407. ServerScriptContext * scriptContext = (ServerScriptContext *)DecodePointer((void*)scriptContextInfoAddress);
  408. if (scriptContext == nullptr)
  409. {
  410. Assert(false);
  411. return RPC_S_INVALID_ARG;
  412. }
  413. return ServerCallWrapper(scriptContext, [&]()->HRESULT
  414. {
  415. scriptContext->DecommitEmitBufferManager(asmJsManager != FALSE);
  416. return S_OK;
  417. });
  418. }
  419. HRESULT
  420. ServerNewInterpreterThunkBlock(
  421. /* [in] */ handle_t binding,
  422. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfo,
  423. /* [in] */ __RPC__in InterpreterThunkInputIDL * thunkInput,
  424. /* [out] */ __RPC__out InterpreterThunkOutputIDL * thunkOutput)
  425. {
  426. memset(thunkOutput, 0, sizeof(InterpreterThunkOutputIDL));
  427. ServerScriptContext * scriptContext = (ServerScriptContext *)DecodePointer(scriptContextInfo);
  428. if (scriptContext == nullptr)
  429. {
  430. Assert(false);
  431. return RPC_S_INVALID_ARG;
  432. }
  433. return ServerCallWrapper(scriptContext, [&]()->HRESULT
  434. {
  435. ServerThreadContext * threadContext = scriptContext->GetThreadContext();
  436. class AutoLocalAlloc
  437. {
  438. public:
  439. AutoLocalAlloc(ServerThreadContext * threadContext) : localAddress(nullptr), threadContext(threadContext) { }
  440. ~AutoLocalAlloc()
  441. {
  442. if (localAddress)
  443. {
  444. threadContext->GetCodePageAllocators()->FreeLocal(this->localAddress, this->segment);
  445. }
  446. }
  447. char * localAddress;
  448. void * segment;
  449. ServerThreadContext * threadContext;
  450. } localAlloc(threadContext);
  451. OOPEmitBufferManager * emitBufferManager = scriptContext->GetEmitBufferManager(thunkInput->asmJsThunk != FALSE);
  452. BYTE* runtimeAddress;
  453. EmitBufferAllocation<SectionAllocWrapper, PreReservedSectionAllocWrapper> * alloc = emitBufferManager->AllocateBuffer(InterpreterThunkEmitter::BlockSize, &runtimeAddress);
  454. CompileAssert(InterpreterThunkEmitter::BlockSize <= CustomHeap::Page::MaxAllocationSize);
  455. localAlloc.segment = alloc->allocation->page->segment;
  456. localAlloc.localAddress = threadContext->GetCodePageAllocators()->AllocLocal((char*)runtimeAddress, InterpreterThunkEmitter::BlockSize, localAlloc.segment);
  457. if (!localAlloc.localAddress)
  458. {
  459. Js::Throw::OutOfMemory();
  460. }
  461. #if PDATA_ENABLED
  462. PRUNTIME_FUNCTION pdataStart = {0};
  463. intptr_t epilogEnd = 0;
  464. #endif
  465. DWORD thunkCount = 0;
  466. InterpreterThunkEmitter::FillBuffer(
  467. threadContext,
  468. thunkInput->asmJsThunk != FALSE,
  469. (intptr_t)runtimeAddress,
  470. InterpreterThunkEmitter::BlockSize,
  471. (BYTE*)localAlloc.localAddress,
  472. #if PDATA_ENABLED
  473. &pdataStart,
  474. &epilogEnd,
  475. #endif
  476. &thunkCount
  477. );
  478. emitBufferManager->CommitBufferForInterpreter(alloc, runtimeAddress, InterpreterThunkEmitter::BlockSize);
  479. // Call to set VALID flag for CFG check
  480. if (CONFIG_FLAG(OOPCFGRegistration))
  481. {
  482. threadContext->SetValidCallTargetForCFG(runtimeAddress);
  483. }
  484. thunkOutput->thunkCount = thunkCount;
  485. thunkOutput->mappedBaseAddr = (intptr_t)runtimeAddress;
  486. #if PDATA_ENABLED
  487. thunkOutput->pdataTableStart = (intptr_t)pdataStart;
  488. thunkOutput->epilogEndAddr = epilogEnd;
  489. #endif
  490. return S_OK;
  491. });
  492. }
  493. #if DBG
  494. HRESULT
  495. ServerIsInterpreterThunkAddr(
  496. /* [in] */ handle_t binding,
  497. /* [in] */ PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  498. /* [in] */ intptr_t address,
  499. /* [in] */ boolean asmjsThunk,
  500. /* [out] */ __RPC__out boolean * result)
  501. {
  502. ServerScriptContext * context = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress);
  503. if (context == nullptr)
  504. {
  505. *result = false;
  506. return RPC_S_INVALID_ARG;
  507. }
  508. OOPEmitBufferManager * manager = context->GetEmitBufferManager(asmjsThunk != FALSE);
  509. if (manager == nullptr)
  510. {
  511. *result = false;
  512. return S_OK;
  513. }
  514. *result = manager->IsInHeap((void*)address);
  515. return S_OK;
  516. }
  517. #endif
  518. HRESULT
  519. ServerFreeAllocation(
  520. /* [in] */ handle_t binding,
  521. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfo,
  522. /* [in] */ intptr_t address)
  523. {
  524. ServerThreadContext * context = (ServerThreadContext*)DecodePointer(threadContextInfo);
  525. if (context == nullptr)
  526. {
  527. Assert(false);
  528. return RPC_S_INVALID_ARG;
  529. }
  530. return ServerCallWrapper(context, [&]()->HRESULT
  531. {
  532. if (CONFIG_FLAG(OOPCFGRegistration))
  533. {
  534. context->SetValidCallTargetForCFG((PVOID)address, false);
  535. }
  536. context->GetCodeGenAllocators()->emitBufferManager.FreeAllocation((void*)address);
  537. return S_OK;
  538. });
  539. }
  540. HRESULT
  541. ServerIsNativeAddr(
  542. /* [in] */ handle_t binding,
  543. /* [in] */ __RPC__in PTHREADCONTEXT_HANDLE threadContextInfo,
  544. /* [in] */ intptr_t address,
  545. /* [out] */ __RPC__out boolean * result)
  546. {
  547. if (result == nullptr)
  548. {
  549. Assert(false);
  550. return RPC_S_INVALID_ARG;
  551. }
  552. *result = false;
  553. ServerThreadContext * context = (ServerThreadContext*)DecodePointer(threadContextInfo);
  554. if (context == nullptr)
  555. {
  556. Assert(false);
  557. return RPC_S_INVALID_ARG;
  558. }
  559. return ServerCallWrapper(context, [&]()->HRESULT
  560. {
  561. PreReservedSectionAllocWrapper *preReservedAllocWrapper = context->GetPreReservedSectionAllocator();
  562. if (preReservedAllocWrapper->IsInRange((void*)address))
  563. {
  564. *result = true;
  565. }
  566. else if (!context->IsAllJITCodeInPreReservedRegion())
  567. {
  568. AutoCriticalSection autoLock(&context->GetCodePageAllocators()->cs);
  569. *result = context->GetCodePageAllocators()->IsInNonPreReservedPageAllocator((void*)address);
  570. }
  571. else
  572. {
  573. *result = false;
  574. }
  575. return S_OK;
  576. });
  577. }
  578. HRESULT
  579. ServerSetIsPRNGSeeded(
  580. /* [in] */ handle_t binding,
  581. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  582. /* [in] */ boolean value)
  583. {
  584. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  585. if (scriptContextInfo == nullptr)
  586. {
  587. Assert(false);
  588. return RPC_S_INVALID_ARG;
  589. }
  590. return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
  591. {
  592. scriptContextInfo->SetIsPRNGSeeded(value != FALSE);
  593. return S_OK;
  594. });
  595. }
  596. HRESULT
  597. ServerRemoteCodeGen(
  598. /* [in] */ handle_t binding,
  599. /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
  600. /* [in] */ __RPC__in CodeGenWorkItemIDL *workItemData,
  601. /* [out] */ __RPC__out JITOutputIDL *jitData)
  602. {
  603. memset(jitData, 0, sizeof(JITOutputIDL));
  604. ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer(scriptContextInfoAddress);
  605. if (scriptContextInfo == nullptr)
  606. {
  607. Assert(false);
  608. return RPC_S_INVALID_ARG;
  609. }
  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. auto profiler = scriptContextInfo->GetCodeGenProfiler();
  639. #ifdef PROFILE_EXEC
  640. if (profiler && !profiler->IsInitialized())
  641. {
  642. profiler->Initialize(pageAllocator, nullptr);
  643. }
  644. #endif
  645. if (jitWorkItem->GetWorkItemData()->xProcNumberPageSegment)
  646. {
  647. jitData->numberPageSegments = (XProcNumberPageSegment*)midl_user_allocate(sizeof(XProcNumberPageSegment));
  648. if (!jitData->numberPageSegments)
  649. {
  650. return E_OUTOFMEMORY;
  651. }
  652. __analysis_assume(jitData->numberPageSegments);
  653. memcpy_s(jitData->numberPageSegments, sizeof(XProcNumberPageSegment), jitWorkItem->GetWorkItemData()->xProcNumberPageSegment, sizeof(XProcNumberPageSegment));
  654. }
  655. Func::Codegen(
  656. &jitArena,
  657. jitWorkItem,
  658. threadContextInfo,
  659. scriptContextInfo,
  660. jitData,
  661. nullptr,
  662. nullptr,
  663. jitWorkItem->GetPolymorphicInlineCacheInfo(),
  664. threadContextInfo->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. return S_OK;
  695. });
  696. }
  697. JsUtil::BaseHashSet<ServerThreadContext*, HeapAllocator> ServerContextManager::threadContexts(&HeapAllocator::Instance);
  698. JsUtil::BaseHashSet<ServerScriptContext*, HeapAllocator> ServerContextManager::scriptContexts(&HeapAllocator::Instance);
  699. CriticalSection ServerContextManager::cs;
  700. #ifdef STACK_BACK_TRACE
  701. SList<ServerContextManager::ClosedContextEntry<ServerThreadContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedThreadContextList(&NoThrowHeapAllocator::Instance);
  702. SList<ServerContextManager::ClosedContextEntry<ServerScriptContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedScriptContextList(&NoThrowHeapAllocator::Instance);
  703. #endif
  704. void ServerContextManager::RegisterThreadContext(ServerThreadContext* threadContext)
  705. {
  706. AutoCriticalSection autoCS(&cs);
  707. threadContexts.Add(threadContext);
  708. }
  709. void ServerContextManager::UnRegisterThreadContext(ServerThreadContext* threadContext)
  710. {
  711. AutoCriticalSection autoCS(&cs);
  712. threadContexts.Remove(threadContext);
  713. auto iter = scriptContexts.GetIteratorWithRemovalSupport();
  714. while (iter.IsValid())
  715. {
  716. ServerScriptContext* scriptContext = iter.Current().Key();
  717. if (scriptContext->GetThreadContext() == threadContext)
  718. {
  719. if (!scriptContext->IsClosed())
  720. {
  721. scriptContext->Close();
  722. }
  723. iter.RemoveCurrent();
  724. }
  725. iter.MoveNext();
  726. }
  727. }
  728. void ServerContextManager::RegisterScriptContext(ServerScriptContext* scriptContext)
  729. {
  730. AutoCriticalSection autoCS(&cs);
  731. scriptContexts.Add(scriptContext);
  732. }
  733. void ServerContextManager::UnRegisterScriptContext(ServerScriptContext* scriptContext)
  734. {
  735. AutoCriticalSection autoCS(&cs);
  736. scriptContexts.Remove(scriptContext);
  737. }
  738. bool ServerContextManager::CheckLivenessAndAddref(ServerScriptContext* context)
  739. {
  740. AutoCriticalSection autoCS(&cs);
  741. if (scriptContexts.LookupWithKey(context))
  742. {
  743. if (!context->IsClosed() && !context->GetThreadContext()->IsClosed())
  744. {
  745. context->AddRef();
  746. context->GetThreadContext()->AddRef();
  747. return true;
  748. }
  749. }
  750. return false;
  751. }
  752. bool ServerContextManager::CheckLivenessAndAddref(ServerThreadContext* context)
  753. {
  754. AutoCriticalSection autoCS(&cs);
  755. if (threadContexts.LookupWithKey(context))
  756. {
  757. if (!context->IsClosed())
  758. {
  759. context->AddRef();
  760. return true;
  761. }
  762. }
  763. return false;
  764. }
  765. template<typename Fn>
  766. HRESULT ServerCallWrapper(ServerThreadContext* threadContextInfo, Fn fn)
  767. {
  768. MemoryOperationLastError::ClearLastError();
  769. HRESULT hr = S_OK;
  770. try
  771. {
  772. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow));
  773. AutoReleaseThreadContext autoThreadContext(threadContextInfo);
  774. hr = fn();
  775. }
  776. catch (ContextClosedException&)
  777. {
  778. hr = E_ACCESSDENIED;
  779. }
  780. catch (Js::OutOfMemoryException)
  781. {
  782. hr = E_OUTOFMEMORY;
  783. }
  784. catch (Js::StackOverflowException)
  785. {
  786. hr = VBSERR_OutOfStack;
  787. }
  788. catch (Js::OperationAbortedException)
  789. {
  790. hr = E_ABORT;
  791. }
  792. catch (...)
  793. {
  794. AssertOrFailFastMsg(false, "Unknown exception caught in JIT server call.");
  795. }
  796. return MemoryOperationLastError::GetLastError();
  797. }
  798. template<typename Fn>
  799. HRESULT ServerCallWrapper(ServerScriptContext* scriptContextInfo, Fn fn)
  800. {
  801. try
  802. {
  803. AutoReleaseScriptContext autoScriptContext(scriptContextInfo);
  804. ServerThreadContext* threadContextInfo = scriptContextInfo->GetThreadContext();
  805. return ServerCallWrapper(threadContextInfo, fn);
  806. }
  807. catch (ContextClosedException&)
  808. {
  809. return E_ACCESSDENIED;
  810. }
  811. }