Ignore:
Timestamp:
Apr 25, 2013, 1:00:36 PM (12 years ago)
Author:
[email protected]
Message:

Stack guards are too conservative
https://bugs.webkit.org/show_bug.cgi?id=115147

Reviewed by Geoffrey Garen.

Reduce the limits and simplify the decision making.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::StackPolicy::StackPolicy):

File:
1 edited

Legend:

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

    r149134 r149136  
    120120    const size_t size = stack.size();
    121121
    122     const size_t DEFAULT_REQUIRED_STACK = 1024 * 1024;
    123     const size_t DEFAULT_MINIMUM_USEABLE_STACK = 128 * 1024;
    124     const size_t DEFAULT_ERROR_MODE_REQUIRED_STACK = 32 * 1024;
    125 
    126     // Here's the policy in a nutshell:
     122    // We have two separate stack limits, one for regular JS execution, and one
     123    // for when we're handling errors. We need the error stack to be smaller
     124    // otherwise there would obviously not be any stack left to execute JS in when
     125    // there's a stack overflow.
    127126    //
    128     // 1. If we have a large stack, let JS use as much stack as possible
    129     //    but require that we have at least DEFAULT_REQUIRED_STACK capacity
    130     //    remaining on the stack:
    131     //
    132     //    stack grows this way -->   
    133     //    ---------------------------------------------------------
    134     //    |         ... | <-- DEFAULT_REQUIRED_STACK --> | ...
    135     //    ---------------------------------------------------------
    136     //    ^             ^
    137     //    start         current sp
    138     //
    139     // 2. In event that we're re-entering the interpreter to handle
    140     //    exceptions (in error mode), we'll be a little more generous and
    141     //    require less stack capacity for the interpreter to be re-entered.
    142     //
    143     //    This is needed because we may have just detected an eminent stack
    144     //    overflow based on the normally computed required stack capacity.
    145     //    However, the normal required capacity far exceeds what is needed
    146     //    for exception handling work. Hence, in error mode, we only require
    147     //    DEFAULT_ERROR_MODE_REQUIRED_STACK capacity.
    148     //
    149     //    stack grows this way -->   
    150     //    -----------------------------------------------------------------
    151     //    |         ... | <-- DEFAULT_ERROR_MODE_REQUIRED_STACK --> | ...
    152     //    -----------------------------------------------------------------
    153     //    ^             ^
    154     //    start         current sp
    155     //
    156     //    This smaller required capacity also means that we won't re-trigger
    157     //    a stack overflow for processing the exception caused by the original
    158     //    StackOverflowError.
    159     //
    160     // 3. If the stack is not large enough, give JS at least a minimum
    161     //    amount of useable stack:
    162     //
    163     //    stack grows this way -->   
    164     //    --------------------------------------------------------------------
    165     //    | <-- DEFAULT_MINIMUM_USEABLE_STACK --> | <-- requiredCapacity --> |
    166     //    --------------------------------------------------------------------
    167     //    ^             ^
    168     //    start         current sp
    169     //
    170     //    The minimum useable capacity is DEFAULT_MINIMUM_USEABLE_STACK.
    171     //    In this case, the requiredCapacity is whatever is left of the
    172     //    total stack capacity after we have give JS its minimum stack
    173     //    i.e. requiredCapacity can even be 0 if there's not enough stack.
    174 
    175 
    176     // Policy 1: Normal mode: required = DEFAULT_REQUIRED_STACK.
    177     // Policy 2: Error mode: required = DEFAULT_ERROR_MODE_REQUIRED_STACK.
    178     size_t requiredCapacity = !m_interpreter.m_errorHandlingModeReentry ?
    179         DEFAULT_REQUIRED_STACK : DEFAULT_ERROR_MODE_REQUIRED_STACK;
    180 
    181     size_t useableStack = (requiredCapacity <= size) ?
    182         size - requiredCapacity : DEFAULT_MINIMUM_USEABLE_STACK;
    183 
    184     // Policy 3: Ensure the useable stack is not too small:
    185     if (useableStack < DEFAULT_MINIMUM_USEABLE_STACK)
    186         useableStack = DEFAULT_MINIMUM_USEABLE_STACK;
    187 
    188     // Sanity check: Make sure we do not use more space than the stack's
    189     // total capacity:
    190     if (useableStack > size)
    191         useableStack = size;
    192 
    193     // Re-compute the requiredCapacity based on the adjusted useable stack
    194     // size:
    195     requiredCapacity = size - useableStack;
    196     ASSERT(requiredCapacity < size);
    197 
     127    // These sizes were derived from the stack usage of a number of sites when
     128    // layout occurs when we've already consumed most of the C stack.
     129    const size_t requiredStack = 64 * KB;
     130    const size_t errorModeRequiredStack = 32 * KB;
     131
     132    size_t requiredCapacity = m_interpreter.m_errorHandlingModeReentry ? errorModeRequiredStack : requiredStack;
     133
     134    RELEASE_ASSERT(size > requiredCapacity);
     135   
    198136    m_requiredCapacity = requiredCapacity;   
    199137}
Note: See TracChangeset for help on using the changeset viewer.