REGRESSION (r225695): Repro crash on yahoo login page
[WebKit-https.git] / Source / JavaScriptCore / yarr / YarrJIT.h
1 /*
2  * Copyright (C) 2009-2017 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 CPU(ARM64) || (CPU(X86_64) && !OS(WINDOWS))
42 #define JIT_ALL_PARENS_EXPRESSIONS
43 constexpr size_t patternContextBufferSize = 8192; // Space caller allocates to save nested parenthesis context
44 #endif
45
46 namespace JSC {
47
48 class VM;
49 class ExecutablePool;
50
51 namespace Yarr {
52
53 class YarrCodeBlock {
54 #if CPU(X86_64) || CPU(ARM64)
55 #ifdef JIT_ALL_PARENS_EXPRESSIONS
56     typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
57     typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
58     typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length, void*, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
59     typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length, void*, void* freeParenContext, unsigned parenContextSize) YARR_CALL;
60 #else
61     typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
62     typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
63     typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
64     typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
65 #endif
66 #else
67     typedef EncodedMatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
68     typedef EncodedMatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
69     typedef EncodedMatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
70     typedef EncodedMatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
71 #endif
72
73 public:
74     YarrCodeBlock()
75         : m_needFallBack(false)
76     {
77     }
78
79     ~YarrCodeBlock()
80     {
81     }
82
83     void setFallBack(bool fallback) { m_needFallBack = fallback; }
84     bool isFallBack() { return m_needFallBack; }
85
86     bool has8BitCode() { return m_ref8.size(); }
87     bool has16BitCode() { return m_ref16.size(); }
88     void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; }
89     void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; }
90
91     bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); }
92     bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); }
93     void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; }
94     void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; }
95
96 #ifdef JIT_ALL_PARENS_EXPRESSIONS
97     MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize)
98     {
99         ASSERT(has8BitCode());
100         return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output, freeParenContext, parenContextSize));
101     }
102
103     MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output, void* freeParenContext, unsigned parenContextSize)
104     {
105         ASSERT(has16BitCode());
106         return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output, freeParenContext, parenContextSize));
107     }
108
109     MatchResult execute(const LChar* input, unsigned start, unsigned length, void* freeParenContext, unsigned parenContextSize)
110     {
111         ASSERT(has8BitCodeMatchOnly());
112         return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length, 0, freeParenContext, parenContextSize));
113     }
114
115     MatchResult execute(const UChar* input, unsigned start, unsigned length, void* freeParenContext, unsigned parenContextSize)
116     {
117         ASSERT(has16BitCodeMatchOnly());
118         return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length, 0, freeParenContext, parenContextSize));
119     }
120 #else
121     MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output)
122     {
123         ASSERT(has8BitCode());
124         return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output));
125     }
126
127     MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output)
128     {
129         ASSERT(has16BitCode());
130         return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output));
131     }
132
133     MatchResult execute(const LChar* input, unsigned start, unsigned length)
134     {
135         ASSERT(has8BitCodeMatchOnly());
136         return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length));
137     }
138
139     MatchResult execute(const UChar* input, unsigned start, unsigned length)
140     {
141         ASSERT(has16BitCodeMatchOnly());
142         return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length));
143     }
144 #endif
145
146 #if ENABLE(REGEXP_TRACING)
147     void *get8BitMatchOnlyAddr()
148     {
149         if (!has8BitCodeMatchOnly())
150             return 0;
151
152         return m_matchOnly8.code().executableAddress();
153     }
154
155     void *get16BitMatchOnlyAddr()
156     {
157         if (!has16BitCodeMatchOnly())
158             return 0;
159
160         return m_matchOnly16.code().executableAddress();
161     }
162
163     void *get8BitMatchAddr()
164     {
165         if (!has8BitCode())
166             return 0;
167
168         return m_ref8.code().executableAddress();
169     }
170
171     void *get16BitMatchAddr()
172     {
173         if (!has16BitCode())
174             return 0;
175
176         return m_ref16.code().executableAddress();
177     }
178 #endif
179
180     size_t size() const
181     {
182         return m_ref8.size() + m_ref16.size() + m_matchOnly8.size() + m_matchOnly16.size();
183     }
184
185     void clear()
186     {
187         m_ref8 = MacroAssemblerCodeRef();
188         m_ref16 = MacroAssemblerCodeRef();
189         m_matchOnly8 = MacroAssemblerCodeRef();
190         m_matchOnly16 = MacroAssemblerCodeRef();
191         m_needFallBack = false;
192     }
193
194 private:
195     MacroAssemblerCodeRef m_ref8;
196     MacroAssemblerCodeRef m_ref16;
197     MacroAssemblerCodeRef m_matchOnly8;
198     MacroAssemblerCodeRef m_matchOnly16;
199     bool m_needFallBack;
200 };
201
202 enum YarrJITCompileMode {
203     MatchOnly,
204     IncludeSubpatterns
205 };
206 void jitCompile(YarrPattern&, YarrCharSize, VM*, YarrCodeBlock& jitObject, YarrJITCompileMode = IncludeSubpatterns);
207
208 } } // namespace JSC::Yarr
209
210 #endif