Title: [272406] trunk
Revision
272406
Author
[email protected]
Date
2021-02-05 00:45:38 -0800 (Fri, 05 Feb 2021)

Log Message

[JSC] JSImmutableButterfly's toString cache should not happen for generic join
https://bugs.webkit.org/show_bug.cgi?id=221444
<rdar://problem/73972862>

Reviewed by Mark Lam.

JSTests:

* stress/immutable-butterfly-to-string-cache-should-not-happen-for-generic-join.js: Added.
(foo):

Source/_javascript_Core:

We should not cache Array#toString results with JSImmutableButterfly if
its join operation becomes generic join: including objects in array, since
this can invoke object.toString(), and it isn't side-effect free.

* runtime/ArrayPrototype.cpp:
(JSC::fastJoin):
(JSC::JSC_DEFINE_HOST_FUNCTION):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (272405 => 272406)


--- trunk/JSTests/ChangeLog	2021-02-05 08:45:09 UTC (rev 272405)
+++ trunk/JSTests/ChangeLog	2021-02-05 08:45:38 UTC (rev 272406)
@@ -1,5 +1,16 @@
 2021-02-05  Yusuke Suzuki  <[email protected]>
 
+        [JSC] JSImmutableButterfly's toString cache should not happen for generic join
+        https://bugs.webkit.org/show_bug.cgi?id=221444
+        <rdar://problem/73972862>
+
+        Reviewed by Mark Lam.
+
+        * stress/immutable-butterfly-to-string-cache-should-not-happen-for-generic-join.js: Added.
+        (foo):
+
+2021-02-05  Yusuke Suzuki  <[email protected]>
+
         [JSC] Atomics.store in DFG / FTL should return ToNumber(input) value
         https://bugs.webkit.org/show_bug.cgi?id=221438
         <rdar://problem/73973264>

Added: trunk/JSTests/stress/immutable-butterfly-to-string-cache-should-not-happen-for-generic-join.js (0 => 272406)


--- trunk/JSTests/stress/immutable-butterfly-to-string-cache-should-not-happen-for-generic-join.js	                        (rev 0)
+++ trunk/JSTests/stress/immutable-butterfly-to-string-cache-should-not-happen-for-generic-join.js	2021-02-05 08:45:38 UTC (rev 272406)
@@ -0,0 +1,10 @@
+let x = {
+  __proto__: Object,
+};
+function foo() {
+  Object.defineProperty(Object, 0, {});
+}
+let o = {
+  toString: foo
+};
+delete {}[[...[o]]];

Modified: trunk/Source/_javascript_Core/ChangeLog (272405 => 272406)


--- trunk/Source/_javascript_Core/ChangeLog	2021-02-05 08:45:09 UTC (rev 272405)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-02-05 08:45:38 UTC (rev 272406)
@@ -1,5 +1,21 @@
 2021-02-05  Yusuke Suzuki  <[email protected]>
 
+        [JSC] JSImmutableButterfly's toString cache should not happen for generic join
+        https://bugs.webkit.org/show_bug.cgi?id=221444
+        <rdar://problem/73972862>
+
+        Reviewed by Mark Lam.
+
+        We should not cache Array#toString results with JSImmutableButterfly if
+        its join operation becomes generic join: including objects in array, since
+        this can invoke object.toString(), and it isn't side-effect free.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::fastJoin):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+
+2021-02-05  Yusuke Suzuki  <[email protected]>
+
         [JSC] Atomics.store in DFG / FTL should return ToNumber(input) value
         https://bugs.webkit.org/show_bug.cgi?id=221438
         <rdar://problem/73973264>

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (272405 => 272406)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2021-02-05 08:45:09 UTC (rev 272405)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2021-02-05 08:45:38 UTC (rev 272406)
@@ -449,7 +449,7 @@
     return false;
 }
 
-inline JSValue fastJoin(JSGlobalObject* globalObject, JSObject* thisObject, StringView separator, unsigned length, bool* sawHoles = nullptr)
+inline JSValue fastJoin(JSGlobalObject* globalObject, JSObject* thisObject, StringView separator, unsigned length, bool& sawHoles, bool& genericCase)
 {
     VM& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -468,8 +468,7 @@
             if (LIKELY(value))
                 joiner.appendNumber(vm, value.asInt32());
             else {
-                if (sawHoles)
-                    *sawHoles = true;
+                sawHoles = true;
                 if (!holesKnownToBeOK) {
                     if (holesMustForwardToPrototype(vm, thisObject))
                         goto generalCase;
@@ -494,8 +493,7 @@
                     goto generalCase;
                 RETURN_IF_EXCEPTION(scope, { });
             } else {
-                if (sawHoles)
-                    *sawHoles = true;
+                sawHoles = true;
                 if (!holesKnownToBeOK) {
                     if (holesMustForwardToPrototype(vm, thisObject))
                         goto generalCase;
@@ -519,8 +517,7 @@
             if (LIKELY(!isHole(value)))
                 joiner.appendNumber(vm, value);
             else {
-                if (sawHoles)
-                    *sawHoles = true;
+                sawHoles = true;
                 if (!holesKnownToBeOK) {
                     if (holesMustForwardToPrototype(vm, thisObject))
                         goto generalCase;
@@ -568,6 +565,7 @@
     }
 
 generalCase:
+    genericCase = true;
     JSStringJoiner joiner(globalObject, separator, length);
     RETURN_IF_EXCEPTION(scope, { });
     for (unsigned i = 0; i < length; ++i) {
@@ -579,6 +577,13 @@
     RELEASE_AND_RETURN(scope, joiner.join(globalObject));
 }
 
+ALWAYS_INLINE JSValue fastJoin(JSGlobalObject* globalObject, JSObject* thisObject, StringView separator, unsigned length)
+{
+    bool sawHoles = false;
+    bool genericCase = false;
+    return fastJoin(globalObject, thisObject, separator, length, sawHoles, genericCase);
+}
+
 inline bool canUseDefaultArrayJoinForToString(VM& vm, JSObject* thisObject)
 {
     JSGlobalObject* globalObject = thisObject->globalObject();
@@ -650,10 +655,11 @@
         }
 
         bool sawHoles = false;
-        JSValue result = fastJoin(globalObject, thisArray, { &comma, 1 }, length, &sawHoles);
+        bool genericCase = false;
+        JSValue result = fastJoin(globalObject, thisArray, { &comma, 1 }, length, sawHoles, genericCase);
         RETURN_IF_EXCEPTION(scope, { });
 
-        if (!sawHoles && result && isJSString(result) && isCoW) {
+        if (!sawHoles && !genericCase && result && isJSString(result) && isCoW) {
             ASSERT(JSImmutableButterfly::fromButterfly(thisArray->butterfly()) == immutableButterfly);
             vm.heap.immutableButterflyToStringCache.add(immutableButterfly, jsCast<JSString*>(result));
         }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to