OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #if V8_TARGET_ARCH_A64 | 30 #if V8_TARGET_ARCH_ARM64 |
31 | 31 |
32 #include "cpu-profiler.h" | 32 #include "cpu-profiler.h" |
33 #include "unicode.h" | 33 #include "unicode.h" |
34 #include "log.h" | 34 #include "log.h" |
35 #include "code-stubs.h" | 35 #include "code-stubs.h" |
36 #include "regexp-stack.h" | 36 #include "regexp-stack.h" |
37 #include "macro-assembler.h" | 37 #include "macro-assembler.h" |
38 #include "regexp-macro-assembler.h" | 38 #include "regexp-macro-assembler.h" |
39 #include "a64/regexp-macro-assembler-a64.h" | 39 #include "arm64/regexp-macro-assembler-arm64.h" |
40 | 40 |
41 namespace v8 { | 41 namespace v8 { |
42 namespace internal { | 42 namespace internal { |
43 | 43 |
44 #ifndef V8_INTERPRETED_REGEXP | 44 #ifndef V8_INTERPRETED_REGEXP |
45 /* | 45 /* |
46 * This assembler uses the following register assignment convention: | 46 * This assembler uses the following register assignment convention: |
47 * - w19 : Used to temporarely store a value before a call to C code. | 47 * - w19 : Used to temporarely store a value before a call to C code. |
48 * See CheckNotBackReferenceIgnoreCase. | 48 * See CheckNotBackReferenceIgnoreCase. |
49 * - x20 : Pointer to the current code object (Code*), | 49 * - x20 : Pointer to the current code object (Code*), |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 * Address input_start, | 117 * Address input_start, |
118 * Address input_end, | 118 * Address input_end, |
119 * int* output, | 119 * int* output, |
120 * int output_size, | 120 * int output_size, |
121 * Address stack_base, | 121 * Address stack_base, |
122 * bool direct_call = false, | 122 * bool direct_call = false, |
123 * Address secondary_return_address, // Only used by native call. | 123 * Address secondary_return_address, // Only used by native call. |
124 * Isolate* isolate) | 124 * Isolate* isolate) |
125 * The call is performed by NativeRegExpMacroAssembler::Execute() | 125 * The call is performed by NativeRegExpMacroAssembler::Execute() |
126 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro | 126 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro |
127 * in a64/simulator-a64.h. | 127 * in arm64/simulator-arm64.h. |
128 * When calling as a non-direct call (i.e., from C++ code), the return address | 128 * When calling as a non-direct call (i.e., from C++ code), the return address |
129 * area is overwritten with the LR register by the RegExp code. When doing a | 129 * area is overwritten with the LR register by the RegExp code. When doing a |
130 * direct call from generated code, the return address is placed there by | 130 * direct call from generated code, the return address is placed there by |
131 * the calling code, as in a normal exit frame. | 131 * the calling code, as in a normal exit frame. |
132 */ | 132 */ |
133 | 133 |
134 #define __ ACCESS_MASM(masm_) | 134 #define __ ACCESS_MASM(masm_) |
135 | 135 |
136 RegExpMacroAssemblerA64::RegExpMacroAssemblerA64( | 136 RegExpMacroAssemblerARM64::RegExpMacroAssemblerARM64( |
137 Mode mode, | 137 Mode mode, |
138 int registers_to_save, | 138 int registers_to_save, |
139 Zone* zone) | 139 Zone* zone) |
140 : NativeRegExpMacroAssembler(zone), | 140 : NativeRegExpMacroAssembler(zone), |
141 masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)), | 141 masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)), |
142 mode_(mode), | 142 mode_(mode), |
143 num_registers_(registers_to_save), | 143 num_registers_(registers_to_save), |
144 num_saved_registers_(registers_to_save), | 144 num_saved_registers_(registers_to_save), |
145 entry_label_(), | 145 entry_label_(), |
146 start_label_(), | 146 start_label_(), |
147 success_label_(), | 147 success_label_(), |
148 backtrack_label_(), | 148 backtrack_label_(), |
149 exit_label_() { | 149 exit_label_() { |
150 __ SetStackPointer(csp); | 150 __ SetStackPointer(csp); |
151 ASSERT_EQ(0, registers_to_save % 2); | 151 ASSERT_EQ(0, registers_to_save % 2); |
152 // We can cache at most 16 W registers in x0-x7. | 152 // We can cache at most 16 W registers in x0-x7. |
153 STATIC_ASSERT(kNumCachedRegisters <= 16); | 153 STATIC_ASSERT(kNumCachedRegisters <= 16); |
154 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); | 154 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); |
155 __ B(&entry_label_); // We'll write the entry code later. | 155 __ B(&entry_label_); // We'll write the entry code later. |
156 __ Bind(&start_label_); // And then continue from here. | 156 __ Bind(&start_label_); // And then continue from here. |
157 } | 157 } |
158 | 158 |
159 | 159 |
160 RegExpMacroAssemblerA64::~RegExpMacroAssemblerA64() { | 160 RegExpMacroAssemblerARM64::~RegExpMacroAssemblerARM64() { |
161 delete masm_; | 161 delete masm_; |
162 // Unuse labels in case we throw away the assembler without calling GetCode. | 162 // Unuse labels in case we throw away the assembler without calling GetCode. |
163 entry_label_.Unuse(); | 163 entry_label_.Unuse(); |
164 start_label_.Unuse(); | 164 start_label_.Unuse(); |
165 success_label_.Unuse(); | 165 success_label_.Unuse(); |
166 backtrack_label_.Unuse(); | 166 backtrack_label_.Unuse(); |
167 exit_label_.Unuse(); | 167 exit_label_.Unuse(); |
168 check_preempt_label_.Unuse(); | 168 check_preempt_label_.Unuse(); |
169 stack_overflow_label_.Unuse(); | 169 stack_overflow_label_.Unuse(); |
170 } | 170 } |
171 | 171 |
172 int RegExpMacroAssemblerA64::stack_limit_slack() { | 172 int RegExpMacroAssemblerARM64::stack_limit_slack() { |
173 return RegExpStack::kStackLimitSlack; | 173 return RegExpStack::kStackLimitSlack; |
174 } | 174 } |
175 | 175 |
176 | 176 |
177 void RegExpMacroAssemblerA64::AdvanceCurrentPosition(int by) { | 177 void RegExpMacroAssemblerARM64::AdvanceCurrentPosition(int by) { |
178 if (by != 0) { | 178 if (by != 0) { |
179 __ Add(current_input_offset(), | 179 __ Add(current_input_offset(), |
180 current_input_offset(), by * char_size()); | 180 current_input_offset(), by * char_size()); |
181 } | 181 } |
182 } | 182 } |
183 | 183 |
184 | 184 |
185 void RegExpMacroAssemblerA64::AdvanceRegister(int reg, int by) { | 185 void RegExpMacroAssemblerARM64::AdvanceRegister(int reg, int by) { |
186 ASSERT((reg >= 0) && (reg < num_registers_)); | 186 ASSERT((reg >= 0) && (reg < num_registers_)); |
187 if (by != 0) { | 187 if (by != 0) { |
188 Register to_advance; | 188 Register to_advance; |
189 RegisterState register_state = GetRegisterState(reg); | 189 RegisterState register_state = GetRegisterState(reg); |
190 switch (register_state) { | 190 switch (register_state) { |
191 case STACKED: | 191 case STACKED: |
192 __ Ldr(w10, register_location(reg)); | 192 __ Ldr(w10, register_location(reg)); |
193 __ Add(w10, w10, by); | 193 __ Add(w10, w10, by); |
194 __ Str(w10, register_location(reg)); | 194 __ Str(w10, register_location(reg)); |
195 break; | 195 break; |
196 case CACHED_LSW: | 196 case CACHED_LSW: |
197 to_advance = GetCachedRegister(reg); | 197 to_advance = GetCachedRegister(reg); |
198 __ Add(to_advance, to_advance, by); | 198 __ Add(to_advance, to_advance, by); |
199 break; | 199 break; |
200 case CACHED_MSW: | 200 case CACHED_MSW: |
201 to_advance = GetCachedRegister(reg); | 201 to_advance = GetCachedRegister(reg); |
202 __ Add(to_advance, to_advance, | 202 __ Add(to_advance, to_advance, |
203 static_cast<int64_t>(by) << kWRegSizeInBits); | 203 static_cast<int64_t>(by) << kWRegSizeInBits); |
204 break; | 204 break; |
205 default: | 205 default: |
206 UNREACHABLE(); | 206 UNREACHABLE(); |
207 break; | 207 break; |
208 } | 208 } |
209 } | 209 } |
210 } | 210 } |
211 | 211 |
212 | 212 |
213 void RegExpMacroAssemblerA64::Backtrack() { | 213 void RegExpMacroAssemblerARM64::Backtrack() { |
214 CheckPreemption(); | 214 CheckPreemption(); |
215 Pop(w10); | 215 Pop(w10); |
216 __ Add(x10, code_pointer(), Operand(w10, UXTW)); | 216 __ Add(x10, code_pointer(), Operand(w10, UXTW)); |
217 __ Br(x10); | 217 __ Br(x10); |
218 } | 218 } |
219 | 219 |
220 | 220 |
221 void RegExpMacroAssemblerA64::Bind(Label* label) { | 221 void RegExpMacroAssemblerARM64::Bind(Label* label) { |
222 __ Bind(label); | 222 __ Bind(label); |
223 } | 223 } |
224 | 224 |
225 | 225 |
226 void RegExpMacroAssemblerA64::CheckCharacter(uint32_t c, Label* on_equal) { | 226 void RegExpMacroAssemblerARM64::CheckCharacter(uint32_t c, Label* on_equal) { |
227 CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal); | 227 CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal); |
228 } | 228 } |
229 | 229 |
230 | 230 |
231 void RegExpMacroAssemblerA64::CheckCharacterGT(uc16 limit, Label* on_greater) { | 231 void RegExpMacroAssemblerARM64::CheckCharacterGT(uc16 limit, |
| 232 Label* on_greater) { |
232 CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater); | 233 CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater); |
233 } | 234 } |
234 | 235 |
235 | 236 |
236 void RegExpMacroAssemblerA64::CheckAtStart(Label* on_at_start) { | 237 void RegExpMacroAssemblerARM64::CheckAtStart(Label* on_at_start) { |
237 Label not_at_start; | 238 Label not_at_start; |
238 // Did we start the match at the start of the input string? | 239 // Did we start the match at the start of the input string? |
239 CompareAndBranchOrBacktrack(start_offset(), 0, ne, ¬_at_start); | 240 CompareAndBranchOrBacktrack(start_offset(), 0, ne, ¬_at_start); |
240 // If we did, are we still at the start of the input string? | 241 // If we did, are we still at the start of the input string? |
241 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); | 242 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); |
242 __ Cmp(x10, input_start()); | 243 __ Cmp(x10, input_start()); |
243 BranchOrBacktrack(eq, on_at_start); | 244 BranchOrBacktrack(eq, on_at_start); |
244 __ Bind(¬_at_start); | 245 __ Bind(¬_at_start); |
245 } | 246 } |
246 | 247 |
247 | 248 |
248 void RegExpMacroAssemblerA64::CheckNotAtStart(Label* on_not_at_start) { | 249 void RegExpMacroAssemblerARM64::CheckNotAtStart(Label* on_not_at_start) { |
249 // Did we start the match at the start of the input string? | 250 // Did we start the match at the start of the input string? |
250 CompareAndBranchOrBacktrack(start_offset(), 0, ne, on_not_at_start); | 251 CompareAndBranchOrBacktrack(start_offset(), 0, ne, on_not_at_start); |
251 // If we did, are we still at the start of the input string? | 252 // If we did, are we still at the start of the input string? |
252 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); | 253 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); |
253 __ Cmp(x10, input_start()); | 254 __ Cmp(x10, input_start()); |
254 BranchOrBacktrack(ne, on_not_at_start); | 255 BranchOrBacktrack(ne, on_not_at_start); |
255 } | 256 } |
256 | 257 |
257 | 258 |
258 void RegExpMacroAssemblerA64::CheckCharacterLT(uc16 limit, Label* on_less) { | 259 void RegExpMacroAssemblerARM64::CheckCharacterLT(uc16 limit, Label* on_less) { |
259 CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less); | 260 CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less); |
260 } | 261 } |
261 | 262 |
262 | 263 |
263 void RegExpMacroAssemblerA64::CheckCharacters(Vector<const uc16> str, | 264 void RegExpMacroAssemblerARM64::CheckCharacters(Vector<const uc16> str, |
264 int cp_offset, | 265 int cp_offset, |
265 Label* on_failure, | 266 Label* on_failure, |
266 bool check_end_of_string) { | 267 bool check_end_of_string) { |
267 // This method is only ever called from the cctests. | 268 // This method is only ever called from the cctests. |
268 | 269 |
269 if (check_end_of_string) { | 270 if (check_end_of_string) { |
270 // Is last character of required match inside string. | 271 // Is last character of required match inside string. |
271 CheckPosition(cp_offset + str.length() - 1, on_failure); | 272 CheckPosition(cp_offset + str.length() - 1, on_failure); |
272 } | 273 } |
273 | 274 |
(...skipping 11 matching lines...) Expand all Loading... |
285 __ Ldrb(w10, MemOperand(characters_address, 1, PostIndex)); | 286 __ Ldrb(w10, MemOperand(characters_address, 1, PostIndex)); |
286 ASSERT(str[i] <= String::kMaxOneByteCharCode); | 287 ASSERT(str[i] <= String::kMaxOneByteCharCode); |
287 } else { | 288 } else { |
288 __ Ldrh(w10, MemOperand(characters_address, 2, PostIndex)); | 289 __ Ldrh(w10, MemOperand(characters_address, 2, PostIndex)); |
289 } | 290 } |
290 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); | 291 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); |
291 } | 292 } |
292 } | 293 } |
293 | 294 |
294 | 295 |
295 void RegExpMacroAssemblerA64::CheckGreedyLoop(Label* on_equal) { | 296 void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) { |
296 __ Ldr(w10, MemOperand(backtrack_stackpointer())); | 297 __ Ldr(w10, MemOperand(backtrack_stackpointer())); |
297 __ Cmp(current_input_offset(), w10); | 298 __ Cmp(current_input_offset(), w10); |
298 __ Cset(x11, eq); | 299 __ Cset(x11, eq); |
299 __ Add(backtrack_stackpointer(), | 300 __ Add(backtrack_stackpointer(), |
300 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); | 301 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); |
301 BranchOrBacktrack(eq, on_equal); | 302 BranchOrBacktrack(eq, on_equal); |
302 } | 303 } |
303 | 304 |
304 void RegExpMacroAssemblerA64::CheckNotBackReferenceIgnoreCase( | 305 void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase( |
305 int start_reg, | 306 int start_reg, |
306 Label* on_no_match) { | 307 Label* on_no_match) { |
307 Label fallthrough; | 308 Label fallthrough; |
308 | 309 |
309 Register capture_start_offset = w10; | 310 Register capture_start_offset = w10; |
310 // Save the capture length in a callee-saved register so it will | 311 // Save the capture length in a callee-saved register so it will |
311 // be preserved if we call a C helper. | 312 // be preserved if we call a C helper. |
312 Register capture_length = w19; | 313 Register capture_length = w19; |
313 ASSERT(kCalleeSaved.IncludesAliasOf(capture_length)); | 314 ASSERT(kCalleeSaved.IncludesAliasOf(capture_length)); |
314 | 315 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 CompareAndBranchOrBacktrack(x0, 0, eq, on_no_match); | 422 CompareAndBranchOrBacktrack(x0, 0, eq, on_no_match); |
422 // On success, increment position by length of capture. | 423 // On success, increment position by length of capture. |
423 __ Add(current_input_offset(), current_input_offset(), capture_length); | 424 __ Add(current_input_offset(), current_input_offset(), capture_length); |
424 // Reset the cached registers. | 425 // Reset the cached registers. |
425 __ PopCPURegList(cached_registers); | 426 __ PopCPURegList(cached_registers); |
426 } | 427 } |
427 | 428 |
428 __ Bind(&fallthrough); | 429 __ Bind(&fallthrough); |
429 } | 430 } |
430 | 431 |
431 void RegExpMacroAssemblerA64::CheckNotBackReference( | 432 void RegExpMacroAssemblerARM64::CheckNotBackReference( |
432 int start_reg, | 433 int start_reg, |
433 Label* on_no_match) { | 434 Label* on_no_match) { |
434 Label fallthrough; | 435 Label fallthrough; |
435 | 436 |
436 Register capture_start_address = x12; | 437 Register capture_start_address = x12; |
437 Register capture_end_address = x13; | 438 Register capture_end_address = x13; |
438 Register current_position_address = x14; | 439 Register current_position_address = x14; |
439 Register capture_length = w15; | 440 Register capture_length = w15; |
440 | 441 |
441 // Find length of back-referenced capture. | 442 // Find length of back-referenced capture. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 if (masm_->emit_debug_code()) { | 484 if (masm_->emit_debug_code()) { |
484 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 485 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
485 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 486 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
486 // The current input offset should be <= 0, and fit in a W register. | 487 // The current input offset should be <= 0, and fit in a W register. |
487 __ Check(le, kOffsetOutOfRange); | 488 __ Check(le, kOffsetOutOfRange); |
488 } | 489 } |
489 __ Bind(&fallthrough); | 490 __ Bind(&fallthrough); |
490 } | 491 } |
491 | 492 |
492 | 493 |
493 void RegExpMacroAssemblerA64::CheckNotCharacter(unsigned c, | 494 void RegExpMacroAssemblerARM64::CheckNotCharacter(unsigned c, |
494 Label* on_not_equal) { | 495 Label* on_not_equal) { |
495 CompareAndBranchOrBacktrack(current_character(), c, ne, on_not_equal); | 496 CompareAndBranchOrBacktrack(current_character(), c, ne, on_not_equal); |
496 } | 497 } |
497 | 498 |
498 | 499 |
499 void RegExpMacroAssemblerA64::CheckCharacterAfterAnd(uint32_t c, | 500 void RegExpMacroAssemblerARM64::CheckCharacterAfterAnd(uint32_t c, |
500 uint32_t mask, | 501 uint32_t mask, |
501 Label* on_equal) { | 502 Label* on_equal) { |
502 __ And(w10, current_character(), mask); | 503 __ And(w10, current_character(), mask); |
503 CompareAndBranchOrBacktrack(w10, c, eq, on_equal); | 504 CompareAndBranchOrBacktrack(w10, c, eq, on_equal); |
504 } | 505 } |
505 | 506 |
506 | 507 |
507 void RegExpMacroAssemblerA64::CheckNotCharacterAfterAnd(unsigned c, | 508 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterAnd(unsigned c, |
508 unsigned mask, | 509 unsigned mask, |
509 Label* on_not_equal) { | 510 Label* on_not_equal) { |
510 __ And(w10, current_character(), mask); | 511 __ And(w10, current_character(), mask); |
511 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); | 512 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); |
512 } | 513 } |
513 | 514 |
514 | 515 |
515 void RegExpMacroAssemblerA64::CheckNotCharacterAfterMinusAnd( | 516 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterMinusAnd( |
516 uc16 c, | 517 uc16 c, |
517 uc16 minus, | 518 uc16 minus, |
518 uc16 mask, | 519 uc16 mask, |
519 Label* on_not_equal) { | 520 Label* on_not_equal) { |
520 ASSERT(minus < String::kMaxUtf16CodeUnit); | 521 ASSERT(minus < String::kMaxUtf16CodeUnit); |
521 __ Sub(w10, current_character(), minus); | 522 __ Sub(w10, current_character(), minus); |
522 __ And(w10, w10, mask); | 523 __ And(w10, w10, mask); |
523 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); | 524 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); |
524 } | 525 } |
525 | 526 |
526 | 527 |
527 void RegExpMacroAssemblerA64::CheckCharacterInRange( | 528 void RegExpMacroAssemblerARM64::CheckCharacterInRange( |
528 uc16 from, | 529 uc16 from, |
529 uc16 to, | 530 uc16 to, |
530 Label* on_in_range) { | 531 Label* on_in_range) { |
531 __ Sub(w10, current_character(), from); | 532 __ Sub(w10, current_character(), from); |
532 // Unsigned lower-or-same condition. | 533 // Unsigned lower-or-same condition. |
533 CompareAndBranchOrBacktrack(w10, to - from, ls, on_in_range); | 534 CompareAndBranchOrBacktrack(w10, to - from, ls, on_in_range); |
534 } | 535 } |
535 | 536 |
536 | 537 |
537 void RegExpMacroAssemblerA64::CheckCharacterNotInRange( | 538 void RegExpMacroAssemblerARM64::CheckCharacterNotInRange( |
538 uc16 from, | 539 uc16 from, |
539 uc16 to, | 540 uc16 to, |
540 Label* on_not_in_range) { | 541 Label* on_not_in_range) { |
541 __ Sub(w10, current_character(), from); | 542 __ Sub(w10, current_character(), from); |
542 // Unsigned higher condition. | 543 // Unsigned higher condition. |
543 CompareAndBranchOrBacktrack(w10, to - from, hi, on_not_in_range); | 544 CompareAndBranchOrBacktrack(w10, to - from, hi, on_not_in_range); |
544 } | 545 } |
545 | 546 |
546 | 547 |
547 void RegExpMacroAssemblerA64::CheckBitInTable( | 548 void RegExpMacroAssemblerARM64::CheckBitInTable( |
548 Handle<ByteArray> table, | 549 Handle<ByteArray> table, |
549 Label* on_bit_set) { | 550 Label* on_bit_set) { |
550 __ Mov(x11, Operand(table)); | 551 __ Mov(x11, Operand(table)); |
551 if ((mode_ != ASCII) || (kTableMask != String::kMaxOneByteCharCode)) { | 552 if ((mode_ != ASCII) || (kTableMask != String::kMaxOneByteCharCode)) { |
552 __ And(w10, current_character(), kTableMask); | 553 __ And(w10, current_character(), kTableMask); |
553 __ Add(w10, w10, ByteArray::kHeaderSize - kHeapObjectTag); | 554 __ Add(w10, w10, ByteArray::kHeaderSize - kHeapObjectTag); |
554 } else { | 555 } else { |
555 __ Add(w10, current_character(), ByteArray::kHeaderSize - kHeapObjectTag); | 556 __ Add(w10, current_character(), ByteArray::kHeaderSize - kHeapObjectTag); |
556 } | 557 } |
557 __ Ldrb(w11, MemOperand(x11, w10, UXTW)); | 558 __ Ldrb(w11, MemOperand(x11, w10, UXTW)); |
558 CompareAndBranchOrBacktrack(w11, 0, ne, on_bit_set); | 559 CompareAndBranchOrBacktrack(w11, 0, ne, on_bit_set); |
559 } | 560 } |
560 | 561 |
561 | 562 |
562 bool RegExpMacroAssemblerA64::CheckSpecialCharacterClass(uc16 type, | 563 bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(uc16 type, |
563 Label* on_no_match) { | 564 Label* on_no_match) { |
564 // Range checks (c in min..max) are generally implemented by an unsigned | 565 // Range checks (c in min..max) are generally implemented by an unsigned |
565 // (c - min) <= (max - min) check | 566 // (c - min) <= (max - min) check |
566 switch (type) { | 567 switch (type) { |
567 case 's': | 568 case 's': |
568 // Match space-characters | 569 // Match space-characters |
569 if (mode_ == ASCII) { | 570 if (mode_ == ASCII) { |
570 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 571 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
571 Label success; | 572 Label success; |
572 // Check for ' ' or 0x00a0. | 573 // Check for ' ' or 0x00a0. |
573 __ Cmp(current_character(), ' '); | 574 __ Cmp(current_character(), ' '); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 case '*': | 657 case '*': |
657 // Match any character. | 658 // Match any character. |
658 return true; | 659 return true; |
659 // No custom implementation (yet): s(UC16), S(UC16). | 660 // No custom implementation (yet): s(UC16), S(UC16). |
660 default: | 661 default: |
661 return false; | 662 return false; |
662 } | 663 } |
663 } | 664 } |
664 | 665 |
665 | 666 |
666 void RegExpMacroAssemblerA64::Fail() { | 667 void RegExpMacroAssemblerARM64::Fail() { |
667 __ Mov(w0, FAILURE); | 668 __ Mov(w0, FAILURE); |
668 __ B(&exit_label_); | 669 __ B(&exit_label_); |
669 } | 670 } |
670 | 671 |
671 | 672 |
672 Handle<HeapObject> RegExpMacroAssemblerA64::GetCode(Handle<String> source) { | 673 Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) { |
673 Label return_w0; | 674 Label return_w0; |
674 // Finalize code - write the entry point code now we know how many | 675 // Finalize code - write the entry point code now we know how many |
675 // registers we need. | 676 // registers we need. |
676 | 677 |
677 // Entry code: | 678 // Entry code: |
678 __ Bind(&entry_label_); | 679 __ Bind(&entry_label_); |
679 | 680 |
680 // Arguments on entry: | 681 // Arguments on entry: |
681 // x0: String* input | 682 // x0: String* input |
682 // x1: int start_offset | 683 // x1: int start_offset |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 | 1059 |
1059 CodeDesc code_desc; | 1060 CodeDesc code_desc; |
1060 masm_->GetCode(&code_desc); | 1061 masm_->GetCode(&code_desc); |
1061 Handle<Code> code = isolate()->factory()->NewCode( | 1062 Handle<Code> code = isolate()->factory()->NewCode( |
1062 code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject()); | 1063 code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject()); |
1063 PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); | 1064 PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); |
1064 return Handle<HeapObject>::cast(code); | 1065 return Handle<HeapObject>::cast(code); |
1065 } | 1066 } |
1066 | 1067 |
1067 | 1068 |
1068 void RegExpMacroAssemblerA64::GoTo(Label* to) { | 1069 void RegExpMacroAssemblerARM64::GoTo(Label* to) { |
1069 BranchOrBacktrack(al, to); | 1070 BranchOrBacktrack(al, to); |
1070 } | 1071 } |
1071 | 1072 |
1072 void RegExpMacroAssemblerA64::IfRegisterGE(int reg, | 1073 void RegExpMacroAssemblerARM64::IfRegisterGE(int reg, int comparand, |
1073 int comparand, | 1074 Label* if_ge) { |
1074 Label* if_ge) { | |
1075 Register to_compare = GetRegister(reg, w10); | 1075 Register to_compare = GetRegister(reg, w10); |
1076 CompareAndBranchOrBacktrack(to_compare, comparand, ge, if_ge); | 1076 CompareAndBranchOrBacktrack(to_compare, comparand, ge, if_ge); |
1077 } | 1077 } |
1078 | 1078 |
1079 | 1079 |
1080 void RegExpMacroAssemblerA64::IfRegisterLT(int reg, | 1080 void RegExpMacroAssemblerARM64::IfRegisterLT(int reg, int comparand, |
1081 int comparand, | 1081 Label* if_lt) { |
1082 Label* if_lt) { | |
1083 Register to_compare = GetRegister(reg, w10); | 1082 Register to_compare = GetRegister(reg, w10); |
1084 CompareAndBranchOrBacktrack(to_compare, comparand, lt, if_lt); | 1083 CompareAndBranchOrBacktrack(to_compare, comparand, lt, if_lt); |
1085 } | 1084 } |
1086 | 1085 |
1087 | 1086 |
1088 void RegExpMacroAssemblerA64::IfRegisterEqPos(int reg, | 1087 void RegExpMacroAssemblerARM64::IfRegisterEqPos(int reg, Label* if_eq) { |
1089 Label* if_eq) { | |
1090 Register to_compare = GetRegister(reg, w10); | 1088 Register to_compare = GetRegister(reg, w10); |
1091 __ Cmp(to_compare, current_input_offset()); | 1089 __ Cmp(to_compare, current_input_offset()); |
1092 BranchOrBacktrack(eq, if_eq); | 1090 BranchOrBacktrack(eq, if_eq); |
1093 } | 1091 } |
1094 | 1092 |
1095 RegExpMacroAssembler::IrregexpImplementation | 1093 RegExpMacroAssembler::IrregexpImplementation |
1096 RegExpMacroAssemblerA64::Implementation() { | 1094 RegExpMacroAssemblerARM64::Implementation() { |
1097 return kA64Implementation; | 1095 return kARM64Implementation; |
1098 } | 1096 } |
1099 | 1097 |
1100 | 1098 |
1101 void RegExpMacroAssemblerA64::LoadCurrentCharacter(int cp_offset, | 1099 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, |
1102 Label* on_end_of_input, | 1100 Label* on_end_of_input, |
1103 bool check_bounds, | 1101 bool check_bounds, |
1104 int characters) { | 1102 int characters) { |
1105 // TODO(pielan): Make sure long strings are caught before this, and not | 1103 // TODO(pielan): Make sure long strings are caught before this, and not |
1106 // just asserted in debug mode. | 1104 // just asserted in debug mode. |
1107 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. | 1105 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. |
1108 // Be sane! (And ensure that an int32_t can be used to index the string) | 1106 // Be sane! (And ensure that an int32_t can be used to index the string) |
1109 ASSERT(cp_offset < (1<<30)); | 1107 ASSERT(cp_offset < (1<<30)); |
1110 if (check_bounds) { | 1108 if (check_bounds) { |
1111 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1109 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
1112 } | 1110 } |
1113 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1111 LoadCurrentCharacterUnchecked(cp_offset, characters); |
1114 } | 1112 } |
1115 | 1113 |
1116 | 1114 |
1117 void RegExpMacroAssemblerA64::PopCurrentPosition() { | 1115 void RegExpMacroAssemblerARM64::PopCurrentPosition() { |
1118 Pop(current_input_offset()); | 1116 Pop(current_input_offset()); |
1119 } | 1117 } |
1120 | 1118 |
1121 | 1119 |
1122 void RegExpMacroAssemblerA64::PopRegister(int register_index) { | 1120 void RegExpMacroAssemblerARM64::PopRegister(int register_index) { |
1123 Pop(w10); | 1121 Pop(w10); |
1124 StoreRegister(register_index, w10); | 1122 StoreRegister(register_index, w10); |
1125 } | 1123 } |
1126 | 1124 |
1127 | 1125 |
1128 void RegExpMacroAssemblerA64::PushBacktrack(Label* label) { | 1126 void RegExpMacroAssemblerARM64::PushBacktrack(Label* label) { |
1129 if (label->is_bound()) { | 1127 if (label->is_bound()) { |
1130 int target = label->pos(); | 1128 int target = label->pos(); |
1131 __ Mov(w10, target + Code::kHeaderSize - kHeapObjectTag); | 1129 __ Mov(w10, target + Code::kHeaderSize - kHeapObjectTag); |
1132 } else { | 1130 } else { |
1133 __ Adr(x10, label); | 1131 __ Adr(x10, label); |
1134 __ Sub(x10, x10, code_pointer()); | 1132 __ Sub(x10, x10, code_pointer()); |
1135 if (masm_->emit_debug_code()) { | 1133 if (masm_->emit_debug_code()) { |
1136 __ Cmp(x10, kWRegMask); | 1134 __ Cmp(x10, kWRegMask); |
1137 // The code offset has to fit in a W register. | 1135 // The code offset has to fit in a W register. |
1138 __ Check(ls, kOffsetOutOfRange); | 1136 __ Check(ls, kOffsetOutOfRange); |
1139 } | 1137 } |
1140 } | 1138 } |
1141 Push(w10); | 1139 Push(w10); |
1142 CheckStackLimit(); | 1140 CheckStackLimit(); |
1143 } | 1141 } |
1144 | 1142 |
1145 | 1143 |
1146 void RegExpMacroAssemblerA64::PushCurrentPosition() { | 1144 void RegExpMacroAssemblerARM64::PushCurrentPosition() { |
1147 Push(current_input_offset()); | 1145 Push(current_input_offset()); |
1148 } | 1146 } |
1149 | 1147 |
1150 | 1148 |
1151 void RegExpMacroAssemblerA64::PushRegister(int register_index, | 1149 void RegExpMacroAssemblerARM64::PushRegister(int register_index, |
1152 StackCheckFlag check_stack_limit) { | 1150 StackCheckFlag check_stack_limit) { |
1153 Register to_push = GetRegister(register_index, w10); | 1151 Register to_push = GetRegister(register_index, w10); |
1154 Push(to_push); | 1152 Push(to_push); |
1155 if (check_stack_limit) CheckStackLimit(); | 1153 if (check_stack_limit) CheckStackLimit(); |
1156 } | 1154 } |
1157 | 1155 |
1158 | 1156 |
1159 void RegExpMacroAssemblerA64::ReadCurrentPositionFromRegister(int reg) { | 1157 void RegExpMacroAssemblerARM64::ReadCurrentPositionFromRegister(int reg) { |
1160 Register cached_register; | 1158 Register cached_register; |
1161 RegisterState register_state = GetRegisterState(reg); | 1159 RegisterState register_state = GetRegisterState(reg); |
1162 switch (register_state) { | 1160 switch (register_state) { |
1163 case STACKED: | 1161 case STACKED: |
1164 __ Ldr(current_input_offset(), register_location(reg)); | 1162 __ Ldr(current_input_offset(), register_location(reg)); |
1165 break; | 1163 break; |
1166 case CACHED_LSW: | 1164 case CACHED_LSW: |
1167 cached_register = GetCachedRegister(reg); | 1165 cached_register = GetCachedRegister(reg); |
1168 __ Mov(current_input_offset(), cached_register.W()); | 1166 __ Mov(current_input_offset(), cached_register.W()); |
1169 break; | 1167 break; |
1170 case CACHED_MSW: | 1168 case CACHED_MSW: |
1171 cached_register = GetCachedRegister(reg); | 1169 cached_register = GetCachedRegister(reg); |
1172 __ Lsr(current_input_offset().X(), cached_register, kWRegSizeInBits); | 1170 __ Lsr(current_input_offset().X(), cached_register, kWRegSizeInBits); |
1173 break; | 1171 break; |
1174 default: | 1172 default: |
1175 UNREACHABLE(); | 1173 UNREACHABLE(); |
1176 break; | 1174 break; |
1177 } | 1175 } |
1178 } | 1176 } |
1179 | 1177 |
1180 | 1178 |
1181 void RegExpMacroAssemblerA64::ReadStackPointerFromRegister(int reg) { | 1179 void RegExpMacroAssemblerARM64::ReadStackPointerFromRegister(int reg) { |
1182 Register read_from = GetRegister(reg, w10); | 1180 Register read_from = GetRegister(reg, w10); |
1183 __ Ldr(x11, MemOperand(frame_pointer(), kStackBase)); | 1181 __ Ldr(x11, MemOperand(frame_pointer(), kStackBase)); |
1184 __ Add(backtrack_stackpointer(), x11, Operand(read_from, SXTW)); | 1182 __ Add(backtrack_stackpointer(), x11, Operand(read_from, SXTW)); |
1185 } | 1183 } |
1186 | 1184 |
1187 | 1185 |
1188 void RegExpMacroAssemblerA64::SetCurrentPositionFromEnd(int by) { | 1186 void RegExpMacroAssemblerARM64::SetCurrentPositionFromEnd(int by) { |
1189 Label after_position; | 1187 Label after_position; |
1190 __ Cmp(current_input_offset(), -by * char_size()); | 1188 __ Cmp(current_input_offset(), -by * char_size()); |
1191 __ B(ge, &after_position); | 1189 __ B(ge, &after_position); |
1192 __ Mov(current_input_offset(), -by * char_size()); | 1190 __ Mov(current_input_offset(), -by * char_size()); |
1193 // On RegExp code entry (where this operation is used), the character before | 1191 // On RegExp code entry (where this operation is used), the character before |
1194 // the current position is expected to be already loaded. | 1192 // the current position is expected to be already loaded. |
1195 // We have advanced the position, so it's safe to read backwards. | 1193 // We have advanced the position, so it's safe to read backwards. |
1196 LoadCurrentCharacterUnchecked(-1, 1); | 1194 LoadCurrentCharacterUnchecked(-1, 1); |
1197 __ Bind(&after_position); | 1195 __ Bind(&after_position); |
1198 } | 1196 } |
1199 | 1197 |
1200 | 1198 |
1201 void RegExpMacroAssemblerA64::SetRegister(int register_index, int to) { | 1199 void RegExpMacroAssemblerARM64::SetRegister(int register_index, int to) { |
1202 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! | 1200 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! |
1203 Register set_to = wzr; | 1201 Register set_to = wzr; |
1204 if (to != 0) { | 1202 if (to != 0) { |
1205 set_to = w10; | 1203 set_to = w10; |
1206 __ Mov(set_to, to); | 1204 __ Mov(set_to, to); |
1207 } | 1205 } |
1208 StoreRegister(register_index, set_to); | 1206 StoreRegister(register_index, set_to); |
1209 } | 1207 } |
1210 | 1208 |
1211 | 1209 |
1212 bool RegExpMacroAssemblerA64::Succeed() { | 1210 bool RegExpMacroAssemblerARM64::Succeed() { |
1213 __ B(&success_label_); | 1211 __ B(&success_label_); |
1214 return global(); | 1212 return global(); |
1215 } | 1213 } |
1216 | 1214 |
1217 | 1215 |
1218 void RegExpMacroAssemblerA64::WriteCurrentPositionToRegister(int reg, | 1216 void RegExpMacroAssemblerARM64::WriteCurrentPositionToRegister(int reg, |
1219 int cp_offset) { | 1217 int cp_offset) { |
1220 Register position = current_input_offset(); | 1218 Register position = current_input_offset(); |
1221 if (cp_offset != 0) { | 1219 if (cp_offset != 0) { |
1222 position = w10; | 1220 position = w10; |
1223 __ Add(position, current_input_offset(), cp_offset * char_size()); | 1221 __ Add(position, current_input_offset(), cp_offset * char_size()); |
1224 } | 1222 } |
1225 StoreRegister(reg, position); | 1223 StoreRegister(reg, position); |
1226 } | 1224 } |
1227 | 1225 |
1228 | 1226 |
1229 void RegExpMacroAssemblerA64::ClearRegisters(int reg_from, int reg_to) { | 1227 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { |
1230 ASSERT(reg_from <= reg_to); | 1228 ASSERT(reg_from <= reg_to); |
1231 int num_registers = reg_to - reg_from + 1; | 1229 int num_registers = reg_to - reg_from + 1; |
1232 | 1230 |
1233 // If the first capture register is cached in a hardware register but not | 1231 // If the first capture register is cached in a hardware register but not |
1234 // aligned on a 64-bit one, we need to clear the first one specifically. | 1232 // aligned on a 64-bit one, we need to clear the first one specifically. |
1235 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { | 1233 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { |
1236 StoreRegister(reg_from, non_position_value()); | 1234 StoreRegister(reg_from, non_position_value()); |
1237 num_registers--; | 1235 num_registers--; |
1238 reg_from++; | 1236 reg_from++; |
1239 } | 1237 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1280 for (int i = reg_from; i <= reg_to; i += 2) { | 1278 for (int i = reg_from; i <= reg_to; i += 2) { |
1281 __ Str(twice_non_position_value(), | 1279 __ Str(twice_non_position_value(), |
1282 MemOperand(frame_pointer(), base_offset)); | 1280 MemOperand(frame_pointer(), base_offset)); |
1283 base_offset -= kWRegSize * 2; | 1281 base_offset -= kWRegSize * 2; |
1284 } | 1282 } |
1285 } | 1283 } |
1286 } | 1284 } |
1287 } | 1285 } |
1288 | 1286 |
1289 | 1287 |
1290 void RegExpMacroAssemblerA64::WriteStackPointerToRegister(int reg) { | 1288 void RegExpMacroAssemblerARM64::WriteStackPointerToRegister(int reg) { |
1291 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); | 1289 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); |
1292 __ Sub(x10, backtrack_stackpointer(), x10); | 1290 __ Sub(x10, backtrack_stackpointer(), x10); |
1293 if (masm_->emit_debug_code()) { | 1291 if (masm_->emit_debug_code()) { |
1294 __ Cmp(x10, Operand(w10, SXTW)); | 1292 __ Cmp(x10, Operand(w10, SXTW)); |
1295 // The stack offset needs to fit in a W register. | 1293 // The stack offset needs to fit in a W register. |
1296 __ Check(eq, kOffsetOutOfRange); | 1294 __ Check(eq, kOffsetOutOfRange); |
1297 } | 1295 } |
1298 StoreRegister(reg, w10); | 1296 StoreRegister(reg, w10); |
1299 } | 1297 } |
1300 | 1298 |
1301 | 1299 |
1302 // Helper function for reading a value out of a stack frame. | 1300 // Helper function for reading a value out of a stack frame. |
1303 template <typename T> | 1301 template <typename T> |
1304 static T& frame_entry(Address re_frame, int frame_offset) { | 1302 static T& frame_entry(Address re_frame, int frame_offset) { |
1305 return *reinterpret_cast<T*>(re_frame + frame_offset); | 1303 return *reinterpret_cast<T*>(re_frame + frame_offset); |
1306 } | 1304 } |
1307 | 1305 |
1308 | 1306 |
1309 int RegExpMacroAssemblerA64::CheckStackGuardState(Address* return_address, | 1307 int RegExpMacroAssemblerARM64::CheckStackGuardState(Address* return_address, |
1310 Code* re_code, | 1308 Code* re_code, |
1311 Address re_frame, | 1309 Address re_frame, |
1312 int start_offset, | 1310 int start_offset, |
1313 const byte** input_start, | 1311 const byte** input_start, |
1314 const byte** input_end) { | 1312 const byte** input_end) { |
1315 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); | 1313 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); |
1316 if (isolate->stack_guard()->IsStackOverflow()) { | 1314 if (isolate->stack_guard()->IsStackOverflow()) { |
1317 isolate->StackOverflow(); | 1315 isolate->StackOverflow(); |
1318 return EXCEPTION; | 1316 return EXCEPTION; |
1319 } | 1317 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1399 // Subject string might have been a ConsString that underwent | 1397 // Subject string might have been a ConsString that underwent |
1400 // short-circuiting during GC. That will not change start_address but | 1398 // short-circuiting during GC. That will not change start_address but |
1401 // will change pointer inside the subject handle. | 1399 // will change pointer inside the subject handle. |
1402 frame_entry<const String*>(re_frame, kInput) = *subject; | 1400 frame_entry<const String*>(re_frame, kInput) = *subject; |
1403 } | 1401 } |
1404 | 1402 |
1405 return 0; | 1403 return 0; |
1406 } | 1404 } |
1407 | 1405 |
1408 | 1406 |
1409 void RegExpMacroAssemblerA64::CheckPosition(int cp_offset, | 1407 void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset, |
1410 Label* on_outside_input) { | 1408 Label* on_outside_input) { |
1411 CompareAndBranchOrBacktrack(current_input_offset(), | 1409 CompareAndBranchOrBacktrack(current_input_offset(), |
1412 -cp_offset * char_size(), | 1410 -cp_offset * char_size(), |
1413 ge, | 1411 ge, |
1414 on_outside_input); | 1412 on_outside_input); |
1415 } | 1413 } |
1416 | 1414 |
1417 | 1415 |
1418 bool RegExpMacroAssemblerA64::CanReadUnaligned() { | 1416 bool RegExpMacroAssemblerARM64::CanReadUnaligned() { |
1419 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1417 // TODO(pielan): See whether or not we should disable unaligned accesses. |
1420 return !slow_safe(); | 1418 return !slow_safe(); |
1421 } | 1419 } |
1422 | 1420 |
1423 | 1421 |
1424 // Private methods: | 1422 // Private methods: |
1425 | 1423 |
1426 void RegExpMacroAssemblerA64::CallCheckStackGuardState(Register scratch) { | 1424 void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch) { |
1427 // Allocate space on the stack to store the return address. The | 1425 // Allocate space on the stack to store the return address. The |
1428 // CheckStackGuardState C++ function will override it if the code | 1426 // CheckStackGuardState C++ function will override it if the code |
1429 // moved. Allocate extra space for 2 arguments passed by pointers. | 1427 // moved. Allocate extra space for 2 arguments passed by pointers. |
1430 // AAPCS64 requires the stack to be 16 byte aligned. | 1428 // AAPCS64 requires the stack to be 16 byte aligned. |
1431 int alignment = masm_->ActivationFrameAlignment(); | 1429 int alignment = masm_->ActivationFrameAlignment(); |
1432 ASSERT_EQ(alignment % 16, 0); | 1430 ASSERT_EQ(alignment % 16, 0); |
1433 int align_mask = (alignment / kXRegSize) - 1; | 1431 int align_mask = (alignment / kXRegSize) - 1; |
1434 int xreg_to_claim = (3 + align_mask) & ~align_mask; | 1432 int xreg_to_claim = (3 + align_mask) & ~align_mask; |
1435 | 1433 |
1436 ASSERT(csp.Is(__ StackPointer())); | 1434 ASSERT(csp.Is(__ StackPointer())); |
(...skipping 26 matching lines...) Expand all Loading... |
1463 __ Peek(input_start(), kPointerSize); | 1461 __ Peek(input_start(), kPointerSize); |
1464 __ Peek(input_end(), 2 * kPointerSize); | 1462 __ Peek(input_end(), 2 * kPointerSize); |
1465 | 1463 |
1466 ASSERT(csp.Is(__ StackPointer())); | 1464 ASSERT(csp.Is(__ StackPointer())); |
1467 __ Drop(xreg_to_claim); | 1465 __ Drop(xreg_to_claim); |
1468 | 1466 |
1469 // Reload the Code pointer. | 1467 // Reload the Code pointer. |
1470 __ Mov(code_pointer(), Operand(masm_->CodeObject())); | 1468 __ Mov(code_pointer(), Operand(masm_->CodeObject())); |
1471 } | 1469 } |
1472 | 1470 |
1473 void RegExpMacroAssemblerA64::BranchOrBacktrack(Condition condition, | 1471 void RegExpMacroAssemblerARM64::BranchOrBacktrack(Condition condition, |
1474 Label* to) { | 1472 Label* to) { |
1475 if (condition == al) { // Unconditional. | 1473 if (condition == al) { // Unconditional. |
1476 if (to == NULL) { | 1474 if (to == NULL) { |
1477 Backtrack(); | 1475 Backtrack(); |
1478 return; | 1476 return; |
1479 } | 1477 } |
1480 __ B(to); | 1478 __ B(to); |
1481 return; | 1479 return; |
1482 } | 1480 } |
1483 if (to == NULL) { | 1481 if (to == NULL) { |
1484 to = &backtrack_label_; | 1482 to = &backtrack_label_; |
1485 } | 1483 } |
1486 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. | 1484 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. |
1487 Condition inverted_condition = InvertCondition(condition); | 1485 Condition inverted_condition = InvertCondition(condition); |
1488 Label no_branch; | 1486 Label no_branch; |
1489 __ B(inverted_condition, &no_branch); | 1487 __ B(inverted_condition, &no_branch); |
1490 __ B(to); | 1488 __ B(to); |
1491 __ Bind(&no_branch); | 1489 __ Bind(&no_branch); |
1492 } | 1490 } |
1493 | 1491 |
1494 void RegExpMacroAssemblerA64::CompareAndBranchOrBacktrack(Register reg, | 1492 void RegExpMacroAssemblerARM64::CompareAndBranchOrBacktrack(Register reg, |
1495 int immediate, | 1493 int immediate, |
1496 Condition condition, | 1494 Condition condition, |
1497 Label* to) { | 1495 Label* to) { |
1498 if ((immediate == 0) && ((condition == eq) || (condition == ne))) { | 1496 if ((immediate == 0) && ((condition == eq) || (condition == ne))) { |
1499 if (to == NULL) { | 1497 if (to == NULL) { |
1500 to = &backtrack_label_; | 1498 to = &backtrack_label_; |
1501 } | 1499 } |
1502 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. | 1500 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. |
1503 Label no_branch; | 1501 Label no_branch; |
1504 if (condition == eq) { | 1502 if (condition == eq) { |
1505 __ Cbnz(reg, &no_branch); | 1503 __ Cbnz(reg, &no_branch); |
1506 } else { | 1504 } else { |
1507 __ Cbz(reg, &no_branch); | 1505 __ Cbz(reg, &no_branch); |
1508 } | 1506 } |
1509 __ B(to); | 1507 __ B(to); |
1510 __ Bind(&no_branch); | 1508 __ Bind(&no_branch); |
1511 } else { | 1509 } else { |
1512 __ Cmp(reg, immediate); | 1510 __ Cmp(reg, immediate); |
1513 BranchOrBacktrack(condition, to); | 1511 BranchOrBacktrack(condition, to); |
1514 } | 1512 } |
1515 } | 1513 } |
1516 | 1514 |
1517 | 1515 |
1518 void RegExpMacroAssemblerA64::CheckPreemption() { | 1516 void RegExpMacroAssemblerARM64::CheckPreemption() { |
1519 // Check for preemption. | 1517 // Check for preemption. |
1520 ExternalReference stack_limit = | 1518 ExternalReference stack_limit = |
1521 ExternalReference::address_of_stack_limit(isolate()); | 1519 ExternalReference::address_of_stack_limit(isolate()); |
1522 __ Mov(x10, stack_limit); | 1520 __ Mov(x10, stack_limit); |
1523 __ Ldr(x10, MemOperand(x10)); | 1521 __ Ldr(x10, MemOperand(x10)); |
1524 ASSERT(csp.Is(__ StackPointer())); | 1522 ASSERT(csp.Is(__ StackPointer())); |
1525 __ Cmp(csp, x10); | 1523 __ Cmp(csp, x10); |
1526 CallIf(&check_preempt_label_, ls); | 1524 CallIf(&check_preempt_label_, ls); |
1527 } | 1525 } |
1528 | 1526 |
1529 | 1527 |
1530 void RegExpMacroAssemblerA64::CheckStackLimit() { | 1528 void RegExpMacroAssemblerARM64::CheckStackLimit() { |
1531 ExternalReference stack_limit = | 1529 ExternalReference stack_limit = |
1532 ExternalReference::address_of_regexp_stack_limit(isolate()); | 1530 ExternalReference::address_of_regexp_stack_limit(isolate()); |
1533 __ Mov(x10, stack_limit); | 1531 __ Mov(x10, stack_limit); |
1534 __ Ldr(x10, MemOperand(x10)); | 1532 __ Ldr(x10, MemOperand(x10)); |
1535 __ Cmp(backtrack_stackpointer(), x10); | 1533 __ Cmp(backtrack_stackpointer(), x10); |
1536 CallIf(&stack_overflow_label_, ls); | 1534 CallIf(&stack_overflow_label_, ls); |
1537 } | 1535 } |
1538 | 1536 |
1539 | 1537 |
1540 void RegExpMacroAssemblerA64::Push(Register source) { | 1538 void RegExpMacroAssemblerARM64::Push(Register source) { |
1541 ASSERT(source.Is32Bits()); | 1539 ASSERT(source.Is32Bits()); |
1542 ASSERT(!source.is(backtrack_stackpointer())); | 1540 ASSERT(!source.is(backtrack_stackpointer())); |
1543 __ Str(source, | 1541 __ Str(source, |
1544 MemOperand(backtrack_stackpointer(), | 1542 MemOperand(backtrack_stackpointer(), |
1545 -static_cast<int>(kWRegSize), | 1543 -static_cast<int>(kWRegSize), |
1546 PreIndex)); | 1544 PreIndex)); |
1547 } | 1545 } |
1548 | 1546 |
1549 | 1547 |
1550 void RegExpMacroAssemblerA64::Pop(Register target) { | 1548 void RegExpMacroAssemblerARM64::Pop(Register target) { |
1551 ASSERT(target.Is32Bits()); | 1549 ASSERT(target.Is32Bits()); |
1552 ASSERT(!target.is(backtrack_stackpointer())); | 1550 ASSERT(!target.is(backtrack_stackpointer())); |
1553 __ Ldr(target, | 1551 __ Ldr(target, |
1554 MemOperand(backtrack_stackpointer(), kWRegSize, PostIndex)); | 1552 MemOperand(backtrack_stackpointer(), kWRegSize, PostIndex)); |
1555 } | 1553 } |
1556 | 1554 |
1557 | 1555 |
1558 Register RegExpMacroAssemblerA64::GetCachedRegister(int register_index) { | 1556 Register RegExpMacroAssemblerARM64::GetCachedRegister(int register_index) { |
1559 ASSERT(register_index < kNumCachedRegisters); | 1557 ASSERT(register_index < kNumCachedRegisters); |
1560 return Register::Create(register_index / 2, kXRegSizeInBits); | 1558 return Register::Create(register_index / 2, kXRegSizeInBits); |
1561 } | 1559 } |
1562 | 1560 |
1563 | 1561 |
1564 Register RegExpMacroAssemblerA64::GetRegister(int register_index, | 1562 Register RegExpMacroAssemblerARM64::GetRegister(int register_index, |
1565 Register maybe_result) { | 1563 Register maybe_result) { |
1566 ASSERT(maybe_result.Is32Bits()); | 1564 ASSERT(maybe_result.Is32Bits()); |
1567 ASSERT(register_index >= 0); | 1565 ASSERT(register_index >= 0); |
1568 if (num_registers_ <= register_index) { | 1566 if (num_registers_ <= register_index) { |
1569 num_registers_ = register_index + 1; | 1567 num_registers_ = register_index + 1; |
1570 } | 1568 } |
1571 Register result; | 1569 Register result; |
1572 RegisterState register_state = GetRegisterState(register_index); | 1570 RegisterState register_state = GetRegisterState(register_index); |
1573 switch (register_state) { | 1571 switch (register_state) { |
1574 case STACKED: | 1572 case STACKED: |
1575 __ Ldr(maybe_result, register_location(register_index)); | 1573 __ Ldr(maybe_result, register_location(register_index)); |
1576 result = maybe_result; | 1574 result = maybe_result; |
1577 break; | 1575 break; |
1578 case CACHED_LSW: | 1576 case CACHED_LSW: |
1579 result = GetCachedRegister(register_index).W(); | 1577 result = GetCachedRegister(register_index).W(); |
1580 break; | 1578 break; |
1581 case CACHED_MSW: | 1579 case CACHED_MSW: |
1582 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), | 1580 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), |
1583 kWRegSizeInBits); | 1581 kWRegSizeInBits); |
1584 result = maybe_result; | 1582 result = maybe_result; |
1585 break; | 1583 break; |
1586 default: | 1584 default: |
1587 UNREACHABLE(); | 1585 UNREACHABLE(); |
1588 break; | 1586 break; |
1589 } | 1587 } |
1590 ASSERT(result.Is32Bits()); | 1588 ASSERT(result.Is32Bits()); |
1591 return result; | 1589 return result; |
1592 } | 1590 } |
1593 | 1591 |
1594 | 1592 |
1595 void RegExpMacroAssemblerA64::StoreRegister(int register_index, | 1593 void RegExpMacroAssemblerARM64::StoreRegister(int register_index, |
1596 Register source) { | 1594 Register source) { |
1597 ASSERT(source.Is32Bits()); | 1595 ASSERT(source.Is32Bits()); |
1598 ASSERT(register_index >= 0); | 1596 ASSERT(register_index >= 0); |
1599 if (num_registers_ <= register_index) { | 1597 if (num_registers_ <= register_index) { |
1600 num_registers_ = register_index + 1; | 1598 num_registers_ = register_index + 1; |
1601 } | 1599 } |
1602 | 1600 |
1603 Register cached_register; | 1601 Register cached_register; |
1604 RegisterState register_state = GetRegisterState(register_index); | 1602 RegisterState register_state = GetRegisterState(register_index); |
1605 switch (register_state) { | 1603 switch (register_state) { |
1606 case STACKED: | 1604 case STACKED: |
1607 __ Str(source, register_location(register_index)); | 1605 __ Str(source, register_location(register_index)); |
1608 break; | 1606 break; |
1609 case CACHED_LSW: | 1607 case CACHED_LSW: |
1610 cached_register = GetCachedRegister(register_index); | 1608 cached_register = GetCachedRegister(register_index); |
1611 if (!source.Is(cached_register.W())) { | 1609 if (!source.Is(cached_register.W())) { |
1612 __ Bfi(cached_register, source.X(), 0, kWRegSizeInBits); | 1610 __ Bfi(cached_register, source.X(), 0, kWRegSizeInBits); |
1613 } | 1611 } |
1614 break; | 1612 break; |
1615 case CACHED_MSW: | 1613 case CACHED_MSW: |
1616 cached_register = GetCachedRegister(register_index); | 1614 cached_register = GetCachedRegister(register_index); |
1617 __ Bfi(cached_register, source.X(), kWRegSizeInBits, kWRegSizeInBits); | 1615 __ Bfi(cached_register, source.X(), kWRegSizeInBits, kWRegSizeInBits); |
1618 break; | 1616 break; |
1619 default: | 1617 default: |
1620 UNREACHABLE(); | 1618 UNREACHABLE(); |
1621 break; | 1619 break; |
1622 } | 1620 } |
1623 } | 1621 } |
1624 | 1622 |
1625 | 1623 |
1626 void RegExpMacroAssemblerA64::CallIf(Label* to, Condition condition) { | 1624 void RegExpMacroAssemblerARM64::CallIf(Label* to, Condition condition) { |
1627 Label skip_call; | 1625 Label skip_call; |
1628 if (condition != al) __ B(&skip_call, InvertCondition(condition)); | 1626 if (condition != al) __ B(&skip_call, InvertCondition(condition)); |
1629 __ Bl(to); | 1627 __ Bl(to); |
1630 __ Bind(&skip_call); | 1628 __ Bind(&skip_call); |
1631 } | 1629 } |
1632 | 1630 |
1633 | 1631 |
1634 void RegExpMacroAssemblerA64::RestoreLinkRegister() { | 1632 void RegExpMacroAssemblerARM64::RestoreLinkRegister() { |
1635 ASSERT(csp.Is(__ StackPointer())); | 1633 ASSERT(csp.Is(__ StackPointer())); |
1636 __ Pop(lr, xzr); | 1634 __ Pop(lr, xzr); |
1637 __ Add(lr, lr, Operand(masm_->CodeObject())); | 1635 __ Add(lr, lr, Operand(masm_->CodeObject())); |
1638 } | 1636 } |
1639 | 1637 |
1640 | 1638 |
1641 void RegExpMacroAssemblerA64::SaveLinkRegister() { | 1639 void RegExpMacroAssemblerARM64::SaveLinkRegister() { |
1642 ASSERT(csp.Is(__ StackPointer())); | 1640 ASSERT(csp.Is(__ StackPointer())); |
1643 __ Sub(lr, lr, Operand(masm_->CodeObject())); | 1641 __ Sub(lr, lr, Operand(masm_->CodeObject())); |
1644 __ Push(xzr, lr); | 1642 __ Push(xzr, lr); |
1645 } | 1643 } |
1646 | 1644 |
1647 | 1645 |
1648 MemOperand RegExpMacroAssemblerA64::register_location(int register_index) { | 1646 MemOperand RegExpMacroAssemblerARM64::register_location(int register_index) { |
1649 ASSERT(register_index < (1<<30)); | 1647 ASSERT(register_index < (1<<30)); |
1650 ASSERT(register_index >= kNumCachedRegisters); | 1648 ASSERT(register_index >= kNumCachedRegisters); |
1651 if (num_registers_ <= register_index) { | 1649 if (num_registers_ <= register_index) { |
1652 num_registers_ = register_index + 1; | 1650 num_registers_ = register_index + 1; |
1653 } | 1651 } |
1654 register_index -= kNumCachedRegisters; | 1652 register_index -= kNumCachedRegisters; |
1655 int offset = kFirstRegisterOnStack - register_index * kWRegSize; | 1653 int offset = kFirstRegisterOnStack - register_index * kWRegSize; |
1656 return MemOperand(frame_pointer(), offset); | 1654 return MemOperand(frame_pointer(), offset); |
1657 } | 1655 } |
1658 | 1656 |
1659 MemOperand RegExpMacroAssemblerA64::capture_location(int register_index, | 1657 MemOperand RegExpMacroAssemblerARM64::capture_location(int register_index, |
1660 Register scratch) { | 1658 Register scratch) { |
1661 ASSERT(register_index < (1<<30)); | 1659 ASSERT(register_index < (1<<30)); |
1662 ASSERT(register_index < num_saved_registers_); | 1660 ASSERT(register_index < num_saved_registers_); |
1663 ASSERT(register_index >= kNumCachedRegisters); | 1661 ASSERT(register_index >= kNumCachedRegisters); |
1664 ASSERT_EQ(register_index % 2, 0); | 1662 ASSERT_EQ(register_index % 2, 0); |
1665 register_index -= kNumCachedRegisters; | 1663 register_index -= kNumCachedRegisters; |
1666 int offset = kFirstCaptureOnStack - register_index * kWRegSize; | 1664 int offset = kFirstCaptureOnStack - register_index * kWRegSize; |
1667 // capture_location is used with Stp instructions to load/store 2 registers. | 1665 // capture_location is used with Stp instructions to load/store 2 registers. |
1668 // The immediate field in the encoding is limited to 7 bits (signed). | 1666 // The immediate field in the encoding is limited to 7 bits (signed). |
1669 if (is_int7(offset)) { | 1667 if (is_int7(offset)) { |
1670 return MemOperand(frame_pointer(), offset); | 1668 return MemOperand(frame_pointer(), offset); |
1671 } else { | 1669 } else { |
1672 __ Add(scratch, frame_pointer(), offset); | 1670 __ Add(scratch, frame_pointer(), offset); |
1673 return MemOperand(scratch); | 1671 return MemOperand(scratch); |
1674 } | 1672 } |
1675 } | 1673 } |
1676 | 1674 |
1677 void RegExpMacroAssemblerA64::LoadCurrentCharacterUnchecked(int cp_offset, | 1675 void RegExpMacroAssemblerARM64::LoadCurrentCharacterUnchecked(int cp_offset, |
1678 int characters) { | 1676 int characters) { |
1679 Register offset = current_input_offset(); | 1677 Register offset = current_input_offset(); |
1680 | 1678 |
1681 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU | 1679 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU |
1682 // and the operating system running on the target allow it. | 1680 // and the operating system running on the target allow it. |
1683 // If unaligned load/stores are not supported then this function must only | 1681 // If unaligned load/stores are not supported then this function must only |
1684 // be used to load a single character at a time. | 1682 // be used to load a single character at a time. |
1685 | 1683 |
1686 // ARMv8 supports unaligned accesses but V8 or the kernel can decide to | 1684 // ARMv8 supports unaligned accesses but V8 or the kernel can decide to |
1687 // disable it. | 1685 // disable it. |
1688 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1686 // TODO(pielan): See whether or not we should disable unaligned accesses. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 ASSERT(characters == 1); | 1718 ASSERT(characters == 1); |
1721 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); | 1719 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); |
1722 } | 1720 } |
1723 } | 1721 } |
1724 } | 1722 } |
1725 | 1723 |
1726 #endif // V8_INTERPRETED_REGEXP | 1724 #endif // V8_INTERPRETED_REGEXP |
1727 | 1725 |
1728 }} // namespace v8::internal | 1726 }} // namespace v8::internal |
1729 | 1727 |
1730 #endif // V8_TARGET_ARCH_A64 | 1728 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |