]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/StringRecursionChecker.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / StringRecursionChecker.h
index 314f14eeb833b77266405580e25ab196ae6f4b2e..0f1990e76f0f2482c9d9b034cb5131bf1bfb5b9e 100644 (file)
@@ -21,6 +21,8 @@
 #define StringRecursionChecker_h
 
 #include "Interpreter.h"
 #define StringRecursionChecker_h
 
 #include "Interpreter.h"
+#include <wtf/StackStats.h>
+#include <wtf/WTFThreadData.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -31,27 +33,37 @@ public:
     StringRecursionChecker(ExecState*, JSObject* thisObject);
     ~StringRecursionChecker();
 
     StringRecursionChecker(ExecState*, JSObject* thisObject);
     ~StringRecursionChecker();
 
-    EncodedJSValue earlyReturnValue() const; // 0 if everything is OK, value to return for failure cases
+    JSValue earlyReturnValue() const; // 0 if everything is OK, value to return for failure cases
 
 private:
 
 private:
-    EncodedJSValue throwStackOverflowError();
-    EncodedJSValue emptyString();
-    EncodedJSValue performCheck();
+    JSValue throwStackOverflowError();
+    JSValue emptyString();
+    JSValue performCheck();
 
     ExecState* m_exec;
     JSObject* m_thisObject;
 
     ExecState* m_exec;
     JSObject* m_thisObject;
-    EncodedJSValue m_earlyReturnValue;
+    JSValue m_earlyReturnValue;
+
+    StackStats::CheckPoint stackCheckpoint;
 };
 
 };
 
-inline EncodedJSValue StringRecursionChecker::performCheck()
+inline JSValue StringRecursionChecker::performCheck()
 {
 {
-    int size = m_exec->globalData().stringRecursionCheckVisitedObjects.size();
-    if (size >= MaxSmallThreadReentryDepth && size >= m_exec->globalData().maxReentryDepth)
+    VM& vm = m_exec->vm();
+    if (!vm.isSafeToRecurse())
         return throwStackOverflowError();
         return throwStackOverflowError();
-    bool alreadyVisited = !m_exec->globalData().stringRecursionCheckVisitedObjects.add(m_thisObject).second;
+
+    bool alreadyVisited = false;
+    if (!vm.stringRecursionCheckFirstObject)
+        vm.stringRecursionCheckFirstObject = m_thisObject;
+    else if (vm.stringRecursionCheckFirstObject == m_thisObject)
+        alreadyVisited = true;
+    else
+        alreadyVisited = !vm.stringRecursionCheckVisitedObjects.add(m_thisObject).isNewEntry;
+
     if (alreadyVisited)
         return emptyString(); // Return empty string to avoid infinite recursion.
     if (alreadyVisited)
         return emptyString(); // Return empty string to avoid infinite recursion.
-    return 0; // Indicate success.
+    return JSValue(); // Indicate success.
 }
 
 inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject* thisObject)
 }
 
 inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject* thisObject)
@@ -61,7 +73,7 @@ inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject*
 {
 }
 
 {
 }
 
-inline EncodedJSValue StringRecursionChecker::earlyReturnValue() const
+inline JSValue StringRecursionChecker::earlyReturnValue() const
 {
     return m_earlyReturnValue;
 }
 {
     return m_earlyReturnValue;
 }
@@ -70,8 +82,14 @@ inline StringRecursionChecker::~StringRecursionChecker()
 {
     if (m_earlyReturnValue)
         return;
 {
     if (m_earlyReturnValue)
         return;
-    ASSERT(m_exec->globalData().stringRecursionCheckVisitedObjects.contains(m_thisObject));
-    m_exec->globalData().stringRecursionCheckVisitedObjects.remove(m_thisObject);
+
+    VM& vm = m_exec->vm();
+    if (vm.stringRecursionCheckFirstObject == m_thisObject)
+        vm.stringRecursionCheckFirstObject = nullptr;
+    else {
+        ASSERT(vm.stringRecursionCheckVisitedObjects.contains(m_thisObject));
+        vm.stringRecursionCheckVisitedObjects.remove(m_thisObject);
+    }
 }
 
 }
 }
 
 }