Changeset 253581 in webkit
- Timestamp:
- Dec 16, 2019, 2:34:50 PM (5 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/Source/JavaScriptCore/ChangeLog ¶
r253576 r253581 1 2019-12-16 Mark Lam <mark.lam@apple.com> 2 3 Changed jsc shell timeout mechanism to leverage the VMTraps and use CPUTime. 4 https://bugs.webkit.org/show_bug.cgi?id=205279 5 <rdar://problem/57971874> 6 7 Reviewed by Saam Barati. 8 9 This fixes all the timeouts that occur due to CPU time starvation when 10 running JSC tests on a debug build. 11 12 What this means is that the timeout mechanism may trigger asynchronous 13 OSR exits. If a test requires no OSR exits, that test should 14 requireOption("--usePollingTraps=true") so that the VMTraps will use its 15 polling implementation instead. 16 17 I've tested this with a full run of the JSC stress tests with a debug 18 build and saw 0 timeouts. I've also tested it with a contrived tests that 19 loops forever, and saw the expected timeout crash. 20 21 Will look into re-tuning needed timeout value (and other JSC tests timeout 22 cleanup) in https://bugs.webkit.org/show_bug.cgi?id=205298. 23 24 * interpreter/Interpreter.cpp: 25 (JSC::Interpreter::executeProgram): 26 (JSC::Interpreter::executeCall): 27 (JSC::Interpreter::executeConstruct): 28 (JSC::Interpreter::execute): 29 (JSC::Interpreter::executeModuleProgram): 30 * interpreter/InterpreterInlines.h: 31 (JSC::Interpreter::execute): 32 * jsc.cpp: 33 (timeoutCheckCallback): 34 (initializeTimeoutIfNeeded): 35 (startTimeoutThreadIfNeeded): 36 (runJSC): 37 (jscmain): 38 * runtime/JSCConfig.h: 39 * runtime/VM.h: 40 (JSC::VM::notifyNeedShellTimeoutCheck): 41 * runtime/VMTraps.cpp: 42 (JSC::VMTraps::handleTraps): 43 * runtime/VMTraps.h: 44 (JSC::VMTraps::Mask::Mask): 45 (JSC::VMTraps::Mask::allEventTypes): 46 (JSC::VMTraps::Mask::init): 47 (JSC::VMTraps::interruptingTraps): 48 * tools/VMInspector.cpp: 49 (JSC::VMInspector::forEachVM): 50 * tools/VMInspector.h: 51 1 52 2019-12-16 Yusuke Suzuki <ysuzuki@apple.com> 2 53 -
TabularUnified trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp ¶
r253520 r253581 821 821 } 822 822 823 VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);824 if (UNLIKELY(vm.needTrapHandling( mask))) {825 vm.handleTraps(globalObject, vm.topCallFrame, mask);823 constexpr auto trapsMask = VMTraps::interruptingTraps(); 824 if (UNLIKELY(vm.needTrapHandling(trapsMask))) { 825 vm.handleTraps(globalObject, vm.topCallFrame, trapsMask); 826 826 RETURN_IF_EXCEPTION(throwScope, throwScope.exception()); 827 827 } … … 882 882 newCodeBlock = 0; 883 883 884 VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);885 if (UNLIKELY(vm.needTrapHandling( mask))) {886 vm.handleTraps(globalObject, vm.topCallFrame, mask);884 constexpr auto trapsMask = VMTraps::interruptingTraps(); 885 if (UNLIKELY(vm.needTrapHandling(trapsMask))) { 886 vm.handleTraps(globalObject, vm.topCallFrame, trapsMask); 887 887 RETURN_IF_EXCEPTION(throwScope, throwScope.exception()); 888 888 } … … 953 953 newCodeBlock = 0; 954 954 955 VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);956 if (UNLIKELY(vm.needTrapHandling( mask))) {957 vm.handleTraps(globalObject, vm.topCallFrame, mask);955 constexpr auto trapsMask = VMTraps::interruptingTraps(); 956 if (UNLIKELY(vm.needTrapHandling(trapsMask))) { 957 vm.handleTraps(globalObject, vm.topCallFrame, trapsMask); 958 958 RETURN_IF_EXCEPTION(throwScope, nullptr); 959 959 } … … 1137 1137 } 1138 1138 1139 VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);1140 if (UNLIKELY(vm.needTrapHandling( mask))) {1141 vm.handleTraps(globalObject, vm.topCallFrame, mask);1139 constexpr auto trapsMask = VMTraps::interruptingTraps(); 1140 if (UNLIKELY(vm.needTrapHandling(trapsMask))) { 1141 vm.handleTraps(globalObject, vm.topCallFrame, trapsMask); 1142 1142 RETURN_IF_EXCEPTION(throwScope, throwScope.exception()); 1143 1143 } … … 1187 1187 } 1188 1188 1189 VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);1190 if (UNLIKELY(vm.needTrapHandling( mask))) {1191 vm.handleTraps(globalObject, vm.topCallFrame, mask);1189 constexpr auto trapsMask = VMTraps::interruptingTraps(); 1190 if (UNLIKELY(vm.needTrapHandling(trapsMask))) { 1191 vm.handleTraps(globalObject, vm.topCallFrame, trapsMask); 1192 1192 RETURN_IF_EXCEPTION(throwScope, throwScope.exception()); 1193 1193 } -
TabularUnified trunk/Source/JavaScriptCore/interpreter/InterpreterInlines.h ¶
r251425 r253581 1 1 /* 2 2 * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com> 3 * Copyright (C) 2016-201 8Apple Inc. All rights reserved.3 * Copyright (C) 2016-2019 Apple Inc. All rights reserved. 4 4 * 5 5 * Redistribution and use in source and binary forms, with or without … … 75 75 StackStats::CheckPoint stackCheckPoint; 76 76 77 VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);78 if (UNLIKELY(vm.needTrapHandling( mask))) {79 vm.handleTraps(closure.protoCallFrame->globalObject, closure.oldCallFrame, mask);77 constexpr auto trapsMask = VMTraps::interruptingTraps(); 78 if (UNLIKELY(vm.needTrapHandling(trapsMask))) { 79 vm.handleTraps(closure.protoCallFrame->globalObject, closure.oldCallFrame, trapsMask); 80 80 RETURN_IF_EXCEPTION(throwScope, throwScope.exception()); 81 81 } -
TabularUnified trunk/Source/JavaScriptCore/jsc.cpp ¶
r253458 r253581 71 71 #include "TestRunnerUtils.h" 72 72 #include "TypedArrayInlines.h" 73 #include "VMInspector.h" 73 74 #include "WasmCapabilities.h" 74 75 #include "WasmContext.h" … … 85 86 #include <type_traits> 86 87 #include <wtf/Box.h> 88 #include <wtf/CPUTime.h> 87 89 #include <wtf/CommaPrinter.h> 88 90 #include <wtf/FileSystem.h> … … 2428 2430 static double s_desiredTimeout; 2429 2431 static double s_timeoutMultiplier = 1.0; 2430 2431 static void startTimeoutThreadIfNeeded() 2432 static Seconds s_timeoutDuration; 2433 static Seconds s_maxAllowedCPUTime; 2434 static VM* s_vm; 2435 2436 static void startTimeoutTimer(Seconds duration) 2437 { 2438 Thread::create("jsc Timeout Thread", [=] () { 2439 sleep(duration); 2440 VMInspector::forEachVM([&] (VM& vm) -> VMInspector::FunctorStatus { 2441 if (&vm != s_vm) 2442 return VMInspector::FunctorStatus::Continue; 2443 vm.notifyNeedShellTimeoutCheck(); 2444 return VMInspector::FunctorStatus::Done; 2445 }); 2446 }); 2447 } 2448 2449 static void timeoutCheckCallback(VM& vm) 2450 { 2451 RELEASE_ASSERT(&vm == s_vm); 2452 auto cpuTime = CPUTime::forCurrentThread(); 2453 if (cpuTime >= s_maxAllowedCPUTime) { 2454 dataLog("Timed out after ", s_timeoutDuration, " seconds!\n"); 2455 CRASH(); 2456 } 2457 auto remainingTime = s_maxAllowedCPUTime - cpuTime; 2458 startTimeoutTimer(remainingTime); 2459 } 2460 2461 static void initializeTimeoutIfNeeded() 2432 2462 { 2433 2463 if (char* timeoutString = getenv("JSCTEST_timeout")) { … … 2435 2465 dataLog("WARNING: timeout string is malformed, got ", timeoutString, 2436 2466 " but expected a number. Not using a timeout.\n"); 2437 } else { 2438 Thread::create("jsc Timeout Thread", [] () { 2439 Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier); 2440 sleep(timeoutDuration); 2441 dataLog("Timed out after ", timeoutDuration, " seconds!\n"); 2442 CRASH(); 2443 }); 2444 } 2445 } 2467 } else 2468 g_jscConfig.shellTimeoutCheckCallback = timeoutCheckCallback; 2469 } 2470 } 2471 2472 static void startTimeoutThreadIfNeeded(VM& vm) 2473 { 2474 if (!g_jscConfig.shellTimeoutCheckCallback) 2475 return; 2476 2477 s_vm = &vm; 2478 s_timeoutDuration = Seconds(s_desiredTimeout * s_timeoutMultiplier); 2479 s_maxAllowedCPUTime = CPUTime::forCurrentThread() + s_timeoutDuration; 2480 Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier); 2481 startTimeoutTimer(timeoutDuration); 2446 2482 } 2447 2483 … … 3000 3036 JSLockHolder locker(vm); 3001 3037 3038 startTimeoutThreadIfNeeded(vm); 3002 3039 if (options.m_profile && !vm.m_perBytecodeProfiler) 3003 3040 vm.m_perBytecodeProfiler = makeUnique<Profiler::Database>(vm); … … 3100 3137 // Initialize JSC before getting VM. 3101 3138 JSC::initializeThreading(); 3102 startTimeoutThreadIfNeeded();3139 initializeTimeoutIfNeeded(); 3103 3140 #if ENABLE(WEBASSEMBLY) 3104 3141 JSC::Wasm::enableFastMemory(); -
TabularUnified trunk/Source/JavaScriptCore/runtime/JSCConfig.h ¶
r252557 r253581 33 33 class ExecutableAllocator; 34 34 class FixedVMPoolExecutableAllocator; 35 class VM; 35 36 36 37 #if CPU(ARM64) || PLATFORM(WATCHOS) … … 83 84 84 85 OptionsStorage options; 86 87 void (*shellTimeoutCheckCallback)(VM&); 85 88 }; 86 89 char ensureSize[ConfigSizeToProtect]; -
TabularUnified trunk/Source/JavaScriptCore/runtime/VM.h ¶
r253576 r253581 1066 1066 1067 1067 void notifyNeedDebuggerBreak() { m_traps.fireTrap(VMTraps::NeedDebuggerBreak); } 1068 void notifyNeedShellTimeoutCheck() { m_traps.fireTrap(VMTraps::NeedShellTimeoutCheck); } 1068 1069 void notifyNeedTermination() { m_traps.fireTrap(VMTraps::NeedTermination); } 1069 1070 void notifyNeedWatchdogCheck() { m_traps.fireTrap(VMTraps::NeedWatchdogCheck); } -
TabularUnified trunk/Source/JavaScriptCore/runtime/VMTraps.cpp ¶
r251690 r253581 358 358 invalidateCodeBlocksOnStack(callFrame); 359 359 break; 360 360 361 361 case NeedWatchdogCheck: 362 362 ASSERT(vm.watchdog()); … … 364 364 continue; 365 365 FALLTHROUGH; 366 367 case NeedShellTimeoutCheck: 368 RELEASE_ASSERT(g_jscConfig.shellTimeoutCheckCallback); 369 g_jscConfig.shellTimeoutCheckCallback(vm); 370 break; 366 371 367 372 case NeedTermination: -
TabularUnified trunk/Source/JavaScriptCore/runtime/VMTraps.h ¶
r251425 r253581 1 1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved.2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 53 53 // Sorted in servicing priority order from highest to lowest. 54 54 NeedDebuggerBreak, 55 NeedShellTimeoutCheck, 55 56 NeedTermination, 56 57 NeedWatchdogCheck, … … 62 63 public: 63 64 enum AllEventTypes { AllEventTypesTag }; 64 Mask(AllEventTypes)65 constexpr Mask(AllEventTypes) 65 66 : m_mask(std::numeric_limits<BitField>::max()) 66 67 { } 67 static Mask allEventTypes() { return Mask(AllEventTypesTag); } 68 static constexpr Mask allEventTypes() { return Mask(AllEventTypesTag); } 69 70 constexpr Mask(const Mask&) = default; 71 constexpr Mask(Mask&&) = default; 68 72 69 73 template<typename... Arguments> 70 Mask(Arguments... args)74 constexpr Mask(Arguments... args) 71 75 : m_mask(0) 72 76 { … … 78 82 private: 79 83 template<typename... Arguments> 80 void init(EventType eventType, Arguments... args)84 constexpr void init(EventType eventType, Arguments... args) 81 85 { 82 86 ASSERT(eventType < NumberOfEventTypes); … … 85 89 } 86 90 87 void init() { }91 constexpr void init() { } 88 92 89 93 BitField m_mask; 90 94 }; 95 96 static constexpr Mask interruptingTraps() { return Mask(NeedShellTimeoutCheck, NeedTermination, NeedWatchdogCheck); } 91 97 92 98 ~VMTraps(); -
TabularUnified trunk/Source/JavaScriptCore/tools/VMInspector.cpp ¶
r252302 r253581 107 107 #endif // ENABLE(JIT) 108 108 109 void VMInspector::forEachVM(Function<FunctorStatus(VM&)>&& func) 110 { 111 VMInspector& inspector = instance(); 112 Locker lock(inspector.getLock()); 113 inspector.iterate(func); 114 } 115 109 116 auto VMInspector::isValidExecutableMemory(const VMInspector::Locker&, void* machinePC) -> Expected<bool, Error> 110 117 { -
TabularUnified trunk/Source/JavaScriptCore/tools/VMInspector.h ¶
r251425 r253581 61 61 void iterate(const Locker&, const Functor& functor) { iterate(functor); } 62 62 63 JS_EXPORT_PRIVATE static void forEachVM(Function<FunctorStatus(VM&)>&&); 64 63 65 Expected<Locker, Error> lock(Seconds timeout = Seconds::infinity()); 64 66
Note:
See TracChangeset
for help on using the changeset viewer.