OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/regexp/ia32/regexp-macro-assembler-ia32.h" | 7 #include "src/regexp/ia32/regexp-macro-assembler-ia32.h" |
8 | 8 |
9 #include "src/log.h" | 9 #include "src/log.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 * - start index (character index of start) | 46 * - start index (character index of start) |
47 * - String* input_string (location of a handle containing the string) | 47 * - String* input_string (location of a handle containing the string) |
48 * --- frame alignment (if applicable) --- | 48 * --- frame alignment (if applicable) --- |
49 * - return address | 49 * - return address |
50 * ebp-> - old ebp | 50 * ebp-> - old ebp |
51 * - backup of caller esi | 51 * - backup of caller esi |
52 * - backup of caller edi | 52 * - backup of caller edi |
53 * - backup of caller ebx | 53 * - backup of caller ebx |
54 * - success counter (only for global regexps to count matches). | 54 * - success counter (only for global regexps to count matches). |
55 * - Offset of location before start of input (effectively character | 55 * - Offset of location before start of input (effectively character |
56 * string start - 1). Used to initialize capture registers to a | 56 * position -1). Used to initialize capture registers to a non-position. |
57 * non-position. | |
58 * - register 0 ebp[-4] (only positions must be stored in the first | 57 * - register 0 ebp[-4] (only positions must be stored in the first |
59 * - register 1 ebp[-8] num_saved_registers_ registers) | 58 * - register 1 ebp[-8] num_saved_registers_ registers) |
60 * - ... | 59 * - ... |
61 * | 60 * |
62 * The first num_saved_registers_ registers are initialized to point to | 61 * The first num_saved_registers_ registers are initialized to point to |
63 * "character -1" in the string (i.e., char_size() bytes before the first | 62 * "character -1" in the string (i.e., char_size() bytes before the first |
64 * character of the string). The remaining registers starts out as garbage. | 63 * character of the string). The remaining registers starts out as garbage. |
65 * | 64 * |
66 * The data up to the return address must be placed there by the calling | 65 * The data up to the return address must be placed there by the calling |
67 * code, by calling the code entry as cast to a function with the signature: | 66 * code, by calling the code entry as cast to a function with the signature: |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 } | 149 } |
151 | 150 |
152 | 151 |
153 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { | 152 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { |
154 __ cmp(current_character(), limit); | 153 __ cmp(current_character(), limit); |
155 BranchOrBacktrack(greater, on_greater); | 154 BranchOrBacktrack(greater, on_greater); |
156 } | 155 } |
157 | 156 |
158 | 157 |
159 void RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) { | 158 void RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) { |
160 __ lea(eax, Operand(edi, -char_size())); | 159 Label not_at_start; |
161 __ cmp(eax, Operand(ebp, kStringStartMinusOne)); | 160 // Did we start the match at the start of the string at all? |
| 161 __ cmp(Operand(ebp, kStartIndex), Immediate(0)); |
| 162 BranchOrBacktrack(not_equal, ¬_at_start); |
| 163 // If we did, are we still at the start of the input? |
| 164 __ lea(eax, Operand(esi, edi, times_1, 0)); |
| 165 __ cmp(eax, Operand(ebp, kInputStart)); |
162 BranchOrBacktrack(equal, on_at_start); | 166 BranchOrBacktrack(equal, on_at_start); |
| 167 __ bind(¬_at_start); |
163 } | 168 } |
164 | 169 |
165 | 170 |
166 void RegExpMacroAssemblerIA32::CheckNotAtStart(int cp_offset, | 171 void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) { |
167 Label* on_not_at_start) { | 172 // Did we start the match at the start of the string at all? |
168 __ lea(eax, Operand(edi, -char_size() + cp_offset * char_size())); | 173 __ cmp(Operand(ebp, kStartIndex), Immediate(0)); |
169 __ cmp(eax, Operand(ebp, kStringStartMinusOne)); | 174 BranchOrBacktrack(not_equal, on_not_at_start); |
| 175 // If we did, are we still at the start of the input? |
| 176 __ lea(eax, Operand(esi, edi, times_1, 0)); |
| 177 __ cmp(eax, Operand(ebp, kInputStart)); |
170 BranchOrBacktrack(not_equal, on_not_at_start); | 178 BranchOrBacktrack(not_equal, on_not_at_start); |
171 } | 179 } |
172 | 180 |
173 | 181 |
174 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { | 182 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { |
175 __ cmp(current_character(), limit); | 183 __ cmp(current_character(), limit); |
176 BranchOrBacktrack(less, on_less); | 184 BranchOrBacktrack(less, on_less); |
177 } | 185 } |
178 | 186 |
179 | 187 |
180 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { | 188 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { |
181 Label fallthrough; | 189 Label fallthrough; |
182 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); | 190 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); |
183 __ j(not_equal, &fallthrough); | 191 __ j(not_equal, &fallthrough); |
184 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. | 192 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. |
185 BranchOrBacktrack(no_condition, on_equal); | 193 BranchOrBacktrack(no_condition, on_equal); |
186 __ bind(&fallthrough); | 194 __ bind(&fallthrough); |
187 } | 195 } |
188 | 196 |
189 | 197 |
190 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( | 198 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( |
191 int start_reg, bool read_backward, Label* on_no_match) { | 199 int start_reg, |
| 200 Label* on_no_match) { |
192 Label fallthrough; | 201 Label fallthrough; |
193 __ mov(edx, register_location(start_reg)); // Index of start of capture | 202 __ mov(edx, register_location(start_reg)); // Index of start of capture |
194 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture | 203 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture |
195 __ sub(ebx, edx); // Length of capture. | 204 __ sub(ebx, edx); // Length of capture. |
196 | 205 |
197 // At this point, the capture registers are either both set or both cleared. | 206 // The length of a capture should not be negative. This can only happen |
198 // If the capture length is zero, then the capture is either empty or cleared. | 207 // if the end of the capture is unrecorded, or at a point earlier than |
199 // Fall through in both cases. | 208 // the start of the capture. |
| 209 BranchOrBacktrack(less, on_no_match); |
| 210 |
| 211 // If length is zero, either the capture is empty or it is completely |
| 212 // uncaptured. In either case succeed immediately. |
200 __ j(equal, &fallthrough); | 213 __ j(equal, &fallthrough); |
201 | 214 |
202 // Check that there are sufficient characters left in the input. | 215 // Check that there are sufficient characters left in the input. |
203 if (read_backward) { | 216 __ mov(eax, edi); |
204 __ mov(eax, Operand(ebp, kStringStartMinusOne)); | 217 __ add(eax, ebx); |
205 __ add(eax, ebx); | 218 BranchOrBacktrack(greater, on_no_match); |
206 __ cmp(edi, eax); | |
207 BranchOrBacktrack(less_equal, on_no_match); | |
208 } else { | |
209 __ mov(eax, edi); | |
210 __ add(eax, ebx); | |
211 BranchOrBacktrack(greater, on_no_match); | |
212 } | |
213 | 219 |
214 if (mode_ == LATIN1) { | 220 if (mode_ == LATIN1) { |
215 Label success; | 221 Label success; |
216 Label fail; | 222 Label fail; |
217 Label loop_increment; | 223 Label loop_increment; |
218 // Save register contents to make the registers available below. | 224 // Save register contents to make the registers available below. |
219 __ push(edi); | 225 __ push(edi); |
220 __ push(backtrack_stackpointer()); | 226 __ push(backtrack_stackpointer()); |
221 // After this, the eax, ecx, and edi registers are available. | 227 // After this, the eax, ecx, and edi registers are available. |
222 | 228 |
223 __ add(edx, esi); // Start of capture | 229 __ add(edx, esi); // Start of capture |
224 __ add(edi, esi); // Start of text to match against capture. | 230 __ add(edi, esi); // Start of text to match against capture. |
225 if (read_backward) { | |
226 __ sub(edi, ebx); // Offset by length when matching backwards. | |
227 } | |
228 __ add(ebx, edi); // End of text to match against capture. | 231 __ add(ebx, edi); // End of text to match against capture. |
229 | 232 |
230 Label loop; | 233 Label loop; |
231 __ bind(&loop); | 234 __ bind(&loop); |
232 __ movzx_b(eax, Operand(edi, 0)); | 235 __ movzx_b(eax, Operand(edi, 0)); |
233 __ cmpb_al(Operand(edx, 0)); | 236 __ cmpb_al(Operand(edx, 0)); |
234 __ j(equal, &loop_increment); | 237 __ j(equal, &loop_increment); |
235 | 238 |
236 // Mismatch, try case-insensitive match (converting letters to lower-case). | 239 // Mismatch, try case-insensitive match (converting letters to lower-case). |
237 __ or_(eax, 0x20); // Convert match character to lower-case. | 240 __ or_(eax, 0x20); // Convert match character to lower-case. |
(...skipping 30 matching lines...) Expand all Loading... |
268 __ pop(edi); | 271 __ pop(edi); |
269 BranchOrBacktrack(no_condition, on_no_match); | 272 BranchOrBacktrack(no_condition, on_no_match); |
270 | 273 |
271 __ bind(&success); | 274 __ bind(&success); |
272 // Restore original value before continuing. | 275 // Restore original value before continuing. |
273 __ pop(backtrack_stackpointer()); | 276 __ pop(backtrack_stackpointer()); |
274 // Drop original value of character position. | 277 // Drop original value of character position. |
275 __ add(esp, Immediate(kPointerSize)); | 278 __ add(esp, Immediate(kPointerSize)); |
276 // Compute new value of character position after the matched part. | 279 // Compute new value of character position after the matched part. |
277 __ sub(edi, esi); | 280 __ sub(edi, esi); |
278 if (read_backward) { | |
279 // Subtract match length if we matched backward. | |
280 __ add(edi, register_location(start_reg)); | |
281 __ sub(edi, register_location(start_reg + 1)); | |
282 } | |
283 } else { | 281 } else { |
284 DCHECK(mode_ == UC16); | 282 DCHECK(mode_ == UC16); |
285 // Save registers before calling C function. | 283 // Save registers before calling C function. |
286 __ push(esi); | 284 __ push(esi); |
287 __ push(edi); | 285 __ push(edi); |
288 __ push(backtrack_stackpointer()); | 286 __ push(backtrack_stackpointer()); |
289 __ push(ebx); | 287 __ push(ebx); |
290 | 288 |
291 static const int argument_count = 4; | 289 static const int argument_count = 4; |
292 __ PrepareCallCFunction(argument_count, ecx); | 290 __ PrepareCallCFunction(argument_count, ecx); |
293 // Put arguments into allocated stack area, last argument highest on stack. | 291 // Put arguments into allocated stack area, last argument highest on stack. |
294 // Parameters are | 292 // Parameters are |
295 // Address byte_offset1 - Address captured substring's start. | 293 // Address byte_offset1 - Address captured substring's start. |
296 // Address byte_offset2 - Address of current character position. | 294 // Address byte_offset2 - Address of current character position. |
297 // size_t byte_length - length of capture in bytes(!) | 295 // size_t byte_length - length of capture in bytes(!) |
298 // Isolate* isolate | 296 // Isolate* isolate |
299 | 297 |
300 // Set isolate. | 298 // Set isolate. |
301 __ mov(Operand(esp, 3 * kPointerSize), | 299 __ mov(Operand(esp, 3 * kPointerSize), |
302 Immediate(ExternalReference::isolate_address(isolate()))); | 300 Immediate(ExternalReference::isolate_address(isolate()))); |
303 // Set byte_length. | 301 // Set byte_length. |
304 __ mov(Operand(esp, 2 * kPointerSize), ebx); | 302 __ mov(Operand(esp, 2 * kPointerSize), ebx); |
305 // Set byte_offset2. | 303 // Set byte_offset2. |
306 // Found by adding negative string-end offset of current position (edi) | 304 // Found by adding negative string-end offset of current position (edi) |
307 // to end of string. | 305 // to end of string. |
308 __ add(edi, esi); | 306 __ add(edi, esi); |
309 if (read_backward) { | |
310 __ sub(edi, ebx); // Offset by length when matching backwards. | |
311 } | |
312 __ mov(Operand(esp, 1 * kPointerSize), edi); | 307 __ mov(Operand(esp, 1 * kPointerSize), edi); |
313 // Set byte_offset1. | 308 // Set byte_offset1. |
314 // Start of capture, where edx already holds string-end negative offset. | 309 // Start of capture, where edx already holds string-end negative offset. |
315 __ add(edx, esi); | 310 __ add(edx, esi); |
316 __ mov(Operand(esp, 0 * kPointerSize), edx); | 311 __ mov(Operand(esp, 0 * kPointerSize), edx); |
317 | 312 |
318 { | 313 { |
319 AllowExternalCallThatCantCauseGC scope(masm_); | 314 AllowExternalCallThatCantCauseGC scope(masm_); |
320 ExternalReference compare = | 315 ExternalReference compare = |
321 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 316 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
322 __ CallCFunction(compare, argument_count); | 317 __ CallCFunction(compare, argument_count); |
323 } | 318 } |
324 // Pop original values before reacting on result value. | 319 // Pop original values before reacting on result value. |
325 __ pop(ebx); | 320 __ pop(ebx); |
326 __ pop(backtrack_stackpointer()); | 321 __ pop(backtrack_stackpointer()); |
327 __ pop(edi); | 322 __ pop(edi); |
328 __ pop(esi); | 323 __ pop(esi); |
329 | 324 |
330 // Check if function returned non-zero for success or zero for failure. | 325 // Check if function returned non-zero for success or zero for failure. |
331 __ or_(eax, eax); | 326 __ or_(eax, eax); |
332 BranchOrBacktrack(zero, on_no_match); | 327 BranchOrBacktrack(zero, on_no_match); |
333 // On success, advance position by length of capture. | 328 // On success, increment position by length of capture. |
334 if (read_backward) { | 329 __ add(edi, ebx); |
335 __ sub(edi, ebx); | |
336 } else { | |
337 __ add(edi, ebx); | |
338 } | |
339 } | 330 } |
340 __ bind(&fallthrough); | 331 __ bind(&fallthrough); |
341 } | 332 } |
342 | 333 |
343 | 334 |
344 void RegExpMacroAssemblerIA32::CheckNotBackReference(int start_reg, | 335 void RegExpMacroAssemblerIA32::CheckNotBackReference( |
345 bool read_backward, | 336 int start_reg, |
346 Label* on_no_match) { | 337 Label* on_no_match) { |
347 Label fallthrough; | 338 Label fallthrough; |
348 Label success; | 339 Label success; |
349 Label fail; | 340 Label fail; |
350 | 341 |
351 // Find length of back-referenced capture. | 342 // Find length of back-referenced capture. |
352 __ mov(edx, register_location(start_reg)); | 343 __ mov(edx, register_location(start_reg)); |
353 __ mov(eax, register_location(start_reg + 1)); | 344 __ mov(eax, register_location(start_reg + 1)); |
354 __ sub(eax, edx); // Length to check. | 345 __ sub(eax, edx); // Length to check. |
355 | 346 // Fail on partial or illegal capture (start of capture after end of capture). |
356 // At this point, the capture registers are either both set or both cleared. | 347 BranchOrBacktrack(less, on_no_match); |
357 // If the capture length is zero, then the capture is either empty or cleared. | 348 // Succeed on empty capture (including no capture) |
358 // Fall through in both cases. | |
359 __ j(equal, &fallthrough); | 349 __ j(equal, &fallthrough); |
360 | 350 |
361 // Check that there are sufficient characters left in the input. | 351 // Check that there are sufficient characters left in the input. |
362 if (read_backward) { | 352 __ mov(ebx, edi); |
363 __ mov(ebx, Operand(ebp, kStringStartMinusOne)); | 353 __ add(ebx, eax); |
364 __ add(ebx, eax); | 354 BranchOrBacktrack(greater, on_no_match); |
365 __ cmp(edi, ebx); | |
366 BranchOrBacktrack(less_equal, on_no_match); | |
367 } else { | |
368 __ mov(ebx, edi); | |
369 __ add(ebx, eax); | |
370 BranchOrBacktrack(greater, on_no_match); | |
371 } | |
372 | 355 |
373 // Save register to make it available below. | 356 // Save register to make it available below. |
374 __ push(backtrack_stackpointer()); | 357 __ push(backtrack_stackpointer()); |
375 | 358 |
376 // Compute pointers to match string and capture string | 359 // Compute pointers to match string and capture string |
| 360 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. |
377 __ add(edx, esi); // Start of capture. | 361 __ add(edx, esi); // Start of capture. |
378 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. | |
379 if (read_backward) { | |
380 __ sub(ebx, eax); // Offset by length when matching backwards. | |
381 } | |
382 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match | 362 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match |
383 | 363 |
384 Label loop; | 364 Label loop; |
385 __ bind(&loop); | 365 __ bind(&loop); |
386 if (mode_ == LATIN1) { | 366 if (mode_ == LATIN1) { |
387 __ movzx_b(eax, Operand(edx, 0)); | 367 __ movzx_b(eax, Operand(edx, 0)); |
388 __ cmpb_al(Operand(ebx, 0)); | 368 __ cmpb_al(Operand(ebx, 0)); |
389 } else { | 369 } else { |
390 DCHECK(mode_ == UC16); | 370 DCHECK(mode_ == UC16); |
391 __ movzx_w(eax, Operand(edx, 0)); | 371 __ movzx_w(eax, Operand(edx, 0)); |
(...skipping 10 matching lines...) Expand all Loading... |
402 | 382 |
403 __ bind(&fail); | 383 __ bind(&fail); |
404 // Restore backtrack stackpointer. | 384 // Restore backtrack stackpointer. |
405 __ pop(backtrack_stackpointer()); | 385 __ pop(backtrack_stackpointer()); |
406 BranchOrBacktrack(no_condition, on_no_match); | 386 BranchOrBacktrack(no_condition, on_no_match); |
407 | 387 |
408 __ bind(&success); | 388 __ bind(&success); |
409 // Move current character position to position after match. | 389 // Move current character position to position after match. |
410 __ mov(edi, ecx); | 390 __ mov(edi, ecx); |
411 __ sub(edi, esi); | 391 __ sub(edi, esi); |
412 if (read_backward) { | |
413 // Subtract match length if we matched backward. | |
414 __ add(edi, register_location(start_reg)); | |
415 __ sub(edi, register_location(start_reg + 1)); | |
416 } | |
417 // Restore backtrack stackpointer. | 392 // Restore backtrack stackpointer. |
418 __ pop(backtrack_stackpointer()); | 393 __ pop(backtrack_stackpointer()); |
419 | 394 |
420 __ bind(&fallthrough); | 395 __ bind(&fallthrough); |
421 } | 396 } |
422 | 397 |
423 | 398 |
424 void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c, | 399 void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c, |
425 Label* on_not_equal) { | 400 Label* on_not_equal) { |
426 __ cmp(current_character(), c); | 401 __ cmp(current_character(), c); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 | 627 |
653 // Actually emit code to start a new stack frame. | 628 // Actually emit code to start a new stack frame. |
654 __ push(ebp); | 629 __ push(ebp); |
655 __ mov(ebp, esp); | 630 __ mov(ebp, esp); |
656 // Save callee-save registers. Order here should correspond to order of | 631 // Save callee-save registers. Order here should correspond to order of |
657 // kBackup_ebx etc. | 632 // kBackup_ebx etc. |
658 __ push(esi); | 633 __ push(esi); |
659 __ push(edi); | 634 __ push(edi); |
660 __ push(ebx); // Callee-save on MacOS. | 635 __ push(ebx); // Callee-save on MacOS. |
661 __ push(Immediate(0)); // Number of successful matches in a global regexp. | 636 __ push(Immediate(0)); // Number of successful matches in a global regexp. |
662 __ push(Immediate(0)); // Make room for "string start - 1" constant. | 637 __ push(Immediate(0)); // Make room for "input start - 1" constant. |
663 | 638 |
664 // Check if we have space on the stack for registers. | 639 // Check if we have space on the stack for registers. |
665 Label stack_limit_hit; | 640 Label stack_limit_hit; |
666 Label stack_ok; | 641 Label stack_ok; |
667 | 642 |
668 ExternalReference stack_limit = | 643 ExternalReference stack_limit = |
669 ExternalReference::address_of_stack_limit(isolate()); | 644 ExternalReference::address_of_stack_limit(isolate()); |
670 __ mov(ecx, esp); | 645 __ mov(ecx, esp); |
671 __ sub(ecx, Operand::StaticVariable(stack_limit)); | 646 __ sub(ecx, Operand::StaticVariable(stack_limit)); |
672 // Handle it if the stack pointer is already below the stack limit. | 647 // Handle it if the stack pointer is already below the stack limit. |
(...skipping 29 matching lines...) Expand all Loading... |
702 // Set eax to address of char before start of the string. | 677 // Set eax to address of char before start of the string. |
703 // (effectively string position -1). | 678 // (effectively string position -1). |
704 __ neg(ebx); | 679 __ neg(ebx); |
705 if (mode_ == UC16) { | 680 if (mode_ == UC16) { |
706 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); | 681 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); |
707 } else { | 682 } else { |
708 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); | 683 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); |
709 } | 684 } |
710 // Store this value in a local variable, for use when clearing | 685 // Store this value in a local variable, for use when clearing |
711 // position registers. | 686 // position registers. |
712 __ mov(Operand(ebp, kStringStartMinusOne), eax); | 687 __ mov(Operand(ebp, kInputStartMinusOne), eax); |
713 | 688 |
714 #if V8_OS_WIN | 689 #if V8_OS_WIN |
715 // Ensure that we write to each stack page, in order. Skipping a page | 690 // Ensure that we write to each stack page, in order. Skipping a page |
716 // on Windows can cause segmentation faults. Assuming page size is 4k. | 691 // on Windows can cause segmentation faults. Assuming page size is 4k. |
717 const int kPageSize = 4096; | 692 const int kPageSize = 4096; |
718 const int kRegistersPerPage = kPageSize / kPointerSize; | 693 const int kRegistersPerPage = kPageSize / kPointerSize; |
719 for (int i = num_saved_registers_ + kRegistersPerPage - 1; | 694 for (int i = num_saved_registers_ + kRegistersPerPage - 1; |
720 i < num_registers_; | 695 i < num_registers_; |
721 i += kRegistersPerPage) { | 696 i += kRegistersPerPage) { |
722 __ mov(register_location(i), eax); // One write every page. | 697 __ mov(register_location(i), eax); // One write every page. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 // Convert to index from start of string, not end. | 760 // Convert to index from start of string, not end. |
786 __ add(eax, ecx); | 761 __ add(eax, ecx); |
787 if (mode_ == UC16) { | 762 if (mode_ == UC16) { |
788 __ sar(eax, 1); // Convert byte index to character index. | 763 __ sar(eax, 1); // Convert byte index to character index. |
789 } | 764 } |
790 __ mov(Operand(ebx, i * kPointerSize), eax); | 765 __ mov(Operand(ebx, i * kPointerSize), eax); |
791 } | 766 } |
792 } | 767 } |
793 | 768 |
794 if (global()) { | 769 if (global()) { |
795 // Restart matching if the regular expression is flagged as global. | 770 // Restart matching if the regular expression is flagged as global. |
796 // Increment success counter. | 771 // Increment success counter. |
797 __ inc(Operand(ebp, kSuccessfulCaptures)); | 772 __ inc(Operand(ebp, kSuccessfulCaptures)); |
798 // Capture results have been stored, so the number of remaining global | 773 // Capture results have been stored, so the number of remaining global |
799 // output registers is reduced by the number of stored captures. | 774 // output registers is reduced by the number of stored captures. |
800 __ mov(ecx, Operand(ebp, kNumOutputRegisters)); | 775 __ mov(ecx, Operand(ebp, kNumOutputRegisters)); |
801 __ sub(ecx, Immediate(num_saved_registers_)); | 776 __ sub(ecx, Immediate(num_saved_registers_)); |
802 // Check whether we have enough room for another set of capture results. | 777 // Check whether we have enough room for another set of capture results. |
803 __ cmp(ecx, Immediate(num_saved_registers_)); | 778 __ cmp(ecx, Immediate(num_saved_registers_)); |
804 __ j(less, &exit_label_); | 779 __ j(less, &exit_label_); |
805 | 780 |
806 __ mov(Operand(ebp, kNumOutputRegisters), ecx); | 781 __ mov(Operand(ebp, kNumOutputRegisters), ecx); |
807 // Advance the location for output. | 782 // Advance the location for output. |
808 __ add(Operand(ebp, kRegisterOutput), | 783 __ add(Operand(ebp, kRegisterOutput), |
809 Immediate(num_saved_registers_ * kPointerSize)); | 784 Immediate(num_saved_registers_ * kPointerSize)); |
810 | 785 |
811 // Prepare eax to initialize registers with its value in the next run. | 786 // Prepare eax to initialize registers with its value in the next run. |
812 __ mov(eax, Operand(ebp, kStringStartMinusOne)); | 787 __ mov(eax, Operand(ebp, kInputStartMinusOne)); |
813 | 788 |
814 if (global_with_zero_length_check()) { | 789 if (global_with_zero_length_check()) { |
815 // Special case for zero-length matches. | 790 // Special case for zero-length matches. |
816 // edx: capture start index | 791 // edx: capture start index |
817 __ cmp(edi, edx); | 792 __ cmp(edi, edx); |
818 // Not a zero-length match, restart. | 793 // Not a zero-length match, restart. |
819 __ j(not_equal, &load_char_start_regexp); | 794 __ j(not_equal, &load_char_start_regexp); |
820 // edi (offset from the end) is zero if we already reached the end. | 795 // edi (offset from the end) is zero if we already reached the end. |
821 __ test(edi, edi); | 796 __ test(edi, edi); |
822 __ j(zero, &exit_label_, Label::kNear); | 797 __ j(zero, &exit_label_, Label::kNear); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 RegExpMacroAssembler::IrregexpImplementation | 937 RegExpMacroAssembler::IrregexpImplementation |
963 RegExpMacroAssemblerIA32::Implementation() { | 938 RegExpMacroAssemblerIA32::Implementation() { |
964 return kIA32Implementation; | 939 return kIA32Implementation; |
965 } | 940 } |
966 | 941 |
967 | 942 |
968 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, | 943 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, |
969 Label* on_end_of_input, | 944 Label* on_end_of_input, |
970 bool check_bounds, | 945 bool check_bounds, |
971 int characters) { | 946 int characters) { |
| 947 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. |
972 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | 948 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
973 if (check_bounds) { | 949 if (check_bounds) { |
974 if (cp_offset >= 0) { | 950 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
975 CheckPosition(cp_offset + characters - 1, on_end_of_input); | |
976 } else { | |
977 CheckPosition(cp_offset, on_end_of_input); | |
978 } | |
979 } | 951 } |
980 LoadCurrentCharacterUnchecked(cp_offset, characters); | 952 LoadCurrentCharacterUnchecked(cp_offset, characters); |
981 } | 953 } |
982 | 954 |
983 | 955 |
984 void RegExpMacroAssemblerIA32::PopCurrentPosition() { | 956 void RegExpMacroAssemblerIA32::PopCurrentPosition() { |
985 Pop(edi); | 957 Pop(edi); |
986 } | 958 } |
987 | 959 |
988 | 960 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 __ mov(register_location(reg), edi); | 1024 __ mov(register_location(reg), edi); |
1053 } else { | 1025 } else { |
1054 __ lea(eax, Operand(edi, cp_offset * char_size())); | 1026 __ lea(eax, Operand(edi, cp_offset * char_size())); |
1055 __ mov(register_location(reg), eax); | 1027 __ mov(register_location(reg), eax); |
1056 } | 1028 } |
1057 } | 1029 } |
1058 | 1030 |
1059 | 1031 |
1060 void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) { | 1032 void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) { |
1061 DCHECK(reg_from <= reg_to); | 1033 DCHECK(reg_from <= reg_to); |
1062 __ mov(eax, Operand(ebp, kStringStartMinusOne)); | 1034 __ mov(eax, Operand(ebp, kInputStartMinusOne)); |
1063 for (int reg = reg_from; reg <= reg_to; reg++) { | 1035 for (int reg = reg_from; reg <= reg_to; reg++) { |
1064 __ mov(register_location(reg), eax); | 1036 __ mov(register_location(reg), eax); |
1065 } | 1037 } |
1066 } | 1038 } |
1067 | 1039 |
1068 | 1040 |
1069 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { | 1041 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { |
1070 __ mov(eax, backtrack_stackpointer()); | 1042 __ mov(eax, backtrack_stackpointer()); |
1071 __ sub(eax, Operand(ebp, kStackHighEnd)); | 1043 __ sub(eax, Operand(ebp, kStackHighEnd)); |
1072 __ mov(register_location(reg), eax); | 1044 __ mov(register_location(reg), eax); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 DCHECK(register_index < (1<<30)); | 1093 DCHECK(register_index < (1<<30)); |
1122 if (num_registers_ <= register_index) { | 1094 if (num_registers_ <= register_index) { |
1123 num_registers_ = register_index + 1; | 1095 num_registers_ = register_index + 1; |
1124 } | 1096 } |
1125 return Operand(ebp, kRegisterZero - register_index * kPointerSize); | 1097 return Operand(ebp, kRegisterZero - register_index * kPointerSize); |
1126 } | 1098 } |
1127 | 1099 |
1128 | 1100 |
1129 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, | 1101 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, |
1130 Label* on_outside_input) { | 1102 Label* on_outside_input) { |
1131 if (cp_offset >= 0) { | 1103 __ cmp(edi, -cp_offset * char_size()); |
1132 __ cmp(edi, -cp_offset * char_size()); | 1104 BranchOrBacktrack(greater_equal, on_outside_input); |
1133 BranchOrBacktrack(greater_equal, on_outside_input); | |
1134 } else { | |
1135 __ lea(eax, Operand(edi, cp_offset * char_size())); | |
1136 __ cmp(eax, Operand(ebp, kStringStartMinusOne)); | |
1137 BranchOrBacktrack(less_equal, on_outside_input); | |
1138 } | |
1139 } | 1105 } |
1140 | 1106 |
1141 | 1107 |
1142 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, | 1108 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, |
1143 Label* to) { | 1109 Label* to) { |
1144 if (condition < 0) { // No condition | 1110 if (condition < 0) { // No condition |
1145 if (to == NULL) { | 1111 if (to == NULL) { |
1146 Backtrack(); | 1112 Backtrack(); |
1147 return; | 1113 return; |
1148 } | 1114 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 | 1219 |
1254 | 1220 |
1255 #undef __ | 1221 #undef __ |
1256 | 1222 |
1257 #endif // V8_INTERPRETED_REGEXP | 1223 #endif // V8_INTERPRETED_REGEXP |
1258 | 1224 |
1259 } // namespace internal | 1225 } // namespace internal |
1260 } // namespace v8 | 1226 } // namespace v8 |
1261 | 1227 |
1262 #endif // V8_TARGET_ARCH_IA32 | 1228 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |