[MERGE #6097 @wyrichte] Fixes #5993 - path to fromCodePoint in JIT now throws range error on large input

Merge pull request #6097 from wyrichte:build/wyrichte/fromCodePoint
diff --git a/lib/Backend/BackwardPass.cpp b/lib/Backend/BackwardPass.cpp
index 6b4c9f9..bbca151 100644
--- a/lib/Backend/BackwardPass.cpp
+++ b/lib/Backend/BackwardPass.cpp
@@ -3857,7 +3857,7 @@
            this->tag == Js::DeadStorePhase
         // We don't do the masking in simplejit due to reduced perf concerns and the issues
         // with handling try/catch structures with late-added blocks
-        && !this->func->IsSimpleJit()
+        && this->func->DoGlobOpt()
         // We don't need the masking blocks in asmjs/wasm mode
         && !block->GetFirstInstr()->m_func->GetJITFunctionBody()->IsAsmJsMode()
         && !block->GetFirstInstr()->m_func->GetJITFunctionBody()->IsWasmFunction()
@@ -7865,7 +7865,8 @@
 
     if (instr->m_opcode == Js::OpCode::ArgIn_A)
     {
-        //Ignore tracking ArgIn for "this", as argInsCount only tracks other params - unless it is a asmjs function(which doesn't have a "this").
+        // Ignore tracking ArgIn for "this" as argInsCount only tracks other
+        // params, unless it is a AsmJS function (which doesn't have a "this").
         if (instr->GetSrc1()->AsSymOpnd()->m_sym->AsStackSym()->GetParamSlotNum() != 1 || func->GetJITFunctionBody()->IsAsmJsMode())
         {
             Assert(this->func->argInsCount > 0);
diff --git a/lib/Backend/GlobOpt.cpp b/lib/Backend/GlobOpt.cpp
index d5a28f0..f3fe5e5 100644
--- a/lib/Backend/GlobOpt.cpp
+++ b/lib/Backend/GlobOpt.cpp
@@ -165,7 +165,13 @@
 GlobOpt::Optimize()
 {
     this->objectTypeSyms = nullptr;
-    this->func->argInsCount = this->func->GetInParamsCount() - 1;   //Don't include "this" pointer in the count.
+
+    this->func->argInsCount = this->func->GetInParamsCount();
+    if (!func->GetJITFunctionBody()->IsAsmJsMode())
+    {
+        // Don't include "this" pointer in the count when not in AsmJs mode (AsmJS does not have "this").
+        this->func->argInsCount--;
+    }
 
     if (!func->DoGlobOpt())
     {
@@ -6960,7 +6966,20 @@
         {
             return false;
         }
-        *result = !src1ValueInfo->IsPrimitive();
+
+        if (src1ValueInfo->IsPrimitive())
+        {
+            *result = false;
+        }
+        else
+        {
+            if (src1ValueInfo->HasBeenPrimitive())
+            {
+                return false;
+            }
+            *result = true;
+        }
+
         break;
     }
     default:
diff --git a/lib/Parser/Parse.cpp b/lib/Parser/Parse.cpp
index 5c0e1a8..e9241f8 100644
--- a/lib/Parser/Parse.cpp
+++ b/lib/Parser/Parse.cpp
@@ -11442,14 +11442,25 @@
 
 void Parser::FinishDeferredFunction(ParseNodeBlock * pnodeScopeList)
 {
-    uint saveNextBlockId = m_nextBlockId;
+    ParseContext parseContext;
+    this->CaptureContext(&parseContext);
+
     m_nextBlockId = pnodeScopeList->blockId + 1;
 
     FinishFunctionsInScope(pnodeScopeList,
-        [this](ParseNodeFnc * pnodeFnc)
+        [this, &parseContext](ParseNodeFnc * pnodeFnc)
     {
         Assert(pnodeFnc->nop == knopFncDecl);
 
+        // We need to scan this function based on the already known limits of the function declaration as some of
+        // the state such as fAllowIn may not be available at this point. Some of this state depends on the context
+        // of the function declaration. For example, a function declaration may be inside a for..in statement's var
+        // declaration. It may not be appropriate/possible to try and save all such context information. Functions
+        // that actually get deferred achieve this by going through the ParseSourceWithOffset code path.
+        this->GetScanner()->Clear();
+        this->GetScanner()->SetText(parseContext.pszSrc, pnodeFnc->cbMin /*+ this->m_scan.m_cMinTokMultiUnits*/, pnodeFnc->LengthInBytes(), pnodeFnc->ichMin, parseContext.isUtf8, parseContext.grfscr, pnodeFnc->lineNumber);
+        this->GetScanner()->Scan();
+
         // Non-simple params (such as default) require a good amount of logic to put vars on appropriate scopes. ParseFncDecl handles it
         // properly (both on defer and non-defer case). This is to avoid write duplicated logic here as well. Function with non-simple-param
         // will remain deferred until they are called.
@@ -11601,7 +11612,7 @@
         }
     });
 
-    m_nextBlockId = saveNextBlockId;
+    this->RestoreContext(&parseContext);
 }
 
 void Parser::InitPids()
diff --git a/lib/Runtime/Library/JavascriptArray.cpp b/lib/Runtime/Library/JavascriptArray.cpp
index c25d18d..6d0578b 100644
--- a/lib/Runtime/Library/JavascriptArray.cpp
+++ b/lib/Runtime/Library/JavascriptArray.cpp
@@ -11919,13 +11919,12 @@
 
         if (IsInlineSegment(src, instance))
         {
-            Assert(src->size <= SparseArraySegmentBase::INLINE_CHUNK_SIZE);
-
             // Copy head segment data between inlined head segments
             dst = DetermineInlineHeadSegmentPointer<T, 0, true>(static_cast<T*>(this));
             dst->left = src->left;
             dst->length = src->length;
-            dst->size = src->size;
+            uint inlineChunkSize = SparseArraySegmentBase::INLINE_CHUNK_SIZE;
+            dst->size = min(src->size, inlineChunkSize);
         }
         else
         {
@@ -11940,7 +11939,8 @@
 
         Assert(IsInlineSegment(src, instance) == IsInlineSegment(dst, static_cast<T*>(this)));
 
-        CopyArray(dst->elements, dst->size, src->elements, src->size);
+        AssertOrFailFast(dst->size <= src->size);
+        CopyArray(dst->elements, dst->size, src->elements, dst->size);
 
         if (!deepCopy)
         {
diff --git a/test/Bugs/misc_bugs.js b/test/Bugs/misc_bugs.js
index fd461bb..454914d 100644
--- a/test/Bugs/misc_bugs.js
+++ b/test/Bugs/misc_bugs.js
@@ -247,6 +247,18 @@
       }

   },

   {

+    name: "Init box javascript array : OS : 20517662",

+    body: function () {

+      var obj = {};

+      obj[0] = 11;

+      obj[1] = {};

+      obj[17] = 222;

+      obj[35] = 333; // This is will increase the size past the inline segment

+      

+      Object.assign({}, obj); // The InitBoxedInlineSegments will be called due to this call.

+    }

+  },

+  {

     name: "calling promise's function as constructor should not be allowed",

     body: function () {

         var var_0 = new Promise(function () {});                                           

diff --git a/test/EH/regionBugSpecHoisting.js b/test/EH/regionBugSpecHoisting.js
new file mode 100644
index 0000000..6fb079b
--- /dev/null
+++ b/test/EH/regionBugSpecHoisting.js
@@ -0,0 +1,28 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+function test0() {
+  var ui8 = new Uint8Array(1);
+  try {
+    try {
+      for (var _strvar28 in ui8) {
+        try {
+          return '';
+        } catch (ex) {
+        }
+        try {
+        } catch (ex) {
+        }
+      }
+   } catch(ex) {
+   }
+  } finally {
+  }
+}
+test0();
+test0();
+test0();
+test0();
+print("Passed\n");
diff --git a/test/EH/rlexe.xml b/test/EH/rlexe.xml
index 4be81de..77f8c3a 100644
--- a/test/EH/rlexe.xml
+++ b/test/EH/rlexe.xml
@@ -210,4 +210,10 @@
       <compile-flags>-args summary -endargs</compile-flags>
     </default>
   </test>
+  <test>
+    <default>
+      <files>regionBugSpecHoisting.js</files>
+      <compile-flags>-mic:1 -off:simplejit</compile-flags>
+    </default>
+  </test>
 </regress-exe>
diff --git a/test/Optimizer/bugconstfoldobject.baseline b/test/Optimizer/bugconstfoldobject.baseline
new file mode 100644
index 0000000..b24310a
--- /dev/null
+++ b/test/Optimizer/bugconstfoldobject.baseline
@@ -0,0 +1,3 @@
+[object Object]

+[object Object]

+[object Object]

diff --git a/test/Optimizer/bugconstfoldobject.js b/test/Optimizer/bugconstfoldobject.js
new file mode 100644
index 0000000..989aef1
--- /dev/null
+++ b/test/Optimizer/bugconstfoldobject.js
@@ -0,0 +1,19 @@
+//-------------------------------------------------------------------------------------------------------

+// Copyright (C) Microsoft. All rights reserved.

+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.

+//-------------------------------------------------------------------------------------------------------

+

+function test0() {

+  class class3 {

+    constructor() {

+      return '9'.match(/^(?=[a7])$/gim);

+    }

+  }

+  strvar0 = new class3();

+  new class3();

+  WScript.Echo(strvar0);

+}

+test0();

+test0();

+test0();

+

diff --git a/test/es6/bug_issue_5994.baseline b/test/es6/bug_issue_5994.baseline
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/es6/bug_issue_5994.baseline
diff --git a/test/es6/bug_issue_5994.js b/test/es6/bug_issue_5994.js
new file mode 100644
index 0000000..fb6a178
--- /dev/null
+++ b/test/es6/bug_issue_5994.js
@@ -0,0 +1,3 @@
+for (var var_01 = () => [].var_02[0][0](function (x, y) {}().var_03) in var_04) {

+    // \0asm\x01\0\0\0\x01À\x80\x80\x80\0\r`\x02\x7F\x7F\x01\x7F`\x02~~\x01\x7F`\x02}}\x01\x7F`\x02||\x01\x7F`\0\0`\0\x01\x7F`\0\x01~`\0\x01}`\0\x01|`\x02\x7F\x7F\0`\x02~~\0`\x02}}\0`\x02||\0\x03\x84\x81\x80\x80\0\x82\x01\0\0\x01\x01\x02\x02\x03\x03\x04\x04\x05\x05\x05\x05\x05\x05\x06\x06\x06\x05\x05\x07\x07\x07\x05\x05\b\b\b\x05\x05\t\n\x0B\f\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x04\x85\x80\x80\x80\0\x01p\x01\b\b\x05\x83\x80\x80\x80\0\x01\0\x01\x07ª\x88\x80\x80\0_\x07i32_add\0#\x07i32_sub\0$\x07i32_mul\0%\ti32_div_s\0&\ti32_div_u\0\'\ti32_rem_s\0(\ti32_rem_u\0)\x07i32_and\0*\x06i32_or\0+\x07i32_xor\0,\x07i32_shl\0-\ti32_shr_u\0.\ti32_shr_s\0/\x06i32_eq\x000\x06i32_ne\x001\bi32_lt_s\x002\bi32_le_s\x003\bi32_lt_u\x004\bi32_le_u\x005\bi32_gt_s\x006\bi32_ge_s\x007\bi32_gt_u\x008\bi32_ge_u\x009\ti32_store\0:\ni32_store8\0;\x0Bi32_store16\0<\bi32_call\0=\x11i32_call_indirect\0>\ni32_select\0?\x07i64_add\0@\x07i64_sub\0A\x07i64_mul\0B\ti64_div_s\0C\ti64_div_u\0D\ti64_rem_s\0E\ti64_rem_u\0F\x07i64_and\0G\x06i64_or\0H\x07i64_xor\0I\x07i64_shl\0J\ti64_shr_u\0K\ti64_shr_s\0L\x06i64_eq\0M\x06i64_ne\0N\bi64_lt_s\0O\bi64_le_s\0P\bi64_lt_u\0Q\bi64_le_u\0R\bi64_gt_s\0S\bi64_ge_s\0T\bi64_gt_u\0U\bi64_ge_u\0V\ti64_store\0W\ni64_store8\0X\x0Bi64_store16\0Y\x0Bi64_store32\0Z\bi64_call\0[\x11i64_call_indirect\0\\\ni64_select\0]\x07f32_add\0^\x07f32_sub\0_\x07f32_mul\0`\x07f32_div\0a\ff32_copysign\0b\x06f32_eq\0c\x06f32_ne\0d\x06f32_lt\0e\x06f32_le\0f\x06f32_gt\0g\x06f32_ge\0h\x07f32_min\0i\x07f32_max\0j\tf32_store\0k\bf32_call\0l\x11f32_call_indirect\0m\nf32_select\0n\x07f64_add\0o\x07f64_sub\0p\x07f64_mul\0q\x07f64_div\0r\ff64_copysign\0s\x06f64_eq\0t\x06f64_ne\0u\x06f64_lt\0v\x06f64_le\0w\x06f64_gt\0x\x06f64_ge\0y\x07f64_min\0z\x07f64_max\0{\tf64_store\0|\bf64_call\0}\x11f64_call_indirect\0~\nf64_select\0\x7F\x05br_if\0\x80\x01\bbr_table\0\x81\x01\t\x8E\x80\x80\x80\0\x01\0A\0\x0B\b\0\x01\x02\x03\x04\x05\x06\x07\n\xB2\x91\x80\x80\0\x82\x01\x84\x80\x80\x80\0\0A\x7F\x0B\x84\x80\x80\x80\0\0A~\x0B\x84\x80\x80\x80\0\0A\x7F\x0B\x84\x80\x80\x80\0\0A~\x0B\x84\x80\x80\x80\0\0A\x7F\x0B\x84\x80\x80\x80\0\0A~\x0B\x84\x80\x80\x80\0\0A\x7F\x0B\x84\x80\x80\x80\0\0A~\x0B\x89\x80\x80\x80\0\0A\bA\x006\x02\0\x0B\xA7\x80\x80\x80\0\0A\x0BA\n-\0\0:\0\0A\nA\t-\0\0:\0\0A\tA\b-\0\0:\0\0A\bA}:\0\0\x0B\x87\x80\x80\x80\0\0A\b(\x02\0\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x01:\0\0A\0\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x02:\0\0A\x01\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x03:\0\0A\x01\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x04:\0\0A\0\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x05:\0\0A\0\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x01:\0\0B\0\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x02:\0\0B\x01\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x03:\0\0B\x01\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x04:\0\0A\x02\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x05:\0\0A\0\x0B\x90\x80\x80\x80\0\0\x10\tA\bA\x01:\0\0C\0\0\0\0\x0B\x90\x80\x80\x80\0\0\x10\tA\bA\x02:\0\0C\0\0\x80?\x0B\x90\x80\x80\x80\0\0\x10\tA\bA\x03:\0\0C\0\0\x80?\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x04:\0\0A\x04\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x05:\0\0A\0\x0B\x94\x80\x80\x80\0\0\x10\tA\bA\x01:\0\0D\0\0\0\0\0\0\0\0\x0B\x94\x80\x80\x80\0\0\x10\tA\bA\x02:\0\0D\0\0\0\0\0\0ð?\x0B\x94\x80\x80\x80\0\0\x10\tA\bA\x03:\0\0D\0\0\0\0\0\0ð?\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x04:\0\0A\x06\x0B\x8D\x80\x80\x80\0\0\x10\tA\bA\x05:\0\0A\0\x0B\x82\x80\x80\x80\0\0\x0B\x82\x80\x80\x80\0\0\x0B\x82\x80\x80\x80\0\0\x0B\x82\x80\x80\x80\0\0\x0B\x8C\x80\x80\x80\0\0\x10\b\x10\x0B\x10\fj\x1A\x10\n\x0B\x8C\x80\x80\x80\0\0\x10\b\x10\x0B\x10\fk\x1A\x10\n\x0B\x8C\x80\x80\x80\0\0\x10\b\x10\x0B\x10\fl\x1A\x10\n\x0B\x8C\x80\x80\x80\0\0\x10\b\x10\x0B\x10\fm\x1A\x10\n\x01\0\0\0\x01À\x80\x80\x80\0\r`\x2

+}

diff --git a/test/es6/rlexe.xml b/test/es6/rlexe.xml
index 64fed61..207717a 100644
--- a/test/es6/rlexe.xml
+++ b/test/es6/rlexe.xml
@@ -1511,4 +1511,11 @@
     <compile-flags>-args summary -endargs</compile-flags>
   </default>
 </test>
+<test>
+  <default>
+    <files>bug_issue_5994.js</files>
+    <compile-flags>-MuteHostErrorMsg</compile-flags>
+    <baseline>bug_issue_5994.baseline</baseline>
+  </default>
+</test>
 </regress-exe>