Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 1857001: Revert "Changing string length field type from int to SMI." (Closed)
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects-inl.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 3904 matching lines...) Expand 10 before | Expand all | Expand 10 after
3915 3915
3916 // There is no virtual frame effect from here up to the final result 3916 // There is no virtual frame effect from here up to the final result
3917 // push. 3917 // push.
3918 3918
3919 // If the receiver is a smi trigger the slow case. 3919 // If the receiver is a smi trigger the slow case.
3920 __ JumpIfSmi(object.reg(), &slow_case); 3920 __ JumpIfSmi(object.reg(), &slow_case);
3921 3921
3922 // If the index is negative or non-smi trigger the slow case. 3922 // If the index is negative or non-smi trigger the slow case.
3923 __ JumpIfNotPositiveSmi(index.reg(), &slow_case); 3923 __ JumpIfNotPositiveSmi(index.reg(), &slow_case);
3924 3924
3925 // Untag the index.
3926 __ SmiToInteger32(index.reg(), index.reg());
3927
3925 __ bind(&try_again_with_new_string); 3928 __ bind(&try_again_with_new_string);
3926 // Fetch the instance type of the receiver into rcx. 3929 // Fetch the instance type of the receiver into rcx.
3927 __ movq(rcx, FieldOperand(object.reg(), HeapObject::kMapOffset)); 3930 __ movq(rcx, FieldOperand(object.reg(), HeapObject::kMapOffset));
3928 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); 3931 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset));
3929 // If the receiver is not a string trigger the slow case. 3932 // If the receiver is not a string trigger the slow case.
3930 __ testb(rcx, Immediate(kIsNotStringMask)); 3933 __ testb(rcx, Immediate(kIsNotStringMask));
3931 __ j(not_zero, &slow_case); 3934 __ j(not_zero, &slow_case);
3932 3935
3933 // Check for index out of range. 3936 // Check for index out of range.
3934 __ SmiCompare(index.reg(), FieldOperand(object.reg(), String::kLengthOffset)); 3937 __ cmpl(index.reg(), FieldOperand(object.reg(), String::kLengthOffset));
3935 __ j(greater_equal, &slow_case); 3938 __ j(greater_equal, &slow_case);
3936 // Reload the instance type (into the temp register this time).. 3939 // Reload the instance type (into the temp register this time)..
3937 __ movq(temp.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset)); 3940 __ movq(temp.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
3938 __ movzxbl(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset)); 3941 __ movzxbl(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
3939 3942
3940 // We need special handling for non-flat strings. 3943 // We need special handling for non-flat strings.
3941 ASSERT_EQ(0, kSeqStringTag); 3944 ASSERT_EQ(0, kSeqStringTag);
3942 __ testb(temp.reg(), Immediate(kStringRepresentationMask)); 3945 __ testb(temp.reg(), Immediate(kStringRepresentationMask));
3943 __ j(not_zero, &not_a_flat_string); 3946 __ j(not_zero, &not_a_flat_string);
3944 // Check for 1-byte or 2-byte string. 3947 // Check for 1-byte or 2-byte string.
3945 ASSERT_EQ(0, kTwoByteStringTag); 3948 ASSERT_EQ(0, kTwoByteStringTag);
3946
3947 // Untag the index.
3948 __ SmiToInteger32(index.reg(), index.reg());
3949
3950 __ testb(temp.reg(), Immediate(kStringEncodingMask)); 3949 __ testb(temp.reg(), Immediate(kStringEncodingMask));
3951 __ j(not_zero, &ascii_string); 3950 __ j(not_zero, &ascii_string);
3952 3951
3953 // 2-byte string. 3952 // 2-byte string.
3954 // Load the 2-byte character code into the temp register. 3953 // Load the 2-byte character code into the temp register.
3955 __ movzxwl(temp.reg(), FieldOperand(object.reg(), 3954 __ movzxwl(temp.reg(), FieldOperand(object.reg(),
3956 index.reg(), 3955 index.reg(),
3957 times_2, 3956 times_2,
3958 SeqTwoByteString::kHeaderSize)); 3957 SeqTwoByteString::kHeaderSize));
3959 __ jmp(&got_char_code); 3958 __ jmp(&got_char_code);
(...skipping 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after
5610 5609
5611 is_string.Bind(&left_side); 5610 is_string.Bind(&left_side);
5612 // left_side is a sequential ASCII string. 5611 // left_side is a sequential ASCII string.
5613 ASSERT(left_side.reg().is(left_reg)); 5612 ASSERT(left_side.reg().is(left_reg));
5614 right_side = Result(right_val); 5613 right_side = Result(right_val);
5615 Result temp2 = allocator_->Allocate(); 5614 Result temp2 = allocator_->Allocate();
5616 ASSERT(temp2.is_valid()); 5615 ASSERT(temp2.is_valid());
5617 // Test string equality and comparison. 5616 // Test string equality and comparison.
5618 if (cc == equal) { 5617 if (cc == equal) {
5619 Label comparison_done; 5618 Label comparison_done;
5620 __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset), 5619 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset),
5621 Smi::FromInt(1)); 5620 Immediate(1));
5622 __ j(not_equal, &comparison_done); 5621 __ j(not_equal, &comparison_done);
5623 uint8_t char_value = 5622 uint8_t char_value =
5624 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 5623 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
5625 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), 5624 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
5626 Immediate(char_value)); 5625 Immediate(char_value));
5627 __ bind(&comparison_done); 5626 __ bind(&comparison_done);
5628 } else { 5627 } else {
5629 __ movq(temp2.reg(), 5628 __ movl(temp2.reg(),
5630 FieldOperand(left_side.reg(), String::kLengthOffset)); 5629 FieldOperand(left_side.reg(), String::kLengthOffset));
5631 __ SmiSubConstant(temp2.reg(), temp2.reg(), Smi::FromInt(1)); 5630 __ subl(temp2.reg(), Immediate(1));
5632 Label comparison; 5631 Label comparison;
5633 // If the length is 0 then the subtraction gave -1 which compares less 5632 // If the length is 0 then the subtraction gave -1 which compares less
5634 // than any character. 5633 // than any character.
5635 __ j(negative, &comparison); 5634 __ j(negative, &comparison);
5636 // Otherwise load the first character. 5635 // Otherwise load the first character.
5637 __ movzxbl(temp2.reg(), 5636 __ movzxbl(temp2.reg(),
5638 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize)); 5637 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
5639 __ bind(&comparison); 5638 __ bind(&comparison);
5640 // Compare the first character of the string with the 5639 // Compare the first character of the string with the
5641 // constant 1-character string. 5640 // constant 1-character string.
5642 uint8_t char_value = 5641 uint8_t char_value =
5643 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0)); 5642 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0));
5644 __ cmpb(temp2.reg(), Immediate(char_value)); 5643 __ cmpb(temp2.reg(), Immediate(char_value));
5645 Label characters_were_different; 5644 Label characters_were_different;
5646 __ j(not_equal, &characters_were_different); 5645 __ j(not_equal, &characters_were_different);
5647 // If the first character is the same then the long string sorts after 5646 // If the first character is the same then the long string sorts after
5648 // the short one. 5647 // the short one.
5649 __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset), 5648 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset),
5650 Smi::FromInt(1)); 5649 Immediate(1));
5651 __ bind(&characters_were_different); 5650 __ bind(&characters_were_different);
5652 } 5651 }
5653 temp2.Unuse(); 5652 temp2.Unuse();
5654 left_side.Unuse(); 5653 left_side.Unuse();
5655 right_side.Unuse(); 5654 right_side.Unuse();
5656 dest->Split(cc); 5655 dest->Split(cc);
5657 } 5656 }
5658 } else { 5657 } else {
5659 // Neither side is a constant Smi, constant 1-char string, or constant null. 5658 // Neither side is a constant Smi, constant 1-char string, or constant null.
5660 // If either side is a non-smi constant, skip the smi check. 5659 // If either side is a non-smi constant, skip the smi check.
(...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after
7089 __ and_(rbx, Immediate(1 << Map::kIsUndetectable)); 7088 __ and_(rbx, Immediate(1 << Map::kIsUndetectable));
7090 __ j(not_zero, &false_result); 7089 __ j(not_zero, &false_result);
7091 7090
7092 // JavaScript object => true. 7091 // JavaScript object => true.
7093 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE)); 7092 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE));
7094 __ j(above_equal, &true_result); 7093 __ j(above_equal, &true_result);
7095 7094
7096 // String value => false iff empty. 7095 // String value => false iff empty.
7097 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE)); 7096 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE));
7098 __ j(above_equal, &not_string); 7097 __ j(above_equal, &not_string);
7099 __ movq(rdx, FieldOperand(rax, String::kLengthOffset)); 7098 __ movl(rdx, FieldOperand(rax, String::kLengthOffset));
7100 __ testq(rdx, rdx); 7099 __ testl(rdx, rdx);
7101 __ j(zero, &false_result); 7100 __ j(zero, &false_result);
7102 __ jmp(&true_result); 7101 __ jmp(&true_result);
7103 7102
7104 __ bind(&not_string); 7103 __ bind(&not_string);
7105 // HeapNumber => false iff +0, -0, or NaN. 7104 // HeapNumber => false iff +0, -0, or NaN.
7106 // These three cases set C3 when compared to zero in the FPU. 7105 // These three cases set C3 when compared to zero in the FPU.
7107 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); 7106 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
7108 __ j(not_equal, &true_result); 7107 __ j(not_equal, &true_result);
7109 __ fldz(); // Load zero onto fp stack 7108 __ fldz(); // Load zero onto fp stack
7110 // Load heap-number double value onto fp stack 7109 // Load heap-number double value onto fp stack
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
7490 __ j(above, &runtime); 7489 __ j(above, &runtime);
7491 7490
7492 // rcx: RegExp data (FixedArray) 7491 // rcx: RegExp data (FixedArray)
7493 // rdx: Number of capture registers 7492 // rdx: Number of capture registers
7494 // Check that the second argument is a string. 7493 // Check that the second argument is a string.
7495 __ movq(rax, Operand(rsp, kSubjectOffset)); 7494 __ movq(rax, Operand(rsp, kSubjectOffset));
7496 __ JumpIfSmi(rax, &runtime); 7495 __ JumpIfSmi(rax, &runtime);
7497 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); 7496 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
7498 __ j(NegateCondition(is_string), &runtime); 7497 __ j(NegateCondition(is_string), &runtime);
7499 // Get the length of the string to rbx. 7498 // Get the length of the string to rbx.
7500 __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); 7499 __ movl(rbx, FieldOperand(rax, String::kLengthOffset));
7501 7500
7502 // rbx: Length of subject string as smi 7501 // rbx: Length of subject string
7503 // rcx: RegExp data (FixedArray) 7502 // rcx: RegExp data (FixedArray)
7504 // rdx: Number of capture registers 7503 // rdx: Number of capture registers
7505 // Check that the third argument is a positive smi less than the string 7504 // Check that the third argument is a positive smi less than the string
7506 // length. A negative value will be greater (unsigned comparison). 7505 // length. A negative value will be greater (unsigned comparison).
7507 __ movq(rax, Operand(rsp, kPreviousIndexOffset)); 7506 __ movq(rax, Operand(rsp, kPreviousIndexOffset));
7508 __ JumpIfNotSmi(rax, &runtime); 7507 __ SmiToInteger32(rax, rax);
7509 __ SmiCompare(rax, rbx); 7508 __ cmpl(rax, rbx);
7510 __ j(above_equal, &runtime); 7509 __ j(above, &runtime);
7511 7510
7512 // rcx: RegExp data (FixedArray) 7511 // rcx: RegExp data (FixedArray)
7513 // rdx: Number of capture registers 7512 // rdx: Number of capture registers
7514 // Check that the fourth object is a JSArray object. 7513 // Check that the fourth object is a JSArray object.
7515 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); 7514 __ movq(rax, Operand(rsp, kLastMatchInfoOffset));
7516 __ JumpIfSmi(rax, &runtime); 7515 __ JumpIfSmi(rax, &runtime);
7517 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); 7516 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister);
7518 __ j(not_equal, &runtime); 7517 __ j(not_equal, &runtime);
7519 // Check that the JSArray is in fast case. 7518 // Check that the JSArray is in fast case.
7520 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); 7519 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset));
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
7653 // Keep track on aliasing between argX defined above and the registers used. 7652 // Keep track on aliasing between argX defined above and the registers used.
7654 // rax: subject string 7653 // rax: subject string
7655 // rbx: previous index 7654 // rbx: previous index
7656 // rdi: encoding of subject string (1 if ascii 0 if two_byte); 7655 // rdi: encoding of subject string (1 if ascii 0 if two_byte);
7657 // r12: code 7656 // r12: code
7658 7657
7659 // Argument 4: End of string data 7658 // Argument 4: End of string data
7660 // Argument 3: Start of string data 7659 // Argument 3: Start of string data
7661 Label setup_two_byte, setup_rest; 7660 Label setup_two_byte, setup_rest;
7662 __ testb(rdi, rdi); 7661 __ testb(rdi, rdi);
7663 __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); 7662 __ movl(rdi, FieldOperand(rax, String::kLengthOffset));
7664 __ j(zero, &setup_two_byte); 7663 __ j(zero, &setup_two_byte);
7665 __ SmiToInteger32(rdi, rdi);
7666 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); 7664 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize));
7667 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); 7665 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize));
7668 __ jmp(&setup_rest); 7666 __ jmp(&setup_rest);
7669 __ bind(&setup_two_byte); 7667 __ bind(&setup_two_byte);
7670 __ SmiToInteger32(rdi, rdi);
7671 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); 7668 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize));
7672 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); 7669 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize));
7673 7670
7674 __ bind(&setup_rest); 7671 __ bind(&setup_rest);
7675 // Argument 2: Previous index. 7672 // Argument 2: Previous index.
7676 __ movq(arg2, rbx); 7673 __ movq(arg2, rbx);
7677 7674
7678 // Argument 1: Subject string. 7675 // Argument 1: Subject string.
7679 __ movq(arg1, rax); 7676 __ movq(arg1, rax);
7680 7677
(...skipping 2139 matching lines...) Expand 10 before | Expand all | Expand 10 after
9820 __ j(is_smi, &string_add_runtime); 9817 __ j(is_smi, &string_add_runtime);
9821 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9); 9818 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
9822 __ j(above_equal, &string_add_runtime); 9819 __ j(above_equal, &string_add_runtime);
9823 } 9820 }
9824 9821
9825 // Both arguments are strings. 9822 // Both arguments are strings.
9826 // rax: first string 9823 // rax: first string
9827 // rdx: second string 9824 // rdx: second string
9828 // Check if either of the strings are empty. In that case return the other. 9825 // Check if either of the strings are empty. In that case return the other.
9829 Label second_not_zero_length, both_not_zero_length; 9826 Label second_not_zero_length, both_not_zero_length;
9830 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset)); 9827 __ movl(rcx, FieldOperand(rdx, String::kLengthOffset));
9831 __ SmiTest(rcx); 9828 __ testl(rcx, rcx);
9832 __ j(not_zero, &second_not_zero_length); 9829 __ j(not_zero, &second_not_zero_length);
9833 // Second string is empty, result is first string which is already in rax. 9830 // Second string is empty, result is first string which is already in rax.
9834 __ IncrementCounter(&Counters::string_add_native, 1); 9831 __ IncrementCounter(&Counters::string_add_native, 1);
9835 __ ret(2 * kPointerSize); 9832 __ ret(2 * kPointerSize);
9836 __ bind(&second_not_zero_length); 9833 __ bind(&second_not_zero_length);
9837 __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); 9834 __ movl(rbx, FieldOperand(rax, String::kLengthOffset));
9838 __ SmiTest(rbx); 9835 __ testl(rbx, rbx);
9839 __ j(not_zero, &both_not_zero_length); 9836 __ j(not_zero, &both_not_zero_length);
9840 // First string is empty, result is second string which is in rdx. 9837 // First string is empty, result is second string which is in rdx.
9841 __ movq(rax, rdx); 9838 __ movq(rax, rdx);
9842 __ IncrementCounter(&Counters::string_add_native, 1); 9839 __ IncrementCounter(&Counters::string_add_native, 1);
9843 __ ret(2 * kPointerSize); 9840 __ ret(2 * kPointerSize);
9844 9841
9845 // Both strings are non-empty. 9842 // Both strings are non-empty.
9846 // rax: first string 9843 // rax: first string
9847 // rbx: length of first string 9844 // rbx: length of first string
9848 // rcx: length of second string 9845 // rcx: length of second string
9849 // rdx: second string 9846 // rdx: second string
9850 // r8: map of first string if string check was performed above 9847 // r8: map of first string if string check was performed above
9851 // r9: map of second string if string check was performed above 9848 // r9: map of second string if string check was performed above
9852 Label string_add_flat_result, longer_than_two; 9849 Label string_add_flat_result, longer_than_two;
9853 __ bind(&both_not_zero_length); 9850 __ bind(&both_not_zero_length);
9854 9851
9855 // If arguments where known to be strings, maps are not loaded to r8 and r9 9852 // If arguments where known to be strings, maps are not loaded to r8 and r9
9856 // by the code above. 9853 // by the code above.
9857 if (!string_check_) { 9854 if (!string_check_) {
9858 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); 9855 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
9859 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); 9856 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
9860 } 9857 }
9861 // Get the instance types of the two strings as they will be needed soon. 9858 // Get the instance types of the two strings as they will be needed soon.
9862 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); 9859 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
9863 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); 9860 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
9864 9861
9865 // Look at the length of the result of adding the two strings. 9862 // Look at the length of the result of adding the two strings.
9866 ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); 9863 __ addl(rbx, rcx);
9867 __ SmiAdd(rbx, rbx, rcx, NULL);
9868 // Use the runtime system when adding two one character strings, as it 9864 // Use the runtime system when adding two one character strings, as it
9869 // contains optimizations for this specific case using the symbol table. 9865 // contains optimizations for this specific case using the symbol table.
9870 __ SmiCompare(rbx, Smi::FromInt(2)); 9866 __ cmpl(rbx, Immediate(2));
9871 __ j(not_equal, &longer_than_two); 9867 __ j(not_equal, &longer_than_two);
9872 9868
9873 // Check that both strings are non-external ascii strings. 9869 // Check that both strings are non-external ascii strings.
9874 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, 9870 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
9875 &string_add_runtime); 9871 &string_add_runtime);
9876 9872
9877 // Get the two characters forming the sub string. 9873 // Get the two characters forming the sub string.
9878 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); 9874 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
9879 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); 9875 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
9880 9876
9881 // Try to lookup two character string in symbol table. If it is not found 9877 // Try to lookup two character string in symbol table. If it is not found
9882 // just allocate a new one. 9878 // just allocate a new one.
9883 Label make_two_character_string, make_flat_ascii_string; 9879 Label make_two_character_string, make_flat_ascii_string;
9884 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, r14, r12, rdi, r15, 9880 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, r14, r12, rdi, r15,
9885 &make_two_character_string); 9881 &make_two_character_string);
9886 __ IncrementCounter(&Counters::string_add_native, 1); 9882 __ IncrementCounter(&Counters::string_add_native, 1);
9887 __ ret(2 * kPointerSize); 9883 __ ret(2 * kPointerSize);
9888 9884
9889 __ bind(&make_two_character_string); 9885 __ bind(&make_two_character_string);
9890 __ Set(rbx, 2); 9886 __ Set(rbx, 2);
9891 __ jmp(&make_flat_ascii_string); 9887 __ jmp(&make_flat_ascii_string);
9892 9888
9893 __ bind(&longer_than_two); 9889 __ bind(&longer_than_two);
9894 // Check if resulting string will be flat. 9890 // Check if resulting string will be flat.
9895 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength)); 9891 __ cmpl(rbx, Immediate(String::kMinNonFlatLength));
9896 __ j(below, &string_add_flat_result); 9892 __ j(below, &string_add_flat_result);
9897 // Handle exceptionally long strings in the runtime system. 9893 // Handle exceptionally long strings in the runtime system.
9898 ASSERT((String::kMaxLength & 0x80000000) == 0); 9894 ASSERT((String::kMaxLength & 0x80000000) == 0);
9899 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength)); 9895 __ cmpl(rbx, Immediate(String::kMaxLength));
9900 __ j(above, &string_add_runtime); 9896 __ j(above, &string_add_runtime);
9901 9897
9902 // If result is not supposed to be flat, allocate a cons string object. If 9898 // If result is not supposed to be flat, allocate a cons string object. If
9903 // both strings are ascii the result is an ascii cons string. 9899 // both strings are ascii the result is an ascii cons string.
9904 // rax: first string 9900 // rax: first string
9905 // ebx: length of resulting flat string 9901 // ebx: length of resulting flat string
9906 // rdx: second string 9902 // rdx: second string
9907 // r8: instance type of first string 9903 // r8: instance type of first string
9908 // r9: instance type of second string 9904 // r9: instance type of second string
9909 Label non_ascii, allocated; 9905 Label non_ascii, allocated;
9910 __ movl(rcx, r8); 9906 __ movl(rcx, r8);
9911 __ and_(rcx, r9); 9907 __ and_(rcx, r9);
9912 ASSERT(kStringEncodingMask == kAsciiStringTag); 9908 ASSERT(kStringEncodingMask == kAsciiStringTag);
9913 __ testl(rcx, Immediate(kAsciiStringTag)); 9909 __ testl(rcx, Immediate(kAsciiStringTag));
9914 __ j(zero, &non_ascii); 9910 __ j(zero, &non_ascii);
9915 // Allocate an acsii cons string. 9911 // Allocate an acsii cons string.
9916 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); 9912 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime);
9917 __ bind(&allocated); 9913 __ bind(&allocated);
9918 // Fill the fields of the cons string. 9914 // Fill the fields of the cons string.
9919 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); 9915 __ movl(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
9920 __ movl(FieldOperand(rcx, ConsString::kHashFieldOffset), 9916 __ movl(FieldOperand(rcx, ConsString::kHashFieldOffset),
9921 Immediate(String::kEmptyHashField)); 9917 Immediate(String::kEmptyHashField));
9922 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); 9918 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
9923 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); 9919 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
9924 __ movq(rax, rcx); 9920 __ movq(rax, rcx);
9925 __ IncrementCounter(&Counters::string_add_native, 1); 9921 __ IncrementCounter(&Counters::string_add_native, 1);
9926 __ ret(2 * kPointerSize); 9922 __ ret(2 * kPointerSize);
9927 __ bind(&non_ascii); 9923 __ bind(&non_ascii);
9928 // Allocate a two byte cons string. 9924 // Allocate a two byte cons string.
9929 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime); 9925 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime);
9930 __ jmp(&allocated); 9926 __ jmp(&allocated);
9931 9927
9932 // Handle creating a flat result. First check that both strings are not 9928 // Handle creating a flat result. First check that both strings are not
9933 // external strings. 9929 // external strings.
9934 // rax: first string 9930 // rax: first string
9935 // ebx: length of resulting flat string as smi 9931 // ebx: length of resulting flat string
9936 // rdx: second string 9932 // rdx: second string
9937 // r8: instance type of first string 9933 // r8: instance type of first string
9938 // r9: instance type of first string 9934 // r9: instance type of first string
9939 __ bind(&string_add_flat_result); 9935 __ bind(&string_add_flat_result);
9940 __ SmiToInteger32(rbx, rbx);
9941 __ movl(rcx, r8); 9936 __ movl(rcx, r8);
9942 __ and_(rcx, Immediate(kStringRepresentationMask)); 9937 __ and_(rcx, Immediate(kStringRepresentationMask));
9943 __ cmpl(rcx, Immediate(kExternalStringTag)); 9938 __ cmpl(rcx, Immediate(kExternalStringTag));
9944 __ j(equal, &string_add_runtime); 9939 __ j(equal, &string_add_runtime);
9945 __ movl(rcx, r9); 9940 __ movl(rcx, r9);
9946 __ and_(rcx, Immediate(kStringRepresentationMask)); 9941 __ and_(rcx, Immediate(kStringRepresentationMask));
9947 __ cmpl(rcx, Immediate(kExternalStringTag)); 9942 __ cmpl(rcx, Immediate(kExternalStringTag));
9948 __ j(equal, &string_add_runtime); 9943 __ j(equal, &string_add_runtime);
9949 // Now check if both strings are ascii strings. 9944 // Now check if both strings are ascii strings.
9950 // rax: first string 9945 // rax: first string
9951 // ebx: length of resulting flat string 9946 // ebx: length of resulting flat string
9952 // rdx: second string 9947 // rdx: second string
9953 // r8: instance type of first string 9948 // r8: instance type of first string
9954 // r9: instance type of second string 9949 // r9: instance type of second string
9955 Label non_ascii_string_add_flat_result; 9950 Label non_ascii_string_add_flat_result;
9956 ASSERT(kStringEncodingMask == kAsciiStringTag); 9951 ASSERT(kStringEncodingMask == kAsciiStringTag);
9957 __ testl(r8, Immediate(kAsciiStringTag)); 9952 __ testl(r8, Immediate(kAsciiStringTag));
9958 __ j(zero, &non_ascii_string_add_flat_result); 9953 __ j(zero, &non_ascii_string_add_flat_result);
9959 __ testl(r9, Immediate(kAsciiStringTag)); 9954 __ testl(r9, Immediate(kAsciiStringTag));
9960 __ j(zero, &string_add_runtime); 9955 __ j(zero, &string_add_runtime);
9961 9956
9962 __ bind(&make_flat_ascii_string); 9957 __ bind(&make_flat_ascii_string);
9963 // Both strings are ascii strings. As they are short they are both flat. 9958 // Both strings are ascii strings. As they are short they are both flat.
9964 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 9959 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
9965 // rcx: result string 9960 // rcx: result string
9966 __ movq(rbx, rcx); 9961 __ movq(rbx, rcx);
9967 // Locate first character of result. 9962 // Locate first character of result.
9968 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9963 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9969 // Locate first character of first argument 9964 // Locate first character of first argument
9970 __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); 9965 __ movl(rdi, FieldOperand(rax, String::kLengthOffset));
9971 __ SmiToInteger32(rdi, rdi);
9972 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9966 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9973 // rax: first char of first argument 9967 // rax: first char of first argument
9974 // rbx: result string 9968 // rbx: result string
9975 // rcx: first character of result 9969 // rcx: first character of result
9976 // rdx: second string 9970 // rdx: second string
9977 // rdi: length of first argument 9971 // rdi: length of first argument
9978 GenerateCopyCharacters(masm, rcx, rax, rdi, true); 9972 GenerateCopyCharacters(masm, rcx, rax, rdi, true);
9979 // Locate first character of second argument. 9973 // Locate first character of second argument.
9980 __ movq(rdi, FieldOperand(rdx, String::kLengthOffset)); 9974 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset));
9981 __ SmiToInteger32(rdi, rdi);
9982 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9975 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9983 // rbx: result string 9976 // rbx: result string
9984 // rcx: next character of result 9977 // rcx: next character of result
9985 // rdx: first char of second argument 9978 // rdx: first char of second argument
9986 // rdi: length of second argument 9979 // rdi: length of second argument
9987 GenerateCopyCharacters(masm, rcx, rdx, rdi, true); 9980 GenerateCopyCharacters(masm, rcx, rdx, rdi, true);
9988 __ movq(rax, rbx); 9981 __ movq(rax, rbx);
9989 __ IncrementCounter(&Counters::string_add_native, 1); 9982 __ IncrementCounter(&Counters::string_add_native, 1);
9990 __ ret(2 * kPointerSize); 9983 __ ret(2 * kPointerSize);
9991 9984
9992 // Handle creating a flat two byte result. 9985 // Handle creating a flat two byte result.
9993 // rax: first string - known to be two byte 9986 // rax: first string - known to be two byte
9994 // rbx: length of resulting flat string 9987 // rbx: length of resulting flat string
9995 // rdx: second string 9988 // rdx: second string
9996 // r8: instance type of first string 9989 // r8: instance type of first string
9997 // r9: instance type of first string 9990 // r9: instance type of first string
9998 __ bind(&non_ascii_string_add_flat_result); 9991 __ bind(&non_ascii_string_add_flat_result);
9999 __ and_(r9, Immediate(kAsciiStringTag)); 9992 __ and_(r9, Immediate(kAsciiStringTag));
10000 __ j(not_zero, &string_add_runtime); 9993 __ j(not_zero, &string_add_runtime);
10001 // Both strings are two byte strings. As they are short they are both 9994 // Both strings are two byte strings. As they are short they are both
10002 // flat. 9995 // flat.
10003 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 9996 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
10004 // rcx: result string 9997 // rcx: result string
10005 __ movq(rbx, rcx); 9998 __ movq(rbx, rcx);
10006 // Locate first character of result. 9999 // Locate first character of result.
10007 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 10000 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
10008 // Locate first character of first argument. 10001 // Locate first character of first argument.
10009 __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); 10002 __ movl(rdi, FieldOperand(rax, String::kLengthOffset));
10010 __ SmiToInteger32(rdi, rdi);
10011 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 10003 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
10012 // rax: first char of first argument 10004 // rax: first char of first argument
10013 // rbx: result string 10005 // rbx: result string
10014 // rcx: first character of result 10006 // rcx: first character of result
10015 // rdx: second argument 10007 // rdx: second argument
10016 // rdi: length of first argument 10008 // rdi: length of first argument
10017 GenerateCopyCharacters(masm, rcx, rax, rdi, false); 10009 GenerateCopyCharacters(masm, rcx, rax, rdi, false);
10018 // Locate first character of second argument. 10010 // Locate first character of second argument.
10019 __ movq(rdi, FieldOperand(rdx, String::kLengthOffset)); 10011 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset));
10020 __ SmiToInteger32(rdi, rdi);
10021 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 10012 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
10022 // rbx: result string 10013 // rbx: result string
10023 // rcx: next character of result 10014 // rcx: next character of result
10024 // rdx: first char of second argument 10015 // rdx: first char of second argument
10025 // rdi: length of second argument 10016 // rdi: length of second argument
10026 GenerateCopyCharacters(masm, rcx, rdx, rdi, false); 10017 GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
10027 __ movq(rax, rbx); 10018 __ movq(rax, rbx);
10028 __ IncrementCounter(&Counters::string_add_native, 1); 10019 __ IncrementCounter(&Counters::string_add_native, 1);
10029 __ ret(2 * kPointerSize); 10020 __ ret(2 * kPointerSize);
10030 10021
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
10192 FieldOperand(symbol_table, 10183 FieldOperand(symbol_table,
10193 scratch, 10184 scratch,
10194 times_pointer_size, 10185 times_pointer_size,
10195 SymbolTable::kElementsStartOffset)); 10186 SymbolTable::kElementsStartOffset));
10196 10187
10197 // If entry is undefined no string with this hash can be found. 10188 // If entry is undefined no string with this hash can be found.
10198 __ cmpq(candidate, undefined); 10189 __ cmpq(candidate, undefined);
10199 __ j(equal, not_found); 10190 __ j(equal, not_found);
10200 10191
10201 // If length is not 2 the string is not a candidate. 10192 // If length is not 2 the string is not a candidate.
10202 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), 10193 __ cmpl(FieldOperand(candidate, String::kLengthOffset), Immediate(2));
10203 Smi::FromInt(2));
10204 __ j(not_equal, &next_probe[i]); 10194 __ j(not_equal, &next_probe[i]);
10205 10195
10206 // We use kScratchRegister as a temporary register in assumption that 10196 // We use kScratchRegister as a temporary register in assumption that
10207 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly 10197 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly
10208 Register temp = kScratchRegister; 10198 Register temp = kScratchRegister;
10209 10199
10210 // Check that the candidate is a non-external ascii string. 10200 // Check that the candidate is a non-external ascii string.
10211 __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset)); 10201 __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset));
10212 __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 10202 __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
10213 __ JumpIfInstanceTypeIsNotSequentialAscii( 10203 __ JumpIfInstanceTypeIsNotSequentialAscii(
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
10437 Register right, 10427 Register right,
10438 Register scratch1, 10428 Register scratch1,
10439 Register scratch2, 10429 Register scratch2,
10440 Register scratch3, 10430 Register scratch3,
10441 Register scratch4) { 10431 Register scratch4) {
10442 // Ensure that you can always subtract a string length from a non-negative 10432 // Ensure that you can always subtract a string length from a non-negative
10443 // number (e.g. another length). 10433 // number (e.g. another length).
10444 ASSERT(String::kMaxLength < 0x7fffffff); 10434 ASSERT(String::kMaxLength < 0x7fffffff);
10445 10435
10446 // Find minimum length and length difference. 10436 // Find minimum length and length difference.
10447 __ movq(scratch1, FieldOperand(left, String::kLengthOffset)); 10437 __ movl(scratch1, FieldOperand(left, String::kLengthOffset));
10448 __ movq(scratch4, scratch1); 10438 __ movl(scratch4, scratch1);
10449 __ SmiSub(scratch4, 10439 __ subl(scratch4, FieldOperand(right, String::kLengthOffset));
10450 scratch4,
10451 FieldOperand(right, String::kLengthOffset),
10452 NULL);
10453 // Register scratch4 now holds left.length - right.length. 10440 // Register scratch4 now holds left.length - right.length.
10454 const Register length_difference = scratch4; 10441 const Register length_difference = scratch4;
10455 Label left_shorter; 10442 Label left_shorter;
10456 __ j(less, &left_shorter); 10443 __ j(less, &left_shorter);
10457 // The right string isn't longer that the left one. 10444 // The right string isn't longer that the left one.
10458 // Get the right string's length by subtracting the (non-negative) difference 10445 // Get the right string's length by subtracting the (non-negative) difference
10459 // from the left string's length. 10446 // from the left string's length.
10460 __ SmiSub(scratch1, scratch1, length_difference, NULL); 10447 __ subl(scratch1, length_difference);
10461 __ bind(&left_shorter); 10448 __ bind(&left_shorter);
10462 // Register scratch1 now holds Min(left.length, right.length). 10449 // Register scratch1 now holds Min(left.length, right.length).
10463 const Register min_length = scratch1; 10450 const Register min_length = scratch1;
10464 10451
10465 Label compare_lengths; 10452 Label compare_lengths;
10466 // If min-length is zero, go directly to comparing lengths. 10453 // If min-length is zero, go directly to comparing lengths.
10467 __ SmiTest(min_length); 10454 __ testl(min_length, min_length);
10468 __ j(zero, &compare_lengths); 10455 __ j(zero, &compare_lengths);
10469 10456
10470 __ SmiToInteger32(min_length, min_length);
10471
10472 // Registers scratch2 and scratch3 are free. 10457 // Registers scratch2 and scratch3 are free.
10473 Label result_not_equal; 10458 Label result_not_equal;
10474 Label loop; 10459 Label loop;
10475 { 10460 {
10476 // Check characters 0 .. min_length - 1 in a loop. 10461 // Check characters 0 .. min_length - 1 in a loop.
10477 // Use scratch3 as loop index, min_length as limit and scratch2 10462 // Use scratch3 as loop index, min_length as limit and scratch2
10478 // for computation. 10463 // for computation.
10479 const Register index = scratch3; 10464 const Register index = scratch3;
10480 __ movl(index, Immediate(0)); // Index into strings. 10465 __ movl(index, Immediate(0)); // Index into strings.
10481 __ bind(&loop); 10466 __ bind(&loop);
(...skipping 10 matching lines...) Expand all
10492 index, 10477 index,
10493 times_1, 10478 times_1,
10494 SeqAsciiString::kHeaderSize - 1)); 10479 SeqAsciiString::kHeaderSize - 1));
10495 __ j(not_equal, &result_not_equal); 10480 __ j(not_equal, &result_not_equal);
10496 __ cmpl(index, min_length); 10481 __ cmpl(index, min_length);
10497 __ j(not_equal, &loop); 10482 __ j(not_equal, &loop);
10498 } 10483 }
10499 // Completed loop without finding different characters. 10484 // Completed loop without finding different characters.
10500 // Compare lengths (precomputed). 10485 // Compare lengths (precomputed).
10501 __ bind(&compare_lengths); 10486 __ bind(&compare_lengths);
10502 __ SmiTest(length_difference); 10487 __ testl(length_difference, length_difference);
10503 __ j(not_zero, &result_not_equal); 10488 __ j(not_zero, &result_not_equal);
10504 10489
10505 // Result is EQUAL. 10490 // Result is EQUAL.
10506 __ Move(rax, Smi::FromInt(EQUAL)); 10491 __ Move(rax, Smi::FromInt(EQUAL));
10507 __ ret(2 * kPointerSize); 10492 __ ret(2 * kPointerSize);
10508 10493
10509 Label result_greater; 10494 Label result_greater;
10510 __ bind(&result_not_equal); 10495 __ bind(&result_not_equal);
10511 // Unequal comparison of left to right, either character or length. 10496 // Unequal comparison of left to right, either character or length.
10512 __ j(greater, &result_greater); 10497 __ j(greater, &result_greater);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
10646 // Call the function from C++. 10631 // Call the function from C++.
10647 return FUNCTION_CAST<ModuloFunction>(buffer); 10632 return FUNCTION_CAST<ModuloFunction>(buffer);
10648 } 10633 }
10649 10634
10650 #endif 10635 #endif
10651 10636
10652 10637
10653 #undef __ 10638 #undef __
10654 10639
10655 } } // namespace v8::internal 10640 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects-inl.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698