OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/builtins/builtins.h" | 5 #include "src/builtins/builtins.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 | 7 |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 assembler->Return(assembler->NaNConstant()); | 470 assembler->Return(assembler->NaNConstant()); |
471 assembler->Bind(&if_positioninbounds); | 471 assembler->Bind(&if_positioninbounds); |
472 } | 472 } |
473 | 473 |
474 // Load the character at the {position} from the {receiver}. | 474 // Load the character at the {position} from the {receiver}. |
475 Node* value = assembler->StringCharCodeAt(receiver, position); | 475 Node* value = assembler->StringCharCodeAt(receiver, position); |
476 Node* result = assembler->SmiFromWord32(value); | 476 Node* result = assembler->SmiFromWord32(value); |
477 assembler->Return(result); | 477 assembler->Return(result); |
478 } | 478 } |
479 | 479 |
480 template <typename schar, typename pchar> | |
Franzi
2016/09/14 15:05:01
I think this should be inside an anonymous namespa
Benedikt Meurer
2016/09/14 17:02:31
Yes, please remove the static and put it into anon
petermarshall
2016/09/15 12:19:59
Done
| |
481 static int StringMatchBackwards(Vector<const schar> subject, | |
482 Vector<const pchar> pattern, int idx) { | |
483 int pattern_length = pattern.length(); | |
484 DCHECK(pattern_length >= 1); | |
485 DCHECK(idx + pattern_length <= subject.length()); | |
486 | |
487 if (sizeof(schar) == 1 && sizeof(pchar) > 1) { | |
488 for (int i = 0; i < pattern_length; i++) { | |
489 uc16 c = pattern[i]; | |
490 if (c > String::kMaxOneByteCharCode) { | |
491 return -1; | |
492 } | |
493 } | |
494 } | |
495 | |
496 pchar pattern_first_char = pattern[0]; | |
497 for (int i = idx; i >= 0; i--) { | |
498 if (subject[i] != pattern_first_char) continue; | |
499 int j = 1; | |
500 while (j < pattern_length) { | |
501 if (pattern[j] != subject[i + j]) { | |
502 break; | |
503 } | |
504 j++; | |
505 } | |
506 if (j == pattern_length) { | |
507 return i; | |
508 } | |
509 } | |
510 return -1; | |
511 } | |
512 | |
513 // ES6 section 21.1.3.9 | |
514 // String.prototype.lastIndexOf ( searchString [ , position ] ) | |
515 BUILTIN(StringPrototypeLastIndexOf) { | |
516 HandleScope handle_scope(isolate); | |
517 TO_THIS_STRING(sub, "String.prototype.lastIndexOf"); | |
518 | |
519 Handle<String> pat; | |
520 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
521 isolate, pat, | |
522 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); | |
523 | |
524 Handle<Object> position; | |
525 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
526 isolate, position, Object::ToNumber(args.atOrUndefined(isolate, 2))); | |
527 | |
528 if (position->IsNaN()) { | |
529 position = isolate->factory()->infinity_value(); | |
Benedikt Meurer
2016/09/14 17:02:32
You can just default to sub->length here, as infin
| |
530 } else { | |
531 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position, | |
532 Object::ToInteger(isolate, position)); | |
533 } | |
534 | |
535 Handle<Object> zero = isolate->factory()->NewNumberFromInt(0); | |
Benedikt Meurer
2016/09/14 17:02:32
You don't need this boxed zero valid, see comments
| |
536 | |
537 if (Object::LessThan(position, zero).FromJust()) { | |
Benedikt Meurer
2016/09/14 17:02:31
No need to use Object::LessThan here, which corres
| |
538 position = zero; | |
539 } | |
540 | |
541 Handle<Object> sub_len_obj = | |
542 isolate->factory()->NewNumberFromInt(sub->length()); | |
Benedikt Meurer
2016/09/14 17:02:31
No need to box the sub->length, just compare again
| |
543 if (Object::LessThan(sub_len_obj, position).FromJust()) { | |
544 position = sub_len_obj; | |
545 } | |
546 | |
547 uint32_t start_index; | |
548 if (!position->ToArrayIndex(&start_index)) return Smi::FromInt(-1); | |
Benedikt Meurer
2016/09/14 17:02:32
At this point you know that position_number is wit
petermarshall
2016/09/15 12:19:59
I reworked this whole section with your comments
| |
549 | |
550 uint32_t pat_length = pat->length(); | |
551 uint32_t sub_length = sub->length(); | |
552 | |
553 if (start_index + pat_length > sub_length) { | |
554 start_index = sub_length - pat_length; | |
555 } | |
556 | |
557 if (pat_length == 0) { | |
558 return Smi::FromInt(start_index); | |
559 } | |
560 | |
561 sub = String::Flatten(sub); | |
562 pat = String::Flatten(pat); | |
563 | |
564 int last_index = -1; | |
565 DisallowHeapAllocation no_gc; // ensure vectors stay valid | |
566 | |
567 String::FlatContent sub_content = sub->GetFlatContent(); | |
568 String::FlatContent pat_content = pat->GetFlatContent(); | |
569 | |
570 if (pat_content.IsOneByte()) { | |
571 Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector(); | |
572 if (sub_content.IsOneByte()) { | |
573 last_index = StringMatchBackwards(sub_content.ToOneByteVector(), | |
574 pat_vector, start_index); | |
575 } else { | |
576 last_index = StringMatchBackwards(sub_content.ToUC16Vector(), pat_vector, | |
577 start_index); | |
578 } | |
579 } else { | |
580 Vector<const uc16> pat_vector = pat_content.ToUC16Vector(); | |
581 if (sub_content.IsOneByte()) { | |
582 last_index = StringMatchBackwards(sub_content.ToOneByteVector(), | |
583 pat_vector, start_index); | |
584 } else { | |
585 last_index = StringMatchBackwards(sub_content.ToUC16Vector(), pat_vector, | |
586 start_index); | |
587 } | |
588 } | |
589 return Smi::FromInt(last_index); | |
590 } | |
591 | |
480 // ES6 section 21.1.3.10 String.prototype.localeCompare ( that ) | 592 // ES6 section 21.1.3.10 String.prototype.localeCompare ( that ) |
481 // | 593 // |
482 // This function is implementation specific. For now, we do not | 594 // This function is implementation specific. For now, we do not |
483 // do anything locale specific. | 595 // do anything locale specific. |
484 // If internationalization is enabled, then i18n.js will override this function | 596 // If internationalization is enabled, then i18n.js will override this function |
485 // and provide the proper functionality, so this is just a fallback. | 597 // and provide the proper functionality, so this is just a fallback. |
486 BUILTIN(StringPrototypeLocaleCompare) { | 598 BUILTIN(StringPrototypeLocaleCompare) { |
487 HandleScope handle_scope(isolate); | 599 HandleScope handle_scope(isolate); |
488 DCHECK_EQ(2, args.length()); | 600 DCHECK_EQ(2, args.length()); |
489 | 601 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 Node* receiver = assembler->Parameter(0); | 714 Node* receiver = assembler->Parameter(0); |
603 Node* context = assembler->Parameter(3); | 715 Node* context = assembler->Parameter(3); |
604 | 716 |
605 Node* result = assembler->ToThisValue( | 717 Node* result = assembler->ToThisValue( |
606 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); | 718 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); |
607 assembler->Return(result); | 719 assembler->Return(result); |
608 } | 720 } |
609 | 721 |
610 } // namespace internal | 722 } // namespace internal |
611 } // namespace v8 | 723 } // namespace v8 |
OLD | NEW |