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