| 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_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/cpu-profiler.h" | 10 #include "src/cpu-profiler.h" |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 __ sub(r1, r1, r0, SetCC); // Length of capture. | 231 __ sub(r1, r1, r0, SetCC); // Length of capture. |
| 232 | 232 |
| 233 // If length is zero, either the capture is empty or it is not participating. | 233 // If length is zero, either the capture is empty or it is not participating. |
| 234 // In either case succeed immediately. | 234 // In either case succeed immediately. |
| 235 __ b(eq, &fallthrough); | 235 __ b(eq, &fallthrough); |
| 236 | 236 |
| 237 // Check that there are enough characters left in the input. | 237 // Check that there are enough characters left in the input. |
| 238 __ cmn(r1, Operand(current_input_offset())); | 238 __ cmn(r1, Operand(current_input_offset())); |
| 239 BranchOrBacktrack(gt, on_no_match); | 239 BranchOrBacktrack(gt, on_no_match); |
| 240 | 240 |
| 241 if (mode_ == ASCII) { | 241 if (mode_ == LATIN1) { |
| 242 Label success; | 242 Label success; |
| 243 Label fail; | 243 Label fail; |
| 244 Label loop_check; | 244 Label loop_check; |
| 245 | 245 |
| 246 // r0 - offset of start of capture | 246 // r0 - offset of start of capture |
| 247 // r1 - length of capture | 247 // r1 - length of capture |
| 248 __ add(r0, r0, Operand(end_of_input_address())); | 248 __ add(r0, r0, Operand(end_of_input_address())); |
| 249 __ add(r2, end_of_input_address(), Operand(current_input_offset())); | 249 __ add(r2, end_of_input_address(), Operand(current_input_offset())); |
| 250 __ add(r1, r0, Operand(r1)); | 250 __ add(r1, r0, Operand(r1)); |
| 251 | 251 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 __ cmn(r1, Operand(current_input_offset())); | 347 __ cmn(r1, Operand(current_input_offset())); |
| 348 BranchOrBacktrack(gt, on_no_match); | 348 BranchOrBacktrack(gt, on_no_match); |
| 349 | 349 |
| 350 // Compute pointers to match string and capture string | 350 // Compute pointers to match string and capture string |
| 351 __ add(r0, r0, Operand(end_of_input_address())); | 351 __ add(r0, r0, Operand(end_of_input_address())); |
| 352 __ add(r2, end_of_input_address(), Operand(current_input_offset())); | 352 __ add(r2, end_of_input_address(), Operand(current_input_offset())); |
| 353 __ add(r1, r1, Operand(r0)); | 353 __ add(r1, r1, Operand(r0)); |
| 354 | 354 |
| 355 Label loop; | 355 Label loop; |
| 356 __ bind(&loop); | 356 __ bind(&loop); |
| 357 if (mode_ == ASCII) { | 357 if (mode_ == LATIN1) { |
| 358 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); | 358 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); |
| 359 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); | 359 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); |
| 360 } else { | 360 } else { |
| 361 DCHECK(mode_ == UC16); | 361 DCHECK(mode_ == UC16); |
| 362 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); | 362 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); |
| 363 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); | 363 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); |
| 364 } | 364 } |
| 365 __ cmp(r3, r4); | 365 __ cmp(r3, r4); |
| 366 BranchOrBacktrack(ne, on_no_match); | 366 BranchOrBacktrack(ne, on_no_match); |
| 367 __ cmp(r0, r1); | 367 __ cmp(r0, r1); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 __ sub(r0, current_character(), Operand(from)); | 436 __ sub(r0, current_character(), Operand(from)); |
| 437 __ cmp(r0, Operand(to - from)); | 437 __ cmp(r0, Operand(to - from)); |
| 438 BranchOrBacktrack(hi, on_not_in_range); // Unsigned higher condition. | 438 BranchOrBacktrack(hi, on_not_in_range); // Unsigned higher condition. |
| 439 } | 439 } |
| 440 | 440 |
| 441 | 441 |
| 442 void RegExpMacroAssemblerARM::CheckBitInTable( | 442 void RegExpMacroAssemblerARM::CheckBitInTable( |
| 443 Handle<ByteArray> table, | 443 Handle<ByteArray> table, |
| 444 Label* on_bit_set) { | 444 Label* on_bit_set) { |
| 445 __ mov(r0, Operand(table)); | 445 __ mov(r0, Operand(table)); |
| 446 if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) { | 446 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { |
| 447 __ and_(r1, current_character(), Operand(kTableSize - 1)); | 447 __ and_(r1, current_character(), Operand(kTableSize - 1)); |
| 448 __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag)); | 448 __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag)); |
| 449 } else { | 449 } else { |
| 450 __ add(r1, | 450 __ add(r1, |
| 451 current_character(), | 451 current_character(), |
| 452 Operand(ByteArray::kHeaderSize - kHeapObjectTag)); | 452 Operand(ByteArray::kHeaderSize - kHeapObjectTag)); |
| 453 } | 453 } |
| 454 __ ldrb(r0, MemOperand(r0, r1)); | 454 __ ldrb(r0, MemOperand(r0, r1)); |
| 455 __ cmp(r0, Operand::Zero()); | 455 __ cmp(r0, Operand::Zero()); |
| 456 BranchOrBacktrack(ne, on_bit_set); | 456 BranchOrBacktrack(ne, on_bit_set); |
| 457 } | 457 } |
| 458 | 458 |
| 459 | 459 |
| 460 bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type, | 460 bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type, |
| 461 Label* on_no_match) { | 461 Label* on_no_match) { |
| 462 // Range checks (c in min..max) are generally implemented by an unsigned | 462 // Range checks (c in min..max) are generally implemented by an unsigned |
| 463 // (c - min) <= (max - min) check | 463 // (c - min) <= (max - min) check |
| 464 switch (type) { | 464 switch (type) { |
| 465 case 's': | 465 case 's': |
| 466 // Match space-characters | 466 // Match space-characters |
| 467 if (mode_ == ASCII) { | 467 if (mode_ == LATIN1) { |
| 468 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 468 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
| 469 Label success; | 469 Label success; |
| 470 __ cmp(current_character(), Operand(' ')); | 470 __ cmp(current_character(), Operand(' ')); |
| 471 __ b(eq, &success); | 471 __ b(eq, &success); |
| 472 // Check range 0x09..0x0d | 472 // Check range 0x09..0x0d |
| 473 __ sub(r0, current_character(), Operand('\t')); | 473 __ sub(r0, current_character(), Operand('\t')); |
| 474 __ cmp(r0, Operand('\r' - '\t')); | 474 __ cmp(r0, Operand('\r' - '\t')); |
| 475 __ b(ls, &success); | 475 __ b(ls, &success); |
| 476 // \u00a0 (NBSP). | 476 // \u00a0 (NBSP). |
| 477 __ cmp(r0, Operand(0x00a0 - '\t')); | 477 __ cmp(r0, Operand(0x00a0 - '\t')); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 BranchOrBacktrack(ls, on_no_match); | 511 BranchOrBacktrack(ls, on_no_match); |
| 512 } | 512 } |
| 513 return true; | 513 return true; |
| 514 } | 514 } |
| 515 case 'n': { | 515 case 'n': { |
| 516 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) | 516 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) |
| 517 __ eor(r0, current_character(), Operand(0x01)); | 517 __ eor(r0, current_character(), Operand(0x01)); |
| 518 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 518 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
| 519 __ sub(r0, r0, Operand(0x0b)); | 519 __ sub(r0, r0, Operand(0x0b)); |
| 520 __ cmp(r0, Operand(0x0c - 0x0b)); | 520 __ cmp(r0, Operand(0x0c - 0x0b)); |
| 521 if (mode_ == ASCII) { | 521 if (mode_ == LATIN1) { |
| 522 BranchOrBacktrack(hi, on_no_match); | 522 BranchOrBacktrack(hi, on_no_match); |
| 523 } else { | 523 } else { |
| 524 Label done; | 524 Label done; |
| 525 __ b(ls, &done); | 525 __ b(ls, &done); |
| 526 // Compare original value to 0x2028 and 0x2029, using the already | 526 // Compare original value to 0x2028 and 0x2029, using the already |
| 527 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 527 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
| 528 // 0x201d (0x2028 - 0x0b) or 0x201e. | 528 // 0x201d (0x2028 - 0x0b) or 0x201e. |
| 529 __ sub(r0, r0, Operand(0x2028 - 0x0b)); | 529 __ sub(r0, r0, Operand(0x2028 - 0x0b)); |
| 530 __ cmp(r0, Operand(1)); | 530 __ cmp(r0, Operand(1)); |
| 531 BranchOrBacktrack(hi, on_no_match); | 531 BranchOrBacktrack(hi, on_no_match); |
| 532 __ bind(&done); | 532 __ bind(&done); |
| 533 } | 533 } |
| 534 return true; | 534 return true; |
| 535 } | 535 } |
| 536 case 'w': { | 536 case 'w': { |
| 537 if (mode_ != ASCII) { | 537 if (mode_ != LATIN1) { |
| 538 // Table is 128 entries, so all ASCII characters can be tested. | 538 // Table is 256 entries, so all Latin1 characters can be tested. |
| 539 __ cmp(current_character(), Operand('z')); | 539 __ cmp(current_character(), Operand('z')); |
| 540 BranchOrBacktrack(hi, on_no_match); | 540 BranchOrBacktrack(hi, on_no_match); |
| 541 } | 541 } |
| 542 ExternalReference map = ExternalReference::re_word_character_map(); | 542 ExternalReference map = ExternalReference::re_word_character_map(); |
| 543 __ mov(r0, Operand(map)); | 543 __ mov(r0, Operand(map)); |
| 544 __ ldrb(r0, MemOperand(r0, current_character())); | 544 __ ldrb(r0, MemOperand(r0, current_character())); |
| 545 __ cmp(r0, Operand::Zero()); | 545 __ cmp(r0, Operand::Zero()); |
| 546 BranchOrBacktrack(eq, on_no_match); | 546 BranchOrBacktrack(eq, on_no_match); |
| 547 return true; | 547 return true; |
| 548 } | 548 } |
| 549 case 'W': { | 549 case 'W': { |
| 550 Label done; | 550 Label done; |
| 551 if (mode_ != ASCII) { | 551 if (mode_ != LATIN1) { |
| 552 // Table is 128 entries, so all ASCII characters can be tested. | 552 // Table is 256 entries, so all Latin1 characters can be tested. |
| 553 __ cmp(current_character(), Operand('z')); | 553 __ cmp(current_character(), Operand('z')); |
| 554 __ b(hi, &done); | 554 __ b(hi, &done); |
| 555 } | 555 } |
| 556 ExternalReference map = ExternalReference::re_word_character_map(); | 556 ExternalReference map = ExternalReference::re_word_character_map(); |
| 557 __ mov(r0, Operand(map)); | 557 __ mov(r0, Operand(map)); |
| 558 __ ldrb(r0, MemOperand(r0, current_character())); | 558 __ ldrb(r0, MemOperand(r0, current_character())); |
| 559 __ cmp(r0, Operand::Zero()); | 559 __ cmp(r0, Operand::Zero()); |
| 560 BranchOrBacktrack(ne, on_no_match); | 560 BranchOrBacktrack(ne, on_no_match); |
| 561 if (mode_ != ASCII) { | 561 if (mode_ != LATIN1) { |
| 562 __ bind(&done); | 562 __ bind(&done); |
| 563 } | 563 } |
| 564 return true; | 564 return true; |
| 565 } | 565 } |
| 566 case '*': | 566 case '*': |
| 567 // Match any character. | 567 // Match any character. |
| 568 return true; | 568 return true; |
| 569 // No custom implementation (yet): s(UC16), S(UC16). | 569 // No custom implementation (yet): s(UC16), S(UC16). |
| 570 default: | 570 default: |
| 571 return false; | 571 return false; |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 return RETRY; | 1060 return RETRY; |
| 1061 } | 1061 } |
| 1062 | 1062 |
| 1063 // Prepare for possible GC. | 1063 // Prepare for possible GC. |
| 1064 HandleScope handles(isolate); | 1064 HandleScope handles(isolate); |
| 1065 Handle<Code> code_handle(re_code); | 1065 Handle<Code> code_handle(re_code); |
| 1066 | 1066 |
| 1067 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); | 1067 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); |
| 1068 | 1068 |
| 1069 // Current string. | 1069 // Current string. |
| 1070 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 1070 bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); |
| 1071 | 1071 |
| 1072 DCHECK(re_code->instruction_start() <= *return_address); | 1072 DCHECK(re_code->instruction_start() <= *return_address); |
| 1073 DCHECK(*return_address <= | 1073 DCHECK(*return_address <= |
| 1074 re_code->instruction_start() + re_code->instruction_size()); | 1074 re_code->instruction_start() + re_code->instruction_size()); |
| 1075 | 1075 |
| 1076 Object* result = isolate->stack_guard()->HandleInterrupts(); | 1076 Object* result = isolate->stack_guard()->HandleInterrupts(); |
| 1077 | 1077 |
| 1078 if (*code_handle != re_code) { // Return address no longer valid | 1078 if (*code_handle != re_code) { // Return address no longer valid |
| 1079 int delta = code_handle->address() - re_code->address(); | 1079 int delta = code_handle->address() - re_code->address(); |
| 1080 // Overwrite the return address on the stack. | 1080 // Overwrite the return address on the stack. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1091 // Extract the underlying string and the slice offset. | 1091 // Extract the underlying string and the slice offset. |
| 1092 if (StringShape(*subject_tmp).IsCons()) { | 1092 if (StringShape(*subject_tmp).IsCons()) { |
| 1093 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); | 1093 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); |
| 1094 } else if (StringShape(*subject_tmp).IsSliced()) { | 1094 } else if (StringShape(*subject_tmp).IsSliced()) { |
| 1095 SlicedString* slice = SlicedString::cast(*subject_tmp); | 1095 SlicedString* slice = SlicedString::cast(*subject_tmp); |
| 1096 subject_tmp = Handle<String>(slice->parent()); | 1096 subject_tmp = Handle<String>(slice->parent()); |
| 1097 slice_offset = slice->offset(); | 1097 slice_offset = slice->offset(); |
| 1098 } | 1098 } |
| 1099 | 1099 |
| 1100 // String might have changed. | 1100 // String might have changed. |
| 1101 if (subject_tmp->IsOneByteRepresentation() != is_ascii) { | 1101 if (subject_tmp->IsOneByteRepresentation() != is_one_byte) { |
| 1102 // If we changed between an ASCII and an UC16 string, the specialized | 1102 // If we changed between an Latin1 and an UC16 string, the specialized |
| 1103 // code cannot be used, and we need to restart regexp matching from | 1103 // code cannot be used, and we need to restart regexp matching from |
| 1104 // scratch (including, potentially, compiling a new version of the code). | 1104 // scratch (including, potentially, compiling a new version of the code). |
| 1105 return RETRY; | 1105 return RETRY; |
| 1106 } | 1106 } |
| 1107 | 1107 |
| 1108 // Otherwise, the content of the string might have moved. It must still | 1108 // Otherwise, the content of the string might have moved. It must still |
| 1109 // be a sequential or external string with the same content. | 1109 // be a sequential or external string with the same content. |
| 1110 // Update the start and end pointers in the stack frame to the current | 1110 // Update the start and end pointers in the stack frame to the current |
| 1111 // location (whether it has actually moved or not). | 1111 // location (whether it has actually moved or not). |
| 1112 DCHECK(StringShape(*subject_tmp).IsSequential() || | 1112 DCHECK(StringShape(*subject_tmp).IsSequential() || |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 offset = r4; | 1242 offset = r4; |
| 1243 } | 1243 } |
| 1244 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU | 1244 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU |
| 1245 // and the operating system running on the target allow it. | 1245 // and the operating system running on the target allow it. |
| 1246 // If unaligned load/stores are not supported then this function must only | 1246 // If unaligned load/stores are not supported then this function must only |
| 1247 // be used to load a single character at a time. | 1247 // be used to load a single character at a time. |
| 1248 if (!CanReadUnaligned()) { | 1248 if (!CanReadUnaligned()) { |
| 1249 DCHECK(characters == 1); | 1249 DCHECK(characters == 1); |
| 1250 } | 1250 } |
| 1251 | 1251 |
| 1252 if (mode_ == ASCII) { | 1252 if (mode_ == LATIN1) { |
| 1253 if (characters == 4) { | 1253 if (characters == 4) { |
| 1254 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); | 1254 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); |
| 1255 } else if (characters == 2) { | 1255 } else if (characters == 2) { |
| 1256 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); | 1256 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); |
| 1257 } else { | 1257 } else { |
| 1258 DCHECK(characters == 1); | 1258 DCHECK(characters == 1); |
| 1259 __ ldrb(current_character(), MemOperand(end_of_input_address(), offset)); | 1259 __ ldrb(current_character(), MemOperand(end_of_input_address(), offset)); |
| 1260 } | 1260 } |
| 1261 } else { | 1261 } else { |
| 1262 DCHECK(mode_ == UC16); | 1262 DCHECK(mode_ == UC16); |
| 1263 if (characters == 2) { | 1263 if (characters == 2) { |
| 1264 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); | 1264 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); |
| 1265 } else { | 1265 } else { |
| 1266 DCHECK(characters == 1); | 1266 DCHECK(characters == 1); |
| 1267 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); | 1267 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); |
| 1268 } | 1268 } |
| 1269 } | 1269 } |
| 1270 } | 1270 } |
| 1271 | 1271 |
| 1272 | 1272 |
| 1273 #undef __ | 1273 #undef __ |
| 1274 | 1274 |
| 1275 #endif // V8_INTERPRETED_REGEXP | 1275 #endif // V8_INTERPRETED_REGEXP |
| 1276 | 1276 |
| 1277 }} // namespace v8::internal | 1277 }} // namespace v8::internal |
| 1278 | 1278 |
| 1279 #endif // V8_TARGET_ARCH_ARM | 1279 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |