Title: [159210] trunk/Source/_javascript_Core
Revision
159210
Author
[email protected]
Date
2013-11-13 11:12:37 -0800 (Wed, 13 Nov 2013)

Log Message

REGRESSION (r158014): Many webpages throw stack overflow exceptions on iOS (because Parser::parseMemberExpression uses ~130K more stack)
https://bugs.webkit.org/show_bug.cgi?id=124177

Reviewed by Michael Saboff.

This patch pushes error handling into NEVER_INLINE functions to perform
the actual error message construction.  This dramatically reduces the
stack usage of the Parser.  For the large functions (such as parseMemberExpression)
the improvement is on the order of 2.5x reduction in stack usage.  For
smaller functions the reduction is in the order of 5-6x.

* parser/Parser.cpp:
(JSC::::logError):
* parser/Parser.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (159209 => 159210)


--- trunk/Source/_javascript_Core/ChangeLog	2013-11-13 18:51:54 UTC (rev 159209)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-11-13 19:12:37 UTC (rev 159210)
@@ -1,3 +1,20 @@
+2013-11-13  Oliver Hunt  <[email protected]>
+
+        REGRESSION (r158014): Many webpages throw stack overflow exceptions on iOS (because Parser::parseMemberExpression uses ~130K more stack)
+        https://bugs.webkit.org/show_bug.cgi?id=124177
+
+        Reviewed by Michael Saboff.
+
+        This patch pushes error handling into NEVER_INLINE functions to perform
+        the actual error message construction.  This dramatically reduces the
+        stack usage of the Parser.  For the large functions (such as parseMemberExpression)
+        the improvement is on the order of 2.5x reduction in stack usage.  For
+        smaller functions the reduction is in the order of 5-6x.
+
+        * parser/Parser.cpp:
+        (JSC::::logError):
+        * parser/Parser.h:
+
 2013-11-13  Julien Brianceau  <[email protected]>
 
         [sh4] Protect repatchCompact from flushConstantPool.

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (159209 => 159210)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2013-11-13 18:51:54 UTC (rev 159209)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2013-11-13 19:12:37 UTC (rev 159210)
@@ -37,22 +37,16 @@
 #include <wtf/StringPrintStream.h>
 #include <wtf/WTFThreadData.h>
 
+
 #define updateErrorMessage(shouldPrintToken, ...) do {\
     ASSERT(!hasError());\
-    StringPrintStream stream;\
-    if (shouldPrintToken) {\
-        printUnexpectedTokenText(stream); \
-        stream.print(". "); \
-    }\
-    stream.print(__VA_ARGS__);\
-    stream.print(".");\
-    setErrorMessage(stream.toString());\
+    logError(shouldPrintToken, __VA_ARGS__); \
 } while (0)
 
 #define propagateError() do { if (hasError()) return 0; } while (0)
-#define internalFailWithMessage(shouldPrintToken, ...) do { if (!hasError()) updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
+#define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
 #define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
-#define failWithMessage(...) do { if (!hasError()) { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
+#define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
 #define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
 #define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
 #define failIfTrue(cond, ...) do { if ((cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
@@ -65,13 +59,9 @@
 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
 #define semanticFailIfTrue(cond, ...) do { if ((cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
 #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
-#define regexFail(failure) do { if (!hasError()) setErrorMessage(failure); return 0; } while (0)
+#define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
 #define failDueToUnexpectedToken() do {\
-    if (!hasError()) {\
-        StringPrintStream stream;\
-        printUnexpectedTokenText(stream); \
-        setErrorMessage(stream.toString());\
-    }\
+        logError(true);\
     return 0;\
 } while (0)
 
@@ -93,6 +83,115 @@
 namespace JSC {
 
 template <typename LexerType>
+void Parser<LexerType>::logError(bool)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    printUnexpectedTokenText(stream);
+    stream.print(". ");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType> template <typename A>
+void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    if (shouldPrintToken) {
+        printUnexpectedTokenText(stream);
+        stream.print(". ");
+    }
+    stream.print(value1, ".");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType> template <typename A, typename B>
+void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    if (shouldPrintToken) {
+        printUnexpectedTokenText(stream);
+        stream.print(". ");
+    }
+    stream.print(value1, value2, ".");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType> template <typename A, typename B, typename C>
+void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    if (shouldPrintToken) {
+        printUnexpectedTokenText(stream);
+        stream.print(". ");
+    }
+    stream.print(value1, value2, value3, ".");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType> template <typename A, typename B, typename C, typename D>
+void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    if (shouldPrintToken) {
+        printUnexpectedTokenText(stream);
+        stream.print(". ");
+    }
+    stream.print(value1, value2, value3, value4, ".");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
+void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    if (shouldPrintToken) {
+        printUnexpectedTokenText(stream);
+        stream.print(". ");
+    }
+    stream.print(value1, value2, value3, value4, value5, ".");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
+void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    if (shouldPrintToken) {
+        printUnexpectedTokenText(stream);
+        stream.print(". ");
+    }
+    stream.print(value1, value2, value3, value4, value5, value6, ".");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
+void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6, const G& value7)
+{
+    if (hasError())
+        return;
+    StringPrintStream stream;
+    if (shouldPrintToken) {
+        printUnexpectedTokenText(stream);
+        stream.print(". ");
+    }
+    stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
+    setErrorMessage(stream.toString());
+}
+
+template <typename LexerType>
 Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
     : m_vm(vm)
     , m_source(&source)

Modified: trunk/Source/_javascript_Core/parser/Parser.h (159209 => 159210)


--- trunk/Source/_javascript_Core/parser/Parser.h	2013-11-13 18:51:54 UTC (rev 159209)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2013-11-13 19:12:37 UTC (rev 159210)
@@ -634,6 +634,15 @@
         m_errorMessage = msg;
     }
     
+    NEVER_INLINE void logError(bool);
+    template <typename A> NEVER_INLINE void logError(bool, const A&);
+    template <typename A, typename B> NEVER_INLINE void logError(bool, const A&, const B&);
+    template <typename A, typename B, typename C> NEVER_INLINE void logError(bool, const A&, const B&, const C&);
+    template <typename A, typename B, typename C, typename D> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&);
+    template <typename A, typename B, typename C, typename D, typename E> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&);
+    template <typename A, typename B, typename C, typename D, typename E, typename F> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&);
+    template <typename A, typename B, typename C, typename D, typename E, typename F, typename G> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&, const G&);
+    
     NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, String name, const char* afterMsg)
     {
         m_errorMessage = makeString(beforeMsg, " '", name, "' ", afterMsg);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to