Chromium Code Reviews| 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 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 typedef compiler::Node Node; | 609 typedef compiler::Node Node; |
| 610 | 610 |
| 611 Node* receiver = assembler->Parameter(0); | 611 Node* receiver = assembler->Parameter(0); |
| 612 Node* context = assembler->Parameter(3); | 612 Node* context = assembler->Parameter(3); |
| 613 | 613 |
| 614 Node* result = assembler->ToThisValue( | 614 Node* result = assembler->ToThisValue( |
| 615 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); | 615 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); |
| 616 assembler->Return(result); | 616 assembler->Return(result); |
| 617 } | 617 } |
| 618 | 618 |
| 619 BUILTIN(StringPrototypeIterator) { | 619 void Builtins::Generate_StringPrototypeIterator(CodeStubAssembler* assembler) { |
| 620 HandleScope scope(isolate); | 620 typedef CodeStubAssembler::Label Label; |
| 621 TO_THIS_STRING(object, "String.prototype[Symbol.iterator]"); | 621 typedef compiler::Node Node; |
| 622 typedef CodeStubAssembler::Variable Variable; | |
| 622 | 623 |
| 623 Handle<String> string; | 624 Variable var_string(assembler, MachineRepresentation::kTagged); |
| 624 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, | 625 Variable var_index(assembler, MachineRepresentation::kWord32); |
| 625 Object::ToString(isolate, object)); | |
| 626 | 626 |
| 627 return *isolate->factory()->NewJSStringIterator(string); | 627 Variable* loop_inputs[] = {&var_string, &var_index}; |
| 628 Label loop(assembler, 2, loop_inputs); | |
| 629 Label allocate_iterator(assembler); | |
| 630 | |
| 631 Node* receiver = assembler->Parameter(0); | |
| 632 Node* context = assembler->Parameter(3); | |
| 633 | |
| 634 Node* string = | |
| 635 assembler->ToThisValue(context, receiver, PrimitiveType::kString, | |
| 636 "String.prototype[Symbol.iterator]"); | |
| 637 var_string.Bind(string); | |
| 638 var_index.Bind(assembler->Int32Constant(0)); | |
| 639 | |
| 640 assembler->Goto(&loop); | |
| 641 assembler->Bind(&loop); | |
| 642 { | |
| 643 // Load the instance type of the {string}. | |
| 644 Node* string_instance_type = assembler->LoadInstanceType(string); | |
| 645 | |
| 646 // Check if the {string} is a SeqString. | |
| 647 Label if_stringisnotsequential(assembler); | |
| 648 assembler->Branch(assembler->Word32Equal( | |
| 649 assembler->Word32And(string_instance_type, | |
| 650 assembler->Int32Constant( | |
| 651 kStringRepresentationMask)), | |
| 652 assembler->Int32Constant(kSeqStringTag)), | |
| 653 &allocate_iterator, &if_stringisnotsequential); | |
| 654 | |
| 655 assembler->Bind(&if_stringisnotsequential); | |
| 656 { | |
| 657 // Check if the {string} is a ConsString. | |
| 658 Label if_stringiscons(assembler), if_stringisnotcons(assembler); | |
| 659 assembler->Branch( | |
| 660 assembler->Word32Equal( | |
| 661 assembler->Word32And( | |
| 662 string_instance_type, | |
| 663 assembler->Int32Constant(kStringRepresentationMask)), | |
| 664 assembler->Int32Constant(kConsStringTag)), | |
| 665 &if_stringiscons, &if_stringisnotcons); | |
| 666 | |
| 667 assembler->Bind(&if_stringiscons); | |
| 668 { | |
| 669 // Flatten cons-string and finish. | |
| 670 var_string.Bind(assembler->CallRuntime( | |
| 671 Runtime::kFlattenString, assembler->NoContextConstant(), string)); | |
| 672 assembler->Goto(&allocate_iterator); | |
| 673 } | |
| 674 | |
| 675 assembler->Bind(&if_stringisnotcons); | |
| 676 { | |
| 677 // Check if the {string} is an ExternalString. | |
| 678 Label if_stringisnotexternal(assembler); | |
| 679 assembler->Branch( | |
| 680 assembler->Word32Equal( | |
| 681 assembler->Word32And( | |
| 682 string_instance_type, | |
| 683 assembler->Int32Constant(kStringRepresentationMask)), | |
| 684 assembler->Int32Constant(kExternalStringTag)), | |
| 685 &allocate_iterator, &if_stringisnotexternal); | |
| 686 | |
| 687 assembler->Bind(&if_stringisnotexternal); | |
| 688 { | |
| 689 // The {string} is a SlicedString, continue with its parent. | |
| 690 Node* index = var_index.value(); | |
| 691 Node* string_offset = assembler->LoadAndUntagObjectField( | |
| 692 string, SlicedString::kOffsetOffset); | |
| 693 Node* string_parent = | |
| 694 assembler->LoadObjectField(string, SlicedString::kParentOffset); | |
| 695 var_index.Bind(assembler->IntPtrAdd(index, string_offset)); | |
| 696 var_string.Bind(string_parent); | |
| 697 assembler->Goto(&loop); | |
| 698 } | |
| 699 } | |
| 700 } | |
| 701 } | |
| 702 | |
| 703 assembler->Bind(&allocate_iterator); | |
| 704 { | |
| 705 Node* native_context = assembler->LoadNativeContext(context); | |
| 706 Node* index = assembler->Int32Constant(Context::STRING_ITERATOR_MAP_INDEX); | |
| 707 Node* map = assembler->LoadFixedArrayElement( | |
| 708 native_context, index, 0, CodeStubAssembler::INTPTR_PARAMETERS); | |
| 709 Node* js_iter = assembler->Allocate(JSStringIterator::kSize); | |
| 710 assembler->StoreMapNoWriteBarrier(js_iter, map); | |
| 711 assembler->StoreObjectFieldRoot(js_iter, JSValue::kPropertiesOffset, | |
| 712 Heap::kEmptyFixedArrayRootIndex); | |
| 713 assembler->StoreObjectFieldRoot(js_iter, JSObject::kElementsOffset, | |
| 714 Heap::kEmptyFixedArrayRootIndex); | |
| 715 assembler->StoreObjectField(js_iter, JSStringIterator::kStringOffset, | |
| 716 var_string.value()); | |
| 717 | |
| 718 assembler->StoreObjectField(js_iter, JSStringIterator::kNextIndexOffset, | |
| 719 assembler->SmiFromWord32(var_index.value())); | |
| 720 assembler->Return(js_iter); | |
| 721 } | |
| 628 } | 722 } |
| 629 | 723 |
| 630 BUILTIN(StringIteratorPrototypeNext) { | 724 void Builtins::Generate_StringIteratorPrototypeNext( |
| 631 HandleScope scope(isolate); | 725 CodeStubAssembler* assembler) { |
| 726 typedef CodeStubAssembler::Label Label; | |
| 727 typedef compiler::Node Node; | |
| 728 typedef CodeStubAssembler::Variable Variable; | |
| 632 | 729 |
| 633 if (!args.receiver()->IsJSStringIterator()) { | 730 Variable var_value(assembler, MachineRepresentation::kTagged); |
| 634 Handle<String> reason = isolate->factory()->NewStringFromAsciiChecked( | 731 Variable var_done(assembler, MachineRepresentation::kTagged); |
| 635 "String Iterator.prototype.next"); | |
| 636 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 637 isolate, | |
| 638 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, reason)); | |
| 639 } | |
| 640 Handle<JSStringIterator> iterator = | |
| 641 Handle<JSStringIterator>::cast(args.receiver()); | |
| 642 Handle<String> string(iterator->string()); | |
| 643 | 732 |
| 644 int position = iterator->index(); | 733 var_value.Bind(assembler->UndefinedConstant()); |
| 645 int length = string->length(); | 734 var_done.Bind(assembler->BooleanConstant(true)); |
| 646 | 735 |
| 647 if (position < length) { | 736 Label throw_bad_receiver(assembler), next_codepoint(assembler), |
| 648 uint16_t lead = string->Get(position); | 737 return_result(assembler); |
| 649 if (lead >= 0xD800 && lead <= 0xDBFF && position + 1 < length) { | |
| 650 uint16_t trail = string->Get(position + 1); | |
| 651 if (V8_LIKELY(trail >= 0xDC00 && trail <= 0xDFFF)) { | |
| 652 // Return surrogate pair code units | |
| 653 iterator->set_index(position + 2); | |
| 654 Handle<String> value = | |
| 655 isolate->factory()->NewSurrogatePairString(lead, trail); | |
| 656 return *isolate->factory()->NewJSIteratorResult(value, false); | |
| 657 } | |
| 658 } | |
| 659 | 738 |
| 660 // Return single code unit | 739 Node* js_iter = assembler->Parameter(0); |
|
Benedikt Meurer
2016/09/22 03:48:23
Nit: rename js_iter to iterator.
| |
| 661 iterator->set_index(position + 1); | 740 Node* context = assembler->Parameter(3); |
| 662 Handle<String> value = | 741 |
| 663 isolate->factory()->LookupSingleCharacterStringFromCode(lead); | 742 assembler->GotoIf(assembler->WordIsSmi(js_iter), &throw_bad_receiver); |
| 664 return *isolate->factory()->NewJSIteratorResult(value, false); | 743 assembler->GotoUnless( |
| 744 assembler->WordEqual(assembler->LoadInstanceType(js_iter), | |
| 745 assembler->Int32Constant(JS_STRING_ITERATOR_TYPE)), | |
| 746 &throw_bad_receiver); | |
| 747 | |
| 748 Node* string = | |
| 749 assembler->LoadObjectField(js_iter, JSStringIterator::kStringOffset); | |
| 750 Node* position = assembler->LoadAndUntagObjectField( | |
| 751 js_iter, JSStringIterator::kNextIndexOffset); | |
| 752 Node* length = | |
| 753 assembler->LoadAndUntagObjectField(string, String::kLengthOffset); | |
| 754 | |
| 755 assembler->Branch(assembler->Int32LessThan(position, length), &next_codepoint, | |
| 756 &return_result); | |
| 757 | |
| 758 assembler->Bind(&next_codepoint); | |
| 759 { | |
| 760 Node* value = assembler->StringFromCodePointAt(string, length, position); | |
| 761 Node* length = | |
| 762 assembler->LoadAndUntagObjectField(value, String::kLengthOffset); | |
| 763 assembler->StoreObjectFieldNoWriteBarrier( | |
| 764 js_iter, JSStringIterator::kNextIndexOffset, | |
| 765 assembler->SmiFromWord32(assembler->Int32Add(position, length))); | |
| 766 var_value.Bind(value); | |
| 767 var_done.Bind(assembler->BooleanConstant(false)); | |
| 768 assembler->Goto(&return_result); | |
| 665 } | 769 } |
| 666 | 770 |
| 667 iterator->set_string(isolate->heap()->empty_string()); | 771 assembler->Bind(&return_result); |
| 772 { | |
| 773 Node* native_context = assembler->LoadNativeContext(context); | |
| 774 Node* map = assembler->LoadFixedArrayElement( | |
| 775 native_context, | |
| 776 assembler->Int32Constant(Context::ITERATOR_RESULT_MAP_INDEX), 0, | |
|
Benedikt Meurer
2016/09/22 03:48:23
This must be IntPtrConstant then.
| |
| 777 CodeStubAssembler::INTPTR_PARAMETERS); | |
| 778 Node* iterator = assembler->Allocate(JSIteratorResult::kSize); | |
|
Benedikt Meurer
2016/09/22 03:48:22
Nit: Rename iterator to result.
| |
| 779 assembler->StoreMapNoWriteBarrier(iterator, map); | |
| 780 assembler->StoreObjectFieldRoot(iterator, | |
| 781 JSIteratorResult::kPropertiesOffset, | |
| 782 Heap::kEmptyFixedArrayRootIndex); | |
| 783 assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset, | |
| 784 Heap::kEmptyFixedArrayRootIndex); | |
| 785 assembler->StoreObjectField(iterator, JSIteratorResult::kValueOffset, | |
| 786 var_value.value()); | |
| 787 assembler->StoreObjectField(iterator, JSIteratorResult::kDoneOffset, | |
| 788 var_done.value()); | |
| 789 assembler->Return(iterator); | |
| 790 } | |
| 668 | 791 |
| 669 return *isolate->factory()->NewJSIteratorResult( | 792 assembler->Bind(&throw_bad_receiver); |
| 670 isolate->factory()->undefined_value(), true); | 793 { |
| 794 // The {receiver} is not a valid JSGeneratorObject. | |
| 795 Node* result = assembler->CallRuntime( | |
| 796 Runtime::kThrowIncompatibleMethodReceiver, context, | |
| 797 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( | |
| 798 "String Iterator.prototype.next", TENURED)), | |
| 799 js_iter); | |
| 800 assembler->Return(result); // Never reached. | |
| 801 } | |
| 671 } | 802 } |
| 672 | 803 |
| 673 } // namespace internal | 804 } // namespace internal |
| 674 } // namespace v8 | 805 } // namespace v8 |
| OLD | NEW |