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 ASAN_ENABLED && COMPILER(GCC_COMPATIBLE)
42#define EXCEPTION_SCOPE_POSITION_FOR_ASAN currentStackPointer()
43#else
44#define EXCEPTION_SCOPE_POSITION_FOR_ASAN nullptr
45#endif
46
47class ExceptionScope {
48public:
49 VM& vm() const { return m_vm; }
50 unsigned recursionDepth() const { return m_recursionDepth; }
51 Exception* exception() { return m_vm.exception(); }
52
53 ALWAYS_INLINE void assertNoException() { RELEASE_ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
54 ALWAYS_INLINE void releaseAssertNoException() { RELEASE_ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
55
56#if ASAN_ENABLED
57 const void* stackPosition() const { return m_location.stackPosition; }
58#else
59 const void* stackPosition() const { return this; }
60#endif
61
62protected:
63 ExceptionScope(VM&, ExceptionEventLocation);
64 ExceptionScope(const ExceptionScope&) = delete;
65 ExceptionScope(ExceptionScope&&) = default;
66 ~ExceptionScope();
67
68 JS_EXPORT_PRIVATE CString unexpectedExceptionMessage();
69
70 VM& m_vm;
71 ExceptionScope* m_previousScope;
72 ExceptionEventLocation m_location;
73 unsigned m_recursionDepth;
74};
75
76#else // not ENABLE(EXCEPTION_SCOPE_VERIFICATION)
77
78#define EXCEPTION_ASSERT(x) ASSERT(x)
79#define EXCEPTION_ASSERT_UNUSED(variable, assertion) ASSERT_UNUSED(variable, assertion)
80#define EXCEPTION_ASSERT_WITH_MESSAGE(assertion, message) ASSERT_WITH_MESSAGE(assertion, message)
81
82class ExceptionScope {
83public:
84 ALWAYS_INLINE VM& vm() const { return m_vm; }
85 ALWAYS_INLINE Exception* exception() { return m_vm.exception(); }
86
87 ALWAYS_INLINE void assertNoException() { ASSERT(!exception()); }
88 ALWAYS_INLINE void releaseAssertNoException() { RELEASE_ASSERT(!exception()); }
89
90protected:
91 ALWAYS_INLINE ExceptionScope(VM& vm)
92 : m_vm(vm)
93 { }
94 ExceptionScope(const ExceptionScope&) = delete;
95 ExceptionScope(ExceptionScope&&) = default;
96
97 ALWAYS_INLINE CString unexpectedExceptionMessage() { return { }; }
98
99 VM& m_vm;
100};
101
102#endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
103
104#define RETURN_IF_EXCEPTION(scope__, value__) do { \
105 if (UNLIKELY((scope__).exception())) \
106 return value__; \
107 } while (false)
108
109#define RELEASE_AND_RETURN(scope__, expression__) do { \
110 scope__.release(); \
111 return expression__; \
112 } while (false)
113
114} // namespace JSC
115