#include "config.h"
#include "ThrowScope.h"
#include "Exception.h"
#include "JSCInlines.h"
#include "VM.h"
namespace JSC {
#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
ThrowScope::ThrowScope(VM& vm, ExceptionEventLocation location)
: ExceptionScope(vm, location)
{
m_vm.verifyExceptionCheckNeedIsSatisfied(m_recursionDepth, m_location);
}
ThrowScope::~ThrowScope()
{
RELEASE_ASSERT(m_vm.m_topExceptionScope);
if (!m_isReleased)
m_vm.verifyExceptionCheckNeedIsSatisfied(m_recursionDepth, m_location);
else {
m_vm.m_needExceptionCheck = false;
}
bool willBeHandleByLLIntOrJIT = false;
const void* previousScopeStackPosition = m_previousScope ? m_previousScope->stackPosition() : nullptr;
void* topEntryFrame = m_vm.topEntryFrame;
if (topEntryFrame && previousScopeStackPosition > topEntryFrame)
willBeHandleByLLIntOrJIT = true;
if (!willBeHandleByLLIntOrJIT)
simulateThrow();
}
void ThrowScope::throwException(ExecState* exec, Exception* exception)
{
if (m_vm.exception() && m_vm.exception() != exception)
m_vm.verifyExceptionCheckNeedIsSatisfied(m_recursionDepth, m_location);
m_vm.throwException(exec, exception);
}
JSValue ThrowScope::throwException(ExecState* exec, JSValue error)
{
if (!error.isCell() || !jsDynamicCast<Exception*>(m_vm, error.asCell()))
m_vm.verifyExceptionCheckNeedIsSatisfied(m_recursionDepth, m_location);
return m_vm.throwException(exec, error);
}
JSObject* ThrowScope::throwException(ExecState* exec, JSObject* obj)
{
if (!jsDynamicCast<Exception*>(m_vm, obj))
m_vm.verifyExceptionCheckNeedIsSatisfied(m_recursionDepth, m_location);
return m_vm.throwException(exec, obj);
}
void ThrowScope::simulateThrow()
{
RELEASE_ASSERT(m_vm.m_topExceptionScope);
m_vm.m_simulatedThrowPointLocation = m_location;
m_vm.m_simulatedThrowPointRecursionDepth = m_recursionDepth;
m_vm.m_needExceptionCheck = true;
if (UNLIKELY(Options::dumpSimulatedThrows()))
m_vm.m_nativeStackTraceOfLastSimulatedThrow = StackTrace::captureStackTrace(Options::unexpectedExceptionStackTraceLimit());
}
#endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
}