OLD | NEW |
1 // Copyright 2008-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 } | 127 } |
128 | 128 |
129 | 129 |
130 int RegExpMacroAssemblerIA32::stack_limit_slack() { | 130 int RegExpMacroAssemblerIA32::stack_limit_slack() { |
131 return RegExpStack::kStackLimitSlack; | 131 return RegExpStack::kStackLimitSlack; |
132 } | 132 } |
133 | 133 |
134 | 134 |
135 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { | 135 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { |
136 if (by != 0) { | 136 if (by != 0) { |
137 __ add(Operand(edi), Immediate(by * char_size())); | 137 __ add(edi, Immediate(by * char_size())); |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 | 141 |
142 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { | 142 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { |
143 ASSERT(reg >= 0); | 143 ASSERT(reg >= 0); |
144 ASSERT(reg < num_registers_); | 144 ASSERT(reg < num_registers_); |
145 if (by != 0) { | 145 if (by != 0) { |
146 __ add(register_location(reg), Immediate(by)); | 146 __ add(register_location(reg), Immediate(by)); |
147 } | 147 } |
148 } | 148 } |
149 | 149 |
150 | 150 |
151 void RegExpMacroAssemblerIA32::Backtrack() { | 151 void RegExpMacroAssemblerIA32::Backtrack() { |
152 CheckPreemption(); | 152 CheckPreemption(); |
153 // Pop Code* offset from backtrack stack, add Code* and jump to location. | 153 // Pop Code* offset from backtrack stack, add Code* and jump to location. |
154 Pop(ebx); | 154 Pop(ebx); |
155 __ add(Operand(ebx), Immediate(masm_->CodeObject())); | 155 __ add(ebx, Immediate(masm_->CodeObject())); |
156 __ jmp(Operand(ebx)); | 156 __ jmp(ebx); |
157 } | 157 } |
158 | 158 |
159 | 159 |
160 void RegExpMacroAssemblerIA32::Bind(Label* label) { | 160 void RegExpMacroAssemblerIA32::Bind(Label* label) { |
161 __ bind(label); | 161 __ bind(label); |
162 } | 162 } |
163 | 163 |
164 | 164 |
165 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { | 165 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { |
166 __ cmp(current_character(), c); | 166 __ cmp(current_character(), c); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 // If input is ASCII, don't even bother calling here if the string to | 212 // If input is ASCII, don't even bother calling here if the string to |
213 // match contains a non-ascii character. | 213 // match contains a non-ascii character. |
214 if (mode_ == ASCII) { | 214 if (mode_ == ASCII) { |
215 ASSERT(String::IsAscii(str.start(), str.length())); | 215 ASSERT(String::IsAscii(str.start(), str.length())); |
216 } | 216 } |
217 #endif | 217 #endif |
218 int byte_length = str.length() * char_size(); | 218 int byte_length = str.length() * char_size(); |
219 int byte_offset = cp_offset * char_size(); | 219 int byte_offset = cp_offset * char_size(); |
220 if (check_end_of_string) { | 220 if (check_end_of_string) { |
221 // Check that there are at least str.length() characters left in the input. | 221 // Check that there are at least str.length() characters left in the input. |
222 __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); | 222 __ cmp(edi, Immediate(-(byte_offset + byte_length))); |
223 BranchOrBacktrack(greater, on_failure); | 223 BranchOrBacktrack(greater, on_failure); |
224 } | 224 } |
225 | 225 |
226 if (on_failure == NULL) { | 226 if (on_failure == NULL) { |
227 // Instead of inlining a backtrack, (re)use the global backtrack target. | 227 // Instead of inlining a backtrack, (re)use the global backtrack target. |
228 on_failure = &backtrack_label_; | 228 on_failure = &backtrack_label_; |
229 } | 229 } |
230 | 230 |
231 // Do one character test first to minimize loading for the case that | 231 // Do one character test first to minimize loading for the case that |
232 // we don't match at all (loading more than one character introduces that | 232 // we don't match at all (loading more than one character introduces that |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 } | 281 } |
282 BranchOrBacktrack(not_equal, on_failure); | 282 BranchOrBacktrack(not_equal, on_failure); |
283 } | 283 } |
284 } | 284 } |
285 | 285 |
286 | 286 |
287 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { | 287 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { |
288 Label fallthrough; | 288 Label fallthrough; |
289 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); | 289 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); |
290 __ j(not_equal, &fallthrough); | 290 __ j(not_equal, &fallthrough); |
291 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); // Pop. | 291 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. |
292 BranchOrBacktrack(no_condition, on_equal); | 292 BranchOrBacktrack(no_condition, on_equal); |
293 __ bind(&fallthrough); | 293 __ bind(&fallthrough); |
294 } | 294 } |
295 | 295 |
296 | 296 |
297 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( | 297 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( |
298 int start_reg, | 298 int start_reg, |
299 Label* on_no_match) { | 299 Label* on_no_match) { |
300 Label fallthrough; | 300 Label fallthrough; |
301 __ mov(edx, register_location(start_reg)); // Index of start of capture | 301 __ mov(edx, register_location(start_reg)); // Index of start of capture |
302 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture | 302 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture |
303 __ sub(ebx, Operand(edx)); // Length of capture. | 303 __ sub(ebx, edx); // Length of capture. |
304 | 304 |
305 // The length of a capture should not be negative. This can only happen | 305 // The length of a capture should not be negative. This can only happen |
306 // if the end of the capture is unrecorded, or at a point earlier than | 306 // if the end of the capture is unrecorded, or at a point earlier than |
307 // the start of the capture. | 307 // the start of the capture. |
308 BranchOrBacktrack(less, on_no_match); | 308 BranchOrBacktrack(less, on_no_match); |
309 | 309 |
310 // If length is zero, either the capture is empty or it is completely | 310 // If length is zero, either the capture is empty or it is completely |
311 // uncaptured. In either case succeed immediately. | 311 // uncaptured. In either case succeed immediately. |
312 __ j(equal, &fallthrough); | 312 __ j(equal, &fallthrough); |
313 | 313 |
314 if (mode_ == ASCII) { | 314 if (mode_ == ASCII) { |
315 Label success; | 315 Label success; |
316 Label fail; | 316 Label fail; |
317 Label loop_increment; | 317 Label loop_increment; |
318 // Save register contents to make the registers available below. | 318 // Save register contents to make the registers available below. |
319 __ push(edi); | 319 __ push(edi); |
320 __ push(backtrack_stackpointer()); | 320 __ push(backtrack_stackpointer()); |
321 // After this, the eax, ecx, and edi registers are available. | 321 // After this, the eax, ecx, and edi registers are available. |
322 | 322 |
323 __ add(edx, Operand(esi)); // Start of capture | 323 __ add(edx, esi); // Start of capture |
324 __ add(edi, Operand(esi)); // Start of text to match against capture. | 324 __ add(edi, esi); // Start of text to match against capture. |
325 __ add(ebx, Operand(edi)); // End of text to match against capture. | 325 __ add(ebx, edi); // End of text to match against capture. |
326 | 326 |
327 Label loop; | 327 Label loop; |
328 __ bind(&loop); | 328 __ bind(&loop); |
329 __ movzx_b(eax, Operand(edi, 0)); | 329 __ movzx_b(eax, Operand(edi, 0)); |
330 __ cmpb_al(Operand(edx, 0)); | 330 __ cmpb_al(Operand(edx, 0)); |
331 __ j(equal, &loop_increment); | 331 __ j(equal, &loop_increment); |
332 | 332 |
333 // Mismatch, try case-insensitive match (converting letters to lower-case). | 333 // Mismatch, try case-insensitive match (converting letters to lower-case). |
334 __ or_(eax, 0x20); // Convert match character to lower-case. | 334 __ or_(eax, 0x20); // Convert match character to lower-case. |
335 __ lea(ecx, Operand(eax, -'a')); | 335 __ lea(ecx, Operand(eax, -'a')); |
336 __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? | 336 __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? |
337 __ j(above, &fail); | 337 __ j(above, &fail); |
338 // Also convert capture character. | 338 // Also convert capture character. |
339 __ movzx_b(ecx, Operand(edx, 0)); | 339 __ movzx_b(ecx, Operand(edx, 0)); |
340 __ or_(ecx, 0x20); | 340 __ or_(ecx, 0x20); |
341 | 341 |
342 __ cmp(eax, Operand(ecx)); | 342 __ cmp(eax, ecx); |
343 __ j(not_equal, &fail); | 343 __ j(not_equal, &fail); |
344 | 344 |
345 __ bind(&loop_increment); | 345 __ bind(&loop_increment); |
346 // Increment pointers into match and capture strings. | 346 // Increment pointers into match and capture strings. |
347 __ add(Operand(edx), Immediate(1)); | 347 __ add(edx, Immediate(1)); |
348 __ add(Operand(edi), Immediate(1)); | 348 __ add(edi, Immediate(1)); |
349 // Compare to end of match, and loop if not done. | 349 // Compare to end of match, and loop if not done. |
350 __ cmp(edi, Operand(ebx)); | 350 __ cmp(edi, ebx); |
351 __ j(below, &loop); | 351 __ j(below, &loop); |
352 __ jmp(&success); | 352 __ jmp(&success); |
353 | 353 |
354 __ bind(&fail); | 354 __ bind(&fail); |
355 // Restore original values before failing. | 355 // Restore original values before failing. |
356 __ pop(backtrack_stackpointer()); | 356 __ pop(backtrack_stackpointer()); |
357 __ pop(edi); | 357 __ pop(edi); |
358 BranchOrBacktrack(no_condition, on_no_match); | 358 BranchOrBacktrack(no_condition, on_no_match); |
359 | 359 |
360 __ bind(&success); | 360 __ bind(&success); |
361 // Restore original value before continuing. | 361 // Restore original value before continuing. |
362 __ pop(backtrack_stackpointer()); | 362 __ pop(backtrack_stackpointer()); |
363 // Drop original value of character position. | 363 // Drop original value of character position. |
364 __ add(Operand(esp), Immediate(kPointerSize)); | 364 __ add(esp, Immediate(kPointerSize)); |
365 // Compute new value of character position after the matched part. | 365 // Compute new value of character position after the matched part. |
366 __ sub(edi, Operand(esi)); | 366 __ sub(edi, esi); |
367 } else { | 367 } else { |
368 ASSERT(mode_ == UC16); | 368 ASSERT(mode_ == UC16); |
369 // Save registers before calling C function. | 369 // Save registers before calling C function. |
370 __ push(esi); | 370 __ push(esi); |
371 __ push(edi); | 371 __ push(edi); |
372 __ push(backtrack_stackpointer()); | 372 __ push(backtrack_stackpointer()); |
373 __ push(ebx); | 373 __ push(ebx); |
374 | 374 |
375 static const int argument_count = 4; | 375 static const int argument_count = 4; |
376 __ PrepareCallCFunction(argument_count, ecx); | 376 __ PrepareCallCFunction(argument_count, ecx); |
377 // Put arguments into allocated stack area, last argument highest on stack. | 377 // Put arguments into allocated stack area, last argument highest on stack. |
378 // Parameters are | 378 // Parameters are |
379 // Address byte_offset1 - Address captured substring's start. | 379 // Address byte_offset1 - Address captured substring's start. |
380 // Address byte_offset2 - Address of current character position. | 380 // Address byte_offset2 - Address of current character position. |
381 // size_t byte_length - length of capture in bytes(!) | 381 // size_t byte_length - length of capture in bytes(!) |
382 // Isolate* isolate | 382 // Isolate* isolate |
383 | 383 |
384 // Set isolate. | 384 // Set isolate. |
385 __ mov(Operand(esp, 3 * kPointerSize), | 385 __ mov(Operand(esp, 3 * kPointerSize), |
386 Immediate(ExternalReference::isolate_address())); | 386 Immediate(ExternalReference::isolate_address())); |
387 // Set byte_length. | 387 // Set byte_length. |
388 __ mov(Operand(esp, 2 * kPointerSize), ebx); | 388 __ mov(Operand(esp, 2 * kPointerSize), ebx); |
389 // Set byte_offset2. | 389 // Set byte_offset2. |
390 // Found by adding negative string-end offset of current position (edi) | 390 // Found by adding negative string-end offset of current position (edi) |
391 // to end of string. | 391 // to end of string. |
392 __ add(edi, Operand(esi)); | 392 __ add(edi, esi); |
393 __ mov(Operand(esp, 1 * kPointerSize), edi); | 393 __ mov(Operand(esp, 1 * kPointerSize), edi); |
394 // Set byte_offset1. | 394 // Set byte_offset1. |
395 // Start of capture, where edx already holds string-end negative offset. | 395 // Start of capture, where edx already holds string-end negative offset. |
396 __ add(edx, Operand(esi)); | 396 __ add(edx, esi); |
397 __ mov(Operand(esp, 0 * kPointerSize), edx); | 397 __ mov(Operand(esp, 0 * kPointerSize), edx); |
398 | 398 |
399 { | 399 { |
400 AllowExternalCallThatCantCauseGC scope(masm_); | 400 AllowExternalCallThatCantCauseGC scope(masm_); |
401 ExternalReference compare = | 401 ExternalReference compare = |
402 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); | 402 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); |
403 __ CallCFunction(compare, argument_count); | 403 __ CallCFunction(compare, argument_count); |
404 } | 404 } |
405 // Pop original values before reacting on result value. | 405 // Pop original values before reacting on result value. |
406 __ pop(ebx); | 406 __ pop(ebx); |
407 __ pop(backtrack_stackpointer()); | 407 __ pop(backtrack_stackpointer()); |
408 __ pop(edi); | 408 __ pop(edi); |
409 __ pop(esi); | 409 __ pop(esi); |
410 | 410 |
411 // Check if function returned non-zero for success or zero for failure. | 411 // Check if function returned non-zero for success or zero for failure. |
412 __ or_(eax, Operand(eax)); | 412 __ or_(eax, eax); |
413 BranchOrBacktrack(zero, on_no_match); | 413 BranchOrBacktrack(zero, on_no_match); |
414 // On success, increment position by length of capture. | 414 // On success, increment position by length of capture. |
415 __ add(edi, Operand(ebx)); | 415 __ add(edi, ebx); |
416 } | 416 } |
417 __ bind(&fallthrough); | 417 __ bind(&fallthrough); |
418 } | 418 } |
419 | 419 |
420 | 420 |
421 void RegExpMacroAssemblerIA32::CheckNotBackReference( | 421 void RegExpMacroAssemblerIA32::CheckNotBackReference( |
422 int start_reg, | 422 int start_reg, |
423 Label* on_no_match) { | 423 Label* on_no_match) { |
424 Label fallthrough; | 424 Label fallthrough; |
425 Label success; | 425 Label success; |
426 Label fail; | 426 Label fail; |
427 | 427 |
428 // Find length of back-referenced capture. | 428 // Find length of back-referenced capture. |
429 __ mov(edx, register_location(start_reg)); | 429 __ mov(edx, register_location(start_reg)); |
430 __ mov(eax, register_location(start_reg + 1)); | 430 __ mov(eax, register_location(start_reg + 1)); |
431 __ sub(eax, Operand(edx)); // Length to check. | 431 __ sub(eax, edx); // Length to check. |
432 // Fail on partial or illegal capture (start of capture after end of capture). | 432 // Fail on partial or illegal capture (start of capture after end of capture). |
433 BranchOrBacktrack(less, on_no_match); | 433 BranchOrBacktrack(less, on_no_match); |
434 // Succeed on empty capture (including no capture) | 434 // Succeed on empty capture (including no capture) |
435 __ j(equal, &fallthrough); | 435 __ j(equal, &fallthrough); |
436 | 436 |
437 // Check that there are sufficient characters left in the input. | 437 // Check that there are sufficient characters left in the input. |
438 __ mov(ebx, edi); | 438 __ mov(ebx, edi); |
439 __ add(ebx, Operand(eax)); | 439 __ add(ebx, eax); |
440 BranchOrBacktrack(greater, on_no_match); | 440 BranchOrBacktrack(greater, on_no_match); |
441 | 441 |
442 // Save register to make it available below. | 442 // Save register to make it available below. |
443 __ push(backtrack_stackpointer()); | 443 __ push(backtrack_stackpointer()); |
444 | 444 |
445 // Compute pointers to match string and capture string | 445 // Compute pointers to match string and capture string |
446 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. | 446 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. |
447 __ add(edx, Operand(esi)); // Start of capture. | 447 __ add(edx, esi); // Start of capture. |
448 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match | 448 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match |
449 | 449 |
450 Label loop; | 450 Label loop; |
451 __ bind(&loop); | 451 __ bind(&loop); |
452 if (mode_ == ASCII) { | 452 if (mode_ == ASCII) { |
453 __ movzx_b(eax, Operand(edx, 0)); | 453 __ movzx_b(eax, Operand(edx, 0)); |
454 __ cmpb_al(Operand(ebx, 0)); | 454 __ cmpb_al(Operand(ebx, 0)); |
455 } else { | 455 } else { |
456 ASSERT(mode_ == UC16); | 456 ASSERT(mode_ == UC16); |
457 __ movzx_w(eax, Operand(edx, 0)); | 457 __ movzx_w(eax, Operand(edx, 0)); |
458 __ cmpw_ax(Operand(ebx, 0)); | 458 __ cmpw_ax(Operand(ebx, 0)); |
459 } | 459 } |
460 __ j(not_equal, &fail); | 460 __ j(not_equal, &fail); |
461 // Increment pointers into capture and match string. | 461 // Increment pointers into capture and match string. |
462 __ add(Operand(edx), Immediate(char_size())); | 462 __ add(edx, Immediate(char_size())); |
463 __ add(Operand(ebx), Immediate(char_size())); | 463 __ add(ebx, Immediate(char_size())); |
464 // Check if we have reached end of match area. | 464 // Check if we have reached end of match area. |
465 __ cmp(ebx, Operand(ecx)); | 465 __ cmp(ebx, ecx); |
466 __ j(below, &loop); | 466 __ j(below, &loop); |
467 __ jmp(&success); | 467 __ jmp(&success); |
468 | 468 |
469 __ bind(&fail); | 469 __ bind(&fail); |
470 // Restore backtrack stackpointer. | 470 // Restore backtrack stackpointer. |
471 __ pop(backtrack_stackpointer()); | 471 __ pop(backtrack_stackpointer()); |
472 BranchOrBacktrack(no_condition, on_no_match); | 472 BranchOrBacktrack(no_condition, on_no_match); |
473 | 473 |
474 __ bind(&success); | 474 __ bind(&success); |
475 // Move current character position to position after match. | 475 // Move current character position to position after match. |
476 __ mov(edi, ecx); | 476 __ mov(edi, ecx); |
477 __ sub(Operand(edi), esi); | 477 __ sub(edi, esi); |
478 // Restore backtrack stackpointer. | 478 // Restore backtrack stackpointer. |
479 __ pop(backtrack_stackpointer()); | 479 __ pop(backtrack_stackpointer()); |
480 | 480 |
481 __ bind(&fallthrough); | 481 __ bind(&fallthrough); |
482 } | 482 } |
483 | 483 |
484 | 484 |
485 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, | 485 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, |
486 int reg2, | 486 int reg2, |
487 Label* on_not_equal) { | 487 Label* on_not_equal) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 BranchOrBacktrack(above, on_no_match); | 570 BranchOrBacktrack(above, on_no_match); |
571 return true; | 571 return true; |
572 case 'D': | 572 case 'D': |
573 // Match non ASCII-digits | 573 // Match non ASCII-digits |
574 __ lea(eax, Operand(current_character(), -'0')); | 574 __ lea(eax, Operand(current_character(), -'0')); |
575 __ cmp(eax, '9' - '0'); | 575 __ cmp(eax, '9' - '0'); |
576 BranchOrBacktrack(below_equal, on_no_match); | 576 BranchOrBacktrack(below_equal, on_no_match); |
577 return true; | 577 return true; |
578 case '.': { | 578 case '.': { |
579 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) | 579 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) |
580 __ mov(Operand(eax), current_character()); | 580 __ mov(eax, current_character()); |
581 __ xor_(Operand(eax), Immediate(0x01)); | 581 __ xor_(eax, Immediate(0x01)); |
582 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 582 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
583 __ sub(Operand(eax), Immediate(0x0b)); | 583 __ sub(eax, Immediate(0x0b)); |
584 __ cmp(eax, 0x0c - 0x0b); | 584 __ cmp(eax, 0x0c - 0x0b); |
585 BranchOrBacktrack(below_equal, on_no_match); | 585 BranchOrBacktrack(below_equal, on_no_match); |
586 if (mode_ == UC16) { | 586 if (mode_ == UC16) { |
587 // Compare original value to 0x2028 and 0x2029, using the already | 587 // Compare original value to 0x2028 and 0x2029, using the already |
588 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 588 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
589 // 0x201d (0x2028 - 0x0b) or 0x201e. | 589 // 0x201d (0x2028 - 0x0b) or 0x201e. |
590 __ sub(Operand(eax), Immediate(0x2028 - 0x0b)); | 590 __ sub(eax, Immediate(0x2028 - 0x0b)); |
591 __ cmp(eax, 0x2029 - 0x2028); | 591 __ cmp(eax, 0x2029 - 0x2028); |
592 BranchOrBacktrack(below_equal, on_no_match); | 592 BranchOrBacktrack(below_equal, on_no_match); |
593 } | 593 } |
594 return true; | 594 return true; |
595 } | 595 } |
596 case 'w': { | 596 case 'w': { |
597 if (mode_ != ASCII) { | 597 if (mode_ != ASCII) { |
598 // Table is 128 entries, so all ASCII characters can be tested. | 598 // Table is 128 entries, so all ASCII characters can be tested. |
599 __ cmp(Operand(current_character()), Immediate('z')); | 599 __ cmp(current_character(), Immediate('z')); |
600 BranchOrBacktrack(above, on_no_match); | 600 BranchOrBacktrack(above, on_no_match); |
601 } | 601 } |
602 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 602 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
603 ExternalReference word_map = ExternalReference::re_word_character_map(); | 603 ExternalReference word_map = ExternalReference::re_word_character_map(); |
604 __ test_b(current_character(), | 604 __ test_b(current_character(), |
605 Operand::StaticArray(current_character(), times_1, word_map)); | 605 Operand::StaticArray(current_character(), times_1, word_map)); |
606 BranchOrBacktrack(zero, on_no_match); | 606 BranchOrBacktrack(zero, on_no_match); |
607 return true; | 607 return true; |
608 } | 608 } |
609 case 'W': { | 609 case 'W': { |
610 Label done; | 610 Label done; |
611 if (mode_ != ASCII) { | 611 if (mode_ != ASCII) { |
612 // Table is 128 entries, so all ASCII characters can be tested. | 612 // Table is 128 entries, so all ASCII characters can be tested. |
613 __ cmp(Operand(current_character()), Immediate('z')); | 613 __ cmp(current_character(), Immediate('z')); |
614 __ j(above, &done); | 614 __ j(above, &done); |
615 } | 615 } |
616 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 616 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
617 ExternalReference word_map = ExternalReference::re_word_character_map(); | 617 ExternalReference word_map = ExternalReference::re_word_character_map(); |
618 __ test_b(current_character(), | 618 __ test_b(current_character(), |
619 Operand::StaticArray(current_character(), times_1, word_map)); | 619 Operand::StaticArray(current_character(), times_1, word_map)); |
620 BranchOrBacktrack(not_zero, on_no_match); | 620 BranchOrBacktrack(not_zero, on_no_match); |
621 if (mode_ != ASCII) { | 621 if (mode_ != ASCII) { |
622 __ bind(&done); | 622 __ bind(&done); |
623 } | 623 } |
624 return true; | 624 return true; |
625 } | 625 } |
626 // Non-standard classes (with no syntactic shorthand) used internally. | 626 // Non-standard classes (with no syntactic shorthand) used internally. |
627 case '*': | 627 case '*': |
628 // Match any character. | 628 // Match any character. |
629 return true; | 629 return true; |
630 case 'n': { | 630 case 'n': { |
631 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). | 631 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). |
632 // The opposite of '.'. | 632 // The opposite of '.'. |
633 __ mov(Operand(eax), current_character()); | 633 __ mov(eax, current_character()); |
634 __ xor_(Operand(eax), Immediate(0x01)); | 634 __ xor_(eax, Immediate(0x01)); |
635 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 635 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
636 __ sub(Operand(eax), Immediate(0x0b)); | 636 __ sub(eax, Immediate(0x0b)); |
637 __ cmp(eax, 0x0c - 0x0b); | 637 __ cmp(eax, 0x0c - 0x0b); |
638 if (mode_ == ASCII) { | 638 if (mode_ == ASCII) { |
639 BranchOrBacktrack(above, on_no_match); | 639 BranchOrBacktrack(above, on_no_match); |
640 } else { | 640 } else { |
641 Label done; | 641 Label done; |
642 BranchOrBacktrack(below_equal, &done); | 642 BranchOrBacktrack(below_equal, &done); |
643 ASSERT_EQ(UC16, mode_); | 643 ASSERT_EQ(UC16, mode_); |
644 // Compare original value to 0x2028 and 0x2029, using the already | 644 // Compare original value to 0x2028 and 0x2029, using the already |
645 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 645 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
646 // 0x201d (0x2028 - 0x0b) or 0x201e. | 646 // 0x201d (0x2028 - 0x0b) or 0x201e. |
647 __ sub(Operand(eax), Immediate(0x2028 - 0x0b)); | 647 __ sub(eax, Immediate(0x2028 - 0x0b)); |
648 __ cmp(eax, 1); | 648 __ cmp(eax, 1); |
649 BranchOrBacktrack(above, on_no_match); | 649 BranchOrBacktrack(above, on_no_match); |
650 __ bind(&done); | 650 __ bind(&done); |
651 } | 651 } |
652 return true; | 652 return true; |
653 } | 653 } |
654 // No custom implementation (yet): s(UC16), S(UC16). | 654 // No custom implementation (yet): s(UC16), S(UC16). |
655 default: | 655 default: |
656 return false; | 656 return false; |
657 } | 657 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 // the stack limit. | 700 // the stack limit. |
701 __ cmp(ecx, num_registers_ * kPointerSize); | 701 __ cmp(ecx, num_registers_ * kPointerSize); |
702 __ j(above_equal, &stack_ok); | 702 __ j(above_equal, &stack_ok); |
703 // Exit with OutOfMemory exception. There is not enough space on the stack | 703 // Exit with OutOfMemory exception. There is not enough space on the stack |
704 // for our working registers. | 704 // for our working registers. |
705 __ mov(eax, EXCEPTION); | 705 __ mov(eax, EXCEPTION); |
706 __ jmp(&exit_label_); | 706 __ jmp(&exit_label_); |
707 | 707 |
708 __ bind(&stack_limit_hit); | 708 __ bind(&stack_limit_hit); |
709 CallCheckStackGuardState(ebx); | 709 CallCheckStackGuardState(ebx); |
710 __ or_(eax, Operand(eax)); | 710 __ or_(eax, eax); |
711 // If returned value is non-zero, we exit with the returned value as result. | 711 // If returned value is non-zero, we exit with the returned value as result. |
712 __ j(not_zero, &exit_label_); | 712 __ j(not_zero, &exit_label_); |
713 | 713 |
714 __ bind(&stack_ok); | 714 __ bind(&stack_ok); |
715 // Load start index for later use. | 715 // Load start index for later use. |
716 __ mov(ebx, Operand(ebp, kStartIndex)); | 716 __ mov(ebx, Operand(ebp, kStartIndex)); |
717 | 717 |
718 // Allocate space on stack for registers. | 718 // Allocate space on stack for registers. |
719 __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize)); | 719 __ sub(esp, Immediate(num_registers_ * kPointerSize)); |
720 // Load string length. | 720 // Load string length. |
721 __ mov(esi, Operand(ebp, kInputEnd)); | 721 __ mov(esi, Operand(ebp, kInputEnd)); |
722 // Load input position. | 722 // Load input position. |
723 __ mov(edi, Operand(ebp, kInputStart)); | 723 __ mov(edi, Operand(ebp, kInputStart)); |
724 // Set up edi to be negative offset from string end. | 724 // Set up edi to be negative offset from string end. |
725 __ sub(edi, Operand(esi)); | 725 __ sub(edi, esi); |
726 | 726 |
727 // Set eax to address of char before start of the string. | 727 // Set eax to address of char before start of the string. |
728 // (effectively string position -1). | 728 // (effectively string position -1). |
729 __ neg(ebx); | 729 __ neg(ebx); |
730 if (mode_ == UC16) { | 730 if (mode_ == UC16) { |
731 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); | 731 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); |
732 } else { | 732 } else { |
733 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); | 733 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); |
734 } | 734 } |
735 // Store this value in a local variable, for use when clearing | 735 // Store this value in a local variable, for use when clearing |
736 // position registers. | 736 // position registers. |
737 __ mov(Operand(ebp, kInputStartMinusOne), eax); | 737 __ mov(Operand(ebp, kInputStartMinusOne), eax); |
738 | 738 |
739 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. | 739 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. |
740 // Fill saved registers with initial value = start offset - 1 | 740 // Fill saved registers with initial value = start offset - 1 |
741 // Fill in stack push order, to avoid accessing across an unwritten | 741 // Fill in stack push order, to avoid accessing across an unwritten |
742 // page (a problem on Windows). | 742 // page (a problem on Windows). |
743 __ mov(ecx, kRegisterZero); | 743 __ mov(ecx, kRegisterZero); |
744 Label init_loop; | 744 Label init_loop; |
745 __ bind(&init_loop); | 745 __ bind(&init_loop); |
746 __ mov(Operand(ebp, ecx, times_1, +0), eax); | 746 __ mov(Operand(ebp, ecx, times_1, +0), eax); |
747 __ sub(Operand(ecx), Immediate(kPointerSize)); | 747 __ sub(ecx, Immediate(kPointerSize)); |
748 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); | 748 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); |
749 __ j(greater, &init_loop); | 749 __ j(greater, &init_loop); |
750 } | 750 } |
751 // Ensure that we have written to each stack page, in order. Skipping a page | 751 // Ensure that we have written to each stack page, in order. Skipping a page |
752 // on Windows can cause segmentation faults. Assuming page size is 4k. | 752 // on Windows can cause segmentation faults. Assuming page size is 4k. |
753 const int kPageSize = 4096; | 753 const int kPageSize = 4096; |
754 const int kRegistersPerPage = kPageSize / kPointerSize; | 754 const int kRegistersPerPage = kPageSize / kPointerSize; |
755 for (int i = num_saved_registers_ + kRegistersPerPage - 1; | 755 for (int i = num_saved_registers_ + kRegistersPerPage - 1; |
756 i < num_registers_; | 756 i < num_registers_; |
757 i += kRegistersPerPage) { | 757 i += kRegistersPerPage) { |
(...skipping 20 matching lines...) Expand all Loading... |
778 __ bind(&success_label_); | 778 __ bind(&success_label_); |
779 if (num_saved_registers_ > 0) { | 779 if (num_saved_registers_ > 0) { |
780 // copy captures to output | 780 // copy captures to output |
781 __ mov(ebx, Operand(ebp, kRegisterOutput)); | 781 __ mov(ebx, Operand(ebp, kRegisterOutput)); |
782 __ mov(ecx, Operand(ebp, kInputEnd)); | 782 __ mov(ecx, Operand(ebp, kInputEnd)); |
783 __ mov(edx, Operand(ebp, kStartIndex)); | 783 __ mov(edx, Operand(ebp, kStartIndex)); |
784 __ sub(ecx, Operand(ebp, kInputStart)); | 784 __ sub(ecx, Operand(ebp, kInputStart)); |
785 if (mode_ == UC16) { | 785 if (mode_ == UC16) { |
786 __ lea(ecx, Operand(ecx, edx, times_2, 0)); | 786 __ lea(ecx, Operand(ecx, edx, times_2, 0)); |
787 } else { | 787 } else { |
788 __ add(ecx, Operand(edx)); | 788 __ add(ecx, edx); |
789 } | 789 } |
790 for (int i = 0; i < num_saved_registers_; i++) { | 790 for (int i = 0; i < num_saved_registers_; i++) { |
791 __ mov(eax, register_location(i)); | 791 __ mov(eax, register_location(i)); |
792 // Convert to index from start of string, not end. | 792 // Convert to index from start of string, not end. |
793 __ add(eax, Operand(ecx)); | 793 __ add(eax, ecx); |
794 if (mode_ == UC16) { | 794 if (mode_ == UC16) { |
795 __ sar(eax, 1); // Convert byte index to character index. | 795 __ sar(eax, 1); // Convert byte index to character index. |
796 } | 796 } |
797 __ mov(Operand(ebx, i * kPointerSize), eax); | 797 __ mov(Operand(ebx, i * kPointerSize), eax); |
798 } | 798 } |
799 } | 799 } |
800 __ mov(eax, Immediate(SUCCESS)); | 800 __ mov(eax, Immediate(SUCCESS)); |
801 } | 801 } |
802 // Exit and return eax | 802 // Exit and return eax |
803 __ bind(&exit_label_); | 803 __ bind(&exit_label_); |
(...skipping 16 matching lines...) Expand all Loading... |
820 Label exit_with_exception; | 820 Label exit_with_exception; |
821 | 821 |
822 // Preempt-code | 822 // Preempt-code |
823 if (check_preempt_label_.is_linked()) { | 823 if (check_preempt_label_.is_linked()) { |
824 SafeCallTarget(&check_preempt_label_); | 824 SafeCallTarget(&check_preempt_label_); |
825 | 825 |
826 __ push(backtrack_stackpointer()); | 826 __ push(backtrack_stackpointer()); |
827 __ push(edi); | 827 __ push(edi); |
828 | 828 |
829 CallCheckStackGuardState(ebx); | 829 CallCheckStackGuardState(ebx); |
830 __ or_(eax, Operand(eax)); | 830 __ or_(eax, eax); |
831 // If returning non-zero, we should end execution with the given | 831 // If returning non-zero, we should end execution with the given |
832 // result as return value. | 832 // result as return value. |
833 __ j(not_zero, &exit_label_); | 833 __ j(not_zero, &exit_label_); |
834 | 834 |
835 __ pop(edi); | 835 __ pop(edi); |
836 __ pop(backtrack_stackpointer()); | 836 __ pop(backtrack_stackpointer()); |
837 // String might have moved: Reload esi from frame. | 837 // String might have moved: Reload esi from frame. |
838 __ mov(esi, Operand(ebp, kInputEnd)); | 838 __ mov(esi, Operand(ebp, kInputEnd)); |
839 SafeReturn(); | 839 SafeReturn(); |
840 } | 840 } |
(...skipping 14 matching lines...) Expand all Loading... |
855 __ mov(Operand(esp, 2 * kPointerSize), | 855 __ mov(Operand(esp, 2 * kPointerSize), |
856 Immediate(ExternalReference::isolate_address())); | 856 Immediate(ExternalReference::isolate_address())); |
857 __ lea(eax, Operand(ebp, kStackHighEnd)); | 857 __ lea(eax, Operand(ebp, kStackHighEnd)); |
858 __ mov(Operand(esp, 1 * kPointerSize), eax); | 858 __ mov(Operand(esp, 1 * kPointerSize), eax); |
859 __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); | 859 __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); |
860 ExternalReference grow_stack = | 860 ExternalReference grow_stack = |
861 ExternalReference::re_grow_stack(masm_->isolate()); | 861 ExternalReference::re_grow_stack(masm_->isolate()); |
862 __ CallCFunction(grow_stack, num_arguments); | 862 __ CallCFunction(grow_stack, num_arguments); |
863 // If return NULL, we have failed to grow the stack, and | 863 // If return NULL, we have failed to grow the stack, and |
864 // must exit with a stack-overflow exception. | 864 // must exit with a stack-overflow exception. |
865 __ or_(eax, Operand(eax)); | 865 __ or_(eax, eax); |
866 __ j(equal, &exit_with_exception); | 866 __ j(equal, &exit_with_exception); |
867 // Otherwise use return value as new stack pointer. | 867 // Otherwise use return value as new stack pointer. |
868 __ mov(backtrack_stackpointer(), eax); | 868 __ mov(backtrack_stackpointer(), eax); |
869 // Restore saved registers and continue. | 869 // Restore saved registers and continue. |
870 __ pop(edi); | 870 __ pop(edi); |
871 __ pop(esi); | 871 __ pop(esi); |
872 SafeReturn(); | 872 SafeReturn(); |
873 } | 873 } |
874 | 874 |
875 if (exit_with_exception.is_linked()) { | 875 if (exit_with_exception.is_linked()) { |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 void RegExpMacroAssemblerIA32::SafeCall(Label* to) { | 1184 void RegExpMacroAssemblerIA32::SafeCall(Label* to) { |
1185 Label return_to; | 1185 Label return_to; |
1186 __ push(Immediate::CodeRelativeOffset(&return_to)); | 1186 __ push(Immediate::CodeRelativeOffset(&return_to)); |
1187 __ jmp(to); | 1187 __ jmp(to); |
1188 __ bind(&return_to); | 1188 __ bind(&return_to); |
1189 } | 1189 } |
1190 | 1190 |
1191 | 1191 |
1192 void RegExpMacroAssemblerIA32::SafeReturn() { | 1192 void RegExpMacroAssemblerIA32::SafeReturn() { |
1193 __ pop(ebx); | 1193 __ pop(ebx); |
1194 __ add(Operand(ebx), Immediate(masm_->CodeObject())); | 1194 __ add(ebx, Immediate(masm_->CodeObject())); |
1195 __ jmp(Operand(ebx)); | 1195 __ jmp(ebx); |
1196 } | 1196 } |
1197 | 1197 |
1198 | 1198 |
1199 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { | 1199 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { |
1200 __ bind(name); | 1200 __ bind(name); |
1201 } | 1201 } |
1202 | 1202 |
1203 | 1203 |
1204 void RegExpMacroAssemblerIA32::Push(Register source) { | 1204 void RegExpMacroAssemblerIA32::Push(Register source) { |
1205 ASSERT(!source.is(backtrack_stackpointer())); | 1205 ASSERT(!source.is(backtrack_stackpointer())); |
1206 // Notice: This updates flags, unlike normal Push. | 1206 // Notice: This updates flags, unlike normal Push. |
1207 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); | 1207 __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); |
1208 __ mov(Operand(backtrack_stackpointer(), 0), source); | 1208 __ mov(Operand(backtrack_stackpointer(), 0), source); |
1209 } | 1209 } |
1210 | 1210 |
1211 | 1211 |
1212 void RegExpMacroAssemblerIA32::Push(Immediate value) { | 1212 void RegExpMacroAssemblerIA32::Push(Immediate value) { |
1213 // Notice: This updates flags, unlike normal Push. | 1213 // Notice: This updates flags, unlike normal Push. |
1214 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); | 1214 __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); |
1215 __ mov(Operand(backtrack_stackpointer(), 0), value); | 1215 __ mov(Operand(backtrack_stackpointer(), 0), value); |
1216 } | 1216 } |
1217 | 1217 |
1218 | 1218 |
1219 void RegExpMacroAssemblerIA32::Pop(Register target) { | 1219 void RegExpMacroAssemblerIA32::Pop(Register target) { |
1220 ASSERT(!target.is(backtrack_stackpointer())); | 1220 ASSERT(!target.is(backtrack_stackpointer())); |
1221 __ mov(target, Operand(backtrack_stackpointer(), 0)); | 1221 __ mov(target, Operand(backtrack_stackpointer(), 0)); |
1222 // Notice: This updates flags, unlike normal Pop. | 1222 // Notice: This updates flags, unlike normal Pop. |
1223 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); | 1223 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); |
1224 } | 1224 } |
1225 | 1225 |
1226 | 1226 |
1227 void RegExpMacroAssemblerIA32::CheckPreemption() { | 1227 void RegExpMacroAssemblerIA32::CheckPreemption() { |
1228 // Check for preemption. | 1228 // Check for preemption. |
1229 Label no_preempt; | 1229 Label no_preempt; |
1230 ExternalReference stack_limit = | 1230 ExternalReference stack_limit = |
1231 ExternalReference::address_of_stack_limit(masm_->isolate()); | 1231 ExternalReference::address_of_stack_limit(masm_->isolate()); |
1232 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 1232 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
1233 __ j(above, &no_preempt); | 1233 __ j(above, &no_preempt); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 } | 1276 } |
1277 | 1277 |
1278 | 1278 |
1279 #undef __ | 1279 #undef __ |
1280 | 1280 |
1281 #endif // V8_INTERPRETED_REGEXP | 1281 #endif // V8_INTERPRETED_REGEXP |
1282 | 1282 |
1283 }} // namespace v8::internal | 1283 }} // namespace v8::internal |
1284 | 1284 |
1285 #endif // V8_TARGET_ARCH_IA32 | 1285 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |