Strict and sloppy functions shouldn't share structure

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@225273 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog
index b384c71..46fe130 100644
--- a/JSTests/ChangeLog
+++ b/JSTests/ChangeLog
@@ -1,3 +1,52 @@
+2017-11-28  JF Bastien  <jfbastien@apple.com>
+
+        Strict and sloppy functions shouldn't share structure
+        https://bugs.webkit.org/show_bug.cgi?id=180103
+        <rdar://problem/35667847>
+
+        Reviewed by Saam Barati.
+
+        * stress/get-by-id-strict-arguments.js: Added. Used to not throw
+        because the IC was wrong.
+        (foo):
+        (bar):
+        (baz):
+        (catch):
+        * stress/get-by-id-strict-callee.js: Added. Not strictly necessary
+        in this patch, but may as well test odd strict mode corner cases.
+        (bar):
+        (baz):
+        (catch):
+        * stress/get-by-id-strict-caller.js: Added. Also IC'd wrong.
+        (foo):
+        (bar):
+        (baz):
+        (catch):
+        * stress/get-by-id-strict-nested-arguments-2.js: Added. Same as
+        next file, but with invalidation of the FunctionExecutable's
+        singletonFunction() to hit SpeculativeJIT::compileNewFunction's
+        slower path.
+        (foo):
+        (bar.const.x):
+        (bar.const.y):
+        (bar):
+        (catch):
+        * stress/get-by-id-strict-nested-arguments.js: Added. Make sure
+        strict nesting works correctly.
+        (foo):
+        (bar.baz):
+        (bar):
+        * stress/strict-function-structure.js: Added. The test used to
+        assert in objectProtoFuncHasOwnProperty.
+        (foo):
+        (bar):
+        (baz):
+        * stress/strict-nested-function-structure.js: Added. Nesting.
+        (foo):
+        (bar):
+        (baz.boo):
+        (baz):
+
 2017-11-29  Robin Morisset  <rmorisset@apple.com>
 
         The recursive tail call optimisation is wrong on closures
diff --git a/JSTests/stress/get-by-id-strict-arguments.js b/JSTests/stress/get-by-id-strict-arguments.js
new file mode 100644
index 0000000..f5607f4
--- /dev/null
+++ b/JSTests/stress/get-by-id-strict-arguments.js
@@ -0,0 +1,28 @@
+let warm = 1000;
+
+function foo(f) {
+    return f.arguments;
+}
+noInline(foo);
+
+function bar() {
+    for (let i = 0; i < warm; ++i)
+        foo(bar);
+}
+function baz() {
+    "use strict";
+    foo(baz);
+}
+
+bar();
+
+let caught = false;
+
+try {
+    baz();
+} catch (e) {
+    caught = true;
+}
+
+if (!caught)
+    throw new Error(`bad!`);
diff --git a/JSTests/stress/get-by-id-strict-callee.js b/JSTests/stress/get-by-id-strict-callee.js
new file mode 100644
index 0000000..929d65e
--- /dev/null
+++ b/JSTests/stress/get-by-id-strict-callee.js
@@ -0,0 +1,24 @@
+let warm = 1000;
+
+function bar() {
+    for (let i = 0; i < warm; ++i)
+        arguments.callee;
+}
+
+function baz() {
+    "use strict";
+    arguments.callee;
+}
+
+bar();
+
+let caught = false;
+
+try {
+    baz();
+} catch (e) {
+    caught = true;
+}
+
+if (!caught)
+    throw new Error(`bad!`);
diff --git a/JSTests/stress/get-by-id-strict-caller.js b/JSTests/stress/get-by-id-strict-caller.js
new file mode 100644
index 0000000..3462ec0
--- /dev/null
+++ b/JSTests/stress/get-by-id-strict-caller.js
@@ -0,0 +1,28 @@
+let warm = 1000;
+
+function foo(f) {
+    return f.caller;
+}
+noInline(foo);
+
+function bar() {
+    for (let i = 0; i < warm; ++i)
+        foo(bar);
+}
+function baz() {
+    "use strict";
+    foo(baz);
+}
+
+bar();
+
+let caught = false;
+
+try {
+    baz();
+} catch (e) {
+    caught = true;
+}
+
+if (!caught)
+    throw new Error(`bad!`);
diff --git a/JSTests/stress/get-by-id-strict-nested-arguments-2.js b/JSTests/stress/get-by-id-strict-nested-arguments-2.js
new file mode 100644
index 0000000..fdfc9a8
--- /dev/null
+++ b/JSTests/stress/get-by-id-strict-nested-arguments-2.js
@@ -0,0 +1,42 @@
+let warm = 1000;
+
+function foo(f) {
+    return f.arguments;
+}
+noInline(foo);
+
+let caught = 0;
+
+function bar() {
+    for (let i = 0; i < warm; ++i)
+        foo(bar);
+    const x = function baz1() { "use strict"; return 42; };
+    const y = function baz2() { "use strict"; return 0xc0defefe; };
+    return [x, y];
+}
+
+bar();
+bar();
+const [baz1, baz2] = bar();
+
+
+if (baz1() !== 42)
+    throw new Error(`bad!`);
+
+if (baz2() !== 0xc0defefe)
+    throw new Error(`bad!`);
+
+try {
+    foo(baz1);
+} catch (e) {
+    ++caught;
+}
+
+try {
+    foo(baz2);
+} catch (e) {
+    ++caught;
+}
+
+if (caught !== 2)
+    throw new Error(`bad!`);
diff --git a/JSTests/stress/get-by-id-strict-nested-arguments.js b/JSTests/stress/get-by-id-strict-nested-arguments.js
new file mode 100644
index 0000000..0d3ceed
--- /dev/null
+++ b/JSTests/stress/get-by-id-strict-nested-arguments.js
@@ -0,0 +1,27 @@
+let warm = 1000;
+
+function foo(f) {
+    return f.arguments;
+}
+noInline(foo);
+
+let caught = false;
+
+function bar() {
+    for (let i = 0; i < warm; ++i)
+        foo(bar);
+    function baz() {
+        "use strict";
+        try {
+            foo(baz);
+        } catch (e) {
+            caught = true;
+        }
+    }
+    baz();
+}
+
+bar();
+
+if (!caught)
+    throw new Error(`bad!`);
diff --git a/JSTests/stress/strict-function-structure.js b/JSTests/stress/strict-function-structure.js
new file mode 100644
index 0000000..2d5ef71
--- /dev/null
+++ b/JSTests/stress/strict-function-structure.js
@@ -0,0 +1,8 @@
+function foo(f) { f.hasOwnProperty("arguments"); }
+noInline(foo);
+
+function bar() {}
+foo(bar);
+
+function baz() { "use strict"; }
+foo(baz);
diff --git a/JSTests/stress/strict-nested-function-structure.js b/JSTests/stress/strict-nested-function-structure.js
new file mode 100644
index 0000000..ef9d235
--- /dev/null
+++ b/JSTests/stress/strict-nested-function-structure.js
@@ -0,0 +1,12 @@
+function foo(f) { f.hasOwnProperty("arguments"); }
+noInline(foo);
+
+function bar() {}
+foo(bar);
+
+function baz() {
+    "use strict";
+    function boo() {}
+    return boo;
+}
+foo(baz());