-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Conversation
@dotnet-bot test OSX x64 Checked Build and Test please |
1 similar comment
@dotnet-bot test OSX x64 Checked Build and Test please |
\CC @seanshpark @wateret |
@parjong I think this refactoring went too far. It seems that instead of defining all the four methods per each register, it would be enough to define just GetRegisterLocation(rd, reg) macro or inline functions GetXXXLocation() where XXX is Eax, Ebx, Ecx, Edx, ... Then you would replace all usages of pXXX by GetXXXLocation(). It seems easier to read that way with using C++ dereferencing to read and write the values instead of introducing new functions. Edit: I can see now that the Trash is actually different from the setter for non-volatile registers. |
Also, I've missed before that you haven't removed the pXXX members for WIN64EXCEPTIONS, which I have expected to happen. |
@janvorli Sorry for late response. I was out of office in last 4 days. Do you mean that the value of For your second comment, this PR removes pXXX members for WIN64EXCEPTIONS. These members are inside |
@parjong than you for your response. As for my last comment, I am sorry, I can see now that you are right and the pXXX members are no longer there for WIN64EXCEPTIONS. I somehow confused myself. As for the GetXXXLocation, you are right, we would also need a SetXXXLocation function. But these two should be sufficient and it would be very easy to understand their intent. |
@janvorli Thank you for comment. Could you let me know some details about
Is it enough to use |
@parjong I think that basically everything that was done through pXXX before should now be done through pCurrentContextPointers->XXX. I see this change as a pure replacement of pXXX with the other ones. |
@dotnet-bot test Windows_NT x64 Debug Build and Test please |
@janvorli PR is revised per feedback. Please take a look. |
src/inc/regdisp.h
Outdated
|
||
#define VOLATILE_REG_METHODS(reg) \ | ||
inline PDWORD Get##reg##Location(void) { return &pCurrentContext->reg; } \ | ||
inline void Set##reg##Location(PDWORD p##reg) { pCurrentContext->reg = *p##reg; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to distinguish between the volatile and non-volatile cases. We can add Eax, Ecx and Edx to the KNONVOLATILE_CONTEXT_POINTERS instead. If you look at the structure for AMD64, you can see that the same thing is done there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SetXXXLocation should really just set the context pointer without touching the register value in the context and that we should update the context as an additional step after the unwinding (in OOPStackUnwinderX86::VirtualUnwind and EECodeManager::QuickUnwindStackFrame). Letting the function have a side effect that's not obvious based on its name is confusing when reading the code that uses this function.
It also seems that it would be better to keep the XXXFrame::UpdateRegDisplay code for x86 Linux as close as possible to the x64 version. And these functions also update context and context pointers separately on x64. And thinking about it more, it seems it would make sense to use the new GetXXXLocation / SetXXXLocation only in code that's common for WIN64EXCEPTIONS and !WIN64EXCEPTIONS, but let places where the code is split into separate WIN64EXCEPTIONS and !WIN64EXCEPTIONS versions access the specific pXXX or pCurrentContextPointers->XXX explicitly for the reason of consistency with the x64 version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@janvorli Could you let me know the role of pCurrentContext
? It seems that pCurrentContextPointers
is enough for the purpose of unwind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pCurrentContext->XXX contain values that the pCurrentContextPointers->XXX point to. Please note that there are actually two context and two context pointer structures. To one of them points the pCurrentContext / pCurrentContextPointers. To the other points the pParentContext / pParentContextPointers. That allows unwinding at some places to eliminate some context / context pointers copying by just switching the the pCurrentXXX and pParentXXX pointers.
While it might theoretically be possible to modify the existing code to not to use pCurrentContext for x86, it would be error prone and make the x86 Linux code even more different from the other targets using WIN64EXCEPTIONS.
src/inc/regdisp.h
Outdated
|
||
#define NONVOLATILE_REG_METHODS(reg) \ | ||
inline PDWORD Get##reg##Location(void) { return (pCurrentContextPointers) ? pCurrentContextPointers->reg : &pCurrentContext->reg; } \ | ||
inline void Set##reg##Location(PDWORD p##reg) { if (pCurrentContextPointers) { pCurrentContextPointers->reg = p##reg; } pCurrentContext->reg = *p##reg; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, let's not check the pCurrentContextPointers here and ensure the pCurrentContextPointers is always valid when calling these functions instead. I think that the only place where this could be called with the context pointers set to NULL is from OOPStackUnwinderX86::VirtualUnwind with the way you've modified the function. If you didn't reassign the pCurrentContextPointers and pCurrentContext and just copied the values as you were doing before, you'd not have this issue. Or is there another place that I am missing?
src/vm/eetwain.cpp
Outdated
@@ -3207,12 +3211,12 @@ const RegMask CALLEE_SAVED_REGISTERS_MASK[] = | |||
RM_EBP // last register to be pushed | |||
}; | |||
|
|||
const SIZE_T REGDISPLAY_OFFSET_OF_CALLEE_SAVED_REGISTERS[] = | |||
const REGDISPLAY::TAG CALLEE_SAVED_REGISTERS_TAG[] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to keep using offsets instead of a tag and switch in the SetLocation. It should work if we let the offsets array for WIN64EXCEPTIONS to keep offsets in the context pointers structure and the code accessing it would use pContext->pCurrentContextPointers as the base.
Since there are five places where we use the offset array the same way, it would then make sense to factor this out into a separate function, e.g. SetRegisterLocation(i, addr)
so that the WIN64EXCEPTIONS changes would be localized.
…into SetXXXLocation
1310d8c
to
8206dc4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, we are almost there! Just a few little things remaining.
src/inc/regdisp.h
Outdated
@@ -430,6 +423,10 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC | |||
pRD->ctxPtrsOne.Esi = &pctx->Esi; | |||
pRD->ctxPtrsOne.Edi = &pctx->Edi; | |||
pRD->ctxPtrsOne.Ebp = &pctx->Ebp; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nit - for consistency with other target, you could now revert back to using a loop for copying the registers if you reordered them in the KNONVOLATILE_CONTEXT_POINTERS to match their order in the CONTEXT.
src/inc/regdisp.h
Outdated
inline void Set##reg##Location(PDWORD p##reg) { pCurrentContext->reg = *p##reg; } | ||
|
||
#define NONVOLATILE_REG_METHODS(reg) \ | ||
#define REG_METHODS(reg) \ | ||
inline PDWORD Get##reg##Location(void) { return (pCurrentContextPointers) ? pCurrentContextPointers->reg : &pCurrentContext->reg; } \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GetXXXLocation should also assume the pCurrentContextPointers is not NULL.
src/unwinder/i386/unwinder_i386.cpp
Outdated
@@ -97,6 +97,10 @@ OOPStackUnwinderX86::VirtualUnwind( | |||
|
|||
ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; | |||
|
|||
#define CALLER_SAVED_REGISTER(reg) if (rd.pCurrentContextPointers->reg) ContextRecord->reg = *rd.pCurrentContextPointers->reg; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not needed. The UnwindStackFrame never sets context pointers of the caller saved registers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UnwindEbpDoubleAlignFrame
sets Eax, Ecx, Edx for debugging purpose:
3832 #ifdef _DEBUG
3833 /* The filter has to be called by the VM. So we dont need to
3834 update callee-saved registers.
3835 */
3836
3837 if (flags & UpdateAllRegs)
3838 {
3839 static DWORD s_badData = 0xDEADBEEF;
3840
3841 pContext->SetEaxLocation(&s_badData);
3842 pContext->SetEcxLocation(&s_badData);
3843 pContext->SetEdxLocation(&s_badData);
3844
3845 pContext->SetEbxLocation(&s_badData);
3846 pContext->SetEsiLocation(&s_badData);
3847 pContext->SetEdiLocation(&s_badData);
3848 }
3849 #endif
I'm not sure which one is better: enclosing this region with _DEBUG, or simply removing it. Please let me know your opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am sorry, I have missed this. So please leave your change as it is.
src/vm/i386/cgenx86.cpp
Outdated
|
||
#else // WIN64EXCEPTIONS | ||
#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContextPointers->regname = &m_ctx.regname; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the amd64 version, we should also set the context pointers for caller saved registers here.
src/vm/i386/cgenx86.cpp
Outdated
ENUM_CALLEE_SAVED_REGISTERS(); | ||
#undef CALLEE_SAVED_REGISTER | ||
|
||
#define CALLER_SAVED_REGISTER(reg) pRD->pCurrentContextPointers->reg = &m_Args->reg; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the amd64 version, context pointers to argument registers (ecx, edx) should be NULLed and only the pointer to the return register (eax) should be set.
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr); | ||
pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR)); | ||
|
||
#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContext->reg = m_Args->reg; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we can use the UpdateRegDisplayFromCalleeSavedRegisters that you've added now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was my first trial, but UpdateRegDisplayFromCalleeSavedRegisters
cannot be used here as m_Args
is of type HijackArgs
(not CalleeSavedRegisters
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see, the HijackArgs differ from the amd64 version.
src/vm/i386/cgencpu.h
Outdated
@@ -154,6 +154,11 @@ typedef INT32 StackElemType; | |||
// This represents some of the FramedMethodFrame fields that are | |||
// stored at negative offsets. | |||
//-------------------------------------------------------------------- | |||
#define ENUM_CALLER_SAVED_REGISTERS() \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nit. These are argument and scratch registers, so it seems it might be better to call it ENUM_ARGUMENT_AND_SCRATCH_REGISTERS. We have ENUM_ARGUMENT_REGISTERS for amd64, so that would make it similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you a lot!
@janvorli Oh, I see. Thank you for your consideration. |
@dotnet-bot test Windows_NT x64 Release Priority 1 Build and Test please |
* [x86/Linux] Do NOT use pXXX fields * Fix x86/Windows build error * Fix another x86/Windows build error * Fix typo * Do NOT trash EBP * Reflect the original semantics of EHContext::UpdateFrame * Unify ReadXXX/LocateXXX into GetXXXLocation, and RestoreXXX/TrashXXX into SetXXXLocation * Revert the order of pXXX fields * Revise cgenx86.cpp * Revert unnecessary changes * Remove direct accesses to CALLEE_SAVED_REGISTERS_TAG * Do NOT update pCurrentContext inside SetXXXLocation * Update RegPtr via offset * Unify REG_METHODS (and revise UpdateRegDisplay methods accordingly) * Revise per feedback * Fix x86/Windows build error Commit migrated from dotnet/coreclr@009c70f
This commit removes pXXX fields in REGDISPLAY, and revises all the references on these fields (as discussed in #8998) to refers corresponding fields in pCurrentContext and pCurrentContetPointers.