2011-01-19 19:30:42 -05:00
/*
2015-02-16 14:07:36 +01:00
* Copyright ( c ) 2011 , 2015 , Oracle and / or its affiliates . All rights reserved .
2011-01-19 19:30:42 -05:00
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
*
*/
# include "precompiled.hpp"
2015-05-13 15:16:06 +02:00
# include "gc/g1/g1CollectedHeap.inline.hpp"
# include "gc/g1/heapRegionRemSet.hpp"
# include "gc/g1/heapRegionSet.inline.hpp"
2011-01-19 19:30:42 -05:00
2014-03-14 10:15:46 +01:00
uint FreeRegionList : : _unrealistically_long_length = 0 ;
2011-01-19 19:30:42 -05:00
2011-03-04 17:13:19 -05:00
void HeapRegionSetBase : : fill_in_ext_msg ( hrs_ext_msg * msg , const char * message ) {
2015-06-24 12:12:25 -04:00
msg - > append ( " [%s] %s ln: %u cy: " SIZE_FORMAT ,
2014-03-14 10:15:46 +01:00
name ( ) , message , length ( ) , total_capacity_bytes ( ) ) ;
2011-01-19 19:30:42 -05:00
fill_in_ext_msg_extra ( msg ) ;
}
2014-03-14 10:15:46 +01:00
# ifndef PRODUCT
void HeapRegionSetBase : : verify_region ( HeapRegion * hr ) {
2014-08-26 09:36:53 +02:00
assert ( hr - > containing_set ( ) = = this , err_msg ( " Inconsistent containing set for %u " , hr - > hrm_index ( ) ) ) ;
assert ( ! hr - > is_young ( ) , err_msg ( " Adding young region %u " , hr - > hrm_index ( ) ) ) ; // currently we don't use these sets for young regions
2014-09-23 11:43:24 +02:00
assert ( hr - > is_humongous ( ) = = regions_humongous ( ) , err_msg ( " Wrong humongous state for region %u and set %s " , hr - > hrm_index ( ) , name ( ) ) ) ;
2014-09-15 12:19:31 +02:00
assert ( hr - > is_free ( ) = = regions_free ( ) , err_msg ( " Wrong free state for region %u and set %s " , hr - > hrm_index ( ) , name ( ) ) ) ;
assert ( ! hr - > is_free ( ) | | hr - > is_empty ( ) , err_msg ( " Free region %u is not empty for set %s " , hr - > hrm_index ( ) , name ( ) ) ) ;
2015-06-12 19:49:54 -04:00
assert ( ! hr - > is_empty ( ) | | hr - > is_free ( ) | | hr - > is_archive ( ) ,
err_msg ( " Empty region %u is not free or archive for set %s " , hr - > hrm_index ( ) , name ( ) ) ) ;
2014-08-26 09:36:53 +02:00
assert ( hr - > rem_set ( ) - > verify_ready_for_par_iteration ( ) , err_msg ( " Wrong iteration state %u " , hr - > hrm_index ( ) ) ) ;
2011-01-19 19:30:42 -05:00
}
2014-03-14 10:15:46 +01:00
# endif
2011-01-19 19:30:42 -05:00
void HeapRegionSetBase : : verify ( ) {
// It's important that we also observe the MT safety protocol even
// for the verification calls. If we do verification without the
// appropriate locks and the set changes underneath our feet
// verification might fail and send us on a wild goose chase.
2014-03-14 10:15:46 +01:00
check_mt_safety ( ) ;
2011-01-19 19:30:42 -05:00
2014-03-14 10:15:46 +01:00
guarantee ( ( is_empty ( ) & & length ( ) = = 0 & & total_capacity_bytes ( ) = = 0 ) | |
2015-02-16 14:07:36 +01:00
( ! is_empty ( ) & & length ( ) > 0 & & total_capacity_bytes ( ) > 0 ) ,
2011-03-04 17:13:19 -05:00
hrs_ext_msg ( this , " invariant " ) ) ;
2011-01-19 19:30:42 -05:00
}
void HeapRegionSetBase : : verify_start ( ) {
// See comment in verify() about MT safety and verification.
2014-03-14 10:15:46 +01:00
check_mt_safety ( ) ;
2011-01-19 19:30:42 -05:00
assert ( ! _verify_in_progress ,
2011-03-04 17:13:19 -05:00
hrs_ext_msg ( this , " verification should not be in progress " ) ) ;
2011-01-19 19:30:42 -05:00
// Do the basic verification first before we do the checks over the regions.
HeapRegionSetBase : : verify ( ) ;
2014-08-18 16:10:44 +02:00
_verify_in_progress = true ;
2011-01-19 19:30:42 -05:00
}
void HeapRegionSetBase : : verify_end ( ) {
// See comment in verify() about MT safety and verification.
2014-03-14 10:15:46 +01:00
check_mt_safety ( ) ;
2011-01-19 19:30:42 -05:00
assert ( _verify_in_progress ,
2011-03-04 17:13:19 -05:00
hrs_ext_msg ( this , " verification should be in progress " ) ) ;
2011-01-19 19:30:42 -05:00
_verify_in_progress = false ;
}
void HeapRegionSetBase : : print_on ( outputStream * out , bool print_contents ) {
out - > cr ( ) ;
2015-06-24 12:12:25 -04:00
out - > print_cr ( " Set: %s ( " PTR_FORMAT " ) " , name ( ) , p2i ( this ) ) ;
2011-01-19 19:30:42 -05:00
out - > print_cr ( " Region Assumptions " ) ;
out - > print_cr ( " humongous : %s " , BOOL_TO_STR ( regions_humongous ( ) ) ) ;
2014-09-15 12:19:31 +02:00
out - > print_cr ( " free : %s " , BOOL_TO_STR ( regions_free ( ) ) ) ;
2011-01-19 19:30:42 -05:00
out - > print_cr ( " Attributes " ) ;
2012-04-18 07:21:15 -04:00
out - > print_cr ( " length : %14u " , length ( ) ) ;
2015-06-24 12:12:25 -04:00
out - > print_cr ( " total capacity : " SIZE_FORMAT_W ( 14 ) " bytes " ,
2011-01-19 19:30:42 -05:00
total_capacity_bytes ( ) ) ;
}
2014-09-15 12:19:31 +02:00
HeapRegionSetBase : : HeapRegionSetBase ( const char * name , bool humongous , bool free , HRSMtSafeChecker * mt_safety_checker )
2011-01-19 19:30:42 -05:00
: _name ( name ) , _verify_in_progress ( false ) ,
2014-09-15 12:19:31 +02:00
_is_humongous ( humongous ) , _is_free ( free ) , _mt_safety_checker ( mt_safety_checker ) ,
2014-03-14 10:15:46 +01:00
_count ( )
{ }
2011-01-19 19:30:42 -05:00
2014-03-14 10:15:46 +01:00
void FreeRegionList : : set_unrealistically_long_length ( uint len ) {
guarantee ( _unrealistically_long_length = = 0 , " should only be set once " ) ;
_unrealistically_long_length = len ;
2011-01-19 19:30:42 -05:00
}
2014-03-14 10:15:46 +01:00
void FreeRegionList : : fill_in_ext_msg_extra ( hrs_ext_msg * msg ) {
2015-06-24 12:12:25 -04:00
msg - > append ( " hd: " PTR_FORMAT " tl: " PTR_FORMAT , p2i ( _head ) , p2i ( _tail ) ) ;
2011-01-19 19:30:42 -05:00
}
2014-03-14 10:15:46 +01:00
void FreeRegionList : : remove_all ( ) {
check_mt_safety ( ) ;
2011-01-19 19:30:42 -05:00
verify_optional ( ) ;
HeapRegion * curr = _head ;
while ( curr ! = NULL ) {
2014-03-14 10:15:46 +01:00
verify_region ( curr ) ;
2011-01-19 19:30:42 -05:00
HeapRegion * next = curr - > next ( ) ;
curr - > set_next ( NULL ) ;
2014-02-28 15:27:09 +01:00
curr - > set_prev ( NULL ) ;
2011-01-19 19:30:42 -05:00
curr - > set_containing_set ( NULL ) ;
curr = next ;
}
clear ( ) ;
verify_optional ( ) ;
}
2014-02-28 15:27:09 +01:00
void FreeRegionList : : add_ordered ( FreeRegionList * from_list ) {
check_mt_safety ( ) ;
from_list - > check_mt_safety ( ) ;
verify_optional ( ) ;
from_list - > verify_optional ( ) ;
if ( from_list - > is_empty ( ) ) {
return ;
}
# ifdef ASSERT
FreeRegionListIterator iter ( from_list ) ;
while ( iter . more_available ( ) ) {
HeapRegion * hr = iter . get_next ( ) ;
// In set_containing_set() we check that we either set the value
// from NULL to non-NULL or vice versa to catch bugs. So, we have
// to NULL it first before setting it to the value.
hr - > set_containing_set ( NULL ) ;
hr - > set_containing_set ( this ) ;
}
# endif // ASSERT
2014-08-18 16:10:44 +02:00
if ( is_empty ( ) ) {
assert ( length ( ) = = 0 & & _tail = = NULL , hrs_ext_msg ( this , " invariant " ) ) ;
_head = from_list - > _head ;
_tail = from_list - > _tail ;
} else {
HeapRegion * curr_to = _head ;
HeapRegion * curr_from = from_list - > _head ;
2014-02-28 15:27:09 +01:00
2014-08-18 16:10:44 +02:00
while ( curr_from ! = NULL ) {
2014-08-26 09:36:53 +02:00
while ( curr_to ! = NULL & & curr_to - > hrm_index ( ) < curr_from - > hrm_index ( ) ) {
2014-08-18 16:10:44 +02:00
curr_to = curr_to - > next ( ) ;
}
2014-02-28 15:27:09 +01:00
2014-08-18 16:10:44 +02:00
if ( curr_to = = NULL ) {
// The rest of the from list should be added as tail
_tail - > set_next ( curr_from ) ;
curr_from - > set_prev ( _tail ) ;
curr_from = NULL ;
2014-02-28 15:27:09 +01:00
} else {
2014-08-18 16:10:44 +02:00
HeapRegion * next_from = curr_from - > next ( ) ;
curr_from - > set_next ( curr_to ) ;
curr_from - > set_prev ( curr_to - > prev ( ) ) ;
if ( curr_to - > prev ( ) = = NULL ) {
_head = curr_from ;
} else {
curr_to - > prev ( ) - > set_next ( curr_from ) ;
}
curr_to - > set_prev ( curr_from ) ;
curr_from = next_from ;
2014-02-28 15:27:09 +01:00
}
}
2014-08-26 09:36:53 +02:00
if ( _tail - > hrm_index ( ) < from_list - > _tail - > hrm_index ( ) ) {
2014-08-18 16:10:44 +02:00
_tail = from_list - > _tail ;
}
2014-02-28 15:27:09 +01:00
}
_count . increment ( from_list - > length ( ) , from_list - > total_capacity_bytes ( ) ) ;
from_list - > clear ( ) ;
verify_optional ( ) ;
from_list - > verify_optional ( ) ;
}
2014-08-18 16:10:44 +02:00
void FreeRegionList : : remove_starting_at ( HeapRegion * first , uint num_regions ) {
2014-03-14 10:15:46 +01:00
check_mt_safety ( ) ;
2014-08-18 16:10:44 +02:00
assert ( num_regions > = 1 , hrs_ext_msg ( this , " pre-condition " ) ) ;
2011-03-04 17:13:19 -05:00
assert ( ! is_empty ( ) , hrs_ext_msg ( this , " pre-condition " ) ) ;
2011-01-19 19:30:42 -05:00
verify_optional ( ) ;
2012-04-18 07:21:15 -04:00
DEBUG_ONLY ( uint old_length = length ( ) ; )
2011-01-19 19:30:42 -05:00
2014-08-18 16:10:44 +02:00
HeapRegion * curr = first ;
2012-04-18 07:21:15 -04:00
uint count = 0 ;
2014-08-18 16:10:44 +02:00
while ( count < num_regions ) {
2014-03-14 10:15:46 +01:00
verify_region ( curr ) ;
2011-01-19 19:30:42 -05:00
HeapRegion * next = curr - > next ( ) ;
2014-02-28 15:27:09 +01:00
HeapRegion * prev = curr - > prev ( ) ;
2011-01-19 19:30:42 -05:00
2014-08-18 16:10:44 +02:00
assert ( count < num_regions ,
hrs_err_msg ( " [%s] should not come across more regions "
" pending for removal than num_regions: %u " ,
name ( ) , num_regions ) ) ;
2011-01-19 19:30:42 -05:00
2014-08-18 16:10:44 +02:00
if ( prev = = NULL ) {
assert ( _head = = curr , hrs_ext_msg ( this , " invariant " ) ) ;
_head = next ;
} else {
assert ( _head ! = curr , hrs_ext_msg ( this , " invariant " ) ) ;
prev - > set_next ( next ) ;
}
if ( next = = NULL ) {
assert ( _tail = = curr , hrs_ext_msg ( this , " invariant " ) ) ;
_tail = prev ;
} else {
assert ( _tail ! = curr , hrs_ext_msg ( this , " invariant " ) ) ;
next - > set_prev ( prev ) ;
}
if ( _last = curr ) {
_last = NULL ;
}
2011-01-19 19:30:42 -05:00
2014-08-18 16:10:44 +02:00
curr - > set_next ( NULL ) ;
curr - > set_prev ( NULL ) ;
remove ( curr ) ;
2011-01-19 19:30:42 -05:00
2014-08-18 16:10:44 +02:00
count + + ;
2011-01-19 19:30:42 -05:00
curr = next ;
}
2014-08-18 16:10:44 +02:00
assert ( count = = num_regions ,
hrs_err_msg ( " [%s] count: %u should be == num_regions: %u " ,
name ( ) , count , num_regions ) ) ;
assert ( length ( ) + num_regions = = old_length ,
2011-03-04 17:13:19 -05:00
hrs_err_msg ( " [%s] new length should be consistent "
2014-08-18 16:10:44 +02:00
" new length: %u old length: %u num_regions: %u " ,
name ( ) , length ( ) , old_length , num_regions ) ) ;
2011-01-19 19:30:42 -05:00
verify_optional ( ) ;
}
2014-03-14 10:15:46 +01:00
void FreeRegionList : : verify ( ) {
2011-01-19 19:30:42 -05:00
// See comment in HeapRegionSetBase::verify() about MT safety and
// verification.
2014-03-14 10:15:46 +01:00
check_mt_safety ( ) ;
2011-01-19 19:30:42 -05:00
// This will also do the basic verification too.
verify_start ( ) ;
2014-03-14 10:15:46 +01:00
verify_list ( ) ;
2011-01-19 19:30:42 -05:00
verify_end ( ) ;
}
2014-03-14 10:15:46 +01:00
void FreeRegionList : : clear ( ) {
_count = HeapRegionSetCount ( ) ;
2011-01-19 19:30:42 -05:00
_head = NULL ;
_tail = NULL ;
2014-02-28 15:27:09 +01:00
_last = NULL ;
2011-01-19 19:30:42 -05:00
}
2014-03-14 10:15:46 +01:00
void FreeRegionList : : print_on ( outputStream * out , bool print_contents ) {
2011-01-19 19:30:42 -05:00
HeapRegionSetBase : : print_on ( out , print_contents ) ;
out - > print_cr ( " Linking " ) ;
2015-06-24 12:12:25 -04:00
out - > print_cr ( " head : " PTR_FORMAT , p2i ( _head ) ) ;
out - > print_cr ( " tail : " PTR_FORMAT , p2i ( _tail ) ) ;
2011-01-19 19:30:42 -05:00
if ( print_contents ) {
out - > print_cr ( " Contents " ) ;
2014-03-14 10:15:46 +01:00
FreeRegionListIterator iter ( this ) ;
2011-01-19 19:30:42 -05:00
while ( iter . more_available ( ) ) {
HeapRegion * hr = iter . get_next ( ) ;
hr - > print_on ( out ) ;
}
}
2014-08-18 16:10:44 +02:00
out - > cr ( ) ;
2011-01-19 19:30:42 -05:00
}
2014-03-17 13:42:16 +01:00
void FreeRegionList : : verify_list ( ) {
2014-08-18 16:10:44 +02:00
HeapRegion * curr = _head ;
2014-03-17 13:42:16 +01:00
HeapRegion * prev1 = NULL ;
HeapRegion * prev0 = NULL ;
uint count = 0 ;
size_t capacity = 0 ;
2014-02-28 15:27:09 +01:00
uint last_index = 0 ;
guarantee ( _head = = NULL | | _head - > prev ( ) = = NULL , " _head should not have a prev " ) ;
2014-03-17 13:42:16 +01:00
while ( curr ! = NULL ) {
verify_region ( curr ) ;
count + + ;
guarantee ( count < _unrealistically_long_length ,
2015-06-24 12:12:25 -04:00
hrs_err_msg ( " [%s] the calculated length: %u seems very long, is there maybe a cycle? curr: " PTR_FORMAT " prev0: " PTR_FORMAT " " " prev1: " PTR_FORMAT " length: %u " ,
2015-03-27 15:03:44 +01:00
name ( ) , count , p2i ( curr ) , p2i ( prev0 ) , p2i ( prev1 ) , length ( ) ) ) ;
2014-03-17 13:42:16 +01:00
2014-02-28 15:27:09 +01:00
if ( curr - > next ( ) ! = NULL ) {
guarantee ( curr - > next ( ) - > prev ( ) = = curr , " Next or prev pointers messed up " ) ;
}
2014-08-26 09:36:53 +02:00
guarantee ( curr - > hrm_index ( ) = = 0 | | curr - > hrm_index ( ) > last_index , " List should be sorted " ) ;
last_index = curr - > hrm_index ( ) ;
2014-02-28 15:27:09 +01:00
2014-03-17 13:42:16 +01:00
capacity + = curr - > capacity ( ) ;
prev1 = prev0 ;
prev0 = curr ;
curr = curr - > next ( ) ;
}
2014-08-26 09:36:53 +02:00
guarantee ( _tail = = prev0 , err_msg ( " Expected %s to end with %u but it ended with %u. " , name ( ) , _tail - > hrm_index ( ) , prev0 - > hrm_index ( ) ) ) ;
2014-02-28 15:27:09 +01:00
guarantee ( _tail = = NULL | | _tail - > next ( ) = = NULL , " _tail should not have a next " ) ;
2014-03-17 13:42:16 +01:00
guarantee ( length ( ) = = count , err_msg ( " %s count mismatch. Expected %u, actual %u. " , name ( ) , length ( ) , count ) ) ;
guarantee ( total_capacity_bytes ( ) = = capacity , err_msg ( " %s capacity mismatch. Expected " SIZE_FORMAT " , actual " SIZE_FORMAT ,
name ( ) , total_capacity_bytes ( ) , capacity ) ) ;
}
// Note on the check_mt_safety() methods below:
//
// Verification of the "master" heap region sets / lists that are
// maintained by G1CollectedHeap is always done during a STW pause and
// by the VM thread at the start / end of the pause. The standard
// verification methods all assert check_mt_safety(). This is
// important as it ensures that verification is done without
// concurrent updates taking place at the same time. It follows, that,
// for the "master" heap region sets / lists, the check_mt_safety()
// method should include the VM thread / STW case.
void MasterFreeRegionListMtSafeChecker : : check ( ) {
// Master Free List MT safety protocol:
// (a) If we're at a safepoint, operations on the master free list
// should be invoked by either the VM thread (which will serialize
// them) or by the GC workers while holding the
// FreeList_lock.
// (b) If we're not at a safepoint, operations on the master free
// list should be invoked while holding the Heap_lock.
if ( SafepointSynchronize : : is_at_safepoint ( ) ) {
guarantee ( Thread : : current ( ) - > is_VM_thread ( ) | |
FreeList_lock - > owned_by_self ( ) , " master free list MT safety protocol at a safepoint " ) ;
} else {
guarantee ( Heap_lock - > owned_by_self ( ) , " master free list MT safety protocol outside a safepoint " ) ;
}
}
void SecondaryFreeRegionListMtSafeChecker : : check ( ) {
// Secondary Free List MT safety protocol:
// Operations on the secondary free list should always be invoked
// while holding the SecondaryFreeList_lock.
guarantee ( SecondaryFreeList_lock - > owned_by_self ( ) , " secondary free list MT safety protocol " ) ;
}
void OldRegionSetMtSafeChecker : : check ( ) {
// Master Old Set MT safety protocol:
// (a) If we're at a safepoint, operations on the master old set
// should be invoked:
// - by the VM thread (which will serialize them), or
// - by the GC workers while holding the FreeList_lock, if we're
// at a safepoint for an evacuation pause (this lock is taken
// anyway when an GC alloc region is retired so that a new one
// is allocated from the free list), or
// - by the GC workers while holding the OldSets_lock, if we're at a
// safepoint for a cleanup pause.
// (b) If we're not at a safepoint, operations on the master old set
// should be invoked while holding the Heap_lock.
if ( SafepointSynchronize : : is_at_safepoint ( ) ) {
guarantee ( Thread : : current ( ) - > is_VM_thread ( )
| | FreeList_lock - > owned_by_self ( ) | | OldSets_lock - > owned_by_self ( ) ,
" master old set MT safety protocol at a safepoint " ) ;
} else {
guarantee ( Heap_lock - > owned_by_self ( ) , " master old set MT safety protocol outside a safepoint " ) ;
}
}
void HumongousRegionSetMtSafeChecker : : check ( ) {
// Humongous Set MT safety protocol:
// (a) If we're at a safepoint, operations on the master humongous
// set should be invoked by either the VM thread (which will
// serialize them) or by the GC workers while holding the
// OldSets_lock.
// (b) If we're not at a safepoint, operations on the master
// humongous set should be invoked while holding the Heap_lock.
if ( SafepointSynchronize : : is_at_safepoint ( ) ) {
guarantee ( Thread : : current ( ) - > is_VM_thread ( ) | |
OldSets_lock - > owned_by_self ( ) ,
" master humongous set MT safety protocol at a safepoint " ) ;
} else {
guarantee ( Heap_lock - > owned_by_self ( ) ,
" master humongous set MT safety protocol outside a safepoint " ) ;
}
}
2014-08-19 14:09:10 +02:00
void FreeRegionList_test ( ) {
FreeRegionList l ( " test " ) ;
const uint num_regions_in_test = 5 ;
// Create a fake heap. It does not need to be valid, as the HeapRegion constructor
// does not access it.
MemRegion heap ( NULL , num_regions_in_test * HeapRegion : : GrainWords ) ;
// Allocate a fake BOT because the HeapRegion constructor initializes
// the BOT.
size_t bot_size = G1BlockOffsetSharedArray : : compute_size ( heap . word_size ( ) ) ;
HeapWord * bot_data = NEW_C_HEAP_ARRAY ( HeapWord , bot_size , mtGC ) ;
ReservedSpace bot_rs ( G1BlockOffsetSharedArray : : compute_size ( heap . word_size ( ) ) ) ;
G1RegionToSpaceMapper * bot_storage =
G1RegionToSpaceMapper : : create_mapper ( bot_rs ,
2015-04-07 10:53:51 +02:00
bot_rs . size ( ) ,
2014-08-19 14:09:10 +02:00
os : : vm_page_size ( ) ,
HeapRegion : : GrainBytes ,
G1BlockOffsetSharedArray : : N_bytes ,
mtGC ) ;
G1BlockOffsetSharedArray oa ( heap , bot_storage ) ;
bot_storage - > commit_regions ( 0 , num_regions_in_test ) ;
2014-11-05 10:12:51 +01:00
// Set up memory regions for the heap regions.
MemRegion mr0 ( heap . start ( ) , HeapRegion : : GrainWords ) ;
MemRegion mr1 ( mr0 . end ( ) , HeapRegion : : GrainWords ) ;
MemRegion mr2 ( mr1 . end ( ) , HeapRegion : : GrainWords ) ;
MemRegion mr3 ( mr2 . end ( ) , HeapRegion : : GrainWords ) ;
MemRegion mr4 ( mr3 . end ( ) , HeapRegion : : GrainWords ) ;
HeapRegion hr0 ( 0 , & oa , mr0 ) ;
HeapRegion hr1 ( 1 , & oa , mr1 ) ;
HeapRegion hr2 ( 2 , & oa , mr2 ) ;
HeapRegion hr3 ( 3 , & oa , mr3 ) ;
HeapRegion hr4 ( 4 , & oa , mr4 ) ;
2014-08-19 14:09:10 +02:00
l . add_ordered ( & hr1 ) ;
l . add_ordered ( & hr0 ) ;
l . add_ordered ( & hr3 ) ;
l . add_ordered ( & hr4 ) ;
l . add_ordered ( & hr2 ) ;
assert ( l . length ( ) = = num_regions_in_test , " wrong length " ) ;
l . verify_list ( ) ;
bot_storage - > uncommit_regions ( 0 , num_regions_in_test ) ;
delete bot_storage ;
2014-12-01 12:16:15 -05:00
FREE_C_HEAP_ARRAY ( HeapWord , bot_data ) ;
2014-08-19 14:09:10 +02:00
}