Changeset 161575 in webkit
- Timestamp:
- Jan 9, 2014, 1:10:46 PM (11 years ago)
- Location:
- branches/jsCStack
- Files:
-
- 3 added
- 38 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/jsCStack/LayoutTests/ChangeLog
r161409 r161575 1 2014-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 1 14 2014-01-06 Filip Pizlo <fpizlo@apple.com> 2 15 -
branches/jsCStack/LayoutTests/js/large-expressions-expected.txt
r75408 r161575 6 6 PASS eval(repeatedExpression("letterA", "+", 100)) is repeatedString("a", 100) 7 7 PASS eval(repeatedExpression("letterA", "+", 1000)) is repeatedString("a", 1000) 8 PASS eval(repeatedExpression("letterA", "+", 10000)) is repeatedString("a", 10000)8 PASS eval(repeatedExpression("letterA", "+", 10000)) threw exception Error: Out of memory. 9 9 PASS eval(repeatedExpression("letterA", "+", 100000)) threw exception Error: Out of memory. 10 10 PASS successfullyParsed is true -
branches/jsCStack/LayoutTests/js/script-tests/large-expressions.js
r156976 r161575 31 31 shouldBe('eval(repeatedExpression("letterA", "+", 100))', 'repeatedString("a", 100)'); 32 32 shouldBe('eval(repeatedExpression("letterA", "+", 1000))', 'repeatedString("a", 1000)'); 33 should Be('eval(repeatedExpression("letterA", "+", 10000))', 'repeatedString("a", 10000)');33 shouldThrow('eval(repeatedExpression("letterA", "+", 10000))'); 34 34 shouldThrow('eval(repeatedExpression("letterA", "+", 100000))'); -
branches/jsCStack/Source/JavaScriptCore/CMakeLists.txt
r161409 r161575 312 312 runtime/Error.cpp 313 313 runtime/ErrorConstructor.cpp 314 runtime/ErrorHandlingScope.cpp 314 315 runtime/ErrorInstance.cpp 315 316 runtime/ErrorPrototype.cpp -
branches/jsCStack/Source/JavaScriptCore/ChangeLog
r161547 r161575 1 2014-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 1 171 2014-01-08 Filip Pizlo <fpizlo@apple.com> 2 172 … … 399 569 400 570 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. 401 572 402 573 In doCallToJavaScript, we fixup VM::m_jsStackLimit once we know what the … … 716 887 https://bugs.webkit.org/show_bug.cgi?id=126320. 717 888 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. 719 891 720 892 With this patch, we now accurately track how much JS stack space the … … 803 975 Not yet reviewed. 804 976 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 805 981 * heap/ConservativeRoots.cpp: 806 982 (JSC::ConservativeRoots::genericAddSpan): … … 812 988 813 989 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. 814 991 815 992 When we start measuring the stack usage of each VMEntryScope, we'll need … … 841 1018 https://bugs.webkit.org/show_bug.cgi?id=126331. 842 1019 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. 844 1022 845 1023 Previously, when using the C stack for the JS stack, VM::m_jsStackLimit is a union … … 876 1054 877 1055 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. 878 1057 879 1058 We need an option to limit the JS stack size. Currently, we just change … … 906 1085 https://bugs.webkit.org/show_bug.cgi?id=126266. 907 1086 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. 909 1089 910 1090 This patch is so that we can distinguish firstEntryScope from topEntryScope -
branches/jsCStack/Source/JavaScriptCore/GNUmakefile.list.am
r161409 r161575 852 852 Source/JavaScriptCore/runtime/Error.cpp \ 853 853 Source/JavaScriptCore/runtime/Error.h \ 854 Source/JavaScriptCore/runtime/ErrorHandlingScope.cpp \ 855 Source/JavaScriptCore/runtime/ErrorHandlingScope.h \ 854 856 Source/JavaScriptCore/runtime/ErrorInstance.cpp \ 855 857 Source/JavaScriptCore/runtime/ErrorInstance.h \ -
branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r161409 r161575 554 554 <ClCompile Include="..\runtime\Error.cpp" /> 555 555 <ClCompile Include="..\runtime\ErrorConstructor.cpp" /> 556 <ClCompile Include="..\runtime\ErrorHandlingScope.cpp" /> 556 557 <ClCompile Include="..\runtime\ErrorInstance.cpp" /> 557 558 <ClCompile Include="..\runtime\ErrorPrototype.cpp" /> … … 1134 1135 <ClInclude Include="..\runtime\Error.h" /> 1135 1136 <ClInclude Include="..\runtime\ErrorConstructor.h" /> 1137 <ClInclude Include="..\runtime\ErrorHandlingScope.h" /> 1136 1138 <ClInclude Include="..\runtime\ErrorInstance.h" /> 1137 1139 <ClInclude Include="..\runtime\ErrorPrototype.h" /> -
branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
r160519 r161575 508 508 <Filter>runtime</Filter> 509 509 </ClCompile> 510 <ClCompile Include="..\runtime\ErrorHandlingScope.cpp"> 511 <Filter>runtime</Filter> 512 </ClCompile> 510 513 <ClCompile Include="..\runtime\ErrorInstance.cpp"> 511 514 <Filter>runtime</Filter> … … 2035 2038 </ClInclude> 2036 2039 <ClInclude Include="..\runtime\ErrorConstructor.h"> 2040 <Filter>runtime</Filter> 2041 </ClInclude> 2042 <ClInclude Include="..\runtime\ErrorHandlingScope.h"> 2037 2043 <Filter>runtime</Filter> 2038 2044 </ClInclude> -
branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r161543 r161575 1284 1284 FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1285 1285 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, ); }; }; 1286 1288 FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = FED287B115EC9A5700DA8161 /* LLIntOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1287 1289 FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */; }; … … 2656 2658 FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = "<group>"; }; 2657 2659 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>"; }; 2658 2662 FED287B115EC9A5700DA8161 /* LLIntOpcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOpcode.h; path = llint/LLIntOpcode.h; sourceTree = "<group>"; }; 2659 2663 FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Watchdog.cpp; sourceTree = "<group>"; }; … … 3493 3497 BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */, 3494 3498 BC02E9050E1839DB000F9297 /* ErrorConstructor.h */, 3499 FEB58C12187B8B160098EF0B /* ErrorHandlingScope.cpp */, 3500 FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */, 3495 3501 BC02E98A0E183E38000F9297 /* ErrorInstance.cpp */, 3496 3502 BC02E98B0E183E38000F9297 /* ErrorInstance.h */, … … 4326 4332 FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */, 4327 4333 0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */, 4334 FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */, 4328 4335 A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */, 4329 4336 C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */, … … 5502 5509 A7D9A29417A0BC7400EE2618 /* DFGAtTailAbstractState.cpp in Sources */, 5503 5510 0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */, 5511 FEB58C14187B8B160098EF0B /* ErrorHandlingScope.cpp in Sources */, 5504 5512 A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */, 5505 5513 A70B083217A0B79B00DAF14B /* DFGBinarySwitch.cpp in Sources */, -
branches/jsCStack/Source/JavaScriptCore/debugger/Debugger.cpp
r161104 r161575 35 35 #include "Parser.h" 36 36 #include "Protect.h" 37 #include "VMEntryScope.h"38 37 39 38 namespace { … … 197 196 // If JavaScript is running, it's not safe to recompile, since we'll end 198 197 // 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) 201 200 return; 202 201 -
branches/jsCStack/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
r159605 r161575 36 36 #include "Parser.h" 37 37 #include "StackVisitor.h" 38 #include "VMEntryScope.h"39 38 40 39 namespace JSC { -
branches/jsCStack/Source/JavaScriptCore/heap/Heap.cpp
r161104 r161575 292 292 void Heap::lastChanceToFinalize() 293 293 { 294 RELEASE_ASSERT(!m_vm-> firstEntryScope);294 RELEASE_ASSERT(!m_vm->entryScope); 295 295 RELEASE_ASSERT(m_operationInProgress == NoOperation); 296 296 … … 696 696 // If JavaScript is running, it's not safe to delete code, since we'll end 697 697 // up deleting code that is live on the stack. 698 if (m_vm-> firstEntryScope)698 if (m_vm->entryScope) 699 699 return; 700 700 -
branches/jsCStack/Source/JavaScriptCore/interpreter/CallFrame.cpp
r161104 r161575 131 131 // For any ExecState that's not a globalExec, the 132 132 // 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(); 135 135 } 136 136 -
branches/jsCStack/Source/JavaScriptCore/interpreter/Interpreter.cpp
r161229 r161575 91 91 92 92 namespace 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 }108 93 109 94 JSValue eval(CallFrame* callFrame) -
branches/jsCStack/Source/JavaScriptCore/interpreter/Interpreter.h
r160831 r161575 191 191 192 192 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 201 193 Interpreter(VM &); 202 194 ~Interpreter(); … … 238 230 SamplingTool* sampler() { return m_sampler.get(); } 239 231 240 bool isInErrorHandlingMode() { return m_errorHandlingModeReentry; }241 242 232 NEVER_INLINE HandlerInfo* unwind(CallFrame*&, JSValue&); 243 233 NEVER_INLINE void debug(CallFrame*, DebugHookID); -
branches/jsCStack/Source/JavaScriptCore/interpreter/JSStack.cpp
r161174 r161575 1 1 /* 2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 32 32 #include "ConservativeRoots.h" 33 33 #include "Interpreter.h" 34 #include " VMEntryScope.h"34 #include "Options.h" 35 35 36 36 namespace JSC { … … 51 51 #if ENABLE(LLINT_C_LOOP) 52 52 , m_end(0) 53 , m_hostZoneSizeInRegisters(0) 53 54 #endif 54 55 { 55 56 #if ENABLE(LLINT_C_LOOP) 56 size_t capacity = Options::max StackSize();57 size_t capacity = Options::maxPerThreadStackUsage(); 57 58 ASSERT(capacity && isPageAligned(capacity)); 58 59 59 m_reservation = PageReservation::reserve( roundUpAllocationSize(capacity, commitSize), OSAllocator::JSVMStackPages);60 m_reservation = PageReservation::reserve(WTF::roundUpToMultipleOf(commitSize, capacity), OSAllocator::JSVMStackPages); 60 61 setStackLimit(highAddress()); 61 62 m_commitTop = highAddress(); 62 63 63 64 m_lastStackTop = baseOfStack(); 64 65 disableErrorStackReserve();66 65 #endif // ENABLE(LLINT_C_LOOP) 67 66 … … 72 71 JSStack::~JSStack() 73 72 { 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); 77 76 m_reservation.deallocate(); 78 77 } … … 80 79 bool JSStack::growSlowCase(Register* newTopOfStack) 81 80 { 81 Register* newTopOfStackWithHostZone = newTopOfStack - m_hostZoneSizeInRegisters; 82 82 83 // If we have already committed enough memory to satisfy this request, 83 84 // just update the end pointer and return. 84 if (newTopOfStack >= m_commitTop) {85 if (newTopOfStackWithHostZone >= m_commitTop) { 85 86 setStackLimit(newTopOfStack); 86 87 return true; … … 90 91 // have it is still within our budget. If not, we'll fail to grow and 91 92 // 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()) 94 97 return false; 95 98 96 99 // Otherwise, the growth is still within our budget. Go ahead and commit 97 100 // it and return true. 98 m_reservation.commit( reinterpret_cast<char*>(m_commitTop) - delta, delta);101 m_reservation.commit(newCommitTop, delta); 99 102 addToCommittedByteCount(delta); 100 m_commitTop = reinterpret_cast_ptr<Register*>(reinterpret_cast<char*>(m_commitTop) - delta);103 m_commitTop = newCommitTop; 101 104 setStackLimit(newTopOfStack); 102 105 return true; … … 128 131 void JSStack::releaseExcessCapacity() 129 132 { 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); 131 135 m_reservation.decommit(m_commitTop, delta); 132 136 addToCommittedByteCount(-delta); 133 m_commitTop = highAddress ();137 m_commitTop = highAddressWithHostZone; 134 138 } 135 139 … … 146 150 } 147 151 148 void JSStack:: enableErrorStackReserve()152 void JSStack::setHostZoneSize(size_t hostZoneSize) 149 153 { 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); 167 157 } 168 158 #endif // ENABLE(LLINT_C_LOOP) … … 172 162 { 173 163 ASSERT(wtfThreadData().stack().isGrowingDownward()); 174 return reinterpret_cast<Register*>(m_vm. jsStackLimit());164 return reinterpret_cast<Register*>(m_vm.stackLimit()); 175 165 } 176 166 … … 197 187 } 198 188 199 void JSStack::updateStackLimit()200 {201 #if ENABLE(LLINT_C_LOOP)202 if (m_vm.interpreter->isInErrorHandlingMode())203 enableErrorStackReserve();204 else205 disableErrorStackReserve();206 #endif207 if (m_vm.topEntryScope)208 m_vm.topEntryScope->updateStackLimits();209 }210 211 189 } // namespace JSC -
branches/jsCStack/Source/JavaScriptCore/interpreter/JSStack.h
r161170 r161575 1 1 /* 2 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 84 84 bool ensureCapacityFor(Register* newTopOfStack); 85 85 86 void updateStackLimit();87 88 86 bool containsAddress(Register* address) { return (lowAddress() <= address && address < highAddress()); } 89 87 static size_t committedByteCount(); … … 109 107 110 108 static void initializeThreading(); 109 110 void setHostZoneSize(size_t); 111 111 112 112 CallFrame* pushFrame(class CodeBlock*, JSScope*, int argsCount, JSObject* callee); … … 168 168 #endif // ENABLE(LLINT_C_LOOP) 169 169 170 void enableErrorStackReserve();171 void disableErrorStackReserve();172 173 170 VM& m_vm; 174 171 CallFrame*& m_topCallFrame; … … 176 173 Register* m_end; 177 174 Register* m_commitTop; 178 Register* m_useableTop;179 175 PageReservation m_reservation; 180 176 Register* m_lastStackTop; 177 ptrdiff_t m_hostZoneSizeInRegisters; 181 178 #endif // ENABLE(LLINT_C_LOOP) 182 179 -
branches/jsCStack/Source/JavaScriptCore/interpreter/JSStackInlines.h
r161170 r161575 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 40 40 #else 41 41 ASSERT(wtfThreadData().stack().isGrowingDownward()); 42 return newTopOfStack >= m_vm. jsStackLimit();42 return newTopOfStack >= m_vm.stackLimit(); 43 43 #endif 44 44 } … … 158 158 return; 159 159 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) 161 166 releaseExcessCapacity(); 162 167 } -
branches/jsCStack/Source/JavaScriptCore/jit/ExecutableAllocator.h
r157474 r161575 79 79 static const unsigned jitAllocationGranule = 32; 80 80 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 boundary86 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 96 81 typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle; 97 82 -
branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.cpp
r160967 r161575 36 36 #include "DFGWorklist.h" 37 37 #include "Error.h" 38 #include "ErrorHandlingScope.h" 38 39 #include "GetterSetter.h" 39 40 #include "HostCallReturnValue.h" … … 80 81 81 82 NativeCallFrameTracer tracer(vm, callerFrame); 82 Interpreter::ErrorHandlingMode mode(callerFrame);83 ErrorHandlingScope errorScope(*vm); 83 84 vm->throwException(callerFrame, createStackOverflowError(callerFrame)); 84 85 } -
branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r161409 r161575 34 34 #include "CommonSlowPaths.h" 35 35 #include "CommonSlowPathsExceptions.h" 36 #include "ErrorHandlingScope.h" 36 37 #include "GetterSetter.h" 37 38 #include "HostCallReturnValue.h" … … 475 476 exec = exec->callerFrame(); 476 477 vm.topCallFrame = exec; 477 Interpreter::ErrorHandlingMode mode(exec);478 ErrorHandlingScope errorScope(vm); 478 479 CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec)); 479 480 pc = returnToThrowForThrownException(exec); -
branches/jsCStack/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r161409 r161575 122 122 checkStackPointerAlignment(temp2, 0xbad0dc01) 123 123 124 # The jsStackLimit was previously computed in VMEntryScope using an125 # estimated stackPointerAtVMEntry value. Adjust the jsStackLimit by126 # the delta between the actual stackPointerAtVMEntry and the estimate127 # that we used previously.128 move sp, temp2129 subp VM::stackPointerAtVMEntry[vm], temp2, temp2130 subp VM::m_jsStackLimit[vm], temp2, temp2131 if C_LOOP132 else133 bpaeq temp2, VM::m_stackLimit[vm], .noNeedToCapJSStackToNativeStackLimit134 loadp VM::m_stackLimit[vm], temp2135 .noNeedToCapJSStackToNativeStackLimit:136 end137 storep temp2, VM::m_jsStackLimit[vm]138 move sp, temp2139 storep temp2, VM::stackPointerAtVMEntry[vm]140 141 124 # The stack host zone ensures that we have adequate space for the 142 125 # VMEntrySentinelFrame. Proceed with allocating and initializing the … … 170 153 end 171 154 172 storep 0, VM::stackPointerAtVMEntry[vm]173 155 cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame) 174 156 callToJavaScriptEpilogue() -
branches/jsCStack/Source/JavaScriptCore/parser/ParserError.h
r160967 r161575 28 28 29 29 #include "Error.h" 30 #include "ErrorHandlingScope.h" 30 31 #include "ExceptionHelpers.h" 31 32 #include "ParserTokens.h" … … 96 97 return createSyntaxError(globalObject, m_message); 97 98 case StackOverflow: { 98 Interpreter::ErrorHandlingMode mode(globalObject->globalExec());99 ErrorHandlingScope errorScope(globalObject->vm()); 99 100 return createStackOverflowError(globalObject); 100 101 } -
branches/jsCStack/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r161445 r161575 35 35 #include "CodeProfiling.h" 36 36 #include "CommonSlowPathsExceptions.h" 37 #include "ErrorHandlingScope.h" 37 38 #include "GetterSetter.h" 38 39 #include "HostCallReturnValue.h" … … 186 187 if (slotsToAdd < 0) { 187 188 exec = exec->callerFrame(); 188 Interpreter::ErrorHandlingMode mode(exec);189 ErrorHandlingScope errorScope(exec->vm()); 189 190 CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec)); 190 191 RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec); … … 199 200 if (slotsToAdd < 0) { 200 201 exec = exec->callerFrame(); 201 Interpreter::ErrorHandlingMode mode(exec);202 ErrorHandlingScope errorScope(exec->vm()); 202 203 CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec)); 203 204 RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec); -
branches/jsCStack/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
r155143 r161575 32 32 #include "CodeBlock.h" 33 33 #include "CallFrame.h" 34 #include "ErrorHandlingScope.h" 34 35 #include "ErrorInstance.h" 35 36 #include "JSGlobalObjectFunctions.h" … … 161 162 JSObject* throwStackOverflowError(ExecState* exec) 162 163 { 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)); 165 167 } 166 168 167 169 JSObject* throwTerminatedExecutionException(ExecState* exec) 168 170 { 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)); 171 174 } 172 175 -
branches/jsCStack/Source/JavaScriptCore/runtime/JSLock.cpp
r157809 r161575 291 291 SpinLockHolder holder(&spinLock); 292 292 #endif 293 m_savedHostZoneSize = m_vm->hostZoneSize(); 294 m_savedStackPointerAtVMEntry = m_vm->stackPointerAtVMEntry; 295 m_vm->stackPointerAtVMEntry = nullptr; 296 293 297 if (alwaysDropLocks) 294 298 m_lockCount = m_vm->apiLock().dropAllLocksUnconditionally(spinLock); … … 307 311 SpinLockHolder holder(&spinLock); 308 312 #endif 313 m_savedHostZoneSize = m_vm->hostZoneSize(); 314 m_savedStackPointerAtVMEntry = m_vm->stackPointerAtVMEntry; 315 m_vm->stackPointerAtVMEntry = nullptr; 316 309 317 if (alwaysDropLocks) 310 318 m_lockCount = m_vm->apiLock().dropAllLocksUnconditionally(spinLock); … … 322 330 #endif 323 331 m_vm->apiLock().grabAllLocks(m_lockCount, spinLock); 332 333 m_vm->stackPointerAtVMEntry = m_savedStackPointerAtVMEntry; 334 m_vm->updateStackLimitWithHostZoneSize(m_savedHostZoneSize); 324 335 } 325 336 -
branches/jsCStack/Source/JavaScriptCore/runtime/JSLock.h
r161372 r161575 111 111 intptr_t m_lockCount; 112 112 RefPtr<VM> m_vm; 113 size_t m_savedHostZoneSize; 114 void* m_savedStackPointerAtVMEntry; 113 115 }; 114 116 -
branches/jsCStack/Source/JavaScriptCore/runtime/Options.h
r161515 r161575 96 96 v(bool, useRegExpJIT, true) \ 97 97 \ 98 v(unsigned, maxStackSize, 4 * MB) \ 98 v(unsigned, maxPerThreadStackUsage, 4 * MB) \ 99 v(unsigned, hostZoneSize, 128 * KB) \ 100 v(unsigned, errorModeHostZoneSize, 64 * KB) \ 99 101 \ 100 102 v(bool, crashIfCantAllocateJITMemory, false) \ -
branches/jsCStack/Source/JavaScriptCore/runtime/VM.cpp
r161219 r161575 201 201 , jsFinalObjectClassInfo(JSFinalObject::info()) 202 202 , sizeOfLastScratchBuffer(0) 203 , firstEntryScope(0) 204 , topEntryScope(0) 203 , entryScope(0) 205 204 , m_enabledProfiler(0) 206 205 , m_regExpCache(new RegExpCache(this)) … … 231 230 interpreter = new Interpreter(*this); 232 231 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 234 236 setLastStackTop(stack.origin()); 235 237 … … 554 556 prepareToDiscardCode(); 555 557 556 if ( firstEntryScope) {558 if (entryScope) { 557 559 StackPreservingRecompiler recompiler; 558 560 HeapIterationScope iterationScope(heap); … … 714 716 } 715 717 718 size_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 716 736 void releaseExecutableMemory(VM& vm) 717 737 { -
branches/jsCStack/Source/JavaScriptCore/runtime/VM.h
r161180 r161575 376 376 JS_EXPORT_PRIVATE JSObject* throwException(ExecState*, JSObject*); 377 377 378 size_t hostZoneSize() const { return m_hostZoneSize; } 379 size_t updateStackLimitWithHostZoneSize(size_t hostZoneSize); 380 378 381 void** addressOfJSStackLimit() { return &m_jsStackLimit; } 382 #if ENABLE(LLINT_C_LOOP) 379 383 void* jsStackLimit() { return m_jsStackLimit; } 380 384 void setJSStackLimit(void* limit) { m_jsStackLimit = limit; } 381 385 #endif 382 386 void* stackLimit() { return m_stackLimit; } 383 void setStackLimit(void* limit) { m_stackLimit = limit; } 387 384 388 bool isSafeToRecurse(size_t neededStackInBytes = 0) const 385 389 { … … 428 432 void gatherConservativeRoots(ConservativeRoots&); 429 433 430 VMEntryScope* firstEntryScope; 431 VMEntryScope* topEntryScope; 434 VMEntryScope* entryScope; 432 435 433 436 HashSet<JSObject*> stringRecursionCheckVisitedObjects; … … 496 499 static VM*& sharedInstanceInternal(); 497 500 void createNativeThunk(); 501 502 void setStackLimit(void* limit) { m_stackLimit = limit; } 503 498 504 #if ENABLE(ASSEMBLER) 499 505 bool m_canUseAssembler; … … 508 514 const ClassInfo* m_initializingObjectClass; 509 515 #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 512 528 void* m_lastStackTop; 513 529 JSValue m_exception; -
branches/jsCStack/Source/JavaScriptCore/runtime/VMEntryScope.cpp
r161369 r161575 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 35 35 VMEntryScope::VMEntryScope(VM& vm, JSGlobalObject* globalObject) 36 36 : m_vm(vm) 37 , m_stack(wtfThreadData().stack())38 37 , 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 #endif45 , m_prevLastStackTop(vm.lastStackTop())46 , m_prevStackPointerAtVMEntry(vm.stackPointerAtVMEntry)47 , m_prevTopCallFrame(vm.topCallFrame)48 38 { 49 39 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) { 61 41 #if ENABLE(ASSEMBLER) 62 42 if (ExecutableAllocator::underMemoryPressure()) 63 43 vm.heap.deleteAllCompiledCode(); 64 44 #endif 65 vm. firstEntryScope = this;45 vm.entryScope = this; 66 46 67 47 // Reset the date cache between JS invocations to force the VM to … … 69 49 vm.resetDateCache(); 70 50 } 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 } 73 56 74 57 // Clear the captured exception stack between entries 75 58 vm.clearExceptionStack(); 76 77 vm.setLastStackTop(m_stack.origin());78 79 // Step 3: Compute the stack limit using the installed entry scope.80 updateStackLimits();81 59 } 82 60 83 61 VMEntryScope::~VMEntryScope() 84 62 { 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); 170 68 } 171 #else172 UNUSED_PARAM(topOfStack);173 UNUSED_PARAM(type);174 ASSERT(type == NativeStackCapacity);175 #endif176 177 // We require a smaller stack budget for the error stack. This is to allow178 // some minimal JS execution to proceed and do the work of throwing a stack179 // overflow error if needed. In contrast, arbitrary JS code will require the180 // more generous stack budget in order to proceed.181 //182 // These sizes were derived from the stack usage of a number of sites when183 // 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;193 69 } 194 70 195 71 } // namespace JSC 196 -
branches/jsCStack/Source/JavaScriptCore/runtime/VMEntryScope.h
r161369 r161575 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 41 41 JS_EXPORT_PRIVATE ~VMEntryScope(); 42 42 43 void updateStackLimits();44 43 JSGlobalObject* globalObject() const { return m_globalObject; } 45 44 46 45 private: 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 55 46 VM& m_vm; 56 47 StackStats::CheckPoint m_stackCheckPoint; 57 StackBounds m_stack;58 48 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; 70 50 }; 71 51 -
branches/jsCStack/Source/WTF/ChangeLog
r161409 r161575 1 2014-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 1 18 2014-01-06 Filip Pizlo <fpizlo@apple.com> 2 19 -
branches/jsCStack/Source/WTF/wtf/StackBounds.h
r159605 r161575 27 27 #ifndef StackBounds_h 28 28 #define StackBounds_h 29 30 #include <algorithm> 29 31 30 32 namespace WTF { … … 66 68 return static_cast<char*>(m_bound) + minAvailableDelta; 67 69 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)); 68 81 } 69 82 -
branches/jsCStack/Source/WebCore/ChangeLog
r160228 r161575 1 2014-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 1 17 2013-12-06 Laszlo Vidacs <lac@inf.u-szeged.hu> 2 18 -
branches/jsCStack/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
r160152 r161575 18592 18592 <ClInclude Include="..\ForwardingHeaders\runtime\DateInstance.h" /> 18593 18593 <ClInclude Include="..\ForwardingHeaders\runtime\Error.h" /> 18594 <ClInclude Include="..\ForwardingHeaders\runtime\ErrorHandlingScope.h" /> 18594 18595 <ClInclude Include="..\ForwardingHeaders\runtime\ErrorPrototype.h" /> 18595 18596 <ClInclude Include="..\ForwardingHeaders\runtime\ExceptionHelpers.h" /> -
branches/jsCStack/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters
r160152 r161575 12635 12635 <Filter>ForwardingHeaders\runtime</Filter> 12636 12636 </ClInclude> 12637 <ClInclude Include="..\ForwardingHeaders\runtime\ErrorHandlingScope.h"> 12638 <Filter>ForwardingHeaders\runtime</Filter> 12639 </ClInclude> 12637 12640 <ClInclude Include="..\ForwardingHeaders\runtime\ErrorPrototype.h"> 12638 12641 <Filter>ForwardingHeaders\runtime</Filter> -
branches/jsCStack/Source/WebCore/bindings/js/JSDOMBinding.cpp
r160208 r161575 40 40 #include <runtime/DateInstance.h> 41 41 #include <runtime/Error.h> 42 #include <runtime/ErrorHandlingScope.h> 42 43 #include <runtime/ExceptionHelpers.h> 43 44 #include <runtime/JSFunction.h> … … 150 151 return; 151 152 152 Interpreter::ErrorHandlingMode mode(exec);153 ErrorHandlingScope errorScope(exec->vm()); 153 154 154 155 RefPtr<ScriptCallStack> callStack(createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture));
Note:
See TracChangeset
for help on using the changeset viewer.