@@ -84,64 +84,20 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed)
8484 }
8585}
8686
87- /* ****************************************************************************
88- *
89- * Generate code to check that the GS cookie wasn't thrashed by a buffer
90- * overrun. If pushReg is true, preserve all registers around code sequence.
91- * Otherwise ECX could be modified.
92- *
93- * Implementation Note: pushReg = true, in case of tail calls.
94- */
95- void CodeGen::genEmitGSCookieCheck (bool pushReg)
87+ // ---------------------------------------------------------------------
88+ // genEmitGSCookieCheck:
89+ // Emit the check that the GS cookie has its original value.
90+ //
91+ // Parameters:
92+ // tailCall - Whether or not this is being emitted for a tail call
93+ //
94+ void CodeGen::genEmitGSCookieCheck (bool tailCall)
9695{
9796 noway_assert (compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal );
9897
99- regNumber regGSCheck;
100- regMaskTP regMaskGSCheck = RBM_NONE;
101-
102- if (!pushReg)
103- {
104- // Non-tail call: we can use any callee trash register that is not
105- // a return register or contain 'this' pointer (keep alive this), since
106- // we are generating GS cookie check after a GT_RETURN block.
107- // Note: On Amd64 System V RDX is an arg register - REG_ARG_2 - as well
108- // as return register for two-register-returned structs.
109- #ifdef TARGET_X86
110- // Note: ARG_0 can be REG_ASYNC_CONTINUATION_RET
111- // we will check for that later if we end up saving/restoring this.
112- regGSCheck = REG_ARG_0;
113- regNumber regGSCheckAlternative = REG_ARG_1;
114- #else
115- // these cannot be a part of any kind of return
116- regGSCheck = REG_R8;
117- regNumber regGSCheckAlternative = REG_R9;
118- #endif
119-
120- if (compiler->lvaKeepAliveAndReportThis () && compiler->lvaGetDesc (compiler->info .compThisArg )->lvIsInReg () &&
121- (compiler->lvaGetDesc (compiler->info .compThisArg )->GetRegNum () == regGSCheck))
122- {
123- regGSCheck = regGSCheckAlternative;
124- }
125- }
126- else
127- {
128- #ifdef TARGET_X86
129- // It doesn't matter which register we pick, since we're going to save and restore it
130- // around the check.
131- // TODO-CQ: Can we optimize the choice of register to avoid doing the push/pop sometimes?
132- regGSCheck = REG_EAX;
133- regMaskGSCheck = RBM_EAX;
134- #else // !TARGET_X86
135- // Jmp calls: specify method handle using which JIT queries VM for its entry point
136- // address and hence it can neither be a VSD call nor PInvoke calli with cookie
137- // parameter. Therefore, in case of jmp calls it is safe to use R11.
138- regGSCheck = REG_R11;
139- #endif // !TARGET_X86
140- }
141-
142- regMaskTP byrefPushedRegs = RBM_NONE;
143- regMaskTP norefPushedRegs = RBM_NONE;
144- regMaskTP pushedRegs = RBM_NONE;
98+ regMaskTP tempRegs = genGetGSCookieTempRegs (tailCall);
99+ assert (tempRegs != RBM_NONE);
100+ regNumber regGSCheck = genFirstRegNumFromMask (tempRegs);
145101
146102 if (compiler->gsGlobalSecurityCookieAddr == nullptr )
147103 {
@@ -163,18 +119,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg)
163119 }
164120 else
165121 {
166- // AOT case - GS cookie value needs to be accessed through an indirection.
167-
168- // if we use the continuation reg, the pop/push requires no-GC
169- // this can happen only when AOT supports async on x86
170- if (compiler->compIsAsync () && (regGSCheck == REG_ASYNC_CONTINUATION_RET))
171- {
172- regMaskGSCheck = RBM_ASYNC_CONTINUATION_RET;
173- GetEmitter ()->emitDisableGC ();
174- }
175-
176- pushedRegs = genPushRegs (regMaskGSCheck, &byrefPushedRegs, &norefPushedRegs);
177-
178122 instGen_Set_Reg_To_Imm (EA_HANDLE_CNS_RELOC, regGSCheck, (ssize_t )compiler->gsGlobalSecurityCookieAddr );
179123 GetEmitter ()->emitIns_R_AR (ins_Load (TYP_I_IMPL), EA_PTRSIZE, regGSCheck, regGSCheck, 0 );
180124 GetEmitter ()->emitIns_S_R (INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie , 0 );
@@ -184,8 +128,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg)
184128 inst_JMP (EJ_je, gsCheckBlk);
185129 genEmitHelperCall (CORINFO_HELP_FAIL_FAST, 0 , EA_UNKNOWN);
186130 genDefineTempLabel (gsCheckBlk);
187-
188- genPopRegs (pushedRegs, byrefPushedRegs, norefPushedRegs);
189131}
190132
191133BasicBlock* CodeGen::genCallFinally (BasicBlock* block)
@@ -6043,24 +5985,6 @@ void CodeGen::genCall(GenTreeCall* call)
60435985 // all virtuals should have been expanded into a control expression
60445986 assert (!call->IsVirtual () || call->gtControlExpr || call->gtCallAddr );
60455987
6046- // Insert a GS check if necessary
6047- if (call->IsTailCallViaJitHelper ())
6048- {
6049- if (compiler->getNeedsGSSecurityCookie ())
6050- {
6051- #if FEATURE_FIXED_OUT_ARGS
6052- // If either of the conditions below is true, we will need a temporary register in order to perform the GS
6053- // cookie check. When FEATURE_FIXED_OUT_ARGS is disabled, we save and restore the temporary register using
6054- // push/pop. When FEATURE_FIXED_OUT_ARGS is enabled, however, we need an alternative solution. For now,
6055- // though, the tail prefix is ignored on all platforms that use fixed out args, so we should never hit this
6056- // case.
6057- assert (compiler->gsGlobalSecurityCookieAddr == nullptr );
6058- assert ((int )compiler->gsGlobalSecurityCookieVal == (ssize_t )compiler->gsGlobalSecurityCookieVal );
6059- #endif
6060- genEmitGSCookieCheck (true );
6061- }
6062- }
6063-
60645988 genCallPlaceRegArgs (call);
60655989
60665990#if defined(TARGET_X86)
0 commit comments