OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 6624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6635 Result temp = allocator()->Allocate(); | 6635 Result temp = allocator()->Allocate(); |
6636 ASSERT(temp.is_valid()); | 6636 ASSERT(temp.is_valid()); |
6637 // Check if the object is a JS array or not. | 6637 // Check if the object is a JS array or not. |
6638 __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, temp.reg()); | 6638 __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, temp.reg()); |
6639 value.Unuse(); | 6639 value.Unuse(); |
6640 temp.Unuse(); | 6640 temp.Unuse(); |
6641 destination()->Split(equal); | 6641 destination()->Split(equal); |
6642 } | 6642 } |
6643 | 6643 |
6644 | 6644 |
6645 void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) { | |
6646 ASSERT(args->length() == 2); | |
6647 Load(args->at(1)); | |
6648 Load(args->at(0)); | |
6649 Result array_result = frame_->Pop(); | |
6650 array_result.ToRegister(eax); | |
6651 frame_->SpillAll(); | |
6652 | |
6653 Label bailout; | |
6654 Label done; | |
6655 // All aliases of the same register have disjoint lifetimes. | |
6656 Register array = eax; | |
6657 Register result_pos = no_reg; | |
6658 | |
6659 Register index = edi; | |
6660 | |
6661 Register current_string_length = ecx; // Will be ecx when live. | |
6662 | |
6663 Register current_string = edx; | |
6664 | |
6665 Register scratch = ebx; | |
6666 | |
6667 Register scratch_2 = esi; | |
6668 Register new_padding_chars = scratch_2; | |
6669 | |
6670 Operand separator = Operand(esp, 4 * kPointerSize); // Already pushed. | |
6671 | |
6672 Operand elements = Operand(esp, 3 * kPointerSize); | |
6673 __ push(scratch); | |
6674 | |
6675 Operand result = Operand(esp, 2 * kPointerSize); | |
6676 __ push(scratch); | |
6677 | |
6678 Operand padding_chars = Operand(esp, 1 * kPointerSize); | |
6679 __ push(scratch); | |
6680 | |
6681 Operand array_length = Operand(esp, 0); | |
6682 __ push(scratch); | |
Lasse Reichstein
2010/11/18 13:26:54
You do four pushes of an unknown value. You might
William Hesse
2010/11/18 17:13:04
Done.
| |
6683 | |
6684 | |
6685 // Check that eax is a JSArray | |
6686 __ test(array, Immediate(kSmiTagMask)); | |
6687 __ j(zero, &bailout); | |
6688 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); | |
6689 __ j(not_equal, &bailout); | |
6690 | |
6691 // Check that the array has fast elements. | |
6692 __ cmpb(FieldOperand(scratch, Map::kBitField2Offset), | |
6693 1 << Map::kHasFastElements); | |
Lasse Reichstein
2010/11/18 13:26:54
Should this be "testb" and should there be a jump
William Hesse
2010/11/18 17:13:04
Done.
| |
6694 // If the array is empty, return the empty string. | |
6695 __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset)); | |
6696 __ sar(scratch, 1); | |
Lasse Reichstein
2010/11/18 13:26:54
You use sar here, but shr later, to convert from S
William Hesse
2010/11/18 17:13:04
Done.
| |
6697 Label non_trivial; | |
6698 __ j(not_zero, &non_trivial); | |
6699 __ mov(result, Factory::empty_string()); | |
6700 __ jmp(&done); | |
6701 | |
6702 __ bind(&non_trivial); | |
6703 __ mov(array_length, scratch); | |
Lasse Reichstein
2010/11/18 13:26:54
It's impossible to distinguish named registers fro
William Hesse
2010/11/18 17:13:04
If an assembly operation compiles, it means the sa
Lasse Reichstein
2010/11/18 17:49:09
But they are not equivalent. I was about to sugges
William Hesse
2010/11/19 08:53:43
That is if you are reading it with a plan to chang
| |
6704 | |
6705 __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset)); | |
6706 __ mov(elements, scratch); | |
6707 | |
6708 // End of array's live range. | |
6709 result_pos = array; | |
6710 array = no_reg; | |
6711 | |
6712 | |
6713 // Check that the separator is a flat ascii string. | |
Lasse Reichstein
2010/11/18 13:26:54
ASCII is an acronym :)
William Hesse
2010/11/18 17:13:04
We use both ASCII and ascii in comments. ascii is
| |
6714 __ mov(current_string, separator); | |
6715 __ test(current_string, Immediate(kSmiTagMask)); | |
6716 __ j(zero, &bailout); | |
6717 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); | |
6718 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | |
6719 __ and_(scratch, Immediate( | |
6720 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | |
6721 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); | |
6722 __ j(not_equal, &bailout); | |
6723 // If the separator is the empty string, replace it with NULL. | |
6724 // The test for NULL is quicker than the empty string test, in a loop. | |
6725 __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset), | |
6726 Immediate(0)); | |
6727 Label separator_checked; | |
6728 __ j(not_zero, &separator_checked); | |
6729 __ mov(separator, Immediate(0)); | |
6730 __ bind(&separator_checked); | |
6731 | |
6732 // Check that elements[0] is a flat ascii string, and copy it in new space. | |
6733 __ mov(scratch, elements); | |
6734 __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize)); | |
6735 __ test(current_string, Immediate(kSmiTagMask)); | |
6736 __ j(zero, &bailout); | |
6737 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); | |
6738 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | |
6739 __ and_(scratch, Immediate( | |
6740 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | |
6741 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); | |
6742 __ j(not_equal, &bailout); | |
6743 | |
6744 // Allocate space to copy it. Round up the size to the alignment granularity. | |
6745 __ mov(current_string_length, | |
6746 FieldOperand(current_string, String::kLengthOffset)); | |
6747 __ shr(current_string_length, 1); | |
6748 | |
6749 // Live registers and stack values: | |
6750 // current_string_length: length of elements[0]. | |
6751 | |
6752 // New string result in new space = elements[0] | |
6753 __ AllocateAsciiString(result_pos, current_string_length, scratch_2, | |
6754 index, no_reg, &bailout); | |
6755 __ mov(result, result_pos); | |
6756 | |
6757 // Adjust current_string_length to include padding bytes at end of string. | |
6758 // Keep track of the number of padding bytes. | |
6759 __ mov(new_padding_chars, current_string_length); | |
6760 __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask)); | |
6761 __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask)); | |
6762 __ sub(new_padding_chars, Operand(current_string_length)); | |
6763 __ neg(new_padding_chars); | |
6764 __ mov(padding_chars, new_padding_chars); | |
6765 | |
6766 Label copy_loop_1_entry; | |
6767 Label copy_loop_1; | |
6768 __ test(current_string_length, Operand(current_string_length)); | |
6769 __ jmp(©_loop_1_entry); | |
Lasse Reichstein
2010/11/18 13:26:54
How about a conditional jump here, if zero: jump t
William Hesse
2010/11/18 17:13:04
That would require another label. The current beh
Lasse Reichstein
2010/11/18 17:49:09
You wouldn't need the entry label then, so the lab
William Hesse
2010/11/19 08:53:43
Done.
| |
6770 __ bind(©_loop_1); | |
6771 __ sub(Operand(current_string_length), Immediate(kPointerSize)); | |
6772 __ mov(scratch, FieldOperand(current_string, current_string_length, | |
6773 times_1, SeqAsciiString::kHeaderSize)); | |
Lasse Reichstein
2010/11/18 13:26:54
Indentation.
William Hesse
2010/11/18 17:13:04
Done.
| |
6774 __ mov(FieldOperand(result_pos, current_string_length, | |
6775 times_1, SeqAsciiString::kHeaderSize), | |
6776 scratch); | |
6777 __ bind(©_loop_1_entry); | |
6778 __ j(not_zero, ©_loop_1); | |
6779 | |
6780 __ mov(index, Immediate(1)); | |
6781 // Loop condition: while (index < length). | |
6782 Label loop; | |
6783 __ bind(&loop); | |
6784 __ cmp(index, array_length); | |
6785 __ j(greater_equal, &done); | |
6786 | |
6787 // If the separator is the empty string, signalled by NULL, skip it. | |
6788 Label separator_done; | |
6789 __ mov(current_string, separator); | |
6790 __ test(current_string, Operand(current_string)); | |
6791 __ j(zero, &separator_done); | |
6792 | |
6793 // Append separator to result. It is known to be a flat ascii string. | |
6794 // Extend the result by the length of the separator. | |
6795 __ mov(current_string_length, | |
Lasse Reichstein
2010/11/18 13:26:54
You should definitly extract the "append seq-ASCII
William Hesse
2010/11/18 17:13:04
Done.
| |
6796 FieldOperand(current_string, String::kLengthOffset)); | |
6797 __ shr(current_string_length, 1); | |
6798 __ sub(current_string_length, padding_chars); | |
6799 __ mov(new_padding_chars, current_string_length); | |
6800 __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask)); | |
6801 __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask)); | |
6802 __ sub(new_padding_chars, Operand(current_string_length)); | |
6803 __ neg(new_padding_chars); | |
Lasse Reichstein
2010/11/18 13:26:54
You negate new_padding_chars, and then use them in
William Hesse
2010/11/18 17:13:04
I would like to do this fix in a separate change.
| |
6804 // We need an allocation even if current_string_length is 0, to fetch | |
6805 // result_pos. Consider using a faster fetch of result_pos in that case. | |
6806 __ AllocateInNewSpace(current_string_length, result_pos, scratch, no_reg, | |
6807 &bailout, NO_ALLOCATION_FLAGS); | |
6808 __ sub(result_pos, padding_chars); | |
6809 __ mov(padding_chars, new_padding_chars); | |
6810 | |
6811 // Copy separator to the end of result. | |
6812 __ mov(current_string_length, | |
6813 FieldOperand(current_string, String::kLengthOffset)); | |
6814 __ mov(scratch, result); | |
6815 __ mov(scratch_2, current_string_length); | |
6816 __ add(scratch_2, FieldOperand(scratch, String::kLengthOffset)); | |
6817 __ mov(FieldOperand(scratch, String::kLengthOffset), scratch_2); | |
6818 __ shr(current_string_length, 1); | |
6819 __ lea(current_string, | |
6820 FieldOperand(current_string, SeqAsciiString::kHeaderSize)); | |
6821 // Loop condition: while (--current_string_length >= 0). | |
6822 Label copy_loop_2; | |
6823 Label copy_loop_2_entry; | |
6824 __ jmp(©_loop_2_entry); | |
6825 __ bind(©_loop_2); | |
6826 __ mov_b(scratch, | |
6827 Operand(current_string, current_string_length, times_1, 0)); | |
Lasse Reichstein
2010/11/18 13:26:54
Indentation.
William Hesse
2010/11/18 17:13:04
Done.
| |
6828 __ mov_b(Operand(result_pos, current_string_length, times_1, 0), | |
6829 scratch); | |
Lasse Reichstein
2010/11/18 13:26:54
Indentation.
William Hesse
2010/11/18 17:13:04
Done.
| |
6830 __ bind(©_loop_2_entry); | |
6831 __ sub(Operand(current_string_length), Immediate(1)); | |
6832 __ j(greater_equal, ©_loop_2); | |
6833 | |
6834 __ bind(&separator_done); | |
6835 | |
6836 // Add next element of array to the end of the result. | |
6837 // Get current_string = array[index]. | |
6838 __ mov(scratch, elements); | |
6839 __ mov(current_string, FieldOperand(scratch, index, | |
6840 times_pointer_size, | |
6841 FixedArray::kHeaderSize)); | |
6842 // If current != flat ascii string drop result, return undefined. | |
6843 __ test(current_string, Immediate(kSmiTagMask)); | |
6844 __ j(zero, &bailout); | |
6845 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); | |
6846 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | |
6847 __ and_(scratch, Immediate( | |
6848 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | |
6849 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); | |
6850 __ j(not_equal, &bailout); | |
6851 | |
6852 // extend result by length(current) | |
Lasse Reichstein
2010/11/18 13:26:54
Capitalize "E" in "extend". Comments are/should be
William Hesse
2010/11/18 17:13:04
Done.
| |
6853 __ mov(current_string_length, | |
6854 FieldOperand(current_string, String::kLengthOffset)); | |
6855 __ shr(current_string_length, 1); | |
6856 __ sub(current_string_length, padding_chars); | |
6857 __ mov(new_padding_chars, current_string_length); | |
6858 __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask)); | |
6859 __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask)); | |
6860 __ sub(new_padding_chars, Operand(current_string_length)); | |
6861 __ neg(new_padding_chars); | |
6862 __ AllocateInNewSpace(current_string_length, result_pos, scratch, no_reg, | |
6863 &bailout, NO_ALLOCATION_FLAGS); | |
6864 __ sub(result_pos, padding_chars); | |
6865 __ mov(padding_chars, new_padding_chars); | |
6866 | |
6867 // copy current to end of result | |
6868 __ mov(current_string_length, | |
6869 FieldOperand(current_string, String::kLengthOffset)); | |
6870 __ mov(scratch, result); | |
6871 __ mov(scratch_2, current_string_length); | |
6872 __ add(scratch_2, FieldOperand(scratch, String::kLengthOffset)); | |
6873 __ mov(FieldOperand(scratch, String::kLengthOffset), scratch_2); | |
6874 __ shr(current_string_length, 1); | |
6875 __ lea(current_string, | |
6876 FieldOperand(current_string, SeqAsciiString::kHeaderSize)); | |
6877 Label copy_loop_3; | |
6878 Label copy_loop_3_entry; | |
6879 __ jmp(©_loop_3_entry); | |
6880 __ bind(©_loop_3); | |
6881 __ mov_b(scratch, | |
6882 Operand(current_string, current_string_length, times_1, 0)); | |
6883 __ mov_b(Operand(result_pos, current_string_length, times_1, 0), | |
6884 scratch); | |
6885 __ bind(©_loop_3_entry); | |
6886 __ sub(Operand(current_string_length), Immediate(1)); | |
6887 __ j(greater_equal, ©_loop_3); | |
6888 | |
6889 __ add(Operand(index), Immediate(1)); | |
6890 // end while | |
6891 __ jmp(&loop); | |
6892 // return current | |
6893 | |
6894 __ bind(&bailout); | |
Lasse Reichstein
2010/11/18 13:26:54
If you bail out to here after having allocated the
William Hesse
2010/11/18 17:13:04
This would be a good fix for a later improved vers
| |
6895 __ mov(result, Factory::undefined_value()); | |
6896 __ bind(&done); | |
6897 __ mov(eax, result); | |
6898 // Drop temp values from the stack, and restore context register. | |
6899 __ add(Operand(esp), Immediate(4 * kPointerSize)); | |
6900 | |
6901 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
6902 frame_->Drop(1); | |
6903 frame_->Push(&array_result); | |
6904 } | |
6905 | |
6906 | |
6645 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { | 6907 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { |
6646 ASSERT(args->length() == 1); | 6908 ASSERT(args->length() == 1); |
6647 Load(args->at(0)); | 6909 Load(args->at(0)); |
6648 Result value = frame_->Pop(); | 6910 Result value = frame_->Pop(); |
6649 value.ToRegister(); | 6911 value.ToRegister(); |
6650 ASSERT(value.is_valid()); | 6912 ASSERT(value.is_valid()); |
6651 __ test(value.reg(), Immediate(kSmiTagMask)); | 6913 __ test(value.reg(), Immediate(kSmiTagMask)); |
6652 destination()->false_target()->Branch(equal); | 6914 destination()->false_target()->Branch(equal); |
6653 // It is a heap object - get map. | 6915 // It is a heap object - get map. |
6654 Result temp = allocator()->Allocate(); | 6916 Result temp = allocator()->Allocate(); |
(...skipping 3427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10082 masm.GetCode(&desc); | 10344 masm.GetCode(&desc); |
10083 // Call the function from C++. | 10345 // Call the function from C++. |
10084 return FUNCTION_CAST<MemCopyFunction>(buffer); | 10346 return FUNCTION_CAST<MemCopyFunction>(buffer); |
10085 } | 10347 } |
10086 | 10348 |
10087 #undef __ | 10349 #undef __ |
10088 | 10350 |
10089 } } // namespace v8::internal | 10351 } } // namespace v8::internal |
10090 | 10352 |
10091 #endif // V8_TARGET_ARCH_IA32 | 10353 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |