1/*
2 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "VM.h"
29#include <wtf/StackPointer.h>
30
31namespace JSC {
32
33class Exception;
34
35#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
36
37#define EXCEPTION_ASSERT(assertion) RELEASE_ASSERT(assertion)
38#define EXCEPTION_ASSERT_UNUSED(variable, assertion) RELEASE_ASSERT(assertion)
39#define EXCEPTION_ASSERT_WITH_MESSAGE(assertion, message) RELEASE_ASSERT_WITH_MESSAGE(assertion, message)
40
41#if ENABLE(C_LOOP)
42#define EXCEPTION_SCOPE_POSITION_FOR_ASAN(vm__) (vm__).currentCLoopStackPointer()
43#elif ASAN_ENABLED && COMPILER(GCC_COMPATIBLE)
44#define EXCEPTION_SCOPE_POSITION_FOR_ASAN(vm__) currentStackPointer()
45#else
46#define EXCEPTION_SCOPE_POSITION_FOR_ASAN(vm__) nullptr
47#endif
48
49class ExceptionScope {
50public:
51 VM& vm() const { return m_vm; }
52 unsigned recursionDepth() const { return m_recursionDepth; }
53 Exception* exception() { return m_vm.exception(); }
54
55 ALWAYS_INLINE void assertNoException() { RELEASE_ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
56 ALWAYS_INLINE void releaseAssertNoException() { RELEASE_ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
57
58#if ASAN_ENABLED || ENABLE(C_LOOP)
59 const void* stackPosition() const { return m_location.stackPosition; }
60#else
61 const void* stackPosition() const { return this; }
62#endif
63
64protected:
65 ExceptionScope(VM&, ExceptionEventLocation);
66 ExceptionScope(const ExceptionScope&) = delete;
67 ExceptionScope(ExceptionScope&&) = default;
68 ~ExceptionScope();
69
70 JS_EXPORT_PRIVATE CString unexpectedExceptionMessage();
71
72 VM& m_vm;
73 ExceptionScope* m_previousScope;
74 ExceptionEventLocation m_location;
75 unsigned m_recursionDepth;
76};
77
78#else // not ENABLE(EXCEPTION_SCOPE_VERIFICATION)
79
80#define EXCEPTION_ASSERT(x) ASSERT(x)
81#define EXCEPTION_ASSERT_UNUSED(variable, assertion) ASSERT_UNUSED(variable, assertion)
82#define EXCEPTION_ASSERT_WITH_MESSAGE(assertion, message) ASSERT_WITH_MESSAGE(assertion, message)
83
84class ExceptionScope {
85public:
86 ALWAYS_INLINE VM& vm() const { return m_vm; }
87 ALWAYS_INLINE Exception* exception() { return m_vm.exception(); }
88
89 ALWAYS_INLINE void assertNoException() { ASSERT(!exception()); }
90 ALWAYS_INLINE void releaseAssertNoException() { RELEASE_ASSERT(!exception()); }
91
92protected:
93 ALWAYS_INLINE ExceptionScope(VM& vm)
94 : m_vm(vm)
95 { }
96 ExceptionScope(const ExceptionScope&) = delete;
97 ExceptionScope(ExceptionScope&&) = default;
98
99 ALWAYS_INLINE CString unexpectedExceptionMessage() { return { }; }
100
101 VM& m_vm;
102};
103
104#endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
105
106#define RETURN_IF_EXCEPTION(scope__, value__) do { \
107 if (UNLIKELY((scope__).exception())) \
108 return value__; \
109 } while (false)
110
111#define RELEASE_AND_RETURN(scope__, expression__) do { \
112 scope__.release(); \
113 return expression__; \
114 } while (false)
115
116} // namespace JSC
117