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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/cpu-profiler.h" | 9 #include "src/cpu-profiler.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 | 213 |
214 // If length is zero, either the capture is empty or it is completely | 214 // If length is zero, either the capture is empty or it is completely |
215 // uncaptured. In either case succeed immediately. | 215 // uncaptured. In either case succeed immediately. |
216 __ j(equal, &fallthrough); | 216 __ j(equal, &fallthrough); |
217 | 217 |
218 // Check that there are sufficient characters left in the input. | 218 // Check that there are sufficient characters left in the input. |
219 __ mov(eax, edi); | 219 __ mov(eax, edi); |
220 __ add(eax, ebx); | 220 __ add(eax, ebx); |
221 BranchOrBacktrack(greater, on_no_match); | 221 BranchOrBacktrack(greater, on_no_match); |
222 | 222 |
223 if (mode_ == ASCII) { | 223 if (mode_ == LATIN1) { |
224 Label success; | 224 Label success; |
225 Label fail; | 225 Label fail; |
226 Label loop_increment; | 226 Label loop_increment; |
227 // Save register contents to make the registers available below. | 227 // Save register contents to make the registers available below. |
228 __ push(edi); | 228 __ push(edi); |
229 __ push(backtrack_stackpointer()); | 229 __ push(backtrack_stackpointer()); |
230 // After this, the eax, ecx, and edi registers are available. | 230 // After this, the eax, ecx, and edi registers are available. |
231 | 231 |
232 __ add(edx, esi); // Start of capture | 232 __ add(edx, esi); // Start of capture |
233 __ add(edi, esi); // Start of text to match against capture. | 233 __ add(edi, esi); // Start of text to match against capture. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 // Save register to make it available below. | 359 // Save register to make it available below. |
360 __ push(backtrack_stackpointer()); | 360 __ push(backtrack_stackpointer()); |
361 | 361 |
362 // Compute pointers to match string and capture string | 362 // Compute pointers to match string and capture string |
363 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. | 363 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. |
364 __ add(edx, esi); // Start of capture. | 364 __ add(edx, esi); // Start of capture. |
365 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match | 365 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match |
366 | 366 |
367 Label loop; | 367 Label loop; |
368 __ bind(&loop); | 368 __ bind(&loop); |
369 if (mode_ == ASCII) { | 369 if (mode_ == LATIN1) { |
370 __ movzx_b(eax, Operand(edx, 0)); | 370 __ movzx_b(eax, Operand(edx, 0)); |
371 __ cmpb_al(Operand(ebx, 0)); | 371 __ cmpb_al(Operand(ebx, 0)); |
372 } else { | 372 } else { |
373 DCHECK(mode_ == UC16); | 373 DCHECK(mode_ == UC16); |
374 __ movzx_w(eax, Operand(edx, 0)); | 374 __ movzx_w(eax, Operand(edx, 0)); |
375 __ cmpw_ax(Operand(ebx, 0)); | 375 __ cmpw_ax(Operand(ebx, 0)); |
376 } | 376 } |
377 __ j(not_equal, &fail); | 377 __ j(not_equal, &fail); |
378 // Increment pointers into capture and match string. | 378 // Increment pointers into capture and match string. |
379 __ add(edx, Immediate(char_size())); | 379 __ add(edx, Immediate(char_size())); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 __ cmp(eax, to - from); | 469 __ cmp(eax, to - from); |
470 BranchOrBacktrack(above, on_not_in_range); | 470 BranchOrBacktrack(above, on_not_in_range); |
471 } | 471 } |
472 | 472 |
473 | 473 |
474 void RegExpMacroAssemblerIA32::CheckBitInTable( | 474 void RegExpMacroAssemblerIA32::CheckBitInTable( |
475 Handle<ByteArray> table, | 475 Handle<ByteArray> table, |
476 Label* on_bit_set) { | 476 Label* on_bit_set) { |
477 __ mov(eax, Immediate(table)); | 477 __ mov(eax, Immediate(table)); |
478 Register index = current_character(); | 478 Register index = current_character(); |
479 if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) { | 479 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { |
480 __ mov(ebx, kTableSize - 1); | 480 __ mov(ebx, kTableSize - 1); |
481 __ and_(ebx, current_character()); | 481 __ and_(ebx, current_character()); |
482 index = ebx; | 482 index = ebx; |
483 } | 483 } |
484 __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 0); | 484 __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 0); |
485 BranchOrBacktrack(not_equal, on_bit_set); | 485 BranchOrBacktrack(not_equal, on_bit_set); |
486 } | 486 } |
487 | 487 |
488 | 488 |
489 bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type, | 489 bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type, |
490 Label* on_no_match) { | 490 Label* on_no_match) { |
491 // Range checks (c in min..max) are generally implemented by an unsigned | 491 // Range checks (c in min..max) are generally implemented by an unsigned |
492 // (c - min) <= (max - min) check | 492 // (c - min) <= (max - min) check |
493 switch (type) { | 493 switch (type) { |
494 case 's': | 494 case 's': |
495 // Match space-characters | 495 // Match space-characters |
496 if (mode_ == ASCII) { | 496 if (mode_ == LATIN1) { |
497 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 497 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
498 Label success; | 498 Label success; |
499 __ cmp(current_character(), ' '); | 499 __ cmp(current_character(), ' '); |
500 __ j(equal, &success, Label::kNear); | 500 __ j(equal, &success, Label::kNear); |
501 // Check range 0x09..0x0d | 501 // Check range 0x09..0x0d |
502 __ lea(eax, Operand(current_character(), -'\t')); | 502 __ lea(eax, Operand(current_character(), -'\t')); |
503 __ cmp(eax, '\r' - '\t'); | 503 __ cmp(eax, '\r' - '\t'); |
504 __ j(below_equal, &success, Label::kNear); | 504 __ j(below_equal, &success, Label::kNear); |
505 // \u00a0 (NBSP). | 505 // \u00a0 (NBSP). |
506 __ cmp(eax, 0x00a0 - '\t'); | 506 __ cmp(eax, 0x00a0 - '\t'); |
(...skipping 29 matching lines...) Expand all Loading... |
536 // Compare original value to 0x2028 and 0x2029, using the already | 536 // Compare original value to 0x2028 and 0x2029, using the already |
537 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 537 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
538 // 0x201d (0x2028 - 0x0b) or 0x201e. | 538 // 0x201d (0x2028 - 0x0b) or 0x201e. |
539 __ sub(eax, Immediate(0x2028 - 0x0b)); | 539 __ sub(eax, Immediate(0x2028 - 0x0b)); |
540 __ cmp(eax, 0x2029 - 0x2028); | 540 __ cmp(eax, 0x2029 - 0x2028); |
541 BranchOrBacktrack(below_equal, on_no_match); | 541 BranchOrBacktrack(below_equal, on_no_match); |
542 } | 542 } |
543 return true; | 543 return true; |
544 } | 544 } |
545 case 'w': { | 545 case 'w': { |
546 if (mode_ != ASCII) { | 546 if (mode_ != LATIN1) { |
547 // Table is 128 entries, so all ASCII characters can be tested. | 547 // Table is 256 entries, so all Latin1 characters can be tested. |
548 __ cmp(current_character(), Immediate('z')); | 548 __ cmp(current_character(), Immediate('z')); |
549 BranchOrBacktrack(above, on_no_match); | 549 BranchOrBacktrack(above, on_no_match); |
550 } | 550 } |
551 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 551 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
552 ExternalReference word_map = ExternalReference::re_word_character_map(); | 552 ExternalReference word_map = ExternalReference::re_word_character_map(); |
553 __ test_b(current_character(), | 553 __ test_b(current_character(), |
554 Operand::StaticArray(current_character(), times_1, word_map)); | 554 Operand::StaticArray(current_character(), times_1, word_map)); |
555 BranchOrBacktrack(zero, on_no_match); | 555 BranchOrBacktrack(zero, on_no_match); |
556 return true; | 556 return true; |
557 } | 557 } |
558 case 'W': { | 558 case 'W': { |
559 Label done; | 559 Label done; |
560 if (mode_ != ASCII) { | 560 if (mode_ != LATIN1) { |
561 // Table is 128 entries, so all ASCII characters can be tested. | 561 // Table is 256 entries, so all Latin1 characters can be tested. |
562 __ cmp(current_character(), Immediate('z')); | 562 __ cmp(current_character(), Immediate('z')); |
563 __ j(above, &done); | 563 __ j(above, &done); |
564 } | 564 } |
565 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 565 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
566 ExternalReference word_map = ExternalReference::re_word_character_map(); | 566 ExternalReference word_map = ExternalReference::re_word_character_map(); |
567 __ test_b(current_character(), | 567 __ test_b(current_character(), |
568 Operand::StaticArray(current_character(), times_1, word_map)); | 568 Operand::StaticArray(current_character(), times_1, word_map)); |
569 BranchOrBacktrack(not_zero, on_no_match); | 569 BranchOrBacktrack(not_zero, on_no_match); |
570 if (mode_ != ASCII) { | 570 if (mode_ != LATIN1) { |
571 __ bind(&done); | 571 __ bind(&done); |
572 } | 572 } |
573 return true; | 573 return true; |
574 } | 574 } |
575 // Non-standard classes (with no syntactic shorthand) used internally. | 575 // Non-standard classes (with no syntactic shorthand) used internally. |
576 case '*': | 576 case '*': |
577 // Match any character. | 577 // Match any character. |
578 return true; | 578 return true; |
579 case 'n': { | 579 case 'n': { |
580 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). | 580 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). |
581 // The opposite of '.'. | 581 // The opposite of '.'. |
582 __ mov(eax, current_character()); | 582 __ mov(eax, current_character()); |
583 __ xor_(eax, Immediate(0x01)); | 583 __ xor_(eax, Immediate(0x01)); |
584 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 584 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
585 __ sub(eax, Immediate(0x0b)); | 585 __ sub(eax, Immediate(0x0b)); |
586 __ cmp(eax, 0x0c - 0x0b); | 586 __ cmp(eax, 0x0c - 0x0b); |
587 if (mode_ == ASCII) { | 587 if (mode_ == LATIN1) { |
588 BranchOrBacktrack(above, on_no_match); | 588 BranchOrBacktrack(above, on_no_match); |
589 } else { | 589 } else { |
590 Label done; | 590 Label done; |
591 BranchOrBacktrack(below_equal, &done); | 591 BranchOrBacktrack(below_equal, &done); |
592 DCHECK_EQ(UC16, mode_); | 592 DCHECK_EQ(UC16, mode_); |
593 // Compare original value to 0x2028 and 0x2029, using the already | 593 // Compare original value to 0x2028 and 0x2029, using the already |
594 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 594 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
595 // 0x201d (0x2028 - 0x0b) or 0x201e. | 595 // 0x201d (0x2028 - 0x0b) or 0x201e. |
596 __ sub(eax, Immediate(0x2028 - 0x0b)); | 596 __ sub(eax, Immediate(0x2028 - 0x0b)); |
597 __ cmp(eax, 1); | 597 __ cmp(eax, 1); |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 return RETRY; | 1092 return RETRY; |
1093 } | 1093 } |
1094 | 1094 |
1095 // Prepare for possible GC. | 1095 // Prepare for possible GC. |
1096 HandleScope handles(isolate); | 1096 HandleScope handles(isolate); |
1097 Handle<Code> code_handle(re_code); | 1097 Handle<Code> code_handle(re_code); |
1098 | 1098 |
1099 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); | 1099 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); |
1100 | 1100 |
1101 // Current string. | 1101 // Current string. |
1102 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 1102 bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); |
1103 | 1103 |
1104 DCHECK(re_code->instruction_start() <= *return_address); | 1104 DCHECK(re_code->instruction_start() <= *return_address); |
1105 DCHECK(*return_address <= | 1105 DCHECK(*return_address <= |
1106 re_code->instruction_start() + re_code->instruction_size()); | 1106 re_code->instruction_start() + re_code->instruction_size()); |
1107 | 1107 |
1108 Object* result = isolate->stack_guard()->HandleInterrupts(); | 1108 Object* result = isolate->stack_guard()->HandleInterrupts(); |
1109 | 1109 |
1110 if (*code_handle != re_code) { // Return address no longer valid | 1110 if (*code_handle != re_code) { // Return address no longer valid |
1111 int delta = code_handle->address() - re_code->address(); | 1111 int delta = code_handle->address() - re_code->address(); |
1112 // Overwrite the return address on the stack. | 1112 // Overwrite the return address on the stack. |
(...skipping 10 matching lines...) Expand all Loading... |
1123 // Extract the underlying string and the slice offset. | 1123 // Extract the underlying string and the slice offset. |
1124 if (StringShape(*subject_tmp).IsCons()) { | 1124 if (StringShape(*subject_tmp).IsCons()) { |
1125 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); | 1125 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); |
1126 } else if (StringShape(*subject_tmp).IsSliced()) { | 1126 } else if (StringShape(*subject_tmp).IsSliced()) { |
1127 SlicedString* slice = SlicedString::cast(*subject_tmp); | 1127 SlicedString* slice = SlicedString::cast(*subject_tmp); |
1128 subject_tmp = Handle<String>(slice->parent()); | 1128 subject_tmp = Handle<String>(slice->parent()); |
1129 slice_offset = slice->offset(); | 1129 slice_offset = slice->offset(); |
1130 } | 1130 } |
1131 | 1131 |
1132 // String might have changed. | 1132 // String might have changed. |
1133 if (subject_tmp->IsOneByteRepresentation() != is_ascii) { | 1133 if (subject_tmp->IsOneByteRepresentation() != is_one_byte) { |
1134 // If we changed between an ASCII and an UC16 string, the specialized | 1134 // If we changed between an LATIN1 and an UC16 string, the specialized |
1135 // code cannot be used, and we need to restart regexp matching from | 1135 // code cannot be used, and we need to restart regexp matching from |
1136 // scratch (including, potentially, compiling a new version of the code). | 1136 // scratch (including, potentially, compiling a new version of the code). |
1137 return RETRY; | 1137 return RETRY; |
1138 } | 1138 } |
1139 | 1139 |
1140 // Otherwise, the content of the string might have moved. It must still | 1140 // Otherwise, the content of the string might have moved. It must still |
1141 // be a sequential or external string with the same content. | 1141 // be a sequential or external string with the same content. |
1142 // Update the start and end pointers in the stack frame to the current | 1142 // Update the start and end pointers in the stack frame to the current |
1143 // location (whether it has actually moved or not). | 1143 // location (whether it has actually moved or not). |
1144 DCHECK(StringShape(*subject_tmp).IsSequential() || | 1144 DCHECK(StringShape(*subject_tmp).IsSequential() || |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 __ j(above, &no_stack_overflow); | 1271 __ j(above, &no_stack_overflow); |
1272 | 1272 |
1273 SafeCall(&stack_overflow_label_); | 1273 SafeCall(&stack_overflow_label_); |
1274 | 1274 |
1275 __ bind(&no_stack_overflow); | 1275 __ bind(&no_stack_overflow); |
1276 } | 1276 } |
1277 | 1277 |
1278 | 1278 |
1279 void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset, | 1279 void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset, |
1280 int characters) { | 1280 int characters) { |
1281 if (mode_ == ASCII) { | 1281 if (mode_ == LATIN1) { |
1282 if (characters == 4) { | 1282 if (characters == 4) { |
1283 __ mov(current_character(), Operand(esi, edi, times_1, cp_offset)); | 1283 __ mov(current_character(), Operand(esi, edi, times_1, cp_offset)); |
1284 } else if (characters == 2) { | 1284 } else if (characters == 2) { |
1285 __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset)); | 1285 __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset)); |
1286 } else { | 1286 } else { |
1287 DCHECK(characters == 1); | 1287 DCHECK(characters == 1); |
1288 __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); | 1288 __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); |
1289 } | 1289 } |
1290 } else { | 1290 } else { |
1291 DCHECK(mode_ == UC16); | 1291 DCHECK(mode_ == UC16); |
1292 if (characters == 2) { | 1292 if (characters == 2) { |
1293 __ mov(current_character(), | 1293 __ mov(current_character(), |
1294 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); | 1294 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); |
1295 } else { | 1295 } else { |
1296 DCHECK(characters == 1); | 1296 DCHECK(characters == 1); |
1297 __ movzx_w(current_character(), | 1297 __ movzx_w(current_character(), |
1298 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); | 1298 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); |
1299 } | 1299 } |
1300 } | 1300 } |
1301 } | 1301 } |
1302 | 1302 |
1303 | 1303 |
1304 #undef __ | 1304 #undef __ |
1305 | 1305 |
1306 #endif // V8_INTERPRETED_REGEXP | 1306 #endif // V8_INTERPRETED_REGEXP |
1307 | 1307 |
1308 }} // namespace v8::internal | 1308 }} // namespace v8::internal |
1309 | 1309 |
1310 #endif // V8_TARGET_ARCH_IA32 | 1310 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |