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_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 __ Subu(a1, a1, a0); // Length of capture. | 234 __ Subu(a1, a1, a0); // Length of capture. |
235 | 235 |
236 // If length is zero, either the capture is empty or it is not participating. | 236 // If length is zero, either the capture is empty or it is not participating. |
237 // In either case succeed immediately. | 237 // In either case succeed immediately. |
238 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); | 238 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); |
239 | 239 |
240 __ Addu(t5, a1, current_input_offset()); | 240 __ Addu(t5, a1, current_input_offset()); |
241 // Check that there are enough characters left in the input. | 241 // Check that there are enough characters left in the input. |
242 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); | 242 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); |
243 | 243 |
244 if (mode_ == ASCII) { | 244 if (mode_ == LATIN1) { |
245 Label success; | 245 Label success; |
246 Label fail; | 246 Label fail; |
247 Label loop_check; | 247 Label loop_check; |
248 | 248 |
249 // a0 - offset of start of capture. | 249 // a0 - offset of start of capture. |
250 // a1 - length of capture. | 250 // a1 - length of capture. |
251 __ Addu(a0, a0, Operand(end_of_input_address())); | 251 __ Addu(a0, a0, Operand(end_of_input_address())); |
252 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); | 252 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); |
253 __ Addu(a1, a0, Operand(a1)); | 253 __ Addu(a1, a0, Operand(a1)); |
254 | 254 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 // Check that there are enough characters left in the input. | 358 // Check that there are enough characters left in the input. |
359 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); | 359 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); |
360 | 360 |
361 // Compute pointers to match string and capture string. | 361 // Compute pointers to match string and capture string. |
362 __ Addu(a0, a0, Operand(end_of_input_address())); | 362 __ Addu(a0, a0, Operand(end_of_input_address())); |
363 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); | 363 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); |
364 __ Addu(a1, a1, Operand(a0)); | 364 __ Addu(a1, a1, Operand(a0)); |
365 | 365 |
366 Label loop; | 366 Label loop; |
367 __ bind(&loop); | 367 __ bind(&loop); |
368 if (mode_ == ASCII) { | 368 if (mode_ == LATIN1) { |
369 __ lbu(a3, MemOperand(a0, 0)); | 369 __ lbu(a3, MemOperand(a0, 0)); |
370 __ addiu(a0, a0, char_size()); | 370 __ addiu(a0, a0, char_size()); |
371 __ lbu(t0, MemOperand(a2, 0)); | 371 __ lbu(t0, MemOperand(a2, 0)); |
372 __ addiu(a2, a2, char_size()); | 372 __ addiu(a2, a2, char_size()); |
373 } else { | 373 } else { |
374 DCHECK(mode_ == UC16); | 374 DCHECK(mode_ == UC16); |
375 __ lhu(a3, MemOperand(a0, 0)); | 375 __ lhu(a3, MemOperand(a0, 0)); |
376 __ addiu(a0, a0, char_size()); | 376 __ addiu(a0, a0, char_size()); |
377 __ lhu(t0, MemOperand(a2, 0)); | 377 __ lhu(t0, MemOperand(a2, 0)); |
378 __ addiu(a2, a2, char_size()); | 378 __ addiu(a2, a2, char_size()); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 __ Subu(a0, current_character(), Operand(from)); | 439 __ Subu(a0, current_character(), Operand(from)); |
440 // Unsigned higher condition. | 440 // Unsigned higher condition. |
441 BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from)); | 441 BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from)); |
442 } | 442 } |
443 | 443 |
444 | 444 |
445 void RegExpMacroAssemblerMIPS::CheckBitInTable( | 445 void RegExpMacroAssemblerMIPS::CheckBitInTable( |
446 Handle<ByteArray> table, | 446 Handle<ByteArray> table, |
447 Label* on_bit_set) { | 447 Label* on_bit_set) { |
448 __ li(a0, Operand(table)); | 448 __ li(a0, Operand(table)); |
449 if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) { | 449 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { |
450 __ And(a1, current_character(), Operand(kTableSize - 1)); | 450 __ And(a1, current_character(), Operand(kTableSize - 1)); |
451 __ Addu(a0, a0, a1); | 451 __ Addu(a0, a0, a1); |
452 } else { | 452 } else { |
453 __ Addu(a0, a0, current_character()); | 453 __ Addu(a0, a0, current_character()); |
454 } | 454 } |
455 | 455 |
456 __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize)); | 456 __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize)); |
457 BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg)); | 457 BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg)); |
458 } | 458 } |
459 | 459 |
460 | 460 |
461 bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type, | 461 bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type, |
462 Label* on_no_match) { | 462 Label* on_no_match) { |
463 // Range checks (c in min..max) are generally implemented by an unsigned | 463 // Range checks (c in min..max) are generally implemented by an unsigned |
464 // (c - min) <= (max - min) check. | 464 // (c - min) <= (max - min) check. |
465 switch (type) { | 465 switch (type) { |
466 case 's': | 466 case 's': |
467 // Match space-characters. | 467 // Match space-characters. |
468 if (mode_ == ASCII) { | 468 if (mode_ == LATIN1) { |
469 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 469 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
470 Label success; | 470 Label success; |
471 __ Branch(&success, eq, current_character(), Operand(' ')); | 471 __ Branch(&success, eq, current_character(), Operand(' ')); |
472 // Check range 0x09..0x0d. | 472 // Check range 0x09..0x0d. |
473 __ Subu(a0, current_character(), Operand('\t')); | 473 __ Subu(a0, current_character(), Operand('\t')); |
474 __ Branch(&success, ls, a0, Operand('\r' - '\t')); | 474 __ Branch(&success, ls, a0, Operand('\r' - '\t')); |
475 // \u00a0 (NBSP). | 475 // \u00a0 (NBSP). |
476 BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00a0 - '\t')); | 476 BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00a0 - '\t')); |
477 __ bind(&success); | 477 __ bind(&success); |
478 return true; | 478 return true; |
479 } | 479 } |
480 return false; | 480 return false; |
481 case 'S': | 481 case 'S': |
482 // The emitted code for generic character classes is good enough. | 482 // The emitted code for generic character classes is good enough. |
483 return false; | 483 return false; |
484 case 'd': | 484 case 'd': |
485 // Match ASCII digits ('0'..'9'). | 485 // Match Latin1 digits ('0'..'9'). |
486 __ Subu(a0, current_character(), Operand('0')); | 486 __ Subu(a0, current_character(), Operand('0')); |
487 BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0')); | 487 BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0')); |
488 return true; | 488 return true; |
489 case 'D': | 489 case 'D': |
490 // Match non ASCII-digits. | 490 // Match non Latin1-digits. |
491 __ Subu(a0, current_character(), Operand('0')); | 491 __ Subu(a0, current_character(), Operand('0')); |
492 BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0')); | 492 BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0')); |
493 return true; | 493 return true; |
494 case '.': { | 494 case '.': { |
495 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). | 495 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). |
496 __ Xor(a0, current_character(), Operand(0x01)); | 496 __ Xor(a0, current_character(), Operand(0x01)); |
497 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. | 497 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. |
498 __ Subu(a0, a0, Operand(0x0b)); | 498 __ Subu(a0, a0, Operand(0x0b)); |
499 BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b)); | 499 BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b)); |
500 if (mode_ == UC16) { | 500 if (mode_ == UC16) { |
501 // Compare original value to 0x2028 and 0x2029, using the already | 501 // Compare original value to 0x2028 and 0x2029, using the already |
502 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 502 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
503 // 0x201d (0x2028 - 0x0b) or 0x201e. | 503 // 0x201d (0x2028 - 0x0b) or 0x201e. |
504 __ Subu(a0, a0, Operand(0x2028 - 0x0b)); | 504 __ Subu(a0, a0, Operand(0x2028 - 0x0b)); |
505 BranchOrBacktrack(on_no_match, ls, a0, Operand(1)); | 505 BranchOrBacktrack(on_no_match, ls, a0, Operand(1)); |
506 } | 506 } |
507 return true; | 507 return true; |
508 } | 508 } |
509 case 'n': { | 509 case 'n': { |
510 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). | 510 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). |
511 __ Xor(a0, current_character(), Operand(0x01)); | 511 __ Xor(a0, current_character(), Operand(0x01)); |
512 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. | 512 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. |
513 __ Subu(a0, a0, Operand(0x0b)); | 513 __ Subu(a0, a0, Operand(0x0b)); |
514 if (mode_ == ASCII) { | 514 if (mode_ == LATIN1) { |
515 BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b)); | 515 BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b)); |
516 } else { | 516 } else { |
517 Label done; | 517 Label done; |
518 BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b)); | 518 BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b)); |
519 // Compare original value to 0x2028 and 0x2029, using the already | 519 // Compare original value to 0x2028 and 0x2029, using the already |
520 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 520 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
521 // 0x201d (0x2028 - 0x0b) or 0x201e. | 521 // 0x201d (0x2028 - 0x0b) or 0x201e. |
522 __ Subu(a0, a0, Operand(0x2028 - 0x0b)); | 522 __ Subu(a0, a0, Operand(0x2028 - 0x0b)); |
523 BranchOrBacktrack(on_no_match, hi, a0, Operand(1)); | 523 BranchOrBacktrack(on_no_match, hi, a0, Operand(1)); |
524 __ bind(&done); | 524 __ bind(&done); |
525 } | 525 } |
526 return true; | 526 return true; |
527 } | 527 } |
528 case 'w': { | 528 case 'w': { |
529 if (mode_ != ASCII) { | 529 if (mode_ != LATIN1) { |
530 // Table is 128 entries, so all ASCII characters can be tested. | 530 // Table is 256 entries, so all Latin1 characters can be tested. |
531 BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z')); | 531 BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z')); |
532 } | 532 } |
533 ExternalReference map = ExternalReference::re_word_character_map(); | 533 ExternalReference map = ExternalReference::re_word_character_map(); |
534 __ li(a0, Operand(map)); | 534 __ li(a0, Operand(map)); |
535 __ Addu(a0, a0, current_character()); | 535 __ Addu(a0, a0, current_character()); |
536 __ lbu(a0, MemOperand(a0, 0)); | 536 __ lbu(a0, MemOperand(a0, 0)); |
537 BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg)); | 537 BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg)); |
538 return true; | 538 return true; |
539 } | 539 } |
540 case 'W': { | 540 case 'W': { |
541 Label done; | 541 Label done; |
542 if (mode_ != ASCII) { | 542 if (mode_ != LATIN1) { |
543 // Table is 128 entries, so all ASCII characters can be tested. | 543 // Table is 256 entries, so all Latin1 characters can be tested. |
544 __ Branch(&done, hi, current_character(), Operand('z')); | 544 __ Branch(&done, hi, current_character(), Operand('z')); |
545 } | 545 } |
546 ExternalReference map = ExternalReference::re_word_character_map(); | 546 ExternalReference map = ExternalReference::re_word_character_map(); |
547 __ li(a0, Operand(map)); | 547 __ li(a0, Operand(map)); |
548 __ Addu(a0, a0, current_character()); | 548 __ Addu(a0, a0, current_character()); |
549 __ lbu(a0, MemOperand(a0, 0)); | 549 __ lbu(a0, MemOperand(a0, 0)); |
550 BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg)); | 550 BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg)); |
551 if (mode_ != ASCII) { | 551 if (mode_ != LATIN1) { |
552 __ bind(&done); | 552 __ bind(&done); |
553 } | 553 } |
554 return true; | 554 return true; |
555 } | 555 } |
556 case '*': | 556 case '*': |
557 // Match any character. | 557 // Match any character. |
558 return true; | 558 return true; |
559 // No custom implementation (yet): s(UC16), S(UC16). | 559 // No custom implementation (yet): s(UC16), S(UC16). |
560 default: | 560 default: |
561 return false; | 561 return false; |
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 if (frame_entry<int>(re_frame, kDirectCall) == 1) { | 1119 if (frame_entry<int>(re_frame, kDirectCall) == 1) { |
1120 return RETRY; | 1120 return RETRY; |
1121 } | 1121 } |
1122 | 1122 |
1123 // Prepare for possible GC. | 1123 // Prepare for possible GC. |
1124 HandleScope handles(isolate); | 1124 HandleScope handles(isolate); |
1125 Handle<Code> code_handle(re_code); | 1125 Handle<Code> code_handle(re_code); |
1126 | 1126 |
1127 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); | 1127 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); |
1128 // Current string. | 1128 // Current string. |
1129 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 1129 bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); |
1130 | 1130 |
1131 DCHECK(re_code->instruction_start() <= *return_address); | 1131 DCHECK(re_code->instruction_start() <= *return_address); |
1132 DCHECK(*return_address <= | 1132 DCHECK(*return_address <= |
1133 re_code->instruction_start() + re_code->instruction_size()); | 1133 re_code->instruction_start() + re_code->instruction_size()); |
1134 | 1134 |
1135 Object* result = isolate->stack_guard()->HandleInterrupts(); | 1135 Object* result = isolate->stack_guard()->HandleInterrupts(); |
1136 | 1136 |
1137 if (*code_handle != re_code) { // Return address no longer valid. | 1137 if (*code_handle != re_code) { // Return address no longer valid. |
1138 int delta = code_handle->address() - re_code->address(); | 1138 int delta = code_handle->address() - re_code->address(); |
1139 // Overwrite the return address on the stack. | 1139 // Overwrite the return address on the stack. |
(...skipping 10 matching lines...) Expand all Loading... |
1150 // Extract the underlying string and the slice offset. | 1150 // Extract the underlying string and the slice offset. |
1151 if (StringShape(*subject_tmp).IsCons()) { | 1151 if (StringShape(*subject_tmp).IsCons()) { |
1152 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); | 1152 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); |
1153 } else if (StringShape(*subject_tmp).IsSliced()) { | 1153 } else if (StringShape(*subject_tmp).IsSliced()) { |
1154 SlicedString* slice = SlicedString::cast(*subject_tmp); | 1154 SlicedString* slice = SlicedString::cast(*subject_tmp); |
1155 subject_tmp = Handle<String>(slice->parent()); | 1155 subject_tmp = Handle<String>(slice->parent()); |
1156 slice_offset = slice->offset(); | 1156 slice_offset = slice->offset(); |
1157 } | 1157 } |
1158 | 1158 |
1159 // String might have changed. | 1159 // String might have changed. |
1160 if (subject_tmp->IsOneByteRepresentation() != is_ascii) { | 1160 if (subject_tmp->IsOneByteRepresentation() != is_one_byte) { |
1161 // If we changed between an ASCII and an UC16 string, the specialized | 1161 // If we changed between an Latin1 and an UC16 string, the specialized |
1162 // code cannot be used, and we need to restart regexp matching from | 1162 // code cannot be used, and we need to restart regexp matching from |
1163 // scratch (including, potentially, compiling a new version of the code). | 1163 // scratch (including, potentially, compiling a new version of the code). |
1164 return RETRY; | 1164 return RETRY; |
1165 } | 1165 } |
1166 | 1166 |
1167 // Otherwise, the content of the string might have moved. It must still | 1167 // Otherwise, the content of the string might have moved. It must still |
1168 // be a sequential or external string with the same content. | 1168 // be a sequential or external string with the same content. |
1169 // Update the start and end pointers in the stack frame to the current | 1169 // Update the start and end pointers in the stack frame to the current |
1170 // location (whether it has actually moved or not). | 1170 // location (whether it has actually moved or not). |
1171 DCHECK(StringShape(*subject_tmp).IsSequential() || | 1171 DCHECK(StringShape(*subject_tmp).IsSequential() || |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1301 Register offset = current_input_offset(); | 1301 Register offset = current_input_offset(); |
1302 if (cp_offset != 0) { | 1302 if (cp_offset != 0) { |
1303 // t7 is not being used to store the capture start index at this point. | 1303 // t7 is not being used to store the capture start index at this point. |
1304 __ Addu(t7, current_input_offset(), Operand(cp_offset * char_size())); | 1304 __ Addu(t7, current_input_offset(), Operand(cp_offset * char_size())); |
1305 offset = t7; | 1305 offset = t7; |
1306 } | 1306 } |
1307 // We assume that we cannot do unaligned loads on MIPS, so this function | 1307 // We assume that we cannot do unaligned loads on MIPS, so this function |
1308 // must only be used to load a single character at a time. | 1308 // must only be used to load a single character at a time. |
1309 DCHECK(characters == 1); | 1309 DCHECK(characters == 1); |
1310 __ Addu(t5, end_of_input_address(), Operand(offset)); | 1310 __ Addu(t5, end_of_input_address(), Operand(offset)); |
1311 if (mode_ == ASCII) { | 1311 if (mode_ == LATIN1) { |
1312 __ lbu(current_character(), MemOperand(t5, 0)); | 1312 __ lbu(current_character(), MemOperand(t5, 0)); |
1313 } else { | 1313 } else { |
1314 DCHECK(mode_ == UC16); | 1314 DCHECK(mode_ == UC16); |
1315 __ lhu(current_character(), MemOperand(t5, 0)); | 1315 __ lhu(current_character(), MemOperand(t5, 0)); |
1316 } | 1316 } |
1317 } | 1317 } |
1318 | 1318 |
1319 | 1319 |
1320 #undef __ | 1320 #undef __ |
1321 | 1321 |
1322 #endif // V8_INTERPRETED_REGEXP | 1322 #endif // V8_INTERPRETED_REGEXP |
1323 | 1323 |
1324 }} // namespace v8::internal | 1324 }} // namespace v8::internal |
1325 | 1325 |
1326 #endif // V8_TARGET_ARCH_MIPS | 1326 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |