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 |