@@ -153,38 +153,76 @@ J9::CodeCache::initialize(TR::CodeCacheManager *manager,
153
153
{
154
154
J9JavaVM * javaVM = jitConfig->javaVM ;
155
155
PORT_ACCESS_FROM_JAVAVM (javaVM); // for j9vmem_supported_page_sizes
156
+ uintptr_t round = (uintptr_t )(j9vmem_supported_page_sizes ()[0 ] - 1 );
157
+
158
+ // The code cache segment start must be page aligned because it was allocated with mmap
159
+ // _warmCodeAllocBase may not be at the very beginning of the segment though (and not page alinged)
160
+ // Align on page boundary going backwards if needed.
161
+ uintptr_t warmSectionStart = (uintptr_t )_warmCodeAllocBase & ~round;
162
+ // The cold section may be followed by trampolines and helpers, so it may not be page aligned.
163
+ // Align it going forward. This will not go past the end of the segment which is page aligned.
164
+ uintptr_t coldSectionEnd = ((uintptr_t )_coldCodeAllocBase + round) & ~round;
165
+ // Find the split point between the warm area (using large pages) and the cold area (using small pages).
166
+ // Experiments have shown that warm/cold code is about 50/50, so we need to find the middle point.
167
+ uintptr_t middle = warmSectionStart + (coldSectionEnd - warmSectionStart) / 2 ;
168
+ uintptr_t coldSectionStart = middle;
169
+ // Since we want to use large pages for the warm area, its end needs to be large page aligned.
170
+ // We cannot determine the size of the THP page with j9vmem_supported_page_sizes(),
171
+ // but we know that on x86, the size of a THP page is 2 MB. Round up/down as needed.
172
+ #if defined(TR_TARGET_X86)
173
+ static const uintptr_t THP_SIZE = 2 * 1024 * 1024 ; // 2 MB
174
+ #elif defined(TR_TARGET_S390)
175
+ static const uintptr_t THP_SIZE = 1 * 1024 * 1024 ; // 1 MB
176
+ #else
177
+ // Power has 64 KB and 16 MB pages (16 MB is too large to be useful for disclaiming)
178
+ // ARM can have many sizes for its large pages: 64 K, 1 MB, 2 MB, 16 MB)
179
+ static const uintptr_t THP_SIZE = 65536 ; // 64K
180
+ #endif
181
+ static const uintptr_t ROUNDING_VALUE = THP_SIZE/2 - 1 ;
182
+ if (codeCacheSegment->segmentTop () - codeCacheSegment->segmentBase () >= 2 * THP_SIZE)
183
+ {
184
+ coldSectionStart = (middle + ROUNDING_VALUE) & ~ROUNDING_VALUE;
185
+ }
186
+ TR_ASSERT_FATAL (coldSectionEnd > coldSectionStart, " A code cache can't be smaller than a page" );
187
+ _smallPageAreaStart = (uint8_t *)coldSectionStart;
188
+ _smallPageAreaEnd = (uint8_t *)coldSectionEnd;
156
189
157
- uint8_t *middle = _warmCodeAlloc + (_coldCodeAllocBase - _warmCodeAlloc) / 2 ;
158
- size_t round = j9vmem_supported_page_sizes ()[0 ] - 1 ;
159
- middle = (uint8_t *)(((size_t )(middle + round)) & ~round);
160
-
161
- TR_ASSERT_FATAL (_coldCodeAlloc > middle, " A code cache can't be smaller than a page" );
190
+ size_t coldCacheSize = coldSectionEnd - coldSectionStart;
162
191
163
- size_t coldCacheSize = _coldCodeAlloc - middle;
164
- coldCacheSize = (coldCacheSize + round) & ~round;
192
+ if (TR::Options::getCmdLineOptions ()->getVerboseOption (TR_VerbosePerformance))
193
+ TR_VerboseLog::writeLineLocked (TR_Vlog_INFO, " Code cache warm area %p - %p (size=%zu); cold area %p - %p (size=%zu)" ,
194
+ (uint8_t *)warmSectionStart, _smallPageAreaStart, _smallPageAreaStart - (uint8_t *)warmSectionStart,
195
+ _smallPageAreaStart, _smallPageAreaEnd, coldCacheSize);
165
196
166
- if (madvise (middle , coldCacheSize, MADV_NOHUGEPAGE) != 0 )
197
+ if (madvise (_smallPageAreaStart , coldCacheSize, MADV_NOHUGEPAGE) != 0 )
167
198
{
168
199
const char *error = strerror (errno);
169
200
if (TR::Options::getCmdLineOptions ()->getVerboseOption (TR_VerbosePerformance))
170
- TR_VerboseLog::writeLineLocked (TR_Vlog_INFO, " Failed to set MADV_NOHUGEPAGE for code cache: %s: %p %zu" , error, middle , coldCacheSize);
201
+ TR_VerboseLog::writeLineLocked (TR_Vlog_INFO, " Failed to set MADV_NOHUGEPAGE for code cache: %s: %p %zu" , error, _smallPageAreaStart , coldCacheSize);
171
202
}
172
203
else if (TR::Options::getCmdLineOptions ()->getVerboseOption (TR_VerbosePerformance))
173
204
{
174
- TR_VerboseLog::writeLineLocked (TR_Vlog_INFO, " Forcing code cache cold region %p-%p to use default size memory pages" , middle, middle + coldCacheSize);
205
+ TR_VerboseLog::writeLineLocked (TR_Vlog_INFO, " Forcing code cache cold region %p-%p of size %zu to use default size memory pages" ,
206
+ _smallPageAreaStart, _smallPageAreaStart + coldCacheSize, coldCacheSize);
175
207
}
176
208
177
209
// If the memory segment is backed by a file, disable read-ahead
178
210
// so that touching one byte brings a single page in
179
211
if (codeCacheSegment->j9segment ()->vmemIdentifier .allocator == OMRPORT_VMEM_RESERVE_USED_MMAP_SHM)
180
212
{
181
- if (madvise (middle , coldCacheSize, MADV_RANDOM) != 0 )
213
+ if (madvise (_smallPageAreaStart , coldCacheSize, MADV_RANDOM) != 0 )
182
214
{
183
215
if (TR::Options::getCmdLineOptions ()->getVerboseOption (TR_VerbosePerformance))
184
216
TR_VerboseLog::writeLineLocked (TR_Vlog_INFO, " Failed to set MADV_RANDOM for cold code cache" );
185
217
}
186
218
}
187
219
}
220
+ else // Disclaim is not allowed
221
+ {
222
+ // Note: if _smallPageAreaStart and _smallPageAreaEnd are the same, there will be no disclaim attempted
223
+ _smallPageAreaStart = _coldCodeAllocBase;
224
+ _smallPageAreaEnd = _coldCodeAllocBase;
225
+ }
188
226
#endif // ifdef LINUX
189
227
190
228
_manager->reportCodeLoadEvents ();
@@ -822,31 +860,35 @@ J9::CodeCache::disclaim(TR::CodeCacheManager *manager, bool canDisclaimOnSwap)
822
860
int32_t disclaimDone = 0 ;
823
861
824
862
#ifdef LINUX
825
- J9JavaVM * javaVM = jitConfig->javaVM ;
826
- PORT_ACCESS_FROM_JAVAVM (javaVM); // for j9vmem_supported_page_sizes
863
+ if ((uintptr_t )_smallPageAreaStart >= (uintptr_t )_smallPageAreaEnd)
864
+ return disclaimDone;
865
+ uint8_t *disclaimStart = _smallPageAreaStart;
866
+ // Some of the warm code could have been written into the small page area.
867
+ // We don't want to disclaim warm code.
868
+ if ((uintptr_t )_warmCodeAlloc > (uintptr_t )_smallPageAreaStart)
869
+ {
870
+ J9JavaVM * javaVM = jitConfig->javaVM ;
871
+ PORT_ACCESS_FROM_JAVAVM (javaVM); // for j9vmem_supported_page_sizes
872
+ uintptr_t round = (uintptr_t )(j9vmem_supported_page_sizes ()[0 ] - 1 );
873
+ disclaimStart = (uint8_t *)(((uintptr_t )_warmCodeAlloc + round) & ~round);
874
+ if ((uintptr_t )disclaimStart >= (uintptr_t )_smallPageAreaEnd) // Nothing to disclaim
875
+ return disclaimDone;
876
+ }
877
+ TR_ASSERT_FATAL ((uintptr_t )_smallPageAreaEnd >= (uintptr_t )disclaimStart, " disclaimStart is past the cold area end" );
827
878
879
+ size_t disclaimSize = _smallPageAreaEnd - disclaimStart;
828
880
bool trace = TR::Options::getCmdLineOptions ()->getVerboseOption (TR_VerbosePerformance);
829
- uint8_t *disclaim_start = _coldCodeAlloc;
830
- size_t pageSize = j9vmem_supported_page_sizes ()[0 ];
831
- size_t round = pageSize - 1 ;
832
- disclaim_start = (uint8_t *)(((size_t )(disclaim_start + round)) & ~round);
833
-
834
- if (_coldCodeAllocBase <= disclaim_start)
835
- return 0 ;
836
-
837
- size_t disclaim_size = (_coldCodeAllocBase - disclaim_start + round) & ~round;
838
-
839
881
if (trace)
840
882
{
841
- size_t warm_size = _warmCodeAlloc - _segment-> segmentBase () + sizeof ( this ) ;
883
+ size_t warm_size = _warmCodeAlloc - _warmCodeAllocBase ;
842
884
size_t cold_size = _coldCodeAllocBase - _coldCodeAlloc;
843
885
844
- TR_VerboseLog::writeLineLocked (TR_Vlog_PERF, " Will disclaim cold code cache %p : coldStart=%p coldBase=%p warm_size=%zuB cold_size=%zuB cold_size/(cold_size + warm_size)=%5.2f%%" ,
845
- this , _coldCodeAlloc, _coldCodeAllocBase,
846
- warm_size, cold_size, cold_size * 100.0 /(cold_size + warm_size));
886
+ TR_VerboseLog::writeLineLocked (TR_Vlog_PERF, " Disclaim code cache %p between Start=%p End=%p. coldStart=%p coldBase=%p warm_size=%zuB cold_size=%zuB cold_size/(cold_size + warm_size)=%5.2f%%" ,
887
+ this , disclaimStart, _smallPageAreaEnd , _coldCodeAlloc, _coldCodeAllocBase,
888
+ warm_size, cold_size, cold_size * 100.0 /(cold_size + warm_size));
847
889
}
848
890
849
- int32_t ret = madvise ((void *)disclaim_start, disclaim_size , MADV_PAGEOUT);
891
+ int32_t ret = madvise ((void *)disclaimStart, disclaimSize , MADV_PAGEOUT);
850
892
851
893
if (ret != 0 )
852
894
{
0 commit comments