- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.2k
Avoid unnecessary allocations of jump stubs #116944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -11725,16 +11725,24 @@ void CEEJitInfo::recordRelocation(void * location, | |
| } | ||
| else | ||
| { | ||
| // | ||
| // When m_fAllowRel32 == FALSE, the JIT will use a REL32s for direct code targets only. | ||
| // Use jump stub. | ||
| // | ||
| delta = rel32UsingJumpStub(fixupLocation, (PCODE)target, m_pMethodBeingCompiled, NULL, false /* throwOnOutOfMemoryWithinRange */); | ||
| if (delta == 0) | ||
| if (m_fJumpStubOverflow) | ||
| { | ||
| // This forces the JIT to retry the method, which allows us to reserve more space for jump stubs and have a higher chance that | ||
| // we will find space for them. | ||
| m_fJumpStubOverflow = TRUE; | ||
| // Do not attempt to allocate more jump stubs. We are going to throw away the code and retry anyway. | ||
| delta = 0; | ||
| } | ||
| else | ||
| { | ||
| // | ||
| // When m_fAllowRel32 == FALSE, the JIT will use a REL32s for direct code targets only. | ||
| // Use jump stub. | ||
| // | ||
| delta = rel32UsingJumpStub(fixupLocation, (PCODE)target, m_pMethodBeingCompiled, NULL, false /* throwOnOutOfMemoryWithinRange */); | ||
| if (delta == 0) | ||
| { | ||
| // This forces the JIT to retry the method, which allows us to reserve more space for jump stubs and have a higher chance that | ||
| // we will find space for them. | ||
| m_fJumpStubOverflow = TRUE; | ||
| } | ||
| } | ||
|  | ||
| // Keep track of conservative estimate of how much memory may be needed by jump stubs. We will use it to reserve extra memory | ||
|  | @@ -11777,24 +11785,35 @@ void CEEJitInfo::recordRelocation(void * location, | |
| // | ||
| if (!FitsInRel28(delta)) | ||
| { | ||
| // Use jump stub. | ||
| // | ||
| TADDR baseAddr = (TADDR)fixupLocation; | ||
| TADDR loAddr = baseAddr - 0x08000000; // -2^27 | ||
| TADDR hiAddr = baseAddr + 0x07FFFFFF; // +2^27-1 | ||
|  | ||
| // Check for the wrap around cases | ||
| if (loAddr > baseAddr) | ||
| loAddr = UINT64_MIN; // overflow | ||
| if (hiAddr < baseAddr) | ||
| hiAddr = UINT64_MAX; // overflow | ||
|  | ||
| PCODE jumpStubAddr = ExecutionManager::jumpStub(m_pMethodBeingCompiled, | ||
| (PCODE) target, | ||
| (BYTE *) loAddr, | ||
| (BYTE *) hiAddr, | ||
| NULL, | ||
| false); | ||
| TADDR jumpStubAddr; | ||
|  | ||
| if (m_fJumpStubOverflow) | ||
| 
     | ||
| { | ||
| // Do not attempt to allocate more jump stubs. We are going to throw away the code and retry anyway. | ||
| jumpStubAddr = 0; | ||
| } | ||
| else | ||
| { | ||
|  | ||
| // Use jump stub. | ||
| // | ||
| TADDR baseAddr = (TADDR)fixupLocation; | ||
| TADDR loAddr = baseAddr - 0x08000000; // -2^27 | ||
| TADDR hiAddr = baseAddr + 0x07FFFFFF; // +2^27-1 | ||
|  | ||
| // Check for the wrap around cases | ||
| if (loAddr > baseAddr) | ||
| loAddr = UINT64_MIN; // overflow | ||
| if (hiAddr < baseAddr) | ||
| hiAddr = UINT64_MAX; // overflow | ||
|  | ||
| jumpStubAddr = ExecutionManager::jumpStub(m_pMethodBeingCompiled, | ||
| (PCODE) target, | ||
| (BYTE *) loAddr, | ||
| (BYTE *) hiAddr, | ||
| NULL, | ||
| false); | ||
| } | ||
|  | ||
| // Keep track of conservative estimate of how much memory may be needed by jump stubs. We will use it to reserve extra memory | ||
| // on retry to increase chances that the retry succeeds. | ||
|  | ||
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.
Is my understanding of what happens in the test correct?
m_fAllowRel32 = falsem_fJumpStubOverflow = falseThere 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.
Or is 1 and 2 happening during the same attempt? And the slowness of the compilation was because of needing to find 284k jump stubs, which all go into the
ReserveWithinRangepath that can be quite slow?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 is 3 step process in the worst-case scenario on x64 like what's exercised by this test. It is 2 step process on arm64 (there is no allowRel32 on arm64.)
It may be possible to make it 2 step process in the worst case on x64 as well if the JIT passed more reloc details to the EE. I do not think we care enough about the extremely large methods like this one to make it better.
Right.
The third allocates a code heap with enough spare space for jump stubs that we may need. Jump stubs are allocated in the same code heap as regular code and we always try to find space for jump stubs in the existing code heaps first.