Ignore:
Timestamp:
Oct 22, 2012, 3:09:58 PM (13 years ago)
Author:
[email protected]
Message:

Change stack recursion checks to be based on stack availability.
https://bugs.webkit.org/show_bug.cgi?id=99872.

Reviewed by Filip Pizlo and Geoffrey Garen.

Source/JavaScriptCore:

  • Remove m_reentryDepth, ThreadStackType which are now obsolete.
  • Replaced the reentryDepth checks with a StackBounds check.
  • Added the Interpreter::StackPolicy class to compute a reasonable stack capacity requirement given the native stack that the interpreter is executing on at that time.
  • Reserved an amount of JSStack space for the use of error handling and enable its use (using Interpreter::ErrorHandlingMode) when we're about to throw or report an exception.
  • Interpreter::StackPolicy also allows more native stack space to be used when in ErrorHandlingMode. This is needed in the case of native stack overflows.
  • Fixed the parser so that it throws a StackOverflowError instead of a SyntaxError when it encounters a stack overflow.
  • API/JSContextRef.cpp:

(JSContextGroupCreate):
(JSGlobalContextCreateInGroup):

(JSC::Interpreter::ErrorHandlingMode::ErrorHandlingMode):
(JSC):
(JSC::Interpreter::ErrorHandlingMode::~ErrorHandlingMode):
(JSC::Interpreter::StackPolicy::StackPolicy):
(JSC::Interpreter::Interpreter):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):

  • interpreter/Interpreter.h:

(JSC):
(Interpreter):
(ErrorHandlingMode):
(StackPolicy):
(JSC::Interpreter::StackPolicy::requiredCapacity):

  • interpreter/JSStack.cpp:

(JSC):
(JSC::JSStack::JSStack):
(JSC::JSStack::growSlowCase):
(JSC::JSStack::enableErrorStackReserve):
(JSC::JSStack::disableErrorStackReserve):

  • interpreter/JSStack.h:

(JSStack):
(JSC::JSStack::reservationEnd):
(JSC):

  • jsc.cpp:

(jscmain):

  • parser/Parser.cpp:

(JSC::::Parser):

  • parser/Parser.h:

(Parser):
(JSC::::parse):

  • runtime/ExceptionHelpers.cpp:

(JSC::throwStackOverflowError):

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::createContextGroup):
(JSC::JSGlobalData::create):
(JSC::JSGlobalData::createLeaked):
(JSC::JSGlobalData::sharedInstance):

  • runtime/JSGlobalData.h:

(JSC):
(JSGlobalData):

  • runtime/StringRecursionChecker.h:

(JSC::StringRecursionChecker::performCheck):

  • testRegExp.cpp:

(realMain):

Source/WebCore:

Removed the use of ThreadStackType. Enabled the reserved JSStack space
for error processing before doing work in reportException().

  • bindings/js/JSDOMBinding.cpp:

(WebCore::reportException):

  • bindings/js/JSDOMWindowBase.cpp:

(WebCore::JSDOMWindowBase::commonJSGlobalData):

  • bindings/js/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::WorkerScriptController):

LayoutTests:

Updated test baseline.

  • fast/js/global-recursion-on-full-stack-expected.txt:
  • fast/xmlhttprequest/xmlhttprequest-recursive-sync-event-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/interpreter/JSStack.cpp

    r130726 r132143  
    4242    return staticMutex;
    4343}   
    44    
     44
     45JSStack::JSStack(size_t capacity)
     46    : m_end(0)
     47{
     48    ASSERT(capacity && isPageAligned(capacity));
     49
     50    m_reservation = PageReservation::reserve(roundUpAllocationSize(capacity * sizeof(Register), commitSize), OSAllocator::JSVMStackPages);
     51    m_end = static_cast<Register*>(m_reservation.base());
     52    m_commitEnd = static_cast<Register*>(m_reservation.base());
     53
     54    disableErrorStackReserve();
     55}
     56
    4557JSStack::~JSStack()
    4658{
     
    5365bool JSStack::growSlowCase(Register* newEnd)
    5466{
     67    // If we have already committed enough memory to satisfy this request,
     68    // just update the end pointer and return.
    5569    if (newEnd <= m_commitEnd) {
    5670        m_end = newEnd;
     
    5872    }
    5973
     74    // Compute the chunk size of additional memory to commit, and see if we
     75    // have it is still within our budget. If not, we'll fail to grow and
     76    // return false.
    6077    long delta = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize);
    61     if (reinterpret_cast<char*>(m_commitEnd) + delta > static_cast<char*>(m_reservation.base()) + m_reservation.size())
     78    if (reinterpret_cast<char*>(m_commitEnd) + delta > reinterpret_cast<char*>(m_useableEnd))
    6279        return false;
    6380
     81    // Otherwise, the growth is still within our budget. Go ahead and commit
     82    // it and return true.
    6483    m_reservation.commit(m_commitEnd, delta);
    6584    addToCommittedByteCount(delta);
     
    105124}
    106125
     126void JSStack::enableErrorStackReserve()
     127{
     128    m_useableEnd = reservationEnd();
     129}
     130
     131void JSStack::disableErrorStackReserve()
     132{
     133    char* useableEnd = reinterpret_cast<char*>(reservationEnd()) - commitSize;
     134    m_useableEnd = reinterpret_cast<Register*>(useableEnd);
     135
     136    // By the time we get here, we are guaranteed to be destructing the last
     137    // Interpreter::ErrorHandlingMode that enabled this reserve in the first
     138    // place. That means the stack space beyond m_useableEnd before we
     139    // enabled the reserve was not previously in use. Hence, it is safe to
     140    // shrink back to that m_useableEnd.
     141    if (m_end > m_useableEnd)
     142        shrink(m_useableEnd);
     143}
     144
    107145} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.