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