Changeset 161575 in webkit


Ignore:
Timestamp:
Jan 9, 2014, 1:10:46 PM (11 years ago)
Author:
mark.lam@apple.com
Message:

CStack: Need a separate stack limit for the JS stack and the C stack.
https://bugs.webkit.org/show_bug.cgi?id=126320.

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

The purpose of this patch is mainly to change the way we compute the stack
limit for JS stack checks. Previously, we tally up the stack usage per
session of VM re-entry as tracked by the VMEntryScope, and we ensure that
the total usage does not exceed Options::maxStackSize(), and of course, is
also capped by the amount of native C stack available. The usage tracking
here does not count host / native function stack usage against the max
stack usage.

The new way is to compute a limit as an offset from the VMEntryScope of
the first entry into the VM. Options::maxPerThreadStackUsage()
will provide that offset. Any host / native function stack usage after
we've entered the VM will be counted against the max stack usage.

This patch supplants parts or all of the following previously committed
patches:

r161104: https://bugs.webkit.org/show_bug.cgi?id=126266

Rename VM::entryScope to firstEntryScope.

r161232: https://bugs.webkit.org/show_bug.cgi?id=126321

Introducing Options::maxStackSize().

r161172: https://bugs.webkit.org/show_bug.cgi?id=126331

Refactor to split the tracking of the jsStackLimit from the
native stackLimit.

r161174: https://bugs.webkit.org/show_bug.cgi?id=126334

Introduce tracking of the top VMEntryScope.

r161361: https://bugs.webkit.org/show_bug.cgi?id=126487

The fixed up jsStackLimit in doCallToJavaScript should not
exceed the native stack limit.

r161180: https://bugs.webkit.org/show_bug.cgi?id=126320

Need a separate stack limit for the JS stack and the C stack.
This was for the old way of tracking chunks of stack usage
per VMEntryScope.

Details of this patch:

  1. Renamed VM::firstEntryScope back to VM::entryScope. Removed the tracking of topEntryScope and related code.
  1. Renamed Options::maxStackSize() to maxPerThreadStackUsage(). Added Options::hostZoneSize() and Options::errorModeHostZoneSize().
  1. The VM now tracks its current hostZoneSize and stack limits. VM::m_stackLimit is computed when the hostZoneSize is set via VM::updateStackLimitWithHostZoneSize().

In the C Loop LLINT case, the VM also provides a setJSStackLimit()
since VM::m_stackLimit and VM::m_jsStackLimit are 2 different values
in that case.

  1. Replaced Interpreter::ErrorHandlingMode with ErrorHandlingScope. The ErrorHandlingScope constructor will set the VM host zone size to Options::errorModeHostZoneSize(), and restore the previous host zone size.

The destructor for ErrorHandlingScope will restore the previous stack
limit. We can enter multiple ErrorHandlingScopes. Only the destruction
of the very first one will restore the stack limit with the non-error
mode host zone.

  1. LLINT C loop JSStack changes: 5.1 Replaced calls to roundUpToAllocationSize() with WTF::roundUpToMultipleOf().

roundUpToAllocationSize() is redundant and is now removed.

5.2 Removed enable/disableErrorStackReserve() and updateStackLimit().

Their function is now handled by JSStack::setHostZoneSize().

5.3 Added accounting for a host zone in the LLINT C loop JSStack.

This includes growing the JS stack to allow space for the host zone
whenever the host zone size is adjusted via JSStack::setHostZoneSize().

Note: though setHostZoneSize() is based on disableErrorStackReserve(),
we don't retain the logic to shrink the stack there. That logic was
always dead code: we only call shrink() if m_end + 1 < m_useableTop,
but shrink() will only shrink the stack if m_end is pointing to the
base of the stack i.e. the 2 conditions are mutually exclusive, and
no work to shrink the stack will ever be done here.

m_useableTop is no longer needed and is now removed.

5.4 Change all non C loop code to reference VM::stackLimit() instead of

VM::jsStackLimit(). Though the 2 are the same for non C loop builds,
this makes it more straightforward. We now only reference the
jsStackLimit in 2 cases:

  1. LLINT and JIT code performing stack checks where they expect the jsStackLimit to be a pseudonym for the stackLimit in non C loop builds.
  1. In the C loop build, the JSStack itself sets VM::m_jsStackLimit() when it adjusts its host zone size.

In all other cases, we work directly with VM::stackLimit().

  1. Simplify the tracking of VM::stackPointerAtVMEntry. We now set VM::stackPointerAtVMEntry when we install a VMEntryScope if and only if it isn't already set.

When we drop the API locks, we'll save the current stackPointerAtVMEntry
and stack limit value, and clear stackPointerAtVMEntry to allow a new
thread acquiring the API locks to re-set it when it installs a VMEntryScope.
When we re-acquire the API locks again, we'll restore the previously saved
stackPointerAtVMEntry and stack limit.

With this change, we also no longer need the stackPointerAtVMEntry fix up
code in doCallToJavaScript(). That code is now removed.

(JSC::Debugger::recompileAllJSFunctions):

  • debugger/DebuggerCallFrame.cpp:
  • heap/Heap.cpp:

(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::deleteAllCompiledCode):

  • interpreter/CallFrame.cpp:

(JSC::CallFrame::vmEntryGlobalObject):

  • interpreter/Interpreter.cpp:
  • interpreter/Interpreter.h:
  • interpreter/JSStack.cpp:

(JSC::JSStack::JSStack):
(JSC::JSStack::~JSStack):
(JSC::JSStack::growSlowCase):
(JSC::JSStack::releaseExcessCapacity):
(JSC::JSStack::setHostZoneSize):
(JSC::JSStack::lowAddress):

  • interpreter/JSStack.h:
  • interpreter/JSStackInlines.h:

(JSC::JSStack::ensureCapacityFor):
(JSC::JSStack::shrink):

  • jit/ExecutableAllocator.h:
  • jit/JITOperations.cpp:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LowLevelInterpreter64.asm:
  • parser/ParserError.h:

(JSC::ParserError::toErrorObject):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/ErrorHandlingScope.cpp: Added.

(JSC::ErrorHandlingScope::ErrorHandlingScope):
(JSC::ErrorHandlingScope::~ErrorHandlingScope):

  • runtime/ErrorHandlingScope.h: Added.
  • runtime/ExceptionHelpers.cpp:

(JSC::throwStackOverflowError):
(JSC::throwTerminatedExecutionException):

  • runtime/JSLock.cpp:

(JSC::JSLock::DropAllLocks::DropAllLocks):
(JSC::JSLock::DropAllLocks::~DropAllLocks):

  • runtime/JSLock.h:
  • runtime/Options.h:
  • runtime/VM.cpp:

(JSC::VM::VM):
(JSC::VM::releaseExecutableMemory):
(JSC::VM::updateStackLimitWithHostZoneSize):

  • runtime/VM.h:
  • runtime/VMEntryScope.cpp:

(JSC::VMEntryScope::VMEntryScope):
(JSC::VMEntryScope::~VMEntryScope):

  • runtime/VMEntryScope.h:

Source/WebCore:

No new tests.

  • ForwardingHeaders/runtime/ErrorHandlingScope.h: Added.
  • WebCore.vcxproj/WebCore.vcxproj:
  • WebCore.vcxproj/WebCore.vcxproj.filters:
  • bindings/js/JSDOMBinding.cpp:

(WebCore::reportException):

  • Updated to use ErrorHandlingScope instead of Interpreter::ErrorHandlingMode.

Source/WTF:

  • wtf/StackBounds.h:

(WTF::StackBounds::recursionLimit):

  • Previously, StackBounds::recursionLimit() only takes a host zone size which it uses to compute the client's desired stack limit. Now, there's an alternate version that also allows the client to explicitly specify its desired stack limit in addition to its hostZoneSize requirement. In both cases, StackBounds::recursionLimit() will cap the limit (with allowance for the hostZoneSize) to be within its bounds, and return the capped limit.

LayoutTests:

  • js/large-expressions-expected.txt:
  • js/script-tests/large-expressions.js:
  • Changed expected result to reflect the much more constrained stack size now that the JS stack limit also limits stack usage by host / native functions.
Location:
branches/jsCStack
Files:
3 added
38 edited

Legend:

Unmodified
Added
Removed
  • branches/jsCStack/LayoutTests/ChangeLog

    r161409 r161575  
     12014-01-08  Mark Lam  <mark.lam@apple.com>
     2
     3        CStack: Need a separate stack limit for the JS stack and the C stack.
     4        https://bugs.webkit.org/show_bug.cgi?id=126320.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * js/large-expressions-expected.txt:
     9        * js/script-tests/large-expressions.js:
     10        - Changed expected result to reflect the much more constrained stack size
     11          now that the JS stack limit also limits stack usage by host / native
     12          functions.
     13
    1142014-01-06  Filip Pizlo  <fpizlo@apple.com>
    215
  • branches/jsCStack/LayoutTests/js/large-expressions-expected.txt

    r75408 r161575  
    66PASS eval(repeatedExpression("letterA", "+", 100)) is repeatedString("a", 100)
    77PASS eval(repeatedExpression("letterA", "+", 1000)) is repeatedString("a", 1000)
    8 PASS eval(repeatedExpression("letterA", "+", 10000)) is repeatedString("a", 10000)
     8PASS eval(repeatedExpression("letterA", "+", 10000)) threw exception Error: Out of memory.
    99PASS eval(repeatedExpression("letterA", "+", 100000)) threw exception Error: Out of memory.
    1010PASS successfullyParsed is true
  • branches/jsCStack/LayoutTests/js/script-tests/large-expressions.js

    r156976 r161575  
    3131shouldBe('eval(repeatedExpression("letterA", "+", 100))', 'repeatedString("a", 100)');
    3232shouldBe('eval(repeatedExpression("letterA", "+", 1000))', 'repeatedString("a", 1000)');
    33 shouldBe('eval(repeatedExpression("letterA", "+", 10000))', 'repeatedString("a", 10000)');
     33shouldThrow('eval(repeatedExpression("letterA", "+", 10000))');
    3434shouldThrow('eval(repeatedExpression("letterA", "+", 100000))');
  • branches/jsCStack/Source/JavaScriptCore/CMakeLists.txt

    r161409 r161575  
    312312    runtime/Error.cpp
    313313    runtime/ErrorConstructor.cpp
     314    runtime/ErrorHandlingScope.cpp
    314315    runtime/ErrorInstance.cpp
    315316    runtime/ErrorPrototype.cpp
  • branches/jsCStack/Source/JavaScriptCore/ChangeLog

    r161547 r161575  
     12014-01-09  Mark Lam  <mark.lam@apple.com>
     2
     3        CStack: Need a separate stack limit for the JS stack and the C stack.
     4        https://bugs.webkit.org/show_bug.cgi?id=126320.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        The purpose of this patch is mainly to change the way we compute the stack
     9        limit for JS stack checks. Previously, we tally up the stack usage per
     10        session of VM re-entry as tracked by the VMEntryScope, and we ensure that
     11        the total usage does not exceed Options::maxStackSize(), and of course, is
     12        also capped by the amount of native C stack available. The usage tracking
     13        here does not count host / native function stack usage against the max
     14        stack usage.
     15
     16        The new way is to compute a limit as an offset from the VMEntryScope of
     17        the first entry into the VM. Options::maxPerThreadStackUsage()
     18        will provide that offset. Any host / native function stack usage after
     19        we've entered the VM will be counted against the max stack usage.
     20
     21        This patch supplants parts or all of the following previously committed
     22        patches:
     23
     24            r161104: https://bugs.webkit.org/show_bug.cgi?id=126266
     25                     Rename VM::entryScope to firstEntryScope.
     26            r161232: https://bugs.webkit.org/show_bug.cgi?id=126321
     27                     Introducing Options::maxStackSize().
     28            r161172: https://bugs.webkit.org/show_bug.cgi?id=126331
     29                     Refactor to split the tracking of the jsStackLimit from the
     30                     native stackLimit.
     31            r161174: https://bugs.webkit.org/show_bug.cgi?id=126334
     32                     Introduce tracking of the top VMEntryScope.
     33            r161361: https://bugs.webkit.org/show_bug.cgi?id=126487
     34                     The fixed up jsStackLimit in doCallToJavaScript should not
     35                     exceed the native stack limit.
     36            r161180: https://bugs.webkit.org/show_bug.cgi?id=126320
     37                     Need a separate stack limit for the JS stack and the C stack.
     38                     This was for the old way of tracking chunks of stack usage
     39                     per VMEntryScope.
     40
     41        Details of this patch:
     42
     43        1. Renamed VM::firstEntryScope back to VM::entryScope.
     44           Removed the tracking of topEntryScope and related code.
     45
     46        2. Renamed Options::maxStackSize() to maxPerThreadStackUsage().
     47           Added Options::hostZoneSize() and Options::errorModeHostZoneSize().
     48
     49        3. The VM now tracks its current hostZoneSize and stack limits.
     50           VM::m_stackLimit is computed when the hostZoneSize is set via
     51           VM::updateStackLimitWithHostZoneSize().
     52
     53           In the C Loop LLINT case, the VM also provides a setJSStackLimit()
     54           since VM::m_stackLimit and VM::m_jsStackLimit are 2 different values
     55           in that case.
     56
     57        4. Replaced Interpreter::ErrorHandlingMode with ErrorHandlingScope.
     58           The ErrorHandlingScope constructor will set the VM host zone size to
     59           Options::errorModeHostZoneSize(), and restore the previous host zone
     60           size.
     61
     62           The destructor for ErrorHandlingScope will restore the previous stack
     63           limit. We can enter multiple ErrorHandlingScopes. Only the destruction
     64           of the very first one will restore the stack limit with the non-error
     65           mode host zone.
     66
     67        5. LLINT C loop JSStack changes:
     68           5.1 Replaced calls to roundUpToAllocationSize() with WTF::roundUpToMultipleOf().
     69               roundUpToAllocationSize() is redundant and is now removed.
     70
     71           5.2 Removed enable/disableErrorStackReserve() and updateStackLimit().
     72               Their function is now handled by JSStack::setHostZoneSize().
     73
     74           5.3 Added accounting for a host zone in the LLINT C loop JSStack.
     75               This includes growing the JS stack to allow space for the host zone
     76               whenever the host zone size is adjusted via JSStack::setHostZoneSize().
     77
     78               Note: though setHostZoneSize() is based on disableErrorStackReserve(),
     79               we don't retain the logic to shrink the stack there. That logic was
     80               always dead code: we only call shrink() if m_end + 1 < m_useableTop,
     81               but shrink() will only shrink the stack if m_end is pointing to the
     82               base of the stack i.e. the 2 conditions are mutually exclusive, and
     83               no work to shrink the stack will ever be done here.
     84
     85               m_useableTop is no longer needed and is now removed.
     86
     87           5.4 Change all non C loop code to reference VM::stackLimit() instead of
     88               VM::jsStackLimit(). Though the 2 are the same for non C loop builds,
     89               this makes it more straightforward. We now only reference the
     90               jsStackLimit in 2 cases:
     91
     92               a. LLINT and JIT code performing stack checks where they expect the
     93                  jsStackLimit to be a pseudonym for the stackLimit in non C loop
     94                  builds.
     95
     96               b. In the C loop build, the JSStack itself sets VM::m_jsStackLimit()
     97                  when it adjusts its host zone size.
     98
     99               In all other cases, we work directly with VM::stackLimit().
     100
     101        6. Simplify the tracking of VM::stackPointerAtVMEntry. We now set
     102           VM::stackPointerAtVMEntry when we install a VMEntryScope if and only if
     103           it isn't already set.
     104
     105           When we drop the API locks, we'll save the current stackPointerAtVMEntry
     106           and stack limit value, and clear stackPointerAtVMEntry to allow a new
     107           thread acquiring the API locks to re-set it when it installs a VMEntryScope.
     108           When we re-acquire the API locks again, we'll restore the previously saved
     109           stackPointerAtVMEntry and stack limit.
     110
     111           With this change, we also no longer need the stackPointerAtVMEntry fix up
     112           code in doCallToJavaScript(). That code is now removed.
     113
     114        * CMakeLists.txt:
     115        * GNUmakefile.list.am:
     116        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     117        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     118        * JavaScriptCore.xcodeproj/project.pbxproj:
     119        * debugger/Debugger.cpp:
     120        (JSC::Debugger::recompileAllJSFunctions):
     121        * debugger/DebuggerCallFrame.cpp:
     122        * heap/Heap.cpp:
     123        (JSC::Heap::lastChanceToFinalize):
     124        (JSC::Heap::deleteAllCompiledCode):
     125        * interpreter/CallFrame.cpp:
     126        (JSC::CallFrame::vmEntryGlobalObject):
     127        * interpreter/Interpreter.cpp:
     128        * interpreter/Interpreter.h:
     129        * interpreter/JSStack.cpp:
     130        (JSC::JSStack::JSStack):
     131        (JSC::JSStack::~JSStack):
     132        (JSC::JSStack::growSlowCase):
     133        (JSC::JSStack::releaseExcessCapacity):
     134        (JSC::JSStack::setHostZoneSize):
     135        (JSC::JSStack::lowAddress):
     136        * interpreter/JSStack.h:
     137        * interpreter/JSStackInlines.h:
     138        (JSC::JSStack::ensureCapacityFor):
     139        (JSC::JSStack::shrink):
     140        * jit/ExecutableAllocator.h:
     141        * jit/JITOperations.cpp:
     142        * llint/LLIntSlowPaths.cpp:
     143        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     144        * llint/LowLevelInterpreter64.asm:
     145        * parser/ParserError.h:
     146        (JSC::ParserError::toErrorObject):
     147        * runtime/CommonSlowPaths.cpp:
     148        (JSC::SLOW_PATH_DECL):
     149        * runtime/ErrorHandlingScope.cpp: Added.
     150        (JSC::ErrorHandlingScope::ErrorHandlingScope):
     151        (JSC::ErrorHandlingScope::~ErrorHandlingScope):
     152        * runtime/ErrorHandlingScope.h: Added.
     153        * runtime/ExceptionHelpers.cpp:
     154        (JSC::throwStackOverflowError):
     155        (JSC::throwTerminatedExecutionException):
     156        * runtime/JSLock.cpp:
     157        (JSC::JSLock::DropAllLocks::DropAllLocks):
     158        (JSC::JSLock::DropAllLocks::~DropAllLocks):
     159        * runtime/JSLock.h:
     160        * runtime/Options.h:
     161        * runtime/VM.cpp:
     162        (JSC::VM::VM):
     163        (JSC::VM::releaseExecutableMemory):
     164        (JSC::VM::updateStackLimitWithHostZoneSize):
     165        * runtime/VM.h:
     166        * runtime/VMEntryScope.cpp:
     167        (JSC::VMEntryScope::VMEntryScope):
     168        (JSC::VMEntryScope::~VMEntryScope):
     169        * runtime/VMEntryScope.h:
     170
    11712014-01-08  Filip Pizlo  <fpizlo@apple.com>
    2172
     
    399569
    400570        Reviewed by Michael Saboff.
     571        Update: this is supplanted by the 2014-01-08 patch for https://bugs.webkit.org/show_bug.cgi?id=126320.
    401572
    402573        In doCallToJavaScript, we fixup VM::m_jsStackLimit once we know what the
     
    716887        https://bugs.webkit.org/show_bug.cgi?id=126320.
    717888
    718         Not yet reviewed.
     889        Rejected by Geoffrey Garen.
     890        Update: this is supplanted by the 2014-01-08 patch for https://bugs.webkit.org/show_bug.cgi?id=126320.
    719891
    720892        With this patch, we now accurately track how much JS stack space the
     
    803975        Not yet reviewed.
    804976
     977        We cannot do a meaningful assertion here on the size of the stack span
     978        because we don't know the stack bounds that the span came from. Hence,
     979        the assertion is now removed.
     980
    805981        * heap/ConservativeRoots.cpp:
    806982        (JSC::ConservativeRoots::genericAddSpan):
     
    812988
    813989        Reviewed by Geoffrey Garen.
     990        Update: this is supplanted by the 2014-01-08 patch for https://bugs.webkit.org/show_bug.cgi?id=126320.
    814991
    815992        When we start measuring the stack usage of each VMEntryScope, we'll need
     
    8411018        https://bugs.webkit.org/show_bug.cgi?id=126331.
    8421019
    843         Not yet reviewed.
     1020        Rejected by Geoffrey Garen.
     1021        Update: this is supplanted by the 2014-01-08 patch for https://bugs.webkit.org/show_bug.cgi?id=126320.
    8441022
    8451023        Previously, when using the C stack for the JS stack, VM::m_jsStackLimit is a union
     
    8761054
    8771055        Reviewed by Geoffrey Garen.
     1056        Update: this is supplanted by the 2014-01-08 patch for https://bugs.webkit.org/show_bug.cgi?id=126320.
    8781057
    8791058        We need an option to limit the JS stack size. Currently, we just change
     
    9061085        https://bugs.webkit.org/show_bug.cgi?id=126266.
    9071086
    908         Not yet reviewed.
     1087        Rejected by Geoffrey Garen.
     1088        Update: this is supplanted by the 2014-01-08 patch for https://bugs.webkit.org/show_bug.cgi?id=126320.
    9091089
    9101090        This patch is so that we can distinguish firstEntryScope from topEntryScope
  • branches/jsCStack/Source/JavaScriptCore/GNUmakefile.list.am

    r161409 r161575  
    852852        Source/JavaScriptCore/runtime/Error.cpp \
    853853        Source/JavaScriptCore/runtime/Error.h \
     854        Source/JavaScriptCore/runtime/ErrorHandlingScope.cpp \
     855        Source/JavaScriptCore/runtime/ErrorHandlingScope.h \
    854856        Source/JavaScriptCore/runtime/ErrorInstance.cpp \
    855857        Source/JavaScriptCore/runtime/ErrorInstance.h \
  • branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r161409 r161575  
    554554    <ClCompile Include="..\runtime\Error.cpp" />
    555555    <ClCompile Include="..\runtime\ErrorConstructor.cpp" />
     556    <ClCompile Include="..\runtime\ErrorHandlingScope.cpp" />
    556557    <ClCompile Include="..\runtime\ErrorInstance.cpp" />
    557558    <ClCompile Include="..\runtime\ErrorPrototype.cpp" />
     
    11341135    <ClInclude Include="..\runtime\Error.h" />
    11351136    <ClInclude Include="..\runtime\ErrorConstructor.h" />
     1137    <ClInclude Include="..\runtime\ErrorHandlingScope.h" />
    11361138    <ClInclude Include="..\runtime\ErrorInstance.h" />
    11371139    <ClInclude Include="..\runtime\ErrorPrototype.h" />
  • branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r160519 r161575  
    508508      <Filter>runtime</Filter>
    509509    </ClCompile>
     510    <ClCompile Include="..\runtime\ErrorHandlingScope.cpp">
     511      <Filter>runtime</Filter>
     512    </ClCompile>
    510513    <ClCompile Include="..\runtime\ErrorInstance.cpp">
    511514      <Filter>runtime</Filter>
     
    20352038    </ClInclude>
    20362039    <ClInclude Include="..\runtime\ErrorConstructor.h">
     2040      <Filter>runtime</Filter>
     2041    </ClInclude>
     2042    <ClInclude Include="..\runtime\ErrorHandlingScope.h">
    20372043      <Filter>runtime</Filter>
    20382044    </ClInclude>
  • branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r161543 r161575  
    12841284                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12851285                FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1286                FEB58C14187B8B160098EF0B /* ErrorHandlingScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEB58C12187B8B160098EF0B /* ErrorHandlingScope.cpp */; };
     1287                FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12861288                FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = FED287B115EC9A5700DA8161 /* LLIntOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12871289                FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */; };
     
    26562658                FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = "<group>"; };
    26572659                FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = "<group>"; };
     2660                FEB58C12187B8B160098EF0B /* ErrorHandlingScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorHandlingScope.cpp; sourceTree = "<group>"; };
     2661                FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorHandlingScope.h; sourceTree = "<group>"; };
    26582662                FED287B115EC9A5700DA8161 /* LLIntOpcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOpcode.h; path = llint/LLIntOpcode.h; sourceTree = "<group>"; };
    26592663                FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Watchdog.cpp; sourceTree = "<group>"; };
     
    34933497                                BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */,
    34943498                                BC02E9050E1839DB000F9297 /* ErrorConstructor.h */,
     3499                                FEB58C12187B8B160098EF0B /* ErrorHandlingScope.cpp */,
     3500                                FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */,
    34953501                                BC02E98A0E183E38000F9297 /* ErrorInstance.cpp */,
    34963502                                BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
     
    43264332                                FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */,
    43274333                                0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */,
     4334                                FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */,
    43284335                                A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */,
    43294336                                C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */,
     
    55025509                                A7D9A29417A0BC7400EE2618 /* DFGAtTailAbstractState.cpp in Sources */,
    55035510                                0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */,
     5511                                FEB58C14187B8B160098EF0B /* ErrorHandlingScope.cpp in Sources */,
    55045512                                A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */,
    55055513                                A70B083217A0B79B00DAF14B /* DFGBinarySwitch.cpp in Sources */,
  • branches/jsCStack/Source/JavaScriptCore/debugger/Debugger.cpp

    r161104 r161575  
    3535#include "Parser.h"
    3636#include "Protect.h"
    37 #include "VMEntryScope.h"
    3837
    3938namespace {
     
    197196    // If JavaScript is running, it's not safe to recompile, since we'll end
    198197    // up throwing away code that is live on the stack.
    199     ASSERT(!vm->firstEntryScope);
    200     if (vm->firstEntryScope)
     198    ASSERT(!vm->entryScope);
     199    if (vm->entryScope)
    201200        return;
    202201   
  • branches/jsCStack/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp

    r159605 r161575  
    3636#include "Parser.h"
    3737#include "StackVisitor.h"
    38 #include "VMEntryScope.h"
    3938
    4039namespace JSC {
  • branches/jsCStack/Source/JavaScriptCore/heap/Heap.cpp

    r161104 r161575  
    292292void Heap::lastChanceToFinalize()
    293293{
    294     RELEASE_ASSERT(!m_vm->firstEntryScope);
     294    RELEASE_ASSERT(!m_vm->entryScope);
    295295    RELEASE_ASSERT(m_operationInProgress == NoOperation);
    296296
     
    696696    // If JavaScript is running, it's not safe to delete code, since we'll end
    697697    // up deleting code that is live on the stack.
    698     if (m_vm->firstEntryScope)
     698    if (m_vm->entryScope)
    699699        return;
    700700
  • branches/jsCStack/Source/JavaScriptCore/interpreter/CallFrame.cpp

    r161104 r161575  
    131131    // For any ExecState that's not a globalExec, the
    132132    // dynamic global object must be set since code is running
    133     ASSERT(vm().firstEntryScope);
    134     return vm().firstEntryScope->globalObject();
     133    ASSERT(vm().entryScope);
     134    return vm().entryScope->globalObject();
    135135}
    136136
  • branches/jsCStack/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r161229 r161575  
    9191
    9292namespace JSC {
    93 
    94 Interpreter::ErrorHandlingMode::ErrorHandlingMode(ExecState *exec)
    95     : m_interpreter(*exec->interpreter())
    96 {
    97     m_interpreter.m_errorHandlingModeReentry++;
    98     m_interpreter.stack().updateStackLimit();
    99 }
    100 
    101 Interpreter::ErrorHandlingMode::~ErrorHandlingMode()
    102 {
    103     m_interpreter.m_errorHandlingModeReentry--;
    104     ASSERT(m_interpreter.m_errorHandlingModeReentry >= 0);
    105     if (!m_interpreter.m_errorHandlingModeReentry)
    106         m_interpreter.stack().updateStackLimit();
    107 }
    10893
    10994JSValue eval(CallFrame* callFrame)
  • branches/jsCStack/Source/JavaScriptCore/interpreter/Interpreter.h

    r160831 r161575  
    191191
    192192    public:
    193         class ErrorHandlingMode {
    194         public:
    195             JS_EXPORT_PRIVATE ErrorHandlingMode(ExecState*);
    196             JS_EXPORT_PRIVATE ~ErrorHandlingMode();
    197         private:
    198             Interpreter& m_interpreter;
    199         };
    200 
    201193        Interpreter(VM &);
    202194        ~Interpreter();
     
    238230        SamplingTool* sampler() { return m_sampler.get(); }
    239231
    240         bool isInErrorHandlingMode() { return m_errorHandlingModeReentry; }
    241 
    242232        NEVER_INLINE HandlerInfo* unwind(CallFrame*&, JSValue&);
    243233        NEVER_INLINE void debug(CallFrame*, DebugHookID);
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStack.cpp

    r161174 r161575  
    11/*
    2  * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3232#include "ConservativeRoots.h"
    3333#include "Interpreter.h"
    34 #include "VMEntryScope.h"
     34#include "Options.h"
    3535
    3636namespace JSC {
     
    5151#if ENABLE(LLINT_C_LOOP)
    5252    , m_end(0)
     53    , m_hostZoneSizeInRegisters(0)
    5354#endif
    5455{
    5556#if ENABLE(LLINT_C_LOOP)
    56     size_t capacity = Options::maxStackSize();
     57    size_t capacity = Options::maxPerThreadStackUsage();
    5758    ASSERT(capacity && isPageAligned(capacity));
    5859
    59     m_reservation = PageReservation::reserve(roundUpAllocationSize(capacity, commitSize), OSAllocator::JSVMStackPages);
     60    m_reservation = PageReservation::reserve(WTF::roundUpToMultipleOf(commitSize, capacity), OSAllocator::JSVMStackPages);
    6061    setStackLimit(highAddress());
    6162    m_commitTop = highAddress();
    6263   
    6364    m_lastStackTop = baseOfStack();
    64 
    65     disableErrorStackReserve();
    6665#endif // ENABLE(LLINT_C_LOOP)
    6766
     
    7271JSStack::~JSStack()
    7372{
    74     void* highAddress = reinterpret_cast<void*>(static_cast<char*>(m_reservation.base()) + m_reservation.size());
    75     m_reservation.decommit(reinterpret_cast<void*>(m_commitTop), reinterpret_cast<intptr_t>(highAddress) - reinterpret_cast<intptr_t>(m_commitTop));
    76     addToCommittedByteCount(-(reinterpret_cast<intptr_t>(highAddress) - reinterpret_cast<intptr_t>(m_commitTop)));
     73    ptrdiff_t sizeToDecommit = reinterpret_cast<char*>(highAddress()) - reinterpret_cast<char*>(m_commitTop);
     74    m_reservation.decommit(reinterpret_cast<void*>(m_commitTop), sizeToDecommit);
     75    addToCommittedByteCount(-sizeToDecommit);
    7776    m_reservation.deallocate();
    7877}
     
    8079bool JSStack::growSlowCase(Register* newTopOfStack)
    8180{
     81    Register* newTopOfStackWithHostZone = newTopOfStack - m_hostZoneSizeInRegisters;
     82
    8283    // If we have already committed enough memory to satisfy this request,
    8384    // just update the end pointer and return.
    84     if (newTopOfStack >= m_commitTop) {
     85    if (newTopOfStackWithHostZone >= m_commitTop) {
    8586        setStackLimit(newTopOfStack);
    8687        return true;
     
    9091    // have it is still within our budget. If not, we'll fail to grow and
    9192    // return false.
    92     long delta = roundUpAllocationSize(reinterpret_cast<char*>(m_commitTop) - reinterpret_cast<char*>(newTopOfStack), commitSize);
    93     if (reinterpret_cast<char*>(m_commitTop) - delta <= reinterpret_cast<char*>(m_useableTop))
     93    ptrdiff_t delta = reinterpret_cast<char*>(m_commitTop) - reinterpret_cast<char*>(newTopOfStackWithHostZone);
     94    delta = WTF::roundUpToMultipleOf(commitSize, delta);
     95    Register* newCommitTop = m_commitTop - (delta / sizeof(Register));
     96    if (newCommitTop < reservationTop())
    9497        return false;
    9598
    9699    // Otherwise, the growth is still within our budget. Go ahead and commit
    97100    // it and return true.
    98     m_reservation.commit(reinterpret_cast<char*>(m_commitTop) - delta, delta);
     101    m_reservation.commit(newCommitTop, delta);
    99102    addToCommittedByteCount(delta);
    100     m_commitTop = reinterpret_cast_ptr<Register*>(reinterpret_cast<char*>(m_commitTop) - delta);
     103    m_commitTop = newCommitTop;
    101104    setStackLimit(newTopOfStack);
    102105    return true;
     
    128131void JSStack::releaseExcessCapacity()
    129132{
    130     ptrdiff_t delta = reinterpret_cast<uintptr_t>(highAddress()) - reinterpret_cast<uintptr_t>(m_commitTop);
     133    Register* highAddressWithHostZone = highAddress() - m_hostZoneSizeInRegisters;
     134    ptrdiff_t delta = reinterpret_cast<char*>(highAddressWithHostZone) - reinterpret_cast<char*>(m_commitTop);
    131135    m_reservation.decommit(m_commitTop, delta);
    132136    addToCommittedByteCount(-delta);
    133     m_commitTop = highAddress();
     137    m_commitTop = highAddressWithHostZone;
    134138}
    135139
     
    146150}
    147151
    148 void JSStack::enableErrorStackReserve()
     152void JSStack::setHostZoneSize(size_t hostZoneSize)
    149153{
    150     m_useableTop = reservationTop();
    151 }
    152 
    153 void JSStack::disableErrorStackReserve()
    154 {
    155     char* useableTop = reinterpret_cast<char*>(reservationTop()) + commitSize;
    156     m_useableTop = reinterpret_cast_ptr<Register*>(useableTop);
    157 
    158     // By the time we get here, we are guaranteed to be destructing the last
    159     // Interpreter::ErrorHandlingMode that enabled this reserve in the first
    160     // place. That means the stack space beyond m_useableTop before we
    161     // enabled the reserve was not previously in use. Hence, it is safe to
    162     // shrink back to that m_useableTop.
    163     if (m_end + 1 < m_useableTop) {
    164         ASSERT(m_topCallFrame->topOfFrame() > m_useableTop);
    165         shrink(m_useableTop);
    166     }
     154    m_hostZoneSizeInRegisters = hostZoneSize / sizeof(Register);
     155    if (m_commitTop >= (m_end + 1) - m_hostZoneSizeInRegisters)
     156        growSlowCase(m_end + 1);
    167157}
    168158#endif // ENABLE(LLINT_C_LOOP)
     
    172162{
    173163    ASSERT(wtfThreadData().stack().isGrowingDownward());
    174     return reinterpret_cast<Register*>(m_vm.jsStackLimit());
     164    return reinterpret_cast<Register*>(m_vm.stackLimit());
    175165}
    176166
     
    197187}
    198188
    199 void JSStack::updateStackLimit()
    200 {
    201 #if ENABLE(LLINT_C_LOOP)
    202     if (m_vm.interpreter->isInErrorHandlingMode())
    203         enableErrorStackReserve();
    204     else
    205         disableErrorStackReserve();
    206 #endif
    207     if (m_vm.topEntryScope)
    208         m_vm.topEntryScope->updateStackLimits();
    209 }
    210 
    211189} // namespace JSC
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStack.h

    r161170 r161575  
    11/*
    2  * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    8484        bool ensureCapacityFor(Register* newTopOfStack);
    8585
    86         void updateStackLimit();
    87 
    8886        bool containsAddress(Register* address) { return (lowAddress() <= address && address < highAddress()); }
    8987        static size_t committedByteCount();
     
    109107
    110108        static void initializeThreading();
     109
     110        void setHostZoneSize(size_t);
    111111
    112112        CallFrame* pushFrame(class CodeBlock*, JSScope*, int argsCount, JSObject* callee);
     
    168168#endif // ENABLE(LLINT_C_LOOP)
    169169
    170         void enableErrorStackReserve();
    171         void disableErrorStackReserve();
    172 
    173170        VM& m_vm;
    174171        CallFrame*& m_topCallFrame;
     
    176173        Register* m_end;
    177174        Register* m_commitTop;
    178         Register* m_useableTop;
    179175        PageReservation m_reservation;
    180176        Register* m_lastStackTop;
     177        ptrdiff_t m_hostZoneSizeInRegisters;
    181178#endif // ENABLE(LLINT_C_LOOP)
    182179
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStackInlines.h

    r161170 r161575  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4040#else
    4141    ASSERT(wtfThreadData().stack().isGrowingDownward());
    42     return newTopOfStack >= m_vm.jsStackLimit();
     42    return newTopOfStack >= m_vm.stackLimit();
    4343#endif
    4444}
     
    158158        return;
    159159    setStackLimit(newTopOfStack);
    160     if (m_end == baseOfStack() && (highAddress() - m_commitTop) >= maxExcessCapacity)
     160    // Note: Clang complains of an unresolved linkage to maxExcessCapacity if
     161    // invoke std::max() with it as an argument. To work around this, we first
     162    // assign the constant to a local variable, and use the local instead.
     163    ptrdiff_t maxExcessCapacity = JSStack::maxExcessCapacity;
     164    ptrdiff_t maxExcessInRegisters = std::max(maxExcessCapacity, m_hostZoneSizeInRegisters);
     165    if (m_end == baseOfStack() && (highAddress() - m_commitTop) >= maxExcessInRegisters)
    161166        releaseExcessCapacity();
    162167}
  • branches/jsCStack/Source/JavaScriptCore/jit/ExecutableAllocator.h

    r157474 r161575  
    7979static const unsigned jitAllocationGranule = 32;
    8080
    81 inline size_t roundUpAllocationSize(size_t request, size_t granularity)
    82 {
    83     RELEASE_ASSERT((std::numeric_limits<size_t>::max() - granularity) > request);
    84    
    85     // Round up to next page boundary
    86     size_t size = request + (granularity - 1);
    87     size = size & ~(granularity - 1);
    88     ASSERT(size >= request);
    89     return size;
    90 }
    91 
    92 }
    93 
    94 namespace JSC {
    95 
    9681typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle;
    9782
  • branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.cpp

    r160967 r161575  
    3636#include "DFGWorklist.h"
    3737#include "Error.h"
     38#include "ErrorHandlingScope.h"
    3839#include "GetterSetter.h"
    3940#include "HostCallReturnValue.h"
     
    8081
    8182    NativeCallFrameTracer tracer(vm, callerFrame);
    82     Interpreter::ErrorHandlingMode mode(callerFrame);
     83    ErrorHandlingScope errorScope(*vm);
    8384    vm->throwException(callerFrame, createStackOverflowError(callerFrame));
    8485}
  • branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r161409 r161575  
    3434#include "CommonSlowPaths.h"
    3535#include "CommonSlowPathsExceptions.h"
     36#include "ErrorHandlingScope.h"
    3637#include "GetterSetter.h"
    3738#include "HostCallReturnValue.h"
     
    475476    exec = exec->callerFrame();
    476477    vm.topCallFrame = exec;
    477     Interpreter::ErrorHandlingMode mode(exec);
     478    ErrorHandlingScope errorScope(vm);
    478479    CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
    479480    pc = returnToThrowForThrownException(exec);
  • branches/jsCStack/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r161409 r161575  
    122122    checkStackPointerAlignment(temp2, 0xbad0dc01)
    123123
    124     # The jsStackLimit was previously computed in VMEntryScope using an
    125     # estimated stackPointerAtVMEntry value. Adjust the jsStackLimit by
    126     # the delta between the actual stackPointerAtVMEntry and the estimate
    127     # that we used previously.
    128     move sp, temp2
    129     subp VM::stackPointerAtVMEntry[vm], temp2, temp2
    130     subp VM::m_jsStackLimit[vm], temp2, temp2
    131 if C_LOOP
    132 else
    133     bpaeq temp2, VM::m_stackLimit[vm], .noNeedToCapJSStackToNativeStackLimit
    134     loadp VM::m_stackLimit[vm], temp2
    135 .noNeedToCapJSStackToNativeStackLimit:
    136 end
    137     storep temp2, VM::m_jsStackLimit[vm]
    138     move sp, temp2
    139     storep temp2, VM::stackPointerAtVMEntry[vm]
    140 
    141124    # The stack host zone ensures that we have adequate space for the
    142125    # VMEntrySentinelFrame. Proceed with allocating and initializing the
     
    170153    end
    171154
    172     storep 0, VM::stackPointerAtVMEntry[vm]
    173155    cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
    174156    callToJavaScriptEpilogue()
  • branches/jsCStack/Source/JavaScriptCore/parser/ParserError.h

    r160967 r161575  
    2828
    2929#include "Error.h"
     30#include "ErrorHandlingScope.h"
    3031#include "ExceptionHelpers.h"
    3132#include "ParserTokens.h"
     
    9697            return createSyntaxError(globalObject, m_message);
    9798        case StackOverflow: {
    98             Interpreter::ErrorHandlingMode mode(globalObject->globalExec());
     99            ErrorHandlingScope errorScope(globalObject->vm());
    99100            return createStackOverflowError(globalObject);
    100101        }
  • branches/jsCStack/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r161445 r161575  
    3535#include "CodeProfiling.h"
    3636#include "CommonSlowPathsExceptions.h"
     37#include "ErrorHandlingScope.h"
    3738#include "GetterSetter.h"
    3839#include "HostCallReturnValue.h"
     
    186187    if (slotsToAdd < 0) {
    187188        exec = exec->callerFrame();
    188         Interpreter::ErrorHandlingMode mode(exec);
     189        ErrorHandlingScope errorScope(exec->vm());
    189190        CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
    190191        RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
     
    199200    if (slotsToAdd < 0) {
    200201        exec = exec->callerFrame();
    201         Interpreter::ErrorHandlingMode mode(exec);
     202        ErrorHandlingScope errorScope(exec->vm());
    202203        CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
    203204        RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
  • branches/jsCStack/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp

    r155143 r161575  
    3232#include "CodeBlock.h"
    3333#include "CallFrame.h"
     34#include "ErrorHandlingScope.h"
    3435#include "ErrorInstance.h"
    3536#include "JSGlobalObjectFunctions.h"
     
    161162JSObject* throwStackOverflowError(ExecState* exec)
    162163{
    163     Interpreter::ErrorHandlingMode mode(exec);
    164     return exec->vm().throwException(exec, createStackOverflowError(exec));
     164    VM& vm = exec->vm();
     165    ErrorHandlingScope errorScope(vm);
     166    return vm.throwException(exec, createStackOverflowError(exec));
    165167}
    166168
    167169JSObject* throwTerminatedExecutionException(ExecState* exec)
    168170{
    169     Interpreter::ErrorHandlingMode mode(exec);
    170     return exec->vm().throwException(exec, createTerminatedExecutionException(&exec->vm()));
     171    VM& vm = exec->vm();
     172    ErrorHandlingScope errorScope(vm);
     173    return vm.throwException(exec, createTerminatedExecutionException(&vm));
    171174}
    172175
  • branches/jsCStack/Source/JavaScriptCore/runtime/JSLock.cpp

    r157809 r161575  
    291291    SpinLockHolder holder(&spinLock);
    292292#endif
     293    m_savedHostZoneSize = m_vm->hostZoneSize();
     294    m_savedStackPointerAtVMEntry = m_vm->stackPointerAtVMEntry;
     295    m_vm->stackPointerAtVMEntry = nullptr;
     296
    293297    if (alwaysDropLocks)
    294298        m_lockCount = m_vm->apiLock().dropAllLocksUnconditionally(spinLock);
     
    307311    SpinLockHolder holder(&spinLock);
    308312#endif
     313    m_savedHostZoneSize = m_vm->hostZoneSize();
     314    m_savedStackPointerAtVMEntry = m_vm->stackPointerAtVMEntry;
     315    m_vm->stackPointerAtVMEntry = nullptr;
     316
    309317    if (alwaysDropLocks)
    310318        m_lockCount = m_vm->apiLock().dropAllLocksUnconditionally(spinLock);
     
    322330#endif
    323331    m_vm->apiLock().grabAllLocks(m_lockCount, spinLock);
     332
     333    m_vm->stackPointerAtVMEntry = m_savedStackPointerAtVMEntry;
     334    m_vm->updateStackLimitWithHostZoneSize(m_savedHostZoneSize);
    324335}
    325336
  • branches/jsCStack/Source/JavaScriptCore/runtime/JSLock.h

    r161372 r161575  
    111111            intptr_t m_lockCount;
    112112            RefPtr<VM> m_vm;
     113            size_t m_savedHostZoneSize;
     114            void* m_savedStackPointerAtVMEntry;
    113115        };
    114116
  • branches/jsCStack/Source/JavaScriptCore/runtime/Options.h

    r161515 r161575  
    9696    v(bool, useRegExpJIT, true) \
    9797    \
    98     v(unsigned, maxStackSize, 4 * MB) \
     98    v(unsigned, maxPerThreadStackUsage, 4 * MB) \
     99    v(unsigned, hostZoneSize, 128 * KB) \
     100    v(unsigned, errorModeHostZoneSize, 64 * KB) \
    99101    \
    100102    v(bool, crashIfCantAllocateJITMemory, false) \
  • branches/jsCStack/Source/JavaScriptCore/runtime/VM.cpp

    r161219 r161575  
    201201    , jsFinalObjectClassInfo(JSFinalObject::info())
    202202    , sizeOfLastScratchBuffer(0)
    203     , firstEntryScope(0)
    204     , topEntryScope(0)
     203    , entryScope(0)
    205204    , m_enabledProfiler(0)
    206205    , m_regExpCache(new RegExpCache(this))
     
    231230    interpreter = new Interpreter(*this);
    232231    StackBounds stack = wtfThreadData().stack();
    233     setStackLimit(stack.recursionLimit());
     232    updateStackLimitWithHostZoneSize(Options::hostZoneSize());
     233#if ENABLE(LLINT_C_LOOP)
     234    interpreter->stack().setHostZoneSize(Options::hostZoneSize());
     235#endif
    234236    setLastStackTop(stack.origin());
    235237
     
    554556    prepareToDiscardCode();
    555557   
    556     if (firstEntryScope) {
     558    if (entryScope) {
    557559        StackPreservingRecompiler recompiler;
    558560        HeapIterationScope iterationScope(heap);
     
    714716}
    715717
     718size_t VM::updateStackLimitWithHostZoneSize(size_t hostZoneSize)
     719{
     720    size_t oldHostZoneSize = m_hostZoneSize;
     721    m_hostZoneSize = hostZoneSize;
     722
     723    void* stackLimit;
     724    if (stackPointerAtVMEntry) {
     725        ASSERT(wtfThreadData().stack().isGrowingDownward());
     726        char* startOfStack = reinterpret_cast<char*>(stackPointerAtVMEntry);
     727        char* desiredStackLimit = startOfStack - Options::maxPerThreadStackUsage() + hostZoneSize;
     728        stackLimit = wtfThreadData().stack().recursionLimit(hostZoneSize, desiredStackLimit);
     729    } else
     730        stackLimit = wtfThreadData().stack().recursionLimit(hostZoneSize);
     731
     732    setStackLimit(stackLimit);
     733    return oldHostZoneSize;
     734}
     735
    716736void releaseExecutableMemory(VM& vm)
    717737{
  • branches/jsCStack/Source/JavaScriptCore/runtime/VM.h

    r161180 r161575  
    376376        JS_EXPORT_PRIVATE JSObject* throwException(ExecState*, JSObject*);
    377377       
     378        size_t hostZoneSize() const { return m_hostZoneSize; }
     379        size_t updateStackLimitWithHostZoneSize(size_t hostZoneSize);
     380
    378381        void** addressOfJSStackLimit() { return &m_jsStackLimit; }
     382#if ENABLE(LLINT_C_LOOP)
    379383        void* jsStackLimit() { return m_jsStackLimit; }
    380384        void setJSStackLimit(void* limit) { m_jsStackLimit = limit; }
    381 
     385#endif
    382386        void* stackLimit() { return m_stackLimit; }
    383         void setStackLimit(void* limit) { m_stackLimit = limit; }
     387
    384388        bool isSafeToRecurse(size_t neededStackInBytes = 0) const
    385389        {
     
    428432        void gatherConservativeRoots(ConservativeRoots&);
    429433
    430         VMEntryScope* firstEntryScope;
    431         VMEntryScope* topEntryScope;
     434        VMEntryScope* entryScope;
    432435
    433436        HashSet<JSObject*> stringRecursionCheckVisitedObjects;
     
    496499        static VM*& sharedInstanceInternal();
    497500        void createNativeThunk();
     501
     502        void setStackLimit(void* limit) { m_stackLimit = limit; }
     503
    498504#if ENABLE(ASSEMBLER)
    499505        bool m_canUseAssembler;
     
    508514        const ClassInfo* m_initializingObjectClass;
    509515#endif
    510         void* m_stackLimit;
    511         void* m_jsStackLimit;
     516        size_t m_hostZoneSize;
     517#if ENABLE(LLINT_C_LOOP)
     518        struct {
     519            void* m_stackLimit;
     520            void* m_jsStackLimit;
     521        };
     522#else
     523        union {
     524            void* m_stackLimit;
     525            void* m_jsStackLimit;
     526        };
     527#endif
    512528        void* m_lastStackTop;
    513529        JSValue m_exception;
  • branches/jsCStack/Source/JavaScriptCore/runtime/VMEntryScope.cpp

    r161369 r161575  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535VMEntryScope::VMEntryScope(VM& vm, JSGlobalObject* globalObject)
    3636    : m_vm(vm)
    37     , m_stack(wtfThreadData().stack())
    3837    , m_globalObject(globalObject)
    39     , m_prevStackUsage(0)
    40     , m_prevTopEntryScope(vm.topEntryScope)
    41     , m_prevStackLimit(vm.stackLimit())
    42 #if !ENABLE(LLINT_C_LOOP)
    43     , m_prevJSStackLimit(vm.jsStackLimit())
    44 #endif
    45     , m_prevLastStackTop(vm.lastStackTop())
    46     , m_prevStackPointerAtVMEntry(vm.stackPointerAtVMEntry)
    47     , m_prevTopCallFrame(vm.topCallFrame)
    4838{
    4939    ASSERT(wtfThreadData().stack().isGrowingDownward());
    50     ASSERT(!vm.topCallFrame || currentStackPointer() <= reinterpret_cast<char*>(vm.topCallFrame->topOfFrame()));
    51 
    52     // Step 1: Compute the stack usage of the last VM entry before we install
    53     // the current entry scope below.
    54     if (vm.topEntryScope) {
    55         char* topOfStack = reinterpret_cast<char*>(vm.topCallFrame->topOfFrame());
    56         m_prevStackUsage = vm.topEntryScope->stackUsageFor(topOfStack);
    57     }
    58 
    59     // Step 2: Install the current entry scope.
    60     if (!vm.firstEntryScope) {
     40    if (!vm.entryScope) {
    6141#if ENABLE(ASSEMBLER)
    6242        if (ExecutableAllocator::underMemoryPressure())
    6343            vm.heap.deleteAllCompiledCode();
    6444#endif
    65         vm.firstEntryScope = this;
     45        vm.entryScope = this;
    6646
    6747        // Reset the date cache between JS invocations to force the VM to
     
    6949        vm.resetDateCache();
    7050    }
    71     vm.stackPointerAtVMEntry = 0;
    72     vm.topEntryScope = this;
     51
     52    if (!vm.stackPointerAtVMEntry) {
     53        vm.stackPointerAtVMEntry = this;
     54        m_savedHostZoneSize = vm.updateStackLimitWithHostZoneSize(Options::hostZoneSize());
     55    }
    7356
    7457    // Clear the captured exception stack between entries
    7558    vm.clearExceptionStack();
    76 
    77     vm.setLastStackTop(m_stack.origin());
    78 
    79     // Step 3: Compute the stack limit using the installed entry scope.
    80     updateStackLimits();
    8159}
    8260
    8361VMEntryScope::~VMEntryScope()
    8462{
    85     if (m_vm.firstEntryScope == this)
    86         m_vm.firstEntryScope = nullptr;
    87     m_vm.topEntryScope = m_prevTopEntryScope;
    88     m_vm.setStackLimit(m_prevStackLimit);
    89 #if !ENABLE(LLINT_C_LOOP)
    90     m_vm.setJSStackLimit(m_prevJSStackLimit);
    91 #endif
    92     m_vm.setLastStackTop(m_prevLastStackTop);
    93     m_vm.stackPointerAtVMEntry = m_prevStackPointerAtVMEntry;
    94     m_vm.topCallFrame = m_prevTopCallFrame;
    95 }
    96 
    97 size_t VMEntryScope::stackUsageFor(char* topOfStack) const
    98 {
    99     size_t currentStackUsage = 0;
    100     ASSERT(m_vm.stackPointerAtVMEntry);
    101     char* startOfStack = reinterpret_cast<char*>(m_vm.stackPointerAtVMEntry);
    102     ASSERT(topOfStack <= startOfStack);
    103     currentStackUsage = startOfStack - topOfStack;
    104 
    105     ASSERT(Options::maxStackSize() >= m_prevStackUsage + currentStackUsage);
    106     return m_prevStackUsage + currentStackUsage;
    107 }
    108 
    109 void VMEntryScope::updateStackLimits()
    110 {
    111     ASSERT(wtfThreadData().stack().isGrowingDownward());
    112     char* topOfStack = currentStackPointer();
    113 
    114 #if !ENABLE(LLINT_C_LOOP)
    115     char* topOfJSStack = m_vm.topCallFrame ? reinterpret_cast<char*>(m_vm.topCallFrame->topOfFrame()) : topOfStack;
    116 
    117     // If we have not re-entered the VM yet via callToJavaScript / callToNativeFunction,
    118     // then stackPointerAtVMEntry will not have been set up yet. Instead, we'll
    119     // compute the stack limit relative to the current topOfJSStack (as an estimate
    120     // of stackPointerAtVMEntry). When we enter callToJavaScript later, we'll adjust
    121     // the stack limit with the delta between the actual stackPointerAtVMEntry and
    122     // the estimate value that we use here.
    123     if (!m_vm.stackPointerAtVMEntry)
    124         m_vm.stackPointerAtVMEntry = topOfJSStack;
    125 
    126     void* jsStackLimit = m_stack.recursionLimit(requiredCapacity(topOfJSStack, JSStackCapacity));
    127 #ifndef NDEBUG
    128     char* startOfStack = reinterpret_cast<char*>(m_vm.stackPointerAtVMEntry);
    129     char* stackLimit = reinterpret_cast<char*>(jsStackLimit);
    130     ASSERT(m_prevStackUsage + (startOfStack - stackLimit) <= Options::maxStackSize());
    131 #endif
    132     m_vm.setJSStackLimit(jsStackLimit);
    133 
    134     // Some sanity checks for our pointers into the stack:
    135     ASSERT(m_vm.interpreter->stack().containsAddress(reinterpret_cast<Register*>(m_vm.stackPointerAtVMEntry)));
    136     ASSERT(m_vm.interpreter->stack().containsAddress(reinterpret_cast<Register*>(topOfJSStack)));
    137     ASSERT(currentStackPointer() <= topOfJSStack);
    138     ASSERT(topOfJSStack <= m_vm.stackPointerAtVMEntry);
    139 #endif // !ENABLE(LLINT_C_LOOP)
    140 
    141     void* nativeStackLimit = m_stack.recursionLimit(requiredCapacity(topOfStack, NativeStackCapacity));
    142     m_vm.setStackLimit(nativeStackLimit);
    143 }
    144 
    145 char* VMEntryScope::currentStackPointer() const
    146 {
    147     char* p;
    148 #if ENABLE(LLINT_C_LOOP)
    149     p = reinterpret_cast<char*>(m_vm.topCallFrame->topOfFrame());
    150 #else
    151     p = reinterpret_cast<char*>(&p);
    152 #endif
    153     return p;
    154 }
    155 
    156 size_t VMEntryScope::requiredCapacity(char* topOfStack, CapacityType type) const
    157 {
    158     ASSERT(m_stack.isGrowingDownward());
    159 
    160     size_t excessCStackSize = 0;
    161 #if !ENABLE(LLINT_C_LOOP)
    162     if (type == JSStackCapacity) {
    163         ASSERT(Options::maxStackSize() >= stackUsageFor(topOfStack));
    164         size_t availableJSStack = Options::maxStackSize() - stackUsageFor(topOfStack);
    165 
    166         char* bottomOfStack = reinterpret_cast<char*>(m_stack.origin());
    167         size_t availableCStack = m_stack.size() - (bottomOfStack - topOfStack);
    168         if (availableCStack > availableJSStack)
    169             excessCStackSize = availableCStack - availableJSStack;
     63    if (m_vm.entryScope == this)
     64        m_vm.entryScope = nullptr;
     65    if (m_vm.stackPointerAtVMEntry == this) {
     66        m_vm.stackPointerAtVMEntry = nullptr;
     67        m_vm.updateStackLimitWithHostZoneSize(m_savedHostZoneSize);
    17068    }
    171 #else
    172     UNUSED_PARAM(topOfStack);
    173     UNUSED_PARAM(type);
    174     ASSERT(type == NativeStackCapacity);
    175 #endif
    176 
    177     // We require a smaller stack budget for the error stack. This is to allow
    178     // some minimal JS execution to proceed and do the work of throwing a stack
    179     // overflow error if needed. In contrast, arbitrary JS code will require the
    180     // more generous stack budget in order to proceed.
    181     //
    182     // These sizes were derived from the stack usage of a number of sites when
    183     // layout occurs when we've already consumed most of the C stack.
    184     const size_t requiredStack = 128 * KB;
    185     const size_t errorModeRequiredStack = 64 * KB;
    186 
    187     Interpreter* interpreter = m_vm.interpreter;
    188     size_t requiredCapacity = interpreter->isInErrorHandlingMode() ? errorModeRequiredStack : requiredStack;
    189     requiredCapacity += excessCStackSize;
    190 
    191     RELEASE_ASSERT(m_stack.size() >= requiredCapacity);
    192     return requiredCapacity;
    19369}
    19470
    19571} // namespace JSC
    196 
  • branches/jsCStack/Source/JavaScriptCore/runtime/VMEntryScope.h

    r161369 r161575  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4141    JS_EXPORT_PRIVATE ~VMEntryScope();
    4242
    43     void updateStackLimits();
    4443    JSGlobalObject* globalObject() const { return m_globalObject; }
    4544
    4645private:
    47     enum CapacityType {
    48         JSStackCapacity,
    49         NativeStackCapacity,
    50     };
    51     size_t requiredCapacity(char* topOfStack, CapacityType) const;
    52     char* currentStackPointer() const;
    53     size_t stackUsageFor(char* topOfStack) const;
    54 
    5546    VM& m_vm;
    5647    StackStats::CheckPoint m_stackCheckPoint;
    57     StackBounds m_stack;
    5848    JSGlobalObject* m_globalObject;
    59     size_t m_prevStackUsage;
    60 
    61     // The following pointers may point to a different thread's stack.
    62     VMEntryScope* m_prevTopEntryScope;
    63     void* m_prevStackLimit;
    64 #if !ENABLE(LLINT_C_LOOP)
    65     void* m_prevJSStackLimit;
    66 #endif
    67     void* m_prevLastStackTop;
    68     void* m_prevStackPointerAtVMEntry;
    69     ExecState* m_prevTopCallFrame;
     49    size_t m_savedHostZoneSize;
    7050};
    7151
  • branches/jsCStack/Source/WTF/ChangeLog

    r161409 r161575  
     12014-01-09  Mark Lam  <mark.lam@apple.com>
     2
     3        CStack: Need a separate stack limit for the JS stack and the C stack.
     4        https://bugs.webkit.org/show_bug.cgi?id=126320.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * wtf/StackBounds.h:
     9        (WTF::StackBounds::recursionLimit):
     10        - Previously, StackBounds::recursionLimit() only takes a host zone size
     11          which it uses to compute the client's desired stack limit. Now, there's
     12          an alternate version that also allows the client to explicitly specify
     13          its desired stack limit in addition to its hostZoneSize requirement.
     14          In both cases, StackBounds::recursionLimit() will cap the limit (with
     15          allowance for the hostZoneSize) to be within its bounds, and return the
     16          capped limit.
     17
    1182014-01-06  Filip Pizlo  <fpizlo@apple.com>
    219
  • branches/jsCStack/Source/WTF/wtf/StackBounds.h

    r159605 r161575  
    2727#ifndef StackBounds_h
    2828#define StackBounds_h
     29
     30#include <algorithm>
    2931
    3032namespace WTF {
     
    6668            return static_cast<char*>(m_bound) + minAvailableDelta;
    6769        return static_cast<char*>(m_bound) - minAvailableDelta;
     70    }
     71
     72    void* recursionLimit(size_t hostZoneSize, void* desiredLimit) const
     73    {
     74        checkConsistency();
     75        if (isGrowingDownward()) {
     76            char* endOfStackWithHostZone = reinterpret_cast<char*>(m_bound) + hostZoneSize;
     77            return std::max(desiredLimit, reinterpret_cast<void*>(endOfStackWithHostZone));
     78        }
     79        char* endOfStackWithHostZone = reinterpret_cast<char*>(m_bound) - hostZoneSize;
     80        return std::min(desiredLimit, reinterpret_cast<void*>(endOfStackWithHostZone));
    6881    }
    6982
  • branches/jsCStack/Source/WebCore/ChangeLog

    r160228 r161575  
     12014-01-09  Mark Lam  <mark.lam@apple.com>
     2
     3        CStack: Need a separate stack limit for the JS stack and the C stack.
     4        https://bugs.webkit.org/show_bug.cgi?id=126320.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        No new tests.
     9
     10        * ForwardingHeaders/runtime/ErrorHandlingScope.h: Added.
     11        * WebCore.vcxproj/WebCore.vcxproj:
     12        * WebCore.vcxproj/WebCore.vcxproj.filters:
     13        * bindings/js/JSDOMBinding.cpp:
     14        (WebCore::reportException):
     15        - Updated to use ErrorHandlingScope instead of Interpreter::ErrorHandlingMode.
     16
    1172013-12-06  Laszlo Vidacs  <lac@inf.u-szeged.hu>
    218
  • branches/jsCStack/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj

    r160152 r161575  
    1859218592    <ClInclude Include="..\ForwardingHeaders\runtime\DateInstance.h" />
    1859318593    <ClInclude Include="..\ForwardingHeaders\runtime\Error.h" />
     18594    <ClInclude Include="..\ForwardingHeaders\runtime\ErrorHandlingScope.h" />
    1859418595    <ClInclude Include="..\ForwardingHeaders\runtime\ErrorPrototype.h" />
    1859518596    <ClInclude Include="..\ForwardingHeaders\runtime\ExceptionHelpers.h" />
  • branches/jsCStack/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters

    r160152 r161575  
    1263512635      <Filter>ForwardingHeaders\runtime</Filter>
    1263612636    </ClInclude>
     12637    <ClInclude Include="..\ForwardingHeaders\runtime\ErrorHandlingScope.h">
     12638      <Filter>ForwardingHeaders\runtime</Filter>
     12639    </ClInclude>
    1263712640    <ClInclude Include="..\ForwardingHeaders\runtime\ErrorPrototype.h">
    1263812641      <Filter>ForwardingHeaders\runtime</Filter>
  • branches/jsCStack/Source/WebCore/bindings/js/JSDOMBinding.cpp

    r160208 r161575  
    4040#include <runtime/DateInstance.h>
    4141#include <runtime/Error.h>
     42#include <runtime/ErrorHandlingScope.h>
    4243#include <runtime/ExceptionHelpers.h>
    4344#include <runtime/JSFunction.h>
     
    150151        return;
    151152
    152     Interpreter::ErrorHandlingMode mode(exec);
     153    ErrorHandlingScope errorScope(exec->vm());
    153154
    154155    RefPtr<ScriptCallStack> callStack(createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture));
Note: See TracChangeset for help on using the changeset viewer.