summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaoni0 <maonis@microsoft.com>2016-06-15 13:37:35 -0700
committerMaoni0 <maonis@microsoft.com>2016-06-20 17:09:53 -0700
commit6a4e02a4ded34e385b7249ed5972b49ad97f354a (patch)
treef7639bccc0c7b60133cec8d27210b6962fa6b1fa
parentf6ad954733e4c8f0bbb342bc3412747663905cb2 (diff)
downloadcoreclr-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.cpp20
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)],