@@ -469,6 +469,21 @@ NativeCodeGenerator::RejitIRViewerFunction(Js::FunctionBody *fn, Js::ScriptConte
469469}
470470#endif /* IR_VIEWER */
471471
472+ #ifdef ALLOW_JIT_REPRO
473+ HRESULT NativeCodeGenerator::JitFromEncodedWorkItem (_In_reads_(bufSize) const byte* buffer, _In_ uint bufferSize)
474+ {
475+ CodeGenWorkItemIDL* workItemData = nullptr ;
476+ HRESULT hr = JITManager::DeserializeRPCData (buffer, bufferSize, &workItemData);
477+ if (FAILED (hr))
478+ {
479+ return hr;
480+ }
481+ JITOutputIDL jitOutput = { 0 };
482+ CodeGen (scriptContext->GetThreadContext ()->GetPageAllocator (), workItemData, jitOutput, true );
483+ return S_OK;
484+ }
485+ #endif
486+
472487// /----------------------------------------------------------------------------
473488// /
474489// / NativeCodeGenerator::GenerateFunction
@@ -791,6 +806,74 @@ NativeCodeGenerator::IsValidVar(const Js::Var var, Recycler *const recycler)
791806volatile UINT_PTR NativeCodeGenerator::CodegenFailureSeed = 0 ;
792807#endif
793808
809+ void NativeCodeGenerator::CodeGen (PageAllocator* pageAllocator, CodeGenWorkItemIDL* workItemData, _Out_ JITOutputIDL& jitWriteData, const bool foreground, Js::EntryPointInfo* epInfo /* = nullptr*/ )
810+ {
811+ if (JITManager::GetJITManager ()->IsOOPJITEnabled ())
812+ {
813+ PSCRIPTCONTEXT_HANDLE remoteScriptContext = this ->scriptContext ->GetRemoteScriptAddr ();
814+ if (!JITManager::GetJITManager ()->IsConnected ())
815+ {
816+ throw Js::OperationAbortedException ();
817+ }
818+ HRESULT hr = JITManager::GetJITManager ()->RemoteCodeGenCall (
819+ workItemData,
820+ remoteScriptContext,
821+ &jitWriteData);
822+ if (hr == E_ACCESSDENIED && scriptContext->IsClosed ())
823+ {
824+ // script context may close after codegen call starts, consider this as aborted codegen
825+ hr = E_ABORT;
826+ }
827+ JITManager::HandleServerCallResult (hr, RemoteCallType::CodeGen);
828+
829+ if (!PreReservedVirtualAllocWrapper::IsInRange ((void *)this ->scriptContext ->GetThreadContext ()->GetPreReservedRegionAddr (), (void *)jitWriteData.codeAddress ))
830+ {
831+ this ->scriptContext ->GetJitFuncRangeCache ()->AddFuncRange ((void *)jitWriteData.codeAddress , jitWriteData.codeSize );
832+ }
833+ Assert (jitWriteData.codeAddress );
834+ Assert (jitWriteData.codeSize );
835+ }
836+ else
837+ {
838+ InProcCodeGenAllocators *const allocators =
839+ foreground ? EnsureForegroundAllocators (pageAllocator) : GetBackgroundAllocator (pageAllocator); // okay to do outside lock since the respective function is called only from one thread
840+ NoRecoverMemoryJitArenaAllocator jitArena (_u (" JITArena" ), pageAllocator, Js::Throw::OutOfMemory);
841+ #if DBG
842+ jitArena.SetNeedsDelayFreeList ();
843+ #endif
844+ JITTimeWorkItem * jitWorkItem = Anew (&jitArena, JITTimeWorkItem, workItemData);
845+
846+ #if !FLOATVAR
847+ CodeGenNumberAllocator* pNumberAllocator = nullptr ;
848+
849+ // the number allocator needs to be on the stack so that if we are doing foreground JIT
850+ // the chunk allocated from the recycler will be stacked pinned
851+ CodeGenNumberAllocator numberAllocator (
852+ foreground ? nullptr : scriptContext->GetThreadContext ()->GetCodeGenNumberThreadAllocator (),
853+ scriptContext->GetRecycler ());
854+ pNumberAllocator = &numberAllocator;
855+ #endif
856+ Js::ScriptContextProfiler *const codeGenProfiler =
857+ #ifdef PROFILE_EXEC
858+ foreground ? EnsureForegroundCodeGenProfiler () : GetBackgroundCodeGenProfiler (pageAllocator); // okay to do outside lock since the respective function is called only from one thread
859+ #else
860+ nullptr ;
861+ #endif
862+
863+ Func::Codegen (&jitArena, jitWorkItem, scriptContext->GetThreadContext (),
864+ scriptContext, &jitWriteData, epInfo, nullptr , jitWorkItem->GetPolymorphicInlineCacheInfo (), allocators,
865+ #if !FLOATVAR
866+ pNumberAllocator,
867+ #endif
868+ codeGenProfiler, !foreground);
869+
870+ if (!this ->scriptContext ->GetThreadContext ()->GetPreReservedVirtualAllocator ()->IsInRange ((void *)jitWriteData.codeAddress ))
871+ {
872+ this ->scriptContext ->GetJitFuncRangeCache ()->AddFuncRange ((void *)jitWriteData.codeAddress , jitWriteData.codeSize );
873+ }
874+ }
875+ }
876+
794877void
795878NativeCodeGenerator::CodeGen (PageAllocator * pageAllocator, CodeGenWorkItem* workItem, const bool foreground)
796879{
@@ -889,70 +972,7 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor
889972 LARGE_INTEGER start_time = { 0 };
890973 NativeCodeGenerator::LogCodeGenStart (workItem, &start_time);
891974 workItem->GetJITData ()->startTime = (int64)start_time.QuadPart ;
892- if (JITManager::GetJITManager ()->IsOOPJITEnabled ())
893- {
894- PSCRIPTCONTEXT_HANDLE remoteScriptContext = this ->scriptContext ->GetRemoteScriptAddr ();
895- if (!JITManager::GetJITManager ()->IsConnected ())
896- {
897- throw Js::OperationAbortedException ();
898- }
899- HRESULT hr = JITManager::GetJITManager ()->RemoteCodeGenCall (
900- workItem->GetJITData (),
901- remoteScriptContext,
902- &jitWriteData);
903- if (hr == E_ACCESSDENIED && body->GetScriptContext ()->IsClosed ())
904- {
905- // script context may close after codegen call starts, consider this as aborted codegen
906- hr = E_ABORT;
907- }
908- JITManager::HandleServerCallResult (hr, RemoteCallType::CodeGen);
909-
910- if (!PreReservedVirtualAllocWrapper::IsInRange ((void *)this ->scriptContext ->GetThreadContext ()->GetPreReservedRegionAddr (), (void *)jitWriteData.codeAddress ))
911- {
912- this ->scriptContext ->GetJitFuncRangeCache ()->AddFuncRange ((void *)jitWriteData.codeAddress , jitWriteData.codeSize );
913- }
914- Assert (jitWriteData.codeAddress );
915- Assert (jitWriteData.codeSize );
916- }
917- else
918- {
919- InProcCodeGenAllocators *const allocators =
920- foreground ? EnsureForegroundAllocators (pageAllocator) : GetBackgroundAllocator (pageAllocator); // okay to do outside lock since the respective function is called only from one thread
921- NoRecoverMemoryJitArenaAllocator jitArena (_u (" JITArena" ), pageAllocator, Js::Throw::OutOfMemory);
922- #if DBG
923- jitArena.SetNeedsDelayFreeList ();
924- #endif
925- JITTimeWorkItem * jitWorkItem = Anew (&jitArena, JITTimeWorkItem, workItem->GetJITData ());
926-
927- #if !FLOATVAR
928- CodeGenNumberAllocator* pNumberAllocator = nullptr ;
929-
930- // the number allocator needs to be on the stack so that if we are doing foreground JIT
931- // the chunk allocated from the recycler will be stacked pinned
932- CodeGenNumberAllocator numberAllocator (
933- foreground ? nullptr : scriptContext->GetThreadContext ()->GetCodeGenNumberThreadAllocator (),
934- scriptContext->GetRecycler ());
935- pNumberAllocator = &numberAllocator;
936- #endif
937- Js::ScriptContextProfiler *const codeGenProfiler =
938- #ifdef PROFILE_EXEC
939- foreground ? EnsureForegroundCodeGenProfiler () : GetBackgroundCodeGenProfiler (pageAllocator); // okay to do outside lock since the respective function is called only from one thread
940- #else
941- nullptr ;
942- #endif
943-
944- Func::Codegen (&jitArena, jitWorkItem, scriptContext->GetThreadContext (),
945- scriptContext, &jitWriteData, epInfo, nullptr , jitWorkItem->GetPolymorphicInlineCacheInfo (), allocators,
946- #if !FLOATVAR
947- pNumberAllocator,
948- #endif
949- codeGenProfiler, !foreground);
950-
951- if (!this ->scriptContext ->GetThreadContext ()->GetPreReservedVirtualAllocator ()->IsInRange ((void *)jitWriteData.codeAddress ))
952- {
953- this ->scriptContext ->GetJitFuncRangeCache ()->AddFuncRange ((void *)jitWriteData.codeAddress , jitWriteData.codeSize );
954- }
955- }
975+ CodeGen (pageAllocator, workItem->GetJITData (), jitWriteData, foreground, epInfo);
956976
957977 if (JITManager::GetJITManager ()->IsOOPJITEnabled () && PHASE_VERBOSE_TRACE (Js::BackEndPhase, workItem->GetFunctionBody ()))
958978 {
@@ -1194,6 +1214,7 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor
11941214#endif
11951215}
11961216
1217+
11971218/* static */
11981219void NativeCodeGenerator::LogCodeGenStart (CodeGenWorkItem * workItem, LARGE_INTEGER * start_time)
11991220{
0 commit comments