Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_REGEXP_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
6 : #define V8_REGEXP_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
7 :
8 : #include "src/macro-assembler.h"
9 : #include "src/regexp/regexp-macro-assembler.h"
10 : #include "src/x64/assembler-x64.h"
11 : #include "src/zone/zone-chunk-list.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
17 : : public NativeRegExpMacroAssembler {
18 : public:
19 : RegExpMacroAssemblerX64(Isolate* isolate, Zone* zone, Mode mode,
20 : int registers_to_save);
21 : ~RegExpMacroAssemblerX64() override;
22 : int stack_limit_slack() override;
23 : void AdvanceCurrentPosition(int by) override;
24 : void AdvanceRegister(int reg, int by) override;
25 : void Backtrack() override;
26 : void Bind(Label* label) override;
27 : void CheckAtStart(Label* on_at_start) override;
28 : void CheckCharacter(uint32_t c, Label* on_equal) override;
29 : void CheckCharacterAfterAnd(uint32_t c, uint32_t mask,
30 : Label* on_equal) override;
31 : void CheckCharacterGT(uc16 limit, Label* on_greater) override;
32 : void CheckCharacterLT(uc16 limit, Label* on_less) override;
33 : // A "greedy loop" is a loop that is both greedy and with a simple
34 : // body. It has a particularly simple implementation.
35 : void CheckGreedyLoop(Label* on_tos_equals_current_position) override;
36 : void CheckNotAtStart(int cp_offset, Label* on_not_at_start) override;
37 : void CheckNotBackReference(int start_reg, bool read_backward,
38 : Label* on_no_match) override;
39 : void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward,
40 : bool unicode,
41 : Label* on_no_match) override;
42 : void CheckNotCharacter(uint32_t c, Label* on_not_equal) override;
43 : void CheckNotCharacterAfterAnd(uint32_t c, uint32_t mask,
44 : Label* on_not_equal) override;
45 : void CheckNotCharacterAfterMinusAnd(uc16 c, uc16 minus, uc16 mask,
46 : Label* on_not_equal) override;
47 : void CheckCharacterInRange(uc16 from, uc16 to, Label* on_in_range) override;
48 : void CheckCharacterNotInRange(uc16 from, uc16 to,
49 : Label* on_not_in_range) override;
50 : void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set) override;
51 :
52 : // Checks whether the given offset from the current position is before
53 : // the end of the string.
54 : void CheckPosition(int cp_offset, Label* on_outside_input) override;
55 : bool CheckSpecialCharacterClass(uc16 type, Label* on_no_match) override;
56 : void Fail() override;
57 : Handle<HeapObject> GetCode(Handle<String> source) override;
58 : void GoTo(Label* label) override;
59 : void IfRegisterGE(int reg, int comparand, Label* if_ge) override;
60 : void IfRegisterLT(int reg, int comparand, Label* if_lt) override;
61 : void IfRegisterEqPos(int reg, Label* if_eq) override;
62 : IrregexpImplementation Implementation() override;
63 : void LoadCurrentCharacter(int cp_offset, Label* on_end_of_input,
64 : bool check_bounds = true,
65 : int characters = 1) override;
66 : void PopCurrentPosition() override;
67 : void PopRegister(int register_index) override;
68 : void PushBacktrack(Label* label) override;
69 : void PushCurrentPosition() override;
70 : void PushRegister(int register_index,
71 : StackCheckFlag check_stack_limit) override;
72 : void ReadCurrentPositionFromRegister(int reg) override;
73 : void ReadStackPointerFromRegister(int reg) override;
74 : void SetCurrentPositionFromEnd(int by) override;
75 : void SetRegister(int register_index, int to) override;
76 : bool Succeed() override;
77 : void WriteCurrentPositionToRegister(int reg, int cp_offset) override;
78 : void ClearRegisters(int reg_from, int reg_to) override;
79 : void WriteStackPointerToRegister(int reg) override;
80 :
81 : // Called from RegExp if the stack-guard is triggered.
82 : // If the code object is relocated, the return address is fixed before
83 : // returning.
84 : // {raw_code} is an Address because this is called via ExternalReference.
85 : static int CheckStackGuardState(Address* return_address, Address raw_code,
86 : Address re_frame);
87 :
88 : private:
89 : // Offsets from rbp of function parameters and stored registers.
90 : static const int kFramePointer = 0;
91 : // Above the frame pointer - function parameters and return address.
92 : static const int kReturn_eip = kFramePointer + kSystemPointerSize;
93 : static const int kFrameAlign = kReturn_eip + kSystemPointerSize;
94 :
95 : #ifdef _WIN64
96 : // Parameters (first four passed as registers, but with room on stack).
97 : // In Microsoft 64-bit Calling Convention, there is room on the callers
98 : // stack (before the return address) to spill parameter registers. We
99 : // use this space to store the register passed parameters.
100 : static const int kInputString = kFrameAlign;
101 : // StartIndex is passed as 32 bit int.
102 : static const int kStartIndex = kInputString + kSystemPointerSize;
103 : static const int kInputStart = kStartIndex + kSystemPointerSize;
104 : static const int kInputEnd = kInputStart + kSystemPointerSize;
105 : static const int kRegisterOutput = kInputEnd + kSystemPointerSize;
106 : // For the case of global regular expression, we have room to store at least
107 : // one set of capture results. For the case of non-global regexp, we ignore
108 : // this value. NumOutputRegisters is passed as 32-bit value. The upper
109 : // 32 bit of this 64-bit stack slot may contain garbage.
110 : static const int kNumOutputRegisters = kRegisterOutput + kSystemPointerSize;
111 : static const int kStackHighEnd = kNumOutputRegisters + kSystemPointerSize;
112 : // DirectCall is passed as 32 bit int (values 0 or 1).
113 : static const int kDirectCall = kStackHighEnd + kSystemPointerSize;
114 : static const int kIsolate = kDirectCall + kSystemPointerSize;
115 : #else
116 : // In AMD64 ABI Calling Convention, the first six integer parameters
117 : // are passed as registers, and caller must allocate space on the stack
118 : // if it wants them stored. We push the parameters after the frame pointer.
119 : static const int kInputString = kFramePointer - kSystemPointerSize;
120 : static const int kStartIndex = kInputString - kSystemPointerSize;
121 : static const int kInputStart = kStartIndex - kSystemPointerSize;
122 : static const int kInputEnd = kInputStart - kSystemPointerSize;
123 : static const int kRegisterOutput = kInputEnd - kSystemPointerSize;
124 :
125 : // For the case of global regular expression, we have room to store at least
126 : // one set of capture results. For the case of non-global regexp, we ignore
127 : // this value.
128 : static const int kNumOutputRegisters = kRegisterOutput - kSystemPointerSize;
129 : static const int kStackHighEnd = kFrameAlign;
130 : static const int kDirectCall = kStackHighEnd + kSystemPointerSize;
131 : static const int kIsolate = kDirectCall + kSystemPointerSize;
132 : #endif
133 :
134 : #ifdef _WIN64
135 : // Microsoft calling convention has three callee-saved registers
136 : // (that we are using). We push these after the frame pointer.
137 : static const int kBackup_rsi = kFramePointer - kSystemPointerSize;
138 : static const int kBackup_rdi = kBackup_rsi - kSystemPointerSize;
139 : static const int kBackup_rbx = kBackup_rdi - kSystemPointerSize;
140 : static const int kLastCalleeSaveRegister = kBackup_rbx;
141 : #else
142 : // AMD64 Calling Convention has only one callee-save register that
143 : // we use. We push this after the frame pointer (and after the
144 : // parameters).
145 : static const int kBackup_rbx = kNumOutputRegisters - kSystemPointerSize;
146 : static const int kLastCalleeSaveRegister = kBackup_rbx;
147 : #endif
148 :
149 : static const int kSuccessfulCaptures =
150 : kLastCalleeSaveRegister - kSystemPointerSize;
151 : // When adding local variables remember to push space for them in
152 : // the frame in GetCode.
153 : static const int kStringStartMinusOne =
154 : kSuccessfulCaptures - kSystemPointerSize;
155 :
156 : // First register address. Following registers are below it on the stack.
157 : static const int kRegisterZero = kStringStartMinusOne - kSystemPointerSize;
158 :
159 : // Initial size of code buffer.
160 : static const int kRegExpCodeSize = 1024;
161 :
162 : // Load a number of characters at the given offset from the
163 : // current position, into the current-character register.
164 : void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
165 :
166 : // Check whether preemption has been requested.
167 : void CheckPreemption();
168 :
169 : // Check whether we are exceeding the stack limit on the backtrack stack.
170 : void CheckStackLimit();
171 :
172 : // Generate a call to CheckStackGuardState.
173 : void CallCheckStackGuardState();
174 :
175 : // The rbp-relative location of a regexp register.
176 : Operand register_location(int register_index);
177 :
178 : // The register containing the current character after LoadCurrentCharacter.
179 : inline Register current_character() { return rdx; }
180 :
181 : // The register containing the backtrack stack top. Provides a meaningful
182 : // name to the register.
183 : inline Register backtrack_stackpointer() { return rcx; }
184 :
185 : // The registers containing a self pointer to this code's Code object.
186 : inline Register code_object_pointer() { return r8; }
187 :
188 : // Byte size of chars in the string to match (decided by the Mode argument)
189 1074678 : inline int char_size() { return static_cast<int>(mode_); }
190 :
191 : // Equivalent to a conditional branch to the label, unless the label
192 : // is nullptr, in which case it is a conditional Backtrack.
193 : void BranchOrBacktrack(Condition condition, Label* to);
194 :
195 : void MarkPositionForCodeRelativeFixup() {
196 525853 : code_relative_fixup_positions_.push_back(masm_.pc_offset());
197 : }
198 :
199 : void FixupCodeRelativePositions();
200 :
201 : // Call and return internally in the generated code in a way that
202 : // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
203 : inline void SafeCall(Label* to);
204 : inline void SafeCallTarget(Label* label);
205 : inline void SafeReturn();
206 :
207 : // Pushes the value of a register on the backtrack stack. Decrements the
208 : // stack pointer (rcx) by a word size and stores the register's value there.
209 : inline void Push(Register source);
210 :
211 : // Pushes a value on the backtrack stack. Decrements the stack pointer (rcx)
212 : // by a word size and stores the value there.
213 : inline void Push(Immediate value);
214 :
215 : // Pushes the Code object relative offset of a label on the backtrack stack
216 : // (i.e., a backtrack target). Decrements the stack pointer (rcx)
217 : // by a word size and stores the value there.
218 : inline void Push(Label* label);
219 :
220 : // Pops a value from the backtrack stack. Reads the word at the stack pointer
221 : // (rcx) and increments it by a word size.
222 : inline void Pop(Register target);
223 :
224 : // Drops the top value from the backtrack stack without reading it.
225 : // Increments the stack pointer (rcx) by a word size.
226 : inline void Drop();
227 :
228 : inline void ReadPositionFromRegister(Register dst, int reg);
229 :
230 : Isolate* isolate() const { return masm_.isolate(); }
231 :
232 : MacroAssembler masm_;
233 : NoRootArrayScope no_root_array_scope_;
234 :
235 : ZoneChunkList<int> code_relative_fixup_positions_;
236 :
237 : // Which mode to generate code for (LATIN1 or UC16).
238 : Mode mode_;
239 :
240 : // One greater than maximal register index actually used.
241 : int num_registers_;
242 :
243 : // Number of registers to output at the end (the saved registers
244 : // are always 0..num_saved_registers_-1)
245 : int num_saved_registers_;
246 :
247 : // Labels used internally.
248 : Label entry_label_;
249 : Label start_label_;
250 : Label success_label_;
251 : Label backtrack_label_;
252 : Label exit_label_;
253 : Label check_preempt_label_;
254 : Label stack_overflow_label_;
255 : };
256 :
257 : } // namespace internal
258 : } // namespace v8
259 :
260 : #endif // V8_REGEXP_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
|