Changeset 203142 in webkit
- Timestamp:
- Jul 12, 2016, 5:19:15 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r203137 r203142 1 2016-07-12 Mark Lam <mark.lam@apple.com> 2 3 We should use different stack limits for stack checks from JS and host code. 4 https://bugs.webkit.org/show_bug.cgi?id=159442 5 <rdar://problem/26889188> 6 7 Reviewed by Geoffrey Garen. 8 9 * js/regress-141098-expected.txt: 10 * js/script-tests/regress-141098.js: 11 (testEval): 12 (probeAndRecurse): 13 - Gave all the test constants names. 14 - Tweaked the constants to allow the test to run in the least amount of time, and 15 also to behave consistently across all test configurations. 16 - Re-enable eager tests now that the test should finish quickly. 17 1 18 2016-07-12 Dean Jackson <dino@apple.com> 2 19 -
trunk/LayoutTests/js/regress-141098-expected.txt
r200117 r203142 5 5 6 6 PASS Initial setup 7 Starting 1st probeAndRecurse 7 8 PASS Exception: RangeError: Maximum call stack size exceeded. 9 Starting 2nd probeAndRecurse 8 10 PASS Exception: RangeError: Maximum call stack size exceeded. 9 11 PASS successfullyParsed is true -
trunk/LayoutTests/js/script-tests/regress-141098.js
r200117 r203142 1 //@ no EagerNoNoLLIntTestsRunLayoutTest1 //@ noNoLLIntRunLayoutTest 2 2 3 3 description("Regression test for https://webkit.org/b/141098. Make sure eval() properly handles running out of stack space. This test should run without crashing."); … … 6 6 // if run in run-jsc-stress-tests with the eager settings. 7 7 8 // countStart, countIncrement, and numberOfFramesToBackoffFromStackOverflowPoint were 9 // empirically determined to be the values that will cause StackOverflowErrors to be 10 // thrown where the tests expects them. If stack frame layouts change sufficiently (e.g. 11 // due to JIT changes) such that this test starts failing (due to text output 12 // differences), then these values will need to be rebased. 13 // Under no circumstance should this test ever crash. 14 let countStart = 2; 15 let countIncrement = 8; 16 let numberOfFramesToBackoffFromStackOverflowPoint = 50; 17 18 // backoffEverything is chosen to be -1 because a negative number will never be 19 // decremented to 0, and hence, will cause probeAndRecurse() to return out of every 20 // frame instead of retrying the eval test. 21 let backoffEverything = -1; 22 8 23 var lastEvalString = ""; 9 24 … … 11 26 { 12 27 var result; 13 var count = 1;28 var count = countStart; 14 29 15 30 if (!maxIterations) 16 31 var result = eval(lastEvalString); 17 32 else { 18 for (var iter = 0; iter < maxIterations; count *= 4, iter++) {33 for (var iter = 0; iter < maxIterations; count *= countIncrement, iter++) { 19 34 var evalString = "\"dummy\".valueOf("; 20 35 … … 36 51 } 37 52 38 function probeAndRecurse( depth,reuseEvalString)53 function probeAndRecurse(reuseEvalString) 39 54 { 40 var result;55 var framesToBackOffFromStackOverflowPoint; 41 56 42 57 // Probe stack depth 43 58 try { 44 re sult = probeAndRecurse(depth+1,reuseEvalString);59 remainingFramesToBackOff = probeAndRecurse(reuseEvalString); 45 60 46 if (!result) { 61 if (!remainingFramesToBackOff) { 62 // We've backed off a number of frames. Now retry the eval test to see if we 63 // still overflow. 47 64 try { 48 65 testEval(1); 49 66 } catch (e) { 50 return -49; 67 // Yikes. We still overflow. Back off some more. 68 return numberOfFramesToBackoffFromStackOverflowPoint; 51 69 } 52 70 } else 53 return re sult +171 return remainingFramesToBackOff - 1 54 72 } catch (e) { 55 73 // We exceeded stack space, now return up the stack until we can execute a simple eval. 56 74 // Then run an eval test to exceed stack. 57 return -49;75 return numberOfFramesToBackoffFromStackOverflowPoint; 58 76 } 59 77 … … 64 82 } 65 83 66 return 1;84 return backoffEverything; 67 85 } 68 86 69 // Because this test intention lly exhausts the stack, we call testPassed() to ensure87 // Because this test intentionally exhausts the stack, we call testPassed() to ensure 70 88 // everything we need in that path has been compiled and is available. Otherwise we 71 89 // might properly handle an out of stack, but run out of stack calling testPassed(). 72 90 testPassed("Initial setup"); 73 91 74 var depth = probeAndRecurse(0, false); 92 debug("Starting 1st probeAndRecurse"); 93 probeAndRecurse(false); 75 94 76 95 // Tier up the eval'ed code. … … 80 99 testEval(0); 81 100 82 probeAndRecurse(0, true); 101 debug("Starting 2nd probeAndRecurse"); 102 probeAndRecurse(true); -
trunk/Source/JavaScriptCore/ChangeLog
r203134 r203142 1 2016-07-12 Mark Lam <mark.lam@apple.com> 2 3 We should use different stack limits for stack checks from JS and host code. 4 https://bugs.webkit.org/show_bug.cgi?id=159442 5 <rdar://problem/26889188> 6 7 Reviewed by Geoffrey Garen. 8 9 We have 2 stack reservedZoneSizes: 10 1. Options::softReservedZoneSize() 11 2. Options::reservedZoneSize() 12 13 Respectively, there are used to define 2 stack limits based on these reserved 14 zone sizes: 15 1. VM::m_softStackLimit 16 2. VM::m_stackLimit 17 18 Options::reservedZoneSize() is the amount of the stack space that JSC guarantees 19 to the VM and client host code for it's use. Host code that has well known 20 stack usage characteristics (i.e. doesn't call arbitrary code) may do stack 21 checks against the VM::m_stackLimit limit (which is computed using 22 Options::reservedZoneSize()). 23 24 Options::softReservedZoneSize() is a more conservative amount of reserved stack 25 space. This is used to compute the VM::m_softStackLimit limit. Any code that 26 is difficult to have its stack usage characterized (i.e. may call arbitrary code) 27 may need more stack space for its work. Hence, these should do stack checks 28 against the VM::m_softStackLimit limit. 29 30 JS code and host code that may call into JS code falls into the category of code 31 that may call arbitrary code. Hence, they should do stack checks against the 32 VM::m_softStackLimit limit. 33 34 Accordingly, the VM now provides 2 recursion check functions: 35 36 1. VM::isSafeToRecurseSoft() will do a stack check against VM::m_softStackLimit. 37 In addition, for C Loop builds, VM::isSafeToRecurseSoft() will also 38 check the CLoopStack against VM::m_cloopStackLimit. 39 40 2. VM::isSafeToRecurse() will do a stack check against VM::m_stackLimit. 41 42 Also added a promise-infinite-recursion-should-not-crash.js test. 43 44 * bytecompiler/BytecodeGenerator.h: 45 (JSC::BytecodeGenerator::emitNodeInTailPosition): 46 (JSC::BytecodeGenerator::emitNodeInConditionContext): 47 * interpreter/CLoopStack.cpp: 48 (JSC::CLoopStack::grow): 49 * interpreter/CLoopStack.h: 50 (JSC::CLoopStack::size): 51 * interpreter/CLoopStackInlines.h: 52 (JSC::CLoopStack::ensureCapacityFor): 53 (JSC::CLoopStack::isSafeToRecurse): 54 (JSC::CLoopStack::topOfFrameFor): 55 * interpreter/CachedCall.h: 56 (JSC::CachedCall::CachedCall): 57 * interpreter/Interpreter.cpp: 58 (JSC::Interpreter::execute): 59 (JSC::Interpreter::executeCall): 60 (JSC::Interpreter::executeConstruct): 61 * llint/LLIntSlowPaths.cpp: 62 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 63 * parser/Parser.cpp: 64 * runtime/Options.h: 65 * runtime/ProxyObject.cpp: 66 (JSC::performProxyGet): 67 (JSC::ProxyObject::performInternalMethodGetOwnProperty): 68 (JSC::ProxyObject::performHasProperty): 69 (JSC::ProxyObject::getOwnPropertySlotCommon): 70 (JSC::ProxyObject::performPut): 71 (JSC::performProxyCall): 72 (JSC::performProxyConstruct): 73 (JSC::ProxyObject::performDelete): 74 (JSC::ProxyObject::performPreventExtensions): 75 (JSC::ProxyObject::performIsExtensible): 76 (JSC::ProxyObject::performDefineOwnProperty): 77 (JSC::ProxyObject::performGetOwnPropertyNames): 78 (JSC::ProxyObject::performSetPrototype): 79 (JSC::ProxyObject::performGetPrototype): 80 * runtime/RegExp.cpp: 81 (JSC::RegExp::finishCreation): 82 (JSC::RegExp::compile): 83 (JSC::RegExp::compileMatchOnly): 84 * runtime/StringRecursionChecker.h: 85 (JSC::StringRecursionChecker::performCheck): 86 * runtime/VM.cpp: 87 (JSC::VM::setStackPointerAtVMEntry): 88 (JSC::VM::updateSoftReservedZoneSize): 89 (JSC::preCommitStackMemory): 90 (JSC::VM::updateStackLimits): 91 (JSC::VM::updateStackLimit): Deleted. 92 * runtime/VM.h: 93 (JSC::VM::stackLimit): 94 (JSC::VM::softStackLimit): 95 (JSC::VM::addressOfSoftStackLimit): 96 (JSC::VM::setCLoopStackLimit): 97 (JSC::VM::isSafeToRecurse): 98 (JSC::VM::lastStackTop): 99 (JSC::VM::setException): 100 * runtime/VMInlines.h: 101 (JSC::VM::ensureStackCapacityFor): 102 (JSC::VM::isSafeToRecurseSoft): 103 (JSC::VM::shouldTriggerTermination): 104 * tests/stress/promise-infinite-recursion-should-not-crash.js: Added. 105 (testPromise): 106 (promiseFunc): 107 * yarr/YarrPattern.cpp: 108 1 109 2016-07-12 Per Arne Vollan <pvollan@apple.com> 2 110 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r203006 r203142 385 385 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary. 386 386 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount()); 387 if ( !m_vm->isSafeToRecurse()) {387 if (UNLIKELY(!m_vm->isSafeToRecurse())) { 388 388 emitThrowExpressionTooDeepException(); 389 389 return; … … 412 412 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary. 413 413 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount()); 414 if ( !m_vm->isSafeToRecurse())414 if (UNLIKELY(!m_vm->isSafeToRecurse())) 415 415 return emitThrowExpressionTooDeepException(); 416 416 return n->emitBytecode(*this, dst); … … 429 429 void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode) 430 430 { 431 if ( !m_vm->isSafeToRecurse()) {431 if (UNLIKELY(!m_vm->isSafeToRecurse())) { 432 432 emitThrowExpressionTooDeepException(); 433 433 return; -
trunk/Source/JavaScriptCore/interpreter/CLoopStack.cpp
r203130 r203142 89 89 90 90 // Compute the chunk size of additional memory to commit, and see if we 91 // have it isstill within our budget. If not, we'll fail to grow and91 // have it still within our budget. If not, we'll fail to grow and 92 92 // return false. 93 93 ptrdiff_t delta = reinterpret_cast<char*>(m_commitTop) - reinterpret_cast<char*>(newTopOfStackWithReservedZone); -
trunk/Source/JavaScriptCore/interpreter/CLoopStack.h
r203130 r203142 69 69 70 70 void setSoftReservedZoneSize(size_t); 71 bool isSafeToRecurse() const; 71 72 72 73 inline Register* topOfStack(); -
trunk/Source/JavaScriptCore/interpreter/CLoopStackInlines.h
r203130 r203142 43 43 } 44 44 45 bool CLoopStack::isSafeToRecurse() const 46 { 47 void* reservationLimit = reinterpret_cast<int8_t*>(reservationTop() + m_reservedZoneSizeInRegisters); 48 return !m_topCallFrame || (m_topCallFrame->topOfFrame() > reservationLimit); 49 } 50 45 51 inline Register* CLoopStack::topOfFrameFor(CallFrame* frame) 46 52 { -
trunk/Source/JavaScriptCore/interpreter/CachedCall.h
r163960 r203142 1 1 /* 2 * Copyright (C) 2009, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 34 34 #include "ProtoCallFrame.h" 35 35 #include "VMEntryScope.h" 36 #include "VMInlines.h" 36 37 37 38 namespace JSC { … … 45 46 { 46 47 ASSERT(!function->isHostFunctionNonInline()); 47 if ( callFrame->vm().isSafeToRecurse()) {48 if (UNLIKELY(callFrame->vm().isSafeToRecurseSoft())) { 48 49 m_arguments.resize(argumentCount); 49 50 m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, &m_protoCallFrame, function, argumentCount + 1, function->scope(), m_arguments.data()); -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r203081 r203142 829 829 return jsNull(); 830 830 831 if ( !vm.isSafeToRecurse())831 if (UNLIKELY(!vm.isSafeToRecurseSoft())) 832 832 return checkedReturn(throwStackOverflowError(callFrame)); 833 833 … … 989 989 990 990 VMEntryScope entryScope(vm, globalObject); 991 if ( !vm.isSafeToRecurse())991 if (UNLIKELY(!vm.isSafeToRecurseSoft())) 992 992 return checkedReturn(throwStackOverflowError(callFrame)); 993 993 … … 1051 1051 1052 1052 VMEntryScope entryScope(vm, globalObject); 1053 if ( !vm.isSafeToRecurse())1053 if (UNLIKELY(!vm.isSafeToRecurseSoft())) 1054 1054 return checkedReturn(throwStackOverflowError(callFrame)); 1055 1055 … … 1148 1148 1149 1149 VMEntryScope entryScope(vm, scope->globalObject()); 1150 if ( !vm.isSafeToRecurse())1150 if (UNLIKELY(!vm.isSafeToRecurseSoft())) 1151 1151 return checkedReturn(throwStackOverflowError(callFrame)); 1152 1152 … … 1249 1249 1250 1250 VMEntryScope entryScope(vm, scope->globalObject()); 1251 if ( !vm.isSafeToRecurse())1251 if (UNLIKELY(!vm.isSafeToRecurseSoft())) 1252 1252 return checkedReturn(throwStackOverflowError(callFrame)); 1253 1253 -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r203130 r203142 483 483 dataLogF("Num vars = %u.\n", exec->codeBlock()->m_numVars); 484 484 485 #if ENABLE(JIT) 486 dataLogF("Current end is at %p.\n", exec->vm().softStackLimit()); 487 #else 488 dataLogF("Current end is at %p.\n", exec->vm().cloopStackLimit()); 485 dataLogF("Current OS stack end is at %p.\n", exec->vm().softStackLimit()); 486 #if !ENABLE(JIT) 487 dataLogF("Current C Loop stack end is at %p.\n", exec->vm().cloopStackLimit()); 489 488 #endif 490 489 -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r202865 r203142 56 56 #define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0) 57 57 #define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0) 58 #define failIfStackOverflow() do { if ( !canRecurse()) failWithStackOverflow(); } while (0)58 #define failIfStackOverflow() do { if (UNLIKELY(!canRecurse())) failWithStackOverflow(); } while (0) 59 59 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0) 60 60 #define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0) -
trunk/Source/JavaScriptCore/runtime/Options.h
r203130 r203142 114 114 \ 115 115 v(unsigned, maxPerThreadStackUsage, 4 * MB, Normal, "Max allowed stack usage by the VM") \ 116 v(unsigned, softReservedZoneSize, 128 * KB, Normal, " The amount of stack JSC usually reserves for host code.") \117 v(unsigned, reservedZoneSize, 64 * KB, Normal, "Th is is the amount of stack JSC guarantees for client and VM code.") \116 v(unsigned, softReservedZoneSize, 128 * KB, Normal, "A buffer greater than reservedZoneSize that reserves space for stringifying exceptions.") \ 117 v(unsigned, reservedZoneSize, 64 * KB, Normal, "The amount of stack space we guarantee to our clients (and to interal VM code that does not call out to clients).") \ 118 118 \ 119 119 v(bool, crashIfCantAllocateJITMemory, false, Normal, nullptr) \ -
trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp
r202124 r203142 34 34 #include "SlotVisitorInlines.h" 35 35 #include "StructureInlines.h" 36 #include "VMInlines.h" 36 37 37 38 // Note that this file is compile with -fno-optimize-sibling-calls because we rely on the machine stack … … 99 100 { 100 101 VM& vm = exec->vm(); 101 if (UNLIKELY(!vm.isSafeToRecurse ())) {102 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 102 103 throwStackOverflowError(exec); 103 104 return JSValue(); … … 168 169 { 169 170 VM& vm = exec->vm(); 170 if (UNLIKELY(!vm.isSafeToRecurse ())) {171 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 171 172 throwStackOverflowError(exec); 172 173 return false; … … 274 275 { 275 276 VM& vm = exec->vm(); 276 if (UNLIKELY(!vm.isSafeToRecurse ())) {277 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 277 278 throwStackOverflowError(exec); 278 279 return false; … … 339 340 bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot) 340 341 { 341 if (UNLIKELY(!exec->vm().isSafeToRecurse ())) {342 if (UNLIKELY(!exec->vm().isSafeToRecurseSoft())) { 342 343 throwStackOverflowError(exec); 343 344 return false; … … 377 378 { 378 379 VM& vm = exec->vm(); 379 if (UNLIKELY(!vm.isSafeToRecurse ())) {380 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 380 381 throwStackOverflowError(exec); 381 382 return false; … … 469 470 { 470 471 VM& vm = exec->vm(); 471 if (UNLIKELY(!vm.isSafeToRecurse ())) {472 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 472 473 throwStackOverflowError(exec); 473 474 return JSValue::encode(JSValue()); … … 518 519 { 519 520 VM& vm = exec->vm(); 520 if (UNLIKELY(!vm.isSafeToRecurse ())) {521 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 521 522 throwStackOverflowError(exec); 522 523 return JSValue::encode(JSValue()); … … 573 574 { 574 575 VM& vm = exec->vm(); 575 if (UNLIKELY(!vm.isSafeToRecurse ())) {576 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 576 577 throwStackOverflowError(exec); 577 578 return false; … … 649 650 { 650 651 VM& vm = exec->vm(); 651 if (UNLIKELY(!vm.isSafeToRecurse ())) {652 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 652 653 throwStackOverflowError(exec); 653 654 return false; … … 701 702 { 702 703 VM& vm = exec->vm(); 703 if (UNLIKELY(!vm.isSafeToRecurse ())) {704 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 704 705 throwStackOverflowError(exec); 705 706 return false; … … 759 760 { 760 761 VM& vm = exec->vm(); 761 if (UNLIKELY(!vm.isSafeToRecurse ())) {762 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 762 763 throwStackOverflowError(exec); 763 764 return false; … … 856 857 { 857 858 VM& vm = exec->vm(); 858 if (UNLIKELY(!vm.isSafeToRecurse ())) {859 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 859 860 throwStackOverflowError(exec); 860 861 return; … … 1005 1006 1006 1007 VM& vm = exec->vm(); 1007 if (UNLIKELY(!vm.isSafeToRecurse ())) {1008 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 1008 1009 throwStackOverflowError(exec); 1009 1010 return false; … … 1069 1070 { 1070 1071 VM& vm = exec->vm(); 1071 if (UNLIKELY(!vm.isSafeToRecurse ())) {1072 if (UNLIKELY(!vm.isSafeToRecurseSoft())) { 1072 1073 throwStackOverflowError(exec); 1073 1074 return JSValue(); -
trunk/Source/JavaScriptCore/runtime/RegExp.cpp
r203130 r203142 223 223 { 224 224 Base::finishCreation(vm); 225 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm.s oftStackLimit());225 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm.stackLimit()); 226 226 if (m_constructionError) 227 227 m_state = ParseError; … … 265 265 ConcurrentJITLocker locker(m_lock); 266 266 267 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->s oftStackLimit());267 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->stackLimit()); 268 268 if (m_constructionError) { 269 269 RELEASE_ASSERT_NOT_REACHED(); … … 318 318 ConcurrentJITLocker locker(m_lock); 319 319 320 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->s oftStackLimit());320 Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->stackLimit()); 321 321 if (m_constructionError) { 322 322 RELEASE_ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/runtime/StringRecursionChecker.h
r184447 r203142 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 22 22 23 23 #include "Interpreter.h" 24 #include "VMInlines.h" 24 25 #include <wtf/StackStats.h> 25 26 #include <wtf/WTFThreadData.h> … … 51 52 { 52 53 VM& vm = m_exec->vm(); 53 if ( !vm.isSafeToRecurse())54 if (UNLIKELY(!vm.isSafeToRecurseSoft())) 54 55 return throwStackOverflowError(); 55 56 -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r203130 r203142 611 611 { 612 612 m_stackPointerAtVMEntry = sp; 613 updateStackLimit ();613 updateStackLimits(); 614 614 } 615 615 … … 622 622 #endif 623 623 624 updateStackLimit ();624 updateStackLimits(); 625 625 626 626 return oldSoftReservedZoneSize; … … 652 652 #endif 653 653 654 inline void VM::updateStackLimit ()654 inline void VM::updateStackLimits() 655 655 { 656 656 #if PLATFORM(WIN) … … 658 658 #endif 659 659 660 size_t reservedZoneSize = Options::reservedZoneSize(); 660 661 if (m_stackPointerAtVMEntry) { 661 662 ASSERT(wtfThreadData().stack().isGrowingDownward()); 662 663 char* startOfStack = reinterpret_cast<char*>(m_stackPointerAtVMEntry); 663 664 m_softStackLimit = wtfThreadData().stack().recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), m_currentSoftReservedZoneSize); 665 m_stackLimit = wtfThreadData().stack().recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), reservedZoneSize); 664 666 } else { 665 667 m_softStackLimit = wtfThreadData().stack().recursionLimit(m_currentSoftReservedZoneSize); 668 m_stackLimit = wtfThreadData().stack().recursionLimit(reservedZoneSize); 666 669 } 667 670 668 671 #if PLATFORM(WIN) 672 // We only need to precommit stack memory dictated by the VM::m_softStackLimit limit. 673 // This is because VM::m_softStackLimit applies to stack usage by LLINT asm or JIT 674 // generated code which can allocate stack space that the C++ compiler does not know 675 // about. As such, we have to precommit that stack memory manually. 676 // 677 // In contrast, we do not need to worry about VM::m_stackLimit because that limit is 678 // used exclusively by C++ code, and the C++ compiler will automatically commit the 679 // needed stack pages. 669 680 if (lastSoftStackLimit != m_softStackLimit) 670 681 preCommitStackMemory(m_softStackLimit); -
trunk/Source/JavaScriptCore/runtime/VM.h
r203130 r203142 466 466 inline bool ensureStackCapacityFor(Register* newTopOfStack); 467 467 468 void* stackLimit() { return m_stackLimit; } 468 469 void* softStackLimit() { return m_softStackLimit; } 469 470 void** addressOfSoftStackLimit() { return &m_softStackLimit; } … … 473 474 #endif 474 475 475 bool isSafeToRecurse(size_t neededStackInBytes = 0) const 476 { 477 ASSERT(wtfThreadData().stack().isGrowingDownward()); 478 int8_t* curr = reinterpret_cast<int8_t*>(&curr); 479 int8_t* limit = reinterpret_cast<int8_t*>(m_softStackLimit); 480 return curr >= limit && static_cast<size_t>(curr - limit) >= neededStackInBytes; 476 inline bool isSafeToRecurseSoft() const; 477 bool isSafeToRecurse() const 478 { 479 return isSafeToRecurse(m_stackLimit); 481 480 } 482 481 … … 627 626 void createNativeThunk(); 628 627 629 void updateStackLimit(); 628 void updateStackLimits(); 629 630 bool isSafeToRecurse(void* stackLimit) const 631 { 632 ASSERT(wtfThreadData().stack().isGrowingDownward()); 633 void* curr = reinterpret_cast<void*>(&curr); 634 return curr >= stackLimit; 635 } 630 636 631 637 void setException(Exception* exception) … … 650 656 void* m_stackPointerAtVMEntry; 651 657 size_t m_currentSoftReservedZoneSize; 658 void* m_stackLimit { nullptr }; 652 659 void* m_softStackLimit { nullptr }; 653 660 #if !ENABLE(JIT) -
trunk/Source/JavaScriptCore/runtime/VMInlines.h
r203130 r203142 48 48 } 49 49 50 bool VM::isSafeToRecurseSoft() const 51 { 52 bool safe = isSafeToRecurse(m_softStackLimit); 53 #if !ENABLE(JIT) 54 safe = safe && interpreter->cloopStack().isSafeToRecurse(); 55 #endif 56 return safe; 57 } 58 50 59 bool VM::shouldTriggerTermination(ExecState* exec) 51 60 { -
trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp
r202490 r203142 581 581 bool setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition, unsigned& newCallFrameSize) WARN_UNUSED_RETURN 582 582 { 583 if ( !isSafeToRecurse())583 if (UNLIKELY(!isSafeToRecurse())) 584 584 return false; 585 585 … … 683 683 bool setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition, unsigned& callFrameSize) WARN_UNUSED_RETURN 684 684 { 685 if ( !isSafeToRecurse())685 if (UNLIKELY(!isSafeToRecurse())) 686 686 return false; 687 687 -
trunk/Tools/ChangeLog
r203141 r203142 1 2016-07-12 Mark Lam <mark.lam@apple.com> 2 3 We should use different stack limits for stack checks from JS and host code. 4 https://bugs.webkit.org/show_bug.cgi?id=159442 5 <rdar://problem/26889188> 6 7 Reviewed by Geoffrey Garen. 8 9 In http://trac.webkit.org/r203067, we limited the amount of stack that tests will 10 run with to keep stack overflow tests sane. Turns out, we also need to teach the 11 LayoutTestRelay to pass env vars over to the iOS simulator. This is needed in 12 order to keep the js/regress-139548.html test happy with this patch. 13 14 Also fixed up run_webkit_tests.py to explicitly pass an int size value for the 15 JSC_maxPerThreadStackUsage option. Otherwise, it will pass a float value. 16 17 * LayoutTestRelay/LayoutTestRelay/LTRelayController.m: 18 (-[LTRelayController _environmentVariables]): 19 * Scripts/webkitpy/layout_tests/run_webkit_tests.py: 20 (main): 21 1 22 2016-07-12 Filip Pizlo <fpizlo@apple.com> 2 23 -
trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m
r202743 r203142 29 29 #import "LTPipeRelay.h" 30 30 #import <AppKit/AppKit.h> 31 #import <crt_externs.h> 31 32 32 33 @interface LTRelayController () … … 194 195 } 195 196 197 for (char** envp = *_NSGetEnviron(); *envp; envp++) { 198 const char* env = *envp; 199 if (!strncmp("JSC_", env, 4) || !strncmp("__XPC_JSC_", env, 10)) { 200 const char* equal = strchr(env, '='); 201 if (!equal) { 202 NSLog(@"Missing '=' in env var '%s'", env); 203 continue; 204 } 205 206 static const size_t maxKeyLength = 256; 207 size_t keyLength = equal - env; 208 if (keyLength >= maxKeyLength) { 209 NSLog(@"Env var '%s' is too long", env); 210 continue; 211 } 212 213 char key[maxKeyLength]; 214 strncpy(key, env, keyLength); 215 key[keyLength] = '\0'; 216 const char* value = equal + 1; 217 218 NSString *nsKey = [NSString stringWithUTF8String:key]; 219 NSString *nsValue = [NSString stringWithUTF8String:value]; 220 [dictionary setObject:nsValue forKey:nsKey]; 221 } 222 } 223 196 224 environmentVariables = [dictionary copy]; 197 225 }); -
trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
r203067 r203142 76 76 try: 77 77 # Force all tests to use a smaller stack so that stack overflow tests can run faster. 78 stackSizeInBytes = 1.5 * 1024 * 102478 stackSizeInBytes = int(1.5 * 1024 * 1024) 79 79 options.additional_env_var.append('JSC_maxPerThreadStackUsage=' + str(stackSizeInBytes)) 80 80 options.additional_env_var.append('__XPC_JSC_maxPerThreadStackUsage=' + str(stackSizeInBytes))
Note:
See TracChangeset
for help on using the changeset viewer.