diff options
author | Maoni0 <maonis@microsoft.com> | 2016-06-15 13:37:35 -0700 |
---|---|---|
committer | Maoni0 <maonis@microsoft.com> | 2016-06-20 17:09:53 -0700 |
commit | 6a4e02a4ded34e385b7249ed5972b49ad97f354a (patch) | |
tree | f7639bccc0c7b60133cec8d27210b6962fa6b1fa | |
parent | f6ad954733e4c8f0bbb342bc3412747663905cb2 (diff) | |
download | coreclr-6a4e02a4ded34e385b7249ed5972b49ad97f354a.tar.gz coreclr-6a4e02a4ded34e385b7249ed5972b49ad97f354a.tar.bz2 coreclr-6a4e02a4ded34e385b7249ed5972b49ad97f354a.zip |
We need to have seg_mapping_table aligned on its natural alignement (ptr size). When it's not aligned,
aside from the perf problem, we also have a functional problem when an address that's not on a heap
segment is passed - we could read an intermediate value which would cause an AV. If the address is
on a heap segment it means we are guaranteed to read a ptr size atomically. This only affects functions
like IsHeapPointer which can be run when EE is not suspended.
-rw-r--r-- | src/gc/gc.cpp | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index adc3a14f56..8481857fb1 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -3377,6 +3377,13 @@ size_t size_seg_mapping_table_of (uint8_t* from, uint8_t* end) return sizeof (seg_mapping)*((end - from) / gc_heap::min_segment_size); } +// for seg_mapping_table we want it to start from a pointer sized address. +inline +size_t align_for_seg_mapping_table (size_t size) +{ + return ((size + (sizeof (uint8_t*) - 1)) &~ (sizeof (uint8_t*) - 1)); +} + inline size_t seg_mapping_word_of (uint8_t* add) { @@ -6910,6 +6917,10 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) #ifdef GROWABLE_SEG_MAPPING_TABLE size_t st = size_seg_mapping_table_of (g_lowest_address, g_highest_address); + size_t st_table_offset = sizeof(card_table_info) + cs + bs + cb + wws; + size_t st_table_offset_aligned = align_for_seg_mapping_table (st_table_offset); + + st += (st_table_offset_aligned - st_table_offset); #else //GROWABLE_SEG_MAPPING_TABLE size_t st = 0; #endif //GROWABLE_SEG_MAPPING_TABLE @@ -6958,7 +6969,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP #ifdef GROWABLE_SEG_MAPPING_TABLE - seg_mapping_table = (seg_mapping*)((uint8_t*)card_table_brick_table (ct) + bs + cb + wws); + seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); seg_mapping_table = (seg_mapping*)((uint8_t*)seg_mapping_table - size_seg_mapping_table_of (0, (align_lower_segment (g_lowest_address)))); #endif //GROWABLE_SEG_MAPPING_TABLE @@ -7098,6 +7109,9 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, #ifdef GROWABLE_SEG_MAPPING_TABLE size_t st = size_seg_mapping_table_of (saved_g_lowest_address, saved_g_highest_address); + size_t st_table_offset = sizeof(card_table_info) + cs + bs + cb + wws; + size_t st_table_offset_aligned = align_for_seg_mapping_table (st_table_offset); + st += (st_table_offset_aligned - st_table_offset); #else //GROWABLE_SEG_MAPPING_TABLE size_t st = 0; #endif //GROWABLE_SEG_MAPPING_TABLE @@ -7120,7 +7134,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, dprintf (GC_TABLE_LOG, ("Table alloc for %Id bytes: [%Ix, %Ix[", alloc_size, (size_t)mem, (size_t)((uint8_t*)mem+alloc_size))); - { + { // mark array will be committed separately (per segment). size_t commit_size = alloc_size - ms; @@ -7160,7 +7174,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, #ifdef GROWABLE_SEG_MAPPING_TABLE { - seg_mapping* new_seg_mapping_table = (seg_mapping*)((uint8_t*)card_table_brick_table (ct) + bs + cb + wws); + seg_mapping* new_seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); new_seg_mapping_table = (seg_mapping*)((uint8_t*)new_seg_mapping_table - size_seg_mapping_table_of (0, (align_lower_segment (saved_g_lowest_address)))); memcpy(&new_seg_mapping_table[seg_mapping_word_of(g_lowest_address)], |