Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (234334 => 234335)
--- trunk/Source/_javascript_Core/ChangeLog 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-07-27 22:44:47 UTC (rev 234335)
@@ -1,3 +1,42 @@
+2018-07-27 Mark Lam <[email protected]>
+
+ Add some crash info to Heap::checkConn() RELEASE_ASSERTs.
+ https://bugs.webkit.org/show_bug.cgi?id=188123
+ <rdar://problem/42672268>
+
+ Reviewed by Keith Miller.
+
+ 1. Add VM::m_id and Heap::m_lastPhase fields. Both of these fit within existing
+ padding space in VM and Heap, and should not cost any measurable perf to
+ initialize and update.
+
+ 2. Add some crash info to the RELEASE_ASSERTs in Heap::checkConn():
+
+ worldState tells us the value we failed the assertion on.
+
+ m_lastPhase, m_currentPhase, and m_nextPhase tells us the GC phase transition
+ that led us here.
+
+ VM::id(), and VM::numberOfIDs() tells us how many VMs may be in play.
+
+ VM::isEntered() tells us if the current VM is currently executing JS code.
+
+ Some of this data may be redundant, but the redundancy is intentional so that
+ we can double check what is really happening at the time of crash.
+
+ * heap/Heap.cpp:
+ (JSC::asInt):
+ (JSC::Heap::checkConn):
+ (JSC::Heap::changePhase):
+ * heap/Heap.h:
+ * runtime/VM.cpp:
+ (JSC::VM::nextID):
+ (JSC::VM::VM):
+ * runtime/VM.h:
+ (JSC::VM::numberOfIDs):
+ (JSC::VM::id const):
+ (JSC::VM::isEntered const):
+
2018-07-25 Yusuke Suzuki <[email protected]>
[JSC] Record CoW status in ArrayProfile correctly
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (234334 => 234335)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2018-07-27 22:44:47 UTC (rev 234335)
@@ -1121,14 +1121,20 @@
}
}
+ALWAYS_INLINE int asInt(CollectorPhase phase)
+{
+ return static_cast<int>(phase);
+}
+
void Heap::checkConn(GCConductor conn)
{
+ unsigned worldState = m_worldState.load();
switch (conn) {
case GCConductor::Mutator:
- RELEASE_ASSERT(m_worldState.load() & mutatorHasConnBit);
+ RELEASE_ASSERT(worldState & mutatorHasConnBit, worldState, asInt(m_lastPhase), asInt(m_currentPhase), asInt(m_nextPhase), vm()->id(), VM::numberOfIDs(), vm()->isEntered());
return;
case GCConductor::Collector:
- RELEASE_ASSERT(!(m_worldState.load() & mutatorHasConnBit));
+ RELEASE_ASSERT(!(worldState & mutatorHasConnBit), worldState, asInt(m_lastPhase), asInt(m_currentPhase), asInt(m_nextPhase), vm()->id(), VM::numberOfIDs(), vm()->isEntered());
return;
}
RELEASE_ASSERT_NOT_REACHED();
@@ -1519,6 +1525,7 @@
{
checkConn(conn);
+ m_lastPhase = m_currentPhase;
m_nextPhase = nextPhase;
return finishChangingPhase(conn);
Modified: trunk/Source/_javascript_Core/heap/Heap.h (234334 => 234335)
--- trunk/Source/_javascript_Core/heap/Heap.h 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2018-07-27 22:44:47 UTC (rev 234335)
@@ -693,6 +693,7 @@
GCRequest m_currentRequest;
Ticket m_lastServedTicket { 0 };
Ticket m_lastGrantedTicket { 0 };
+ CollectorPhase m_lastPhase { CollectorPhase::NotRunning };
CollectorPhase m_currentPhase { CollectorPhase::NotRunning };
CollectorPhase m_nextPhase { CollectorPhase::NotRunning };
bool m_threadShouldStop { false };
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (234334 => 234335)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2018-07-27 22:44:47 UTC (rev 234335)
@@ -182,6 +182,8 @@
bool VM::s_canUseJIT = false;
#endif
+Atomic<unsigned> VM::s_numberOfIDs;
+
// Note: Platform.h will enforce that ENABLE(ASSEMBLER) is true if either
// ENABLE(JIT) or ENABLE(YARR_JIT) or both are enabled. The code below
// just checks for ENABLE(JIT) or ENABLE(YARR_JIT) with this premise in mind.
@@ -247,8 +249,20 @@
return !canUseJIT() || Options::forceMiniVMMode();
}
+inline unsigned VM::nextID()
+{
+ for (;;) {
+ unsigned currentNumberOfIDs = s_numberOfIDs.load();
+ unsigned newID = currentNumberOfIDs + 1;
+ if (s_numberOfIDs.compareExchangeWeak(currentNumberOfIDs, newID))
+ return newID;
+ }
+}
+
+
VM::VM(VMType vmType, HeapType heapType)
- : m_apiLock(adoptRef(new JSLock(this)))
+ : m_id(nextID())
+ , m_apiLock(adoptRef(new JSLock(this)))
#if USE(CF)
, m_runLoop(CFRunLoopGetCurrent())
#endif // USE(CF)
Modified: trunk/Source/_javascript_Core/runtime/VM.h (234334 => 234335)
--- trunk/Source/_javascript_Core/runtime/VM.h 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2018-07-27 22:44:47 UTC (rev 234335)
@@ -289,7 +289,16 @@
JS_EXPORT_PRIVATE SamplingProfiler& ensureSamplingProfiler(RefPtr<Stopwatch>&&);
#endif
+ static unsigned numberOfIDs() { return s_numberOfIDs.load(); }
+ unsigned id() const { return m_id; }
+ bool isEntered() const { return !!entryScope; }
+
private:
+ unsigned nextID();
+
+ static Atomic<unsigned> s_numberOfIDs;
+
+ unsigned m_id;
RefPtr<JSLock> m_apiLock;
#if USE(CF)
// These need to be initialized before heap below.
Modified: trunk/Source/WTF/ChangeLog (234334 => 234335)
--- trunk/Source/WTF/ChangeLog 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/WTF/ChangeLog 2018-07-27 22:44:47 UTC (rev 234335)
@@ -1,3 +1,44 @@
+2018-07-27 Mark Lam <[email protected]>
+
+ Add some crash info to Heap::checkConn() RELEASE_ASSERTs.
+ https://bugs.webkit.org/show_bug.cgi?id=188123
+ <rdar://problem/42672268>
+
+ Reviewed by Keith Miller.
+
+ 1. Rename STUFF_FOR_CRASH_REGISTERx to CRASH_GPRx. These are only used in
+ locally in Assertions.cpp. There is little to no chance of a name collision,
+ and the shorter names will be much easier to read and grok in the code.
+
+ 2. Added an additional 2 registers so that we can pass more info.
+
+ 3. Change the WTFCrashWithInfo() implementations to issue only a single asm
+ statement so that the compiler does not inadvertently move values out of the
+ CRASH_GPRs that we want them to be in.
+
+ 4. Use register targeting for local variables to get the compiler to put our
+ desired values in specific registers. For how this works, see
+ https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables
+
+ "The only supported use for this feature is to specify registers for input and
+ output operands when calling Extended asm (see Extended Asm). This may be
+ necessary if the constraints for a particular machine don’t provide sufficient
+ control to select the desired register."
+
+ 5. Enhance ASSERT, ASSERT_UNUSED, RELEASE_ASSERT, RELEASE_ASSERT_NOT_REACHED to
+ accept crash info arguments. We no longer need to use an if statement with a
+ call to CRASH_WITH_INFO instead of these assertions. The only case not handled
+ yet is one where we might want to dataLog some info before the crash. I'll
+ add that functionality in a subsequent patch.
+
+ 6. Move UNREACHABLE_FOR_PLATFORM to the bottom of Assertions.h because it depends
+ on the definition of RELEASE_ASSERT_NOT_REACHED, which now depends on the
+ definiton of CRASH_WITH_INFO.
+
+ * wtf/Assertions.cpp:
+ (WTFCrashWithInfo):
+ * wtf/Assertions.h:
+
2018-07-27 Alex Christensen <[email protected]>
Make CompletionHandler more const correct
Modified: trunk/Source/WTF/wtf/Assertions.cpp (234334 => 234335)
--- trunk/Source/WTF/wtf/Assertions.cpp 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/WTF/wtf/Assertions.cpp 2018-07-27 22:44:47 UTC (rev 234335)
@@ -566,76 +566,115 @@
#if OS(DARWIN) && (CPU(X86_64) || CPU(ARM64))
#if CPU(X86_64)
-#define STUFF_REGISTER_FOR_CRASH(reg, info) __asm__ volatile ("movq %0, %%" reg : : "r" (static_cast<uint64_t>(info)) : reg)
+#define CRASH_INST "int3"
+
// This ordering was chosen to be consistent with JSC's JIT asserts. We probably shouldn't change this ordering
// since it would make tooling crash reports much harder. If, for whatever reason, we decide to change the ordering
// here we should update the abortWithuint64_t functions.
-#define STUFF_FOR_CRASH_REGISTER1 "r11"
-#define STUFF_FOR_CRASH_REGISTER2 "r10"
-#define STUFF_FOR_CRASH_REGISTER3 "r9"
-#define STUFF_FOR_CRASH_REGISTER4 "r8"
-#define STUFF_FOR_CRASH_REGISTER5 "r15"
+#define CRASH_GPR0 "r11"
+#define CRASH_GPR1 "r10"
+#define CRASH_GPR2 "r9"
+#define CRASH_GPR3 "r8"
+#define CRASH_GPR4 "r15"
+#define CRASH_GPR5 "r14"
+#define CRASH_GPR6 "r13"
#elif CPU(ARM64) // CPU(X86_64)
-#define STUFF_REGISTER_FOR_CRASH(reg, info) __asm__ volatile ("mov " reg ", %0" : : "r" (static_cast<uint64_t>(info)) : reg)
+#define CRASH_INST "brk #0"
+
// See comment above on the ordering.
-#define STUFF_FOR_CRASH_REGISTER1 "x16"
-#define STUFF_FOR_CRASH_REGISTER2 "x17"
-#define STUFF_FOR_CRASH_REGISTER3 "x18"
-#define STUFF_FOR_CRASH_REGISTER4 "x19"
-#define STUFF_FOR_CRASH_REGISTER5 "x20"
+#define CRASH_GPR0 "x16"
+#define CRASH_GPR1 "x17"
+#define CRASH_GPR2 "x18"
+#define CRASH_GPR3 "x19"
+#define CRASH_GPR4 "x20"
+#define CRASH_GPR5 "x21"
+#define CRASH_GPR6 "x22"
#endif // CPU(ARM64)
+void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5, uint64_t misc6)
+{
+ register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
+ register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
+ register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
+ register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
+ register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
+ register uint64_t misc5GPR asm(CRASH_GPR5) = misc5;
+ register uint64_t misc6GPR asm(CRASH_GPR6) = misc6;
+ __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR), "r"(misc6GPR));
+ __builtin_unreachable();
+}
+
+void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5)
+{
+ register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
+ register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
+ register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
+ register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
+ register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
+ register uint64_t misc5GPR asm(CRASH_GPR5) = misc5;
+ __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR));
+ __builtin_unreachable();
+}
+
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4)
{
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER4, misc3);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER5, misc4);
- CRASH();
+ register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
+ register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
+ register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
+ register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
+ register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
+ __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR));
+ __builtin_unreachable();
}
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3)
{
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER4, misc3);
- CRASH();
+ register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
+ register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
+ register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
+ register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
+ __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR));
+ __builtin_unreachable();
}
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2)
{
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
- CRASH();
+ register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
+ register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
+ register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
+ __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR));
+ __builtin_unreachable();
}
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1)
{
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
- CRASH();
+ register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
+ register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
+ __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR));
+ __builtin_unreachable();
}
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason)
{
- STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
- CRASH();
+ register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
+ __asm__ volatile (CRASH_INST : : "r"(reasonGPR));
+ __builtin_unreachable();
}
void WTFCrashWithInfo(int, const char*, const char*, int)
{
- CRASH();
+ __asm__ volatile (CRASH_INST : : );
+ __builtin_unreachable();
}
#else
+void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
+void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t) { CRASH(); }
Modified: trunk/Source/WTF/wtf/Assertions.h (234334 => 234335)
--- trunk/Source/WTF/wtf/Assertions.h 2018-07-27 22:33:52 UTC (rev 234334)
+++ trunk/Source/WTF/wtf/Assertions.h 2018-07-27 22:44:47 UTC (rev 234335)
@@ -289,15 +289,15 @@
#if ASSERT_DISABLED
-#define ASSERT(assertion) ((void)0)
+#define ASSERT(assertion, ...) ((void)0)
#define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ((void)0)
#define ASSERT_AT(assertion, file, line, function) ((void)0)
-#define ASSERT_NOT_REACHED() ((void)0)
+#define ASSERT_NOT_REACHED(...) ((void)0)
#define ASSERT_NOT_IMPLEMENTED_YET() ((void)0)
#define ASSERT_IMPLIES(condition, assertion) ((void)0)
#define NO_RETURN_DUE_TO_ASSERT
-#define ASSERT_UNUSED(variable, assertion) ((void)variable)
+#define ASSERT_UNUSED(variable, assertion, ...) ((void)variable)
#if ENABLE(SECURITY_ASSERTIONS)
#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
@@ -314,10 +314,10 @@
#else
-#define ASSERT(assertion) do { \
+#define ASSERT(assertion, ...) do { \
if (!(assertion)) { \
WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
- CRASH(); \
+ CRASH_WITH_INFO(__VA_ARGS__); \
} \
} while (0)
@@ -335,9 +335,9 @@
} \
} while (0)
-#define ASSERT_NOT_REACHED() do { \
+#define ASSERT_NOT_REACHED(...) do { \
WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
- CRASH(); \
+ CRASH_WITH_INFO(__VA_ARGS__); \
} while (0)
#define ASSERT_NOT_IMPLEMENTED_YET() do { \
@@ -352,7 +352,7 @@
} \
} while (0)
-#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
+#define ASSERT_UNUSED(variable, assertion, ...) ASSERT(assertion, __VA_ARGS__)
#define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
@@ -510,42 +510,26 @@
/* RELEASE_ASSERT */
#if ASSERT_DISABLED
-#define RELEASE_ASSERT(assertion) do { \
+#define RELEASE_ASSERT(assertion, ...) do { \
if (UNLIKELY(!(assertion))) \
- CRASH(); \
+ CRASH_WITH_INFO(__VA_ARGS__); \
} while (0)
#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
#define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) RELEASE_ASSERT(assertion)
-#define RELEASE_ASSERT_NOT_REACHED() CRASH()
+#define RELEASE_ASSERT_NOT_REACHED(...) CRASH_WITH_INFO(__VA_ARGS__)
#else
-#define RELEASE_ASSERT(assertion) ASSERT(assertion)
+#define RELEASE_ASSERT(assertion, ...) ASSERT(assertion, __VA_ARGS__)
#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
#define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT_WITH_SECURITY_IMPLICATION(assertion)
#define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
#endif
-/* UNREACHABLE_FOR_PLATFORM */
-
-#if COMPILER(CLANG)
-// This would be a macro except that its use of #pragma works best around
-// a function. Hence it uses macro naming convention.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wmissing-noreturn"
-static inline void UNREACHABLE_FOR_PLATFORM()
-{
- // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
- // going.
- RELEASE_ASSERT_NOT_REACHED();
-}
-#pragma clang diagnostic pop
-#else
-#define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
-#endif
-
#ifdef __cplusplus
// The combination of line, file, function, and counter should be a unique number per call to this crash. This tricks the compiler into not coalescing calls to WTFCrashWithInfo.
// The easiest way to fill these values per translation unit is to pass __LINE__, __FILE__, WTF_PRETTY_FUNCTION, and __COUNTER__.
+WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5, uint64_t misc6);
+WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5);
WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4);
WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3);
WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2);
@@ -592,6 +576,30 @@
#define CRASH_WITH_SECURITY_IMPLICATION_AND_INFO CRASH_WITH_INFO
#endif // CRASH_WITH_SECURITY_IMPLICATION_AND_INFO
-#endif // __cplusplus
+#else /* not __cplusplus */
+#ifndef CRASH_WITH_INFO
+#define CRASH_WITH_INFO() CRASH()
+#endif
+
+#endif /* __cplusplus */
+
+/* UNREACHABLE_FOR_PLATFORM */
+
+#if COMPILER(CLANG)
+// This would be a macro except that its use of #pragma works best around
+// a function. Hence it uses macro naming convention.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+static inline void UNREACHABLE_FOR_PLATFORM()
+{
+ // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
+ // going.
+ RELEASE_ASSERT_NOT_REACHED();
+}
+#pragma clang diagnostic pop
+#else
+#define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
+#endif
+
#endif /* WTF_Assertions_h */