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