1/*
2 * Copyright (C) 2009-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 <Platform.h>
29
30#if ENABLE(YARR_JIT)
31
32#include "MacroAssemblerCodeRef.h"
33#include "MatchResult.h"
34#include "Yarr.h"
35#include "YarrPattern.h"
36
37#if CPU(X86) && !COMPILER(MSVC)
38#define YARR_CALL __attribute__ ((regparm (3)))
39#else
40#define YARR_CALL
41#endif
42
43#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
44constexpr size_t patternContextBufferSize = 8192; // Space caller allocates to save nested parenthesis context
45#endif
46
47namespace JSC {
48
49class VM;
50class ExecutablePool;
51
52namespace Yarr {
53
54enum class JITFailureReason : uint8_t {
55 DecodeSurrogatePair,
56 BackReference,
57 ForwardReference,
58 VariableCountedParenthesisWithNonZeroMinimum,
59 ParenthesizedSubpattern,
60 FixedCountParenthesizedSubpattern,
61 ExecutableMemoryAllocationFailure,
62};
63
64class YarrCodeBlock {
65#if CPU(X86_64) || CPU(ARM64)
66#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
67 typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
68 typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
69 typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length, void*, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
70 typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length, void*, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
71#else
72 typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
73 typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
74 typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
75 typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
76#endif
77#else
78 typedef EncodedMatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
79 typedef EncodedMatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
80 typedef EncodedMatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
81 typedef EncodedMatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
82#endif
83
84public:
85 YarrCodeBlock() = default;
86 ~YarrCodeBlock() { clear(); }
87
88 static void replaceCodeRef(MacroAssemblerCodeRef &target, const MacroAssemblerCodeRef &source);
89
90 void setFallBackWithFailureReason(JITFailureReason failureReason) { m_failureReason = failureReason; }
91 std::optional<JITFailureReason> failureReason() { return m_failureReason; }
92
93 bool has8BitCode() { return m_ref8.size(); }
94 bool has16BitCode() { return m_ref16.size(); }
95 void set8BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(target&: m_ref8, source: ref); }
96 void set16BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(target&: m_ref16, source: ref); }
97
98 bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); }
99 bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); }
100 void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly)
101 {
102 replaceCodeRef(target&: m_matchOnly8, source: matchOnly);
103 }
104 void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly)
105 {
106 replaceCodeRef(target&: m_matchOnly16, source: matchOnly);
107 }
108
109#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
110 bool usesPatternContextBuffer() { return m_usesPatternContextBuffer; }
111 void setUsesPatternContextBuffer() { m_usesPatternContextBuffer = true; }
112
113 MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize)
114 {
115 ASSERT(has8BitCode());
116 return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output, freeParenContext, parenContextSize));
117 }
118
119 MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize)
120 {
121 ASSERT(has16BitCode());
122 return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output, freeParenContext, parenContextSize));
123 }
124
125 MatchResult execute(const LChar* input, unsigned start, unsigned length, void* freeParenContext, unsigned parenContextSize)
126 {
127 ASSERT(has8BitCodeMatchOnly());
128 return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length, 0, freeParenContext, parenContextSize));
129 }
130
131 MatchResult execute(const UChar* input, unsigned start, unsigned length, void* freeParenContext, unsigned parenContextSize)
132 {
133 ASSERT(has16BitCodeMatchOnly());
134 return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length, 0, freeParenContext, parenContextSize));
135 }
136#else
137 MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output)
138 {
139 ASSERT(has8BitCode());
140 return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output));
141 }
142
143 MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output)
144 {
145 ASSERT(has16BitCode());
146 return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output));
147 }
148
149 MatchResult execute(const LChar* input, unsigned start, unsigned length)
150 {
151 ASSERT(has8BitCodeMatchOnly());
152 return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length));
153 }
154
155 MatchResult execute(const UChar* input, unsigned start, unsigned length)
156 {
157 ASSERT(has16BitCodeMatchOnly());
158 return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length));
159 }
160#endif
161
162#if ENABLE(REGEXP_TRACING)
163 void *get8BitMatchOnlyAddr()
164 {
165 if (!has8BitCodeMatchOnly())
166 return 0;
167
168 return m_matchOnly8.code().executableAddress();
169 }
170
171 void *get16BitMatchOnlyAddr()
172 {
173 if (!has16BitCodeMatchOnly())
174 return 0;
175
176 return m_matchOnly16.code().executableAddress();
177 }
178
179 void *get8BitMatchAddr()
180 {
181 if (!has8BitCode())
182 return 0;
183
184 return m_ref8.code().executableAddress();
185 }
186
187 void *get16BitMatchAddr()
188 {
189 if (!has16BitCode())
190 return 0;
191
192 return m_ref16.code().executableAddress();
193 }
194#endif
195
196 size_t size() const
197 {
198 return m_ref8.size() + m_ref16.size() + m_matchOnly8.size() + m_matchOnly16.size();
199 }
200
201 void clear()
202 {
203 replaceCodeRef(target&: m_ref8, source: MacroAssemblerCodeRef());
204 replaceCodeRef(target&: m_ref16, source: MacroAssemblerCodeRef());
205 replaceCodeRef(target&: m_matchOnly8, source: MacroAssemblerCodeRef());
206 replaceCodeRef(target&: m_matchOnly16, source: MacroAssemblerCodeRef());
207 m_failureReason = std::nullopt;
208 }
209
210private:
211 MacroAssemblerCodeRef m_ref8;
212 MacroAssemblerCodeRef m_ref16;
213 MacroAssemblerCodeRef m_matchOnly8;
214 MacroAssemblerCodeRef m_matchOnly16;
215#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
216 bool m_usesPatternContextBuffer;
217#endif
218 std::optional<JITFailureReason> m_failureReason;
219};
220
221enum YarrJITCompileMode {
222 MatchOnly,
223 IncludeSubpatterns
224};
225void jitCompile(YarrPattern&, YarrCharSize, VM*, YarrCodeBlock& jitObject, YarrJITCompileMode = IncludeSubpatterns);
226
227} } // namespace JSC::Yarr
228
229#endif
230

source code of qtdeclarative/src/3rdparty/masm/yarr/YarrJIT.h