1/*
2 * Copyright (C) 2009 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#ifndef YarrJIT_h
27#define YarrJIT_h
28
29#if ENABLE(YARR_JIT)
30
31#include "VM.h"
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
43namespace JSC {
44
45class VM;
46class ExecutablePool;
47
48namespace Yarr {
49
50class YarrCodeBlock {
51#if CPU(X86_64) || CPU(ARM64)
52    typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
53    typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
54    typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
55    typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
56#else
57    typedef EncodedMatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
58    typedef EncodedMatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
59    typedef EncodedMatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
60    typedef EncodedMatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
61#endif
62
63public:
64    YarrCodeBlock()
65        : m_needFallBack(false)
66    {
67    }
68
69    ~YarrCodeBlock()
70    {
71    }
72
73    void setFallBack(bool fallback) { m_needFallBack = fallback; }
74    bool isFallBack() { return m_needFallBack; }
75
76    bool has8BitCode() { return m_ref8.size(); }
77    bool has16BitCode() { return m_ref16.size(); }
78    void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; }
79    void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; }
80
81    bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); }
82    bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); }
83    void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; }
84    void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; }
85
86    MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output)
87    {
88        ASSERT(has8BitCode());
89        return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output));
90    }
91
92    MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output)
93    {
94        ASSERT(has16BitCode());
95        return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output));
96    }
97
98    MatchResult execute(const LChar* input, unsigned start, unsigned length)
99    {
100        ASSERT(has8BitCodeMatchOnly());
101        return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length));
102    }
103
104    MatchResult execute(const UChar* input, unsigned start, unsigned length)
105    {
106        ASSERT(has16BitCodeMatchOnly());
107        return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length));
108    }
109
110#if ENABLE(REGEXP_TRACING)
111    void *get8BitMatchOnlyAddr()
112    {
113        if (!has8BitCodeMatchOnly())
114            return 0;
115
116        return m_matchOnly8.code().executableAddress();
117    }
118
119    void *get16BitMatchOnlyAddr()
120    {
121        if (!has16BitCodeMatchOnly())
122            return 0;
123
124        return m_matchOnly16.code().executableAddress();
125    }
126
127    void *get8BitMatchAddr()
128    {
129        if (!has8BitCode())
130            return 0;
131
132        return m_ref8.code().executableAddress();
133    }
134
135    void *get16BitMatchAddr()
136    {
137        if (!has16BitCode())
138            return 0;
139
140        return m_ref16.code().executableAddress();
141    }
142#endif
143
144    void clear()
145    {
146        m_ref8 = MacroAssemblerCodeRef();
147        m_ref16 = MacroAssemblerCodeRef();
148        m_matchOnly8 = MacroAssemblerCodeRef();
149        m_matchOnly16 = MacroAssemblerCodeRef();
150        m_needFallBack = false;
151    }
152
153private:
154    MacroAssemblerCodeRef m_ref8;
155    MacroAssemblerCodeRef m_ref16;
156    MacroAssemblerCodeRef m_matchOnly8;
157    MacroAssemblerCodeRef m_matchOnly16;
158    bool m_needFallBack;
159};
160
161enum YarrJITCompileMode {
162    MatchOnly,
163    IncludeSubpatterns
164};
165void jitCompile(YarrPattern&, YarrCharSize, VM*, YarrCodeBlock& jitObject, YarrJITCompileMode = IncludeSubpatterns);
166
167} } // namespace JSC::Yarr
168
169#endif
170
171#endif // YarrJIT_h
172