| 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 |