@@ -3799,6 +3799,14 @@ void CodeGen::genCheckUseBlockInit()
37993799 JITDUMP (" must init a tracked V%02u because it a struct with a GC ref\n " , varNum);
38003800 mustInitThisVar = true ;
38013801 }
3802+ #ifdef TARGET_WASM
3803+ else if (hasGCPtr)
3804+ {
3805+ // On wasm all GC vars are reported as untracked, so the slot must be zero-inited.
3806+ JITDUMP (" must init V%02u because wasm reports tracked GC vars as untracked\n " , varNum);
3807+ mustInitThisVar = true ;
3808+ }
3809+ #endif
38023810 else
38033811 {
38043812 // We are done with tracked or GC vars, now look at untracked vars without GC refs.
@@ -3858,7 +3866,12 @@ void CodeGen::genCheckUseBlockInit()
38583866 // If this logic changes, Compiler::fgVarNeedsExplicitZeroInit needs
38593867 // to be modified.
38603868
3861- #ifdef TARGET_64BIT
3869+ #ifdef TARGET_WASM
3870+
3871+ // On WASM we always use a single memory.fill for prolog zeroing.
3872+ genUseBlockInit = (genInitStkLclCnt > 0 );
3873+
3874+ #elif defined(TARGET_64BIT)
38623875#if defined(TARGET_AMD64)
38633876
38643877 // We can clear using aligned SIMD so the threshold is lower,
@@ -5107,7 +5120,52 @@ void CodeGen::genFnProlog()
51075120 regMaskTP initFltRegs = RBM_NONE; // FP registers which must be init'ed.
51085121 regMaskTP initDblRegs = RBM_NONE;
51095122
5110- #ifndef TARGET_WASM
5123+ #ifdef TARGET_WASM
5124+ // For Wasm we only need to zero locals on the shadow stack; wasm locals are
5125+ // automatically zeroed.
5126+ for (unsigned varNum = 0 ; varNum < m_compiler->lvaCount ; ++varNum)
5127+ {
5128+ LclVarDsc* varDsc = m_compiler->lvaGetDesc (varNum);
5129+
5130+ if (varDsc->lvIsParam && !varDsc->lvIsRegArg )
5131+ {
5132+ continue ;
5133+ }
5134+ if (!varDsc->lvOnFrame || !varDsc->lvMustInit )
5135+ {
5136+ continue ;
5137+ }
5138+ if (m_compiler->lvaIsUnknownSizeLocal (varNum))
5139+ {
5140+ continue ;
5141+ }
5142+ // Defensively skip the wasm frame-header locals so we never overwrite the
5143+ // funclet info written by genAllocLclFrame at fp[0].
5144+ if ((varNum == m_compiler->lvaWasmFunctionIndex ) || (varNum == m_compiler->lvaWasmVirtualIP ) ||
5145+ (varNum == m_compiler->lvaWasmResumeIP ))
5146+ {
5147+ continue ;
5148+ }
5149+
5150+ signed int loOffs = varDsc->GetStackOffset ();
5151+ signed int hiOffs = loOffs + m_compiler->lvaLclStackHomeSize (varNum);
5152+
5153+ hasUntrLcl = true ;
5154+
5155+ if (loOffs < untrLclLo)
5156+ {
5157+ untrLclLo = loOffs;
5158+ }
5159+ if (hiOffs > untrLclHi)
5160+ {
5161+ untrLclHi = hiOffs;
5162+ }
5163+ }
5164+
5165+ // GC spill temps are not produced on wasm today.
5166+ assert (regSet.tmpAllFree ());
5167+ assert (regSet.tmpListBeg () == nullptr );
5168+ #else // !TARGET_WASM
51115169 unsigned varNum;
51125170 LclVarDsc* varDsc;
51135171
@@ -5266,6 +5324,7 @@ void CodeGen::genFnProlog()
52665324 untrLclHi = hiOffs;
52675325 }
52685326 }
5327+ #endif // !TARGET_WASM
52695328
52705329 // TODO-Cleanup: Add suitable assert for the OSR case.
52715330 assert (m_compiler->opts .IsOSR () || ((genInitStkLclCnt > 0 ) == hasUntrLcl));
@@ -5281,6 +5340,7 @@ void CodeGen::genFnProlog()
52815340 }
52825341#endif
52835342
5343+ #ifndef TARGET_WASM
52845344#ifdef TARGET_ARM
52855345 // On the ARM we will spill any incoming struct args in the first instruction in the prolog
52865346 // Ditto for all enregistered user arguments in a varargs method.
@@ -5569,13 +5629,13 @@ void CodeGen::genFnProlog()
55695629 }
55705630#endif // TARGET_ARM
55715631
5572- #ifndef TARGET_WASM // TODO-WASM: temporary; un-undefine as needed.
55735632 //
55745633 // Zero out the frame as needed
55755634 //
55765635
55775636 genZeroInitFrame (untrLclHi, untrLclLo, initReg, &initRegZeroed);
55785637
5638+ #ifndef TARGET_WASM // TODO-WASM: enable as needed.
55795639 genReportGenericContextArg (initReg, &initRegZeroed);
55805640
55815641#ifdef JIT32_GCENCODER
0 commit comments