AbsenceOfSetEffect property condition should mind put() overrides
https://bugs.webkit.org/show_bug.cgi?id=241574
<rdar://91833733>

Reviewed by Yusuke Suzuki.

Since JSArray's "length" and RegExpObject's "lastIndex" may be reconfigured as non-writable,
we need to handle them separately in AbsenceOfSetEffect property condition to ensure that compiler
takes a slow path in that case, following the spec and throwing an exception in strict mode [1].

I'm not sure how to make a test case capturing this though.

[1]: https://tc39.es/ecma262/#sec-ordinarysetwithowndescriptor (step 2.a)

* Source/JavaScriptCore/bytecode/PropertyCondition.cpp:
(JSC::nonStructurePropertyMayBecomeReadOnlyWithoutTransition):
(JSC::PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint const):

Canonical link: https://commits.webkit.org/251615@main


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@295610 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecode/PropertyCondition.cpp b/Source/JavaScriptCore/bytecode/PropertyCondition.cpp
index 8218fee..ee2b6d1 100644
--- a/Source/JavaScriptCore/bytecode/PropertyCondition.cpp
+++ b/Source/JavaScriptCore/bytecode/PropertyCondition.cpp
@@ -69,6 +69,21 @@
     dumpInContext(out, nullptr);
 }
 
+ALWAYS_INLINE static bool nonStructurePropertyMayBecomeReadOnlyWithoutTransition(Structure* structure, UniquedStringImpl* uid)
+{
+    switch (structure->typeInfo().type()) {
+    case ArrayType:
+    case DerivedArrayType:
+        return uid == structure->vm().propertyNames->length.impl();
+
+    case RegExpObjectType:
+        return uid == structure->vm().propertyNames->lastIndex.impl();
+
+    default:
+        return false;
+    }
+}
+
 bool PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(
     Concurrency concurrency, Structure* structure, JSObject* base) const
 {
@@ -173,6 +188,10 @@
                 }
                 return false;
             }
+        } else if (nonStructurePropertyMayBecomeReadOnlyWithoutTransition(structure, uid())) {
+            if (PropertyConditionInternal::verbose)
+                dataLog("Invalid because its put() override may treat ", uid(), " property as read-only.\n");
+            return false;
         }
 
         if (structure->hasPolyProto()) {