Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Gillespie <segilles@microsoft.com>2017-09-29 08:00:05 +0300
committerJan Kotas <jkotas@microsoft.com>2017-09-29 08:00:05 +0300
commit1a119b57822d0daf921eee265f701cbe056af306 (patch)
tree0388f3ffb7bbc86e4b59b2c9ed33e3c60f19e31b
parent0ed8a8c8dd52be027fe6f174f6ecb3ad4aaacb06 (diff)
Port CoreCLR#13736 fix to CoreRT (#4627)
-rw-r--r--src/Native/gc/gc.cpp54
-rw-r--r--src/System.Private.CoreLib/src/Resources/Strings.resx3
-rw-r--r--src/System.Private.CoreLib/src/System/GC.cs35
3 files changed, 69 insertions, 23 deletions
diff --git a/src/Native/gc/gc.cpp b/src/Native/gc/gc.cpp
index e95ac1f93..1800d84bc 100644
--- a/src/Native/gc/gc.cpp
+++ b/src/Native/gc/gc.cpp
@@ -15752,40 +15752,66 @@ start_no_gc_region_status gc_heap::prepare_for_no_gc_region (uint64_t total_size
save_data_for_no_gc();
settings.pause_mode = pause_no_gc;
current_no_gc_region_info.start_status = start_no_gc_success;
-
- size_t allocation_no_gc_loh = 0;
- size_t allocation_no_gc_soh = 0;
- size_t size_per_heap = 0;
- total_size = (size_t)((float)total_size * 1.05);
+ uint64_t allocation_no_gc_loh = 0;
+ uint64_t allocation_no_gc_soh = 0;
+ assert(total_size != 0);
if (loh_size_known)
{
- loh_size = (size_t)((float)loh_size * 1.05);
- allocation_no_gc_loh = (size_t)loh_size;
- allocation_no_gc_soh = (size_t)(total_size - loh_size);
+ assert(loh_size != 0);
+ assert(loh_size <= total_size);
+ allocation_no_gc_loh = loh_size;
+ allocation_no_gc_soh = total_size - loh_size;
}
else
{
- allocation_no_gc_soh = (size_t)total_size;
- allocation_no_gc_loh = (size_t)total_size;
+ allocation_no_gc_soh = total_size;
+ allocation_no_gc_loh = total_size;
}
size_t soh_segment_size = get_valid_segment_size();
int soh_align_const = get_alignment_constant (TRUE);
- size_t max_soh_allocated = (soh_segment_size - OS_PAGE_SIZE - eph_gen_starts_size);
+ size_t max_soh_allocated = soh_segment_size - OS_PAGE_SIZE - eph_gen_starts_size;
+ size_t size_per_heap = 0;
+ const double scale_factor = 1.05;
int num_heaps = 1;
#ifdef MULTIPLE_HEAPS
num_heaps = n_heaps;
-#endif //MULTIPLE_HEAPS
- size_t total_allowed_soh_allocation = max_soh_allocated * num_heaps;
+#endif // MULTIPLE_HEAPS
- if (allocation_no_gc_soh > total_allowed_soh_allocation)
+ uint64_t total_allowed_soh_allocation = max_soh_allocated * num_heaps;
+ // [LOCALGC TODO]
+ // In theory, the upper limit here is the physical memory of the machine, not
+ // SIZE_T_MAX. This is not true today because total_physical_mem can be
+ // larger than SIZE_T_MAX if running in wow64 on a machine with more than
+ // 4GB of RAM. Once Local GC code divergence is resolved and code is flowing
+ // more freely between branches, it would be good to clean this up to use
+ // total_physical_mem instead of SIZE_T_MAX.
+ assert(total_allowed_soh_allocation <= SIZE_T_MAX);
+ uint64_t total_allowed_loh_allocation = SIZE_T_MAX;
+ uint64_t total_allowed_soh_alloc_scaled = allocation_no_gc_soh > 0 ? static_cast<uint64_t>(total_allowed_soh_allocation / scale_factor) : 0;
+ uint64_t total_allowed_loh_alloc_scaled = allocation_no_gc_loh > 0 ? static_cast<uint64_t>(total_allowed_loh_allocation / scale_factor) : 0;
+
+ if (allocation_no_gc_soh > total_allowed_soh_alloc_scaled ||
+ allocation_no_gc_loh > total_allowed_loh_alloc_scaled)
{
status = start_no_gc_too_large;
goto done;
}
+ if (allocation_no_gc_soh > 0)
+ {
+ allocation_no_gc_soh = static_cast<uint64_t>(allocation_no_gc_soh * scale_factor);
+ allocation_no_gc_soh = min (allocation_no_gc_soh, total_allowed_soh_alloc_scaled);
+ }
+
+ if (allocation_no_gc_loh > 0)
+ {
+ allocation_no_gc_loh = static_cast<uint64_t>(allocation_no_gc_loh * scale_factor);
+ allocation_no_gc_loh = min (allocation_no_gc_loh, total_allowed_loh_alloc_scaled);
+ }
+
if (disallow_full_blocking)
current_no_gc_region_info.minimal_gc_p = TRUE;
diff --git a/src/System.Private.CoreLib/src/Resources/Strings.resx b/src/System.Private.CoreLib/src/Resources/Strings.resx
index e3827350b..9d57c995b 100644
--- a/src/System.Private.CoreLib/src/Resources/Strings.resx
+++ b/src/System.Private.CoreLib/src/Resources/Strings.resx
@@ -939,6 +939,9 @@
<data name="ArgumentOutOfRange_NegativeLength" xml:space="preserve">
<value>Length cannot be less than zero.</value>
</data>
+ <data name="ArgumentOutOfRange_NoGCLohSizeGreaterTotalSize" xml:space="preserve">
+ <value>lohSize can't be greater than totalSize</value>
+ </data>
<data name="ArgumentOutOfRange_OffsetLength" xml:space="preserve">
<value>Offset and length must refer to a position in the string.</value>
</data>
diff --git a/src/System.Private.CoreLib/src/System/GC.cs b/src/System.Private.CoreLib/src/System/GC.cs
index 5e350b028..b6b7b09a1 100644
--- a/src/System.Private.CoreLib/src/System/GC.cs
+++ b/src/System.Private.CoreLib/src/System/GC.cs
@@ -324,24 +324,41 @@ namespace System
private static bool StartNoGCRegionWorker(long totalSize, bool hasLohSize, long lohSize, bool disallowFullBlockingGC)
{
- StartNoGCRegionStatus status =
- (StartNoGCRegionStatus)RuntimeImports.RhStartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC);
- if (status == StartNoGCRegionStatus.AmountTooLarge)
+ if (totalSize <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(totalSize),
- SR.ArgumentOutOfRangeException_NoGCRegionSizeTooLarge);
+ SR.Format(SR.ArgumentOutOfRange_MustBePositive, nameof(totalSize)));
}
- else if (status == StartNoGCRegionStatus.AlreadyInProgress)
+
+ if (hasLohSize)
{
- throw new InvalidOperationException(
- SR.InvalidOperationException_AlreadyInNoGCRegion);
+ if (lohSize <= 0)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(lohSize),
+ SR.Format(SR.ArgumentOutOfRange_MustBePositive, nameof(lohSize)));
+ }
+
+ if (lohSize > totalSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(lohSize), SR.ArgumentOutOfRange_NoGCLohSizeGreaterTotalSize);
+ }
}
- else if (status == StartNoGCRegionStatus.NotEnoughMemory)
+
+ StartNoGCRegionStatus status =
+ (StartNoGCRegionStatus)RuntimeImports.RhStartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC);
+ switch (status)
{
- return false;
+ case StartNoGCRegionStatus.NotEnoughMemory:
+ return false;
+ case StartNoGCRegionStatus.AlreadyInProgress:
+ throw new InvalidOperationException(SR.InvalidOperationException_AlreadyInNoGCRegion);
+ case StartNoGCRegionStatus.AmountTooLarge:
+ throw new ArgumentOutOfRangeException(nameof(totalSize), SR.ArgumentOutOfRangeException_NoGCRegionSizeTooLarge);
}
+ Debug.Assert(status == StartNoGCRegionStatus.Succeeded);
return true;
}