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