Diff
Modified: branches/safari-605-branch/JSTests/ChangeLog (228515 => 228516)
--- branches/safari-605-branch/JSTests/ChangeLog 2018-02-15 17:30:11 UTC (rev 228515)
+++ branches/safari-605-branch/JSTests/ChangeLog 2018-02-15 17:30:14 UTC (rev 228516)
@@ -1,3 +1,16 @@
+2018-02-15 Jason Marcell <[email protected]>
+
+ Cherry-pick r228488. rdar://problem/37570860
+
+ 2018-02-14 Saam Barati <[email protected]>
+
+ Setting a VMTrap shouldn't look at topCallFrame since that may imply we're in C code and holding the malloc lock
+ https://bugs.webkit.org/show_bug.cgi?id=182801
+
+ Reviewed by Keith Miller.
+
+ * stress/watchdog-dont-malloc-when-in-c-code.js: Added.
+
2018-02-13 Jason Marcell <[email protected]>
Cherry-pick r228401. rdar://problem/37521078
Added: branches/safari-605-branch/JSTests/stress/watchdog-dont-malloc-when-in-c-code.js (0 => 228516)
--- branches/safari-605-branch/JSTests/stress/watchdog-dont-malloc-when-in-c-code.js (rev 0)
+++ branches/safari-605-branch/JSTests/stress/watchdog-dont-malloc-when-in-c-code.js 2018-02-15 17:30:14 UTC (rev 228516)
@@ -0,0 +1,5 @@
+//@ runFTLEagerWatchdog
+
+for (let i = 0; i < 7000; ++i) {
+ mallocInALoop();
+}
Modified: branches/safari-605-branch/Source/_javascript_Core/ChangeLog (228515 => 228516)
--- branches/safari-605-branch/Source/_javascript_Core/ChangeLog 2018-02-15 17:30:11 UTC (rev 228515)
+++ branches/safari-605-branch/Source/_javascript_Core/ChangeLog 2018-02-15 17:30:14 UTC (rev 228516)
@@ -1,3 +1,29 @@
+2018-02-15 Jason Marcell <[email protected]>
+
+ Cherry-pick r228488. rdar://problem/37570860
+
+ 2018-02-14 Saam Barati <[email protected]>
+
+ Setting a VMTrap shouldn't look at topCallFrame since that may imply we're in C code and holding the malloc lock
+ https://bugs.webkit.org/show_bug.cgi?id=182801
+
+ Reviewed by Keith Miller.
+
+ VMTraps would sometimes install traps when it paused the JS thread when it
+ was in C code. This is wrong, as installing traps mallocs, and the JS thread
+ may have been holding the malloc lock while in C code. This could lead to a
+ deadlock when C code was holding the malloc lock.
+
+ This patch makes it so that we only install traps when we've proven the PC
+ is in JIT or LLInt code. If we're in JIT/LLInt code, we are guaranteed that
+ we're not holding the malloc lock.
+
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ (functionMallocInALoop):
+ * runtime/VMTraps.cpp:
+ (JSC::VMTraps::tryInstallTrapBreakpoints):
+
2018-02-13 Jason Marcell <[email protected]>
Cherry-pick r228420. rdar://problem/37521084
Modified: branches/safari-605-branch/Source/_javascript_Core/jsc.cpp (228515 => 228516)
--- branches/safari-605-branch/Source/_javascript_Core/jsc.cpp 2018-02-15 17:30:11 UTC (rev 228515)
+++ branches/safari-605-branch/Source/_javascript_Core/jsc.cpp 2018-02-15 17:30:14 UTC (rev 228516)
@@ -342,6 +342,7 @@
static EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionDisableRichSourceInfo(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionMallocInALoop(ExecState*);
struct Script {
enum class StrictMode {
@@ -599,6 +600,7 @@
addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
addFunction(vm, "disableRichSourceInfo", functionDisableRichSourceInfo, 0);
+ addFunction(vm, "mallocInALoop", functionMallocInALoop, 0);
}
void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
@@ -1748,6 +1750,16 @@
return JSValue::encode(jsUndefined());
}
+EncodedJSValue JSC_HOST_CALL functionMallocInALoop(ExecState*)
+{
+ Vector<void*> ptrs;
+ for (unsigned i = 0; i < 5000; ++i)
+ ptrs.append(fastMalloc(1024 * 2));
+ for (void* ptr : ptrs)
+ fastFree(ptr);
+ return JSValue::encode(jsUndefined());
+}
+
template<typename ValueType>
typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/VMTraps.cpp (228515 => 228516)
--- branches/safari-605-branch/Source/_javascript_Core/runtime/VMTraps.cpp 2018-02-15 17:30:11 UTC (rev 228515)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/VMTraps.cpp 2018-02-15 17:30:14 UTC (rev 228516)
@@ -72,23 +72,6 @@
return !vm.entryScope && !vm.ownerThread();
}
-inline CallFrame* sanitizedTopCallFrame(CallFrame* topCallFrame)
-{
-#if !defined(NDEBUG) && !CPU(ARM) && !CPU(MIPS)
- // prepareForExternalCall() in DFGSpeculativeJIT.h may set topCallFrame to a bad word
- // before calling native functions, but tryInstallTrapBreakpoints() below expects
- // topCallFrame to be null if not set.
-#if USE(JSVALUE64)
- const uintptr_t badBeefWord = 0xbadbeef0badbeef;
-#else
- const uintptr_t badBeefWord = 0xbadbeef;
-#endif
- if (topCallFrame == reinterpret_cast<CallFrame*>(badBeefWord))
- topCallFrame = nullptr;
-#endif
- return topCallFrame;
-}
-
static bool isSaneFrame(CallFrame* frame, CallFrame* calleeFrame, EntryFrame* entryFrame, StackBounds stackBounds)
{
if (reinterpret_cast<void*>(frame) >= reinterpret_cast<void*>(entryFrame))
@@ -104,22 +87,19 @@
// Let's get the thread to break at invalidation points if needed.
VM& vm = this->vm();
void* trapPC = context.trapPC;
+ // We must ensure we're in JIT/LLint code. If we are, we know a few things:
+ // - The JS thread isn't holding the malloc lock. Therefore, it's safe to malloc below.
+ // - The JS thread isn't holding the CodeBlockSet lock.
+ // If we're not in JIT/LLInt code, we can't run the C++ code below because it
+ // mallocs, and we must prove the JS thread isn't holding the malloc lock
+ // to be able to do that without risking a deadlock.
+ if (!isJITPC(trapPC) && !LLInt::isLLIntPC(trapPC))
+ return;
CallFrame* callFrame = reinterpret_cast<CallFrame*>(context.framePointer);
- auto& lock = vm.heap.codeBlockSet().getLock();
- // If the target thread is in C++ code it might be holding the codeBlockSet lock.
- // if it's in JIT code then it cannot be holding that lock but the GC might be.
- auto codeBlockSetLocker = isJITPC(trapPC) ? holdLock(lock) : tryHoldLock(lock);
- if (!codeBlockSetLocker)
- return; // Let the SignalSender try again later.
+ auto codeBlockSetLocker = holdLock(vm.heap.codeBlockSet().getLock());
- if (!isJITPC(trapPC) && !LLInt::isLLIntPC(trapPC)) {
- // We resort to topCallFrame to see if we can get anything
- // useful. We usually get here when we're executing C code.
- callFrame = sanitizedTopCallFrame(vm.topCallFrame);
- }
-
CodeBlock* foundCodeBlock = nullptr;
EntryFrame* entryFrame = vm.topEntryFrame;