Procházet zdrojové kódy

[MERGE #5095 @leirocks] cap single allocation

Merge pull request #5095 from leirocks:alloclmt1

add cap single recycler allocation in test and checked build to collect the data
also save the raw config flags to easier read in crawler
Lei Shi (CHAKRA) před 7 roky
rodič
revize
b8a00104bb

+ 3 - 0
lib/Common/ConfigFlagsList.h

@@ -522,6 +522,7 @@ PHASE(All)
 
 #define DEFAULT_CONFIG_LowMemoryCap         (0xB900000) // 185 MB - based on memory cap for process on low-capacity device
 #define DEFAULT_CONFIG_NewPagesCapDuringBGSweeping    (15000 * 4)
+#define DEFAULT_CONFIG_MaxSingleAllocSizeInMB  (2048)
 
 #define DEFAULT_CONFIG_MaxCodeFill          (500)
 #define DEFAULT_CONFIG_MaxLoopsPerFunction  (10)
@@ -1613,6 +1614,8 @@ FLAGNR(Boolean, VerifyBarrierBit, "Verify software write barrier bit is set whil
 FLAGNR(Boolean, EnableBGFreeZero, "Use to turn off background freeing and zeroing to simulate linux", DEFAULT_CONFIG_EnableBGFreeZero)
 FLAGNR(Boolean, KeepRecyclerTrackData, "Keep recycler track data after sweep until reuse", DEFAULT_CONFIG_KeepRecyclerTrackData)
 
+FLAGNR(Number, MaxSingleAllocSizeInMB, "Max size(in MB) in single allocation", DEFAULT_CONFIG_MaxSingleAllocSizeInMB)
+
 #undef FLAG_REGOVR_EXP
 #undef FLAG_EXPERIMENTAL
 #undef FLAG

+ 5 - 0
lib/Common/Core/ConfigFlagsTable.cpp

@@ -338,6 +338,11 @@ namespace Js
 
         // set all parent flags to their default (setting all child flags to their right values)
         this->SetAllParentFlagsAsDefaultValue();
+
+#if defined(ENABLE_DEBUG_CONFIG_OPTIONS) && CONFIG_PARSE_CONFIG_FILE
+        rawInputFromConfigFileIndex = 0;
+        memset(rawInputFromConfigFile, 0, sizeof(rawInputFromConfigFile));
+#endif
     }
 
 

+ 6 - 0
lib/Common/Core/ConfigFlagsTable.h

@@ -502,6 +502,12 @@ namespace Js
 
                 bool            flagPresent[FlagCount];
 
+#if defined(ENABLE_DEBUG_CONFIG_OPTIONS) && CONFIG_PARSE_CONFIG_FILE
+                // save the jscript.config for easier to get the raw input while analyzing dump file
+                char16          rawInputFromConfigFile[512];
+                int             rawInputFromConfigFileIndex;
+#endif
+
     private:
         //
         // This variable is defined for the constructor

+ 5 - 0
lib/Common/Core/ConfigParser.cpp

@@ -447,6 +447,11 @@ void ConfigParser::ParseConfig(HANDLE hmod, CmdLineArgsParser &parser, const cha
     {
         CharType curChar = ReadChar(configFile);
 
+        if (this->_flags.rawInputFromConfigFileIndex < sizeof(this->_flags.rawInputFromConfigFile) / sizeof(this->_flags.rawInputFromConfigFile[0]))
+        {
+            this->_flags.rawInputFromConfigFile[this->_flags.rawInputFromConfigFileIndex++] = curChar;
+        }
+
         if (curChar == EndChar || isspace(curChar) || curChar == 0)
         {
             configBuffer[index] = 0;

+ 12 - 0
lib/Common/Exceptions/ReportError.cpp

@@ -145,4 +145,16 @@ _NOINLINE void OutOfMemory_unrecoverable_error()
     ReportFatalException(NULL, E_OUTOFMEMORY, Fatal_OutOfMemory, scenario);
 }
 
+_NOINLINE void RecyclerSingleAllocationLimit_unrecoverable_error()
+{
+    int scenario = 10;
+    ReportFatalException(NULL, E_OUTOFMEMORY, Fatal_OutOfMemory, scenario);
+}
+
+_NOINLINE void MemGCSingleAllocationLimit_unrecoverable_error()
+{
+    int scenario = 11;
+    ReportFatalException(NULL, E_OUTOFMEMORY, Fatal_OutOfMemory, scenario);
+}
+
 #pragma optimize("",on)

+ 2 - 0
lib/Common/Exceptions/ReportError.h

@@ -74,6 +74,8 @@ void FromDOM_NoScriptScope_unrecoverable_error();
 void Debugger_AttachDetach_unrecoverable_error(HRESULT hr);
 void RpcFailure_unrecoverable_error(HRESULT hr);
 void OutOfMemory_unrecoverable_error();
+void RecyclerSingleAllocationLimit_unrecoverable_error();
+void MemGCSingleAllocationLimit_unrecoverable_error();
 
 #ifndef DISABLE_SEH
 // RtlReportException is available on Vista and up, but we cannot use it for OOB release.

+ 0 - 2
lib/Common/Memory/HeapConstants.h

@@ -19,8 +19,6 @@ public:
     static const uint MaxMediumObjectSize = 9216;
 #endif
 
-    static const uint MaxLargeObjectSize = 1u << 31; // Maximum recycler object is 2GB
-
 #if defined(TARGET_32)
     // Only if a pointer points to first 8k region of a large object, it will set the mark bit in the chunk->MarkBits
     // If the pointer points outside of that region, no mark bit will be set

+ 20 - 1
lib/Common/Memory/Recycler.cpp

@@ -1320,10 +1320,29 @@ Recycler::LargeAlloc(HeapInfo* heap, size_t size, ObjectInfoBits attributes)
 {
     Assert((attributes & InternalObjectInfoBitMask) == attributes);
 
-    if (size >= HeapConstants::MaxLargeObjectSize)
+#if ENABLE_DEBUG_CONFIG_OPTIONS
+    size_t limit = (size_t)GetRecyclerFlagsTable().MaxSingleAllocSizeInMB * 1024 * 1024;
+#else
+    size_t limit = (size_t)CONFIG_FLAG(MaxSingleAllocSizeInMB) * 1024 * 1024;
+#endif
+
+    if (size >= limit)
     {
         if (nothrow == false)
         {
+#if ENABLE_DEBUG_CONFIG_OPTIONS
+            if (GetRecyclerFlagsTable().EnableFatalErrorOnOOM)
+            {
+                if (this->IsMemProtectMode())
+                {
+                    MemGCSingleAllocationLimit_unrecoverable_error();
+                }
+                else
+                {
+                    RecyclerSingleAllocationLimit_unrecoverable_error();
+                }
+            }
+#endif
             this->OutOfMemory();
         }
         else