OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 __ test(scratch, scratch); | 742 __ test(scratch, scratch); |
743 __ j(positive, &done, Label::kNear); | 743 __ j(positive, &done, Label::kNear); |
744 __ neg(ecx); | 744 __ neg(ecx); |
745 __ jmp(&done, Label::kNear); | 745 __ jmp(&done, Label::kNear); |
746 } | 746 } |
747 | 747 |
748 __ bind(&normal_exponent); | 748 __ bind(&normal_exponent); |
749 // Exponent word in scratch, exponent part of exponent word in scratch2. | 749 // Exponent word in scratch, exponent part of exponent word in scratch2. |
750 // Zero in ecx. | 750 // Zero in ecx. |
751 // We know the exponent is smaller than 30 (biased). If it is less than | 751 // We know the exponent is smaller than 30 (biased). If it is less than |
752 // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie | 752 // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e. |
753 // it rounds to zero. | 753 // it rounds to zero. |
754 const uint32_t zero_exponent = | 754 const uint32_t zero_exponent = |
755 (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift; | 755 (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift; |
756 __ sub(scratch2, Immediate(zero_exponent)); | 756 __ sub(scratch2, Immediate(zero_exponent)); |
757 // ecx already has a Smi zero. | 757 // ecx already has a Smi zero. |
758 __ j(less, &done, Label::kNear); | 758 __ j(less, &done, Label::kNear); |
759 | 759 |
760 // We have a shifted exponent between 0 and 30 in scratch2. | 760 // We have a shifted exponent between 0 and 30 in scratch2. |
761 __ shr(scratch2, HeapNumber::kExponentShift); | 761 __ shr(scratch2, HeapNumber::kExponentShift); |
762 __ mov(ecx, Immediate(30)); | 762 __ mov(ecx, Immediate(30)); |
(...skipping 2953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3716 __ mov(eax, Operand(esp, kSubjectOffset)); | 3716 __ mov(eax, Operand(esp, kSubjectOffset)); |
3717 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3717 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3718 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 3718 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
3719 // First check for flat two byte string. | 3719 // First check for flat two byte string. |
3720 __ and_(ebx, kIsNotStringMask | | 3720 __ and_(ebx, kIsNotStringMask | |
3721 kStringRepresentationMask | | 3721 kStringRepresentationMask | |
3722 kStringEncodingMask | | 3722 kStringEncodingMask | |
3723 kShortExternalStringMask); | 3723 kShortExternalStringMask); |
3724 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 3724 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
3725 __ j(zero, &seq_two_byte_string, Label::kNear); | 3725 __ j(zero, &seq_two_byte_string, Label::kNear); |
3726 // Any other flat string must be a flat ascii string. None of the following | 3726 // Any other flat string must be a flat ASCII string. None of the following |
3727 // string type tests will succeed if subject is not a string or a short | 3727 // string type tests will succeed if subject is not a string or a short |
3728 // external string. | 3728 // external string. |
3729 __ and_(ebx, Immediate(kIsNotStringMask | | 3729 __ and_(ebx, Immediate(kIsNotStringMask | |
3730 kStringRepresentationMask | | 3730 kStringRepresentationMask | |
3731 kShortExternalStringMask)); | 3731 kShortExternalStringMask)); |
3732 __ j(zero, &seq_ascii_string, Label::kNear); | 3732 __ j(zero, &seq_ascii_string, Label::kNear); |
3733 | 3733 |
3734 // ebx: whether subject is a string and if yes, its string representation | 3734 // ebx: whether subject is a string and if yes, its string representation |
3735 // Check for flat cons string or sliced string. | 3735 // Check for flat cons string or sliced string. |
3736 // A flat cons string is a cons string where the second part is the empty | 3736 // A flat cons string is a cons string where the second part is the empty |
(...skipping 28 matching lines...) Expand all Loading... |
3765 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 3765 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
3766 __ bind(&check_encoding); | 3766 __ bind(&check_encoding); |
3767 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3767 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3768 // eax: first part of cons string or parent of sliced string. | 3768 // eax: first part of cons string or parent of sliced string. |
3769 // ebx: map of first part of cons string or map of parent of sliced string. | 3769 // ebx: map of first part of cons string or map of parent of sliced string. |
3770 // Is first part of cons or parent of slice a flat two byte string? | 3770 // Is first part of cons or parent of slice a flat two byte string? |
3771 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | 3771 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), |
3772 kStringRepresentationMask | kStringEncodingMask); | 3772 kStringRepresentationMask | kStringEncodingMask); |
3773 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 3773 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
3774 __ j(zero, &seq_two_byte_string, Label::kNear); | 3774 __ j(zero, &seq_two_byte_string, Label::kNear); |
3775 // Any other flat string must be sequential ascii or external. | 3775 // Any other flat string must be sequential ASCII or external. |
3776 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | 3776 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), |
3777 kStringRepresentationMask); | 3777 kStringRepresentationMask); |
3778 __ j(not_zero, &external_string); | 3778 __ j(not_zero, &external_string); |
3779 | 3779 |
3780 __ bind(&seq_ascii_string); | 3780 __ bind(&seq_ascii_string); |
3781 // eax: subject string (flat ascii) | 3781 // eax: subject string (flat ASCII) |
3782 // ecx: RegExp data (FixedArray) | 3782 // ecx: RegExp data (FixedArray) |
3783 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); | 3783 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
3784 __ Set(ecx, Immediate(1)); // Type is ascii. | 3784 __ Set(ecx, Immediate(1)); // Type is ASCII. |
3785 __ jmp(&check_code, Label::kNear); | 3785 __ jmp(&check_code, Label::kNear); |
3786 | 3786 |
3787 __ bind(&seq_two_byte_string); | 3787 __ bind(&seq_two_byte_string); |
3788 // eax: subject string (flat two byte) | 3788 // eax: subject string (flat two byte) |
3789 // ecx: RegExp data (FixedArray) | 3789 // ecx: RegExp data (FixedArray) |
3790 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); | 3790 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); |
3791 __ Set(ecx, Immediate(0)); // Type is two byte. | 3791 __ Set(ecx, Immediate(0)); // Type is two byte. |
3792 | 3792 |
3793 __ bind(&check_code); | 3793 __ bind(&check_code); |
3794 // Check that the irregexp code has been generated for the actual string | 3794 // Check that the irregexp code has been generated for the actual string |
3795 // encoding. If it has, the field contains a code object otherwise it contains | 3795 // encoding. If it has, the field contains a code object otherwise it contains |
3796 // a smi (code flushing support). | 3796 // a smi (code flushing support). |
3797 __ JumpIfSmi(edx, &runtime); | 3797 __ JumpIfSmi(edx, &runtime); |
3798 | 3798 |
3799 // eax: subject string | 3799 // eax: subject string |
3800 // edx: code | 3800 // edx: code |
3801 // ecx: encoding of subject string (1 if ascii, 0 if two_byte); | 3801 // ecx: encoding of subject string (1 if ASCII, 0 if two_byte); |
3802 // Load used arguments before starting to push arguments for call to native | 3802 // Load used arguments before starting to push arguments for call to native |
3803 // RegExp code to avoid handling changing stack height. | 3803 // RegExp code to avoid handling changing stack height. |
3804 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 3804 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
3805 __ SmiUntag(ebx); // Previous index from smi. | 3805 __ SmiUntag(ebx); // Previous index from smi. |
3806 | 3806 |
3807 // eax: subject string | 3807 // eax: subject string |
3808 // ebx: previous index | 3808 // ebx: previous index |
3809 // edx: code | 3809 // edx: code |
3810 // ecx: encoding of subject string (1 if ascii 0 if two_byte); | 3810 // ecx: encoding of subject string (1 if ASCII 0 if two_byte); |
3811 // All checks done. Now push arguments for native regexp code. | 3811 // All checks done. Now push arguments for native regexp code. |
3812 Counters* counters = masm->isolate()->counters(); | 3812 Counters* counters = masm->isolate()->counters(); |
3813 __ IncrementCounter(counters->regexp_entry_native(), 1); | 3813 __ IncrementCounter(counters->regexp_entry_native(), 1); |
3814 | 3814 |
3815 // Isolates: note we add an additional parameter here (isolate pointer). | 3815 // Isolates: note we add an additional parameter here (isolate pointer). |
3816 static const int kRegExpExecuteArguments = 8; | 3816 static const int kRegExpExecuteArguments = 8; |
3817 __ EnterApiExitFrame(kRegExpExecuteArguments); | 3817 __ EnterApiExitFrame(kRegExpExecuteArguments); |
3818 | 3818 |
3819 // Argument 8: Pass current isolate address. | 3819 // Argument 8: Pass current isolate address. |
3820 __ mov(Operand(esp, 7 * kPointerSize), | 3820 __ mov(Operand(esp, 7 * kPointerSize), |
(...skipping 19 matching lines...) Expand all Loading... |
3840 // The original subject is in the previous stack frame. Therefore we have to | 3840 // The original subject is in the previous stack frame. Therefore we have to |
3841 // use ebp, which points exactly to one pointer size below the previous esp. | 3841 // use ebp, which points exactly to one pointer size below the previous esp. |
3842 // (Because creating a new stack frame pushes the previous ebp onto the stack | 3842 // (Because creating a new stack frame pushes the previous ebp onto the stack |
3843 // and thereby moves up esp by one kPointerSize.) | 3843 // and thereby moves up esp by one kPointerSize.) |
3844 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); | 3844 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); |
3845 __ mov(Operand(esp, 0 * kPointerSize), esi); | 3845 __ mov(Operand(esp, 0 * kPointerSize), esi); |
3846 | 3846 |
3847 // esi: original subject string | 3847 // esi: original subject string |
3848 // eax: underlying subject string | 3848 // eax: underlying subject string |
3849 // ebx: previous index | 3849 // ebx: previous index |
3850 // ecx: encoding of subject string (1 if ascii 0 if two_byte); | 3850 // ecx: encoding of subject string (1 if ASCII 0 if two_byte); |
3851 // edx: code | 3851 // edx: code |
3852 // Argument 4: End of string data | 3852 // Argument 4: End of string data |
3853 // Argument 3: Start of string data | 3853 // Argument 3: Start of string data |
3854 // Prepare start and end index of the input. | 3854 // Prepare start and end index of the input. |
3855 // Load the length from the original sliced string if that is the case. | 3855 // Load the length from the original sliced string if that is the case. |
3856 __ mov(esi, FieldOperand(esi, String::kLengthOffset)); | 3856 __ mov(esi, FieldOperand(esi, String::kLengthOffset)); |
3857 __ add(esi, edi); // Calculate input end wrt offset. | 3857 __ add(esi, edi); // Calculate input end wrt offset. |
3858 __ SmiUntag(edi); | 3858 __ SmiUntag(edi); |
3859 __ add(ebx, edi); // Calculate input start wrt offset. | 3859 __ add(ebx, edi); // Calculate input start wrt offset. |
3860 | 3860 |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4468 // are symbols they aren't equal. Register eax already holds a | 4468 // are symbols they aren't equal. Register eax already holds a |
4469 // non-zero value, which indicates not equal, so just return. | 4469 // non-zero value, which indicates not equal, so just return. |
4470 __ ret(0); | 4470 __ ret(0); |
4471 } | 4471 } |
4472 | 4472 |
4473 __ bind(&check_for_strings); | 4473 __ bind(&check_for_strings); |
4474 | 4474 |
4475 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, | 4475 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, |
4476 &check_unequal_objects); | 4476 &check_unequal_objects); |
4477 | 4477 |
4478 // Inline comparison of ascii strings. | 4478 // Inline comparison of ASCII strings. |
4479 if (cc_ == equal) { | 4479 if (cc_ == equal) { |
4480 StringCompareStub::GenerateFlatAsciiStringEquals(masm, | 4480 StringCompareStub::GenerateFlatAsciiStringEquals(masm, |
4481 edx, | 4481 edx, |
4482 eax, | 4482 eax, |
4483 ecx, | 4483 ecx, |
4484 ebx); | 4484 ebx); |
4485 } else { | 4485 } else { |
4486 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, | 4486 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, |
4487 edx, | 4487 edx, |
4488 eax, | 4488 eax, |
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5421 __ test(code_, | 5421 __ test(code_, |
5422 Immediate(kSmiTagMask | | 5422 Immediate(kSmiTagMask | |
5423 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); | 5423 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); |
5424 __ j(not_zero, &slow_case_); | 5424 __ j(not_zero, &slow_case_); |
5425 | 5425 |
5426 Factory* factory = masm->isolate()->factory(); | 5426 Factory* factory = masm->isolate()->factory(); |
5427 __ Set(result_, Immediate(factory->single_character_string_cache())); | 5427 __ Set(result_, Immediate(factory->single_character_string_cache())); |
5428 STATIC_ASSERT(kSmiTag == 0); | 5428 STATIC_ASSERT(kSmiTag == 0); |
5429 STATIC_ASSERT(kSmiTagSize == 1); | 5429 STATIC_ASSERT(kSmiTagSize == 1); |
5430 STATIC_ASSERT(kSmiShiftSize == 0); | 5430 STATIC_ASSERT(kSmiShiftSize == 0); |
5431 // At this point code register contains smi tagged ascii char code. | 5431 // At this point code register contains smi tagged ASCII char code. |
5432 __ mov(result_, FieldOperand(result_, | 5432 __ mov(result_, FieldOperand(result_, |
5433 code_, times_half_pointer_size, | 5433 code_, times_half_pointer_size, |
5434 FixedArray::kHeaderSize)); | 5434 FixedArray::kHeaderSize)); |
5435 __ cmp(result_, factory->undefined_value()); | 5435 __ cmp(result_, factory->undefined_value()); |
5436 __ j(equal, &slow_case_); | 5436 __ j(equal, &slow_case_); |
5437 __ bind(&exit_); | 5437 __ bind(&exit_); |
5438 } | 5438 } |
5439 | 5439 |
5440 | 5440 |
5441 void StringCharFromCodeGenerator::GenerateSlow( | 5441 void StringCharFromCodeGenerator::GenerateSlow( |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5541 __ bind(&both_not_zero_length); | 5541 __ bind(&both_not_zero_length); |
5542 __ add(ebx, ecx); | 5542 __ add(ebx, ecx); |
5543 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength); | 5543 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength); |
5544 // Handle exceptionally long strings in the runtime system. | 5544 // Handle exceptionally long strings in the runtime system. |
5545 __ j(overflow, &call_runtime); | 5545 __ j(overflow, &call_runtime); |
5546 // Use the symbol table when adding two one character strings, as it | 5546 // Use the symbol table when adding two one character strings, as it |
5547 // helps later optimizations to return a symbol here. | 5547 // helps later optimizations to return a symbol here. |
5548 __ cmp(ebx, Immediate(Smi::FromInt(2))); | 5548 __ cmp(ebx, Immediate(Smi::FromInt(2))); |
5549 __ j(not_equal, &longer_than_two); | 5549 __ j(not_equal, &longer_than_two); |
5550 | 5550 |
5551 // Check that both strings are non-external ascii strings. | 5551 // Check that both strings are non-external ASCII strings. |
5552 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime); | 5552 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime); |
5553 | 5553 |
5554 // Get the two characters forming the new string. | 5554 // Get the two characters forming the new string. |
5555 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); | 5555 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); |
5556 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); | 5556 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); |
5557 | 5557 |
5558 // Try to lookup two character string in symbol table. If it is not found | 5558 // Try to lookup two character string in symbol table. If it is not found |
5559 // just allocate a new one. | 5559 // just allocate a new one. |
5560 Label make_two_character_string, make_two_character_string_no_reload; | 5560 Label make_two_character_string, make_two_character_string_no_reload; |
5561 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 5561 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
(...skipping 20 matching lines...) Expand all Loading... |
5582 __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx); | 5582 __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx); |
5583 __ IncrementCounter(counters->string_add_native(), 1); | 5583 __ IncrementCounter(counters->string_add_native(), 1); |
5584 __ ret(2 * kPointerSize); | 5584 __ ret(2 * kPointerSize); |
5585 | 5585 |
5586 __ bind(&longer_than_two); | 5586 __ bind(&longer_than_two); |
5587 // Check if resulting string will be flat. | 5587 // Check if resulting string will be flat. |
5588 __ cmp(ebx, Immediate(Smi::FromInt(String::kMinNonFlatLength))); | 5588 __ cmp(ebx, Immediate(Smi::FromInt(String::kMinNonFlatLength))); |
5589 __ j(below, &string_add_flat_result); | 5589 __ j(below, &string_add_flat_result); |
5590 | 5590 |
5591 // If result is not supposed to be flat allocate a cons string object. If both | 5591 // If result is not supposed to be flat allocate a cons string object. If both |
5592 // strings are ascii the result is an ascii cons string. | 5592 // strings are ASCII the result is an ASCII cons string. |
5593 Label non_ascii, allocated, ascii_data; | 5593 Label non_ascii, allocated, ascii_data; |
5594 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); | 5594 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); |
5595 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); | 5595 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); |
5596 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 5596 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
5597 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); | 5597 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); |
5598 __ and_(ecx, edi); | 5598 __ and_(ecx, edi); |
5599 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); | 5599 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
5600 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | 5600 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
5601 __ test(ecx, Immediate(kStringEncodingMask)); | 5601 __ test(ecx, Immediate(kStringEncodingMask)); |
5602 __ j(zero, &non_ascii); | 5602 __ j(zero, &non_ascii); |
5603 __ bind(&ascii_data); | 5603 __ bind(&ascii_data); |
5604 // Allocate an acsii cons string. | 5604 // Allocate an ASCII cons string. |
5605 __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime); | 5605 __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime); |
5606 __ bind(&allocated); | 5606 __ bind(&allocated); |
5607 // Fill the fields of the cons string. | 5607 // Fill the fields of the cons string. |
5608 if (FLAG_debug_code) __ AbortIfNotSmi(ebx); | 5608 if (FLAG_debug_code) __ AbortIfNotSmi(ebx); |
5609 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); | 5609 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); |
5610 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), | 5610 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), |
5611 Immediate(String::kEmptyHashField)); | 5611 Immediate(String::kEmptyHashField)); |
5612 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); | 5612 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); |
5613 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); | 5613 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); |
5614 __ mov(eax, ecx); | 5614 __ mov(eax, ecx); |
5615 __ IncrementCounter(counters->string_add_native(), 1); | 5615 __ IncrementCounter(counters->string_add_native(), 1); |
5616 __ ret(2 * kPointerSize); | 5616 __ ret(2 * kPointerSize); |
5617 __ bind(&non_ascii); | 5617 __ bind(&non_ascii); |
5618 // At least one of the strings is two-byte. Check whether it happens | 5618 // At least one of the strings is two-byte. Check whether it happens |
5619 // to contain only ascii characters. | 5619 // to contain only ASCII characters. |
5620 // ecx: first instance type AND second instance type. | 5620 // ecx: first instance type AND second instance type. |
5621 // edi: second instance type. | 5621 // edi: second instance type. |
5622 __ test(ecx, Immediate(kAsciiDataHintMask)); | 5622 __ test(ecx, Immediate(kAsciiDataHintMask)); |
5623 __ j(not_zero, &ascii_data); | 5623 __ j(not_zero, &ascii_data); |
5624 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 5624 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
5625 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 5625 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
5626 __ xor_(edi, ecx); | 5626 __ xor_(edi, ecx); |
5627 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); | 5627 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); |
5628 __ and_(edi, kAsciiStringTag | kAsciiDataHintTag); | 5628 __ and_(edi, kAsciiStringTag | kAsciiDataHintTag); |
5629 __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag); | 5629 __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5684 __ push(edx); | 5684 __ push(edx); |
5685 __ push(eax); | 5685 __ push(eax); |
5686 | 5686 |
5687 Label non_ascii_string_add_flat_result, call_runtime_drop_two; | 5687 Label non_ascii_string_add_flat_result, call_runtime_drop_two; |
5688 // edi: instance type of second string | 5688 // edi: instance type of second string |
5689 // First string and second string have the same encoding. | 5689 // First string and second string have the same encoding. |
5690 STATIC_ASSERT(kTwoByteStringTag == 0); | 5690 STATIC_ASSERT(kTwoByteStringTag == 0); |
5691 __ test_b(edi, kStringEncodingMask); | 5691 __ test_b(edi, kStringEncodingMask); |
5692 __ j(zero, &non_ascii_string_add_flat_result); | 5692 __ j(zero, &non_ascii_string_add_flat_result); |
5693 | 5693 |
5694 // Both strings are ascii strings. | 5694 // Both strings are ASCII strings. |
5695 // ebx: length of resulting flat string as a smi | 5695 // ebx: length of resulting flat string as a smi |
5696 __ SmiUntag(ebx); | 5696 __ SmiUntag(ebx); |
5697 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two); | 5697 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two); |
5698 // eax: result string | 5698 // eax: result string |
5699 __ mov(ecx, eax); | 5699 __ mov(ecx, eax); |
5700 // Locate first character of result. | 5700 // Locate first character of result. |
5701 __ add(ecx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5701 __ add(ecx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
5702 // Load first argument's length and first character location. Account for | 5702 // Load first argument's length and first character location. Account for |
5703 // values currently on the stack when fetching arguments from it. | 5703 // values currently on the stack when fetching arguments from it. |
5704 __ mov(edx, Operand(esp, 4 * kPointerSize)); | 5704 __ mov(edx, Operand(esp, 4 * kPointerSize)); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5994 // If length is not 2 the string is not a candidate. | 5994 // If length is not 2 the string is not a candidate. |
5995 __ cmp(FieldOperand(candidate, String::kLengthOffset), | 5995 __ cmp(FieldOperand(candidate, String::kLengthOffset), |
5996 Immediate(Smi::FromInt(2))); | 5996 Immediate(Smi::FromInt(2))); |
5997 __ j(not_equal, &next_probe[i]); | 5997 __ j(not_equal, &next_probe[i]); |
5998 | 5998 |
5999 // As we are out of registers save the mask on the stack and use that | 5999 // As we are out of registers save the mask on the stack and use that |
6000 // register as a temporary. | 6000 // register as a temporary. |
6001 __ push(mask); | 6001 __ push(mask); |
6002 Register temp = mask; | 6002 Register temp = mask; |
6003 | 6003 |
6004 // Check that the candidate is a non-external ascii string. | 6004 // Check that the candidate is a non-external ASCII string. |
6005 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); | 6005 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); |
6006 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 6006 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
6007 __ JumpIfInstanceTypeIsNotSequentialAscii( | 6007 __ JumpIfInstanceTypeIsNotSequentialAscii( |
6008 temp, temp, &next_probe_pop_mask[i]); | 6008 temp, temp, &next_probe_pop_mask[i]); |
6009 | 6009 |
6010 // Check if the two characters match. | 6010 // Check if the two characters match. |
6011 __ mov(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize)); | 6011 __ mov(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize)); |
6012 __ and_(temp, 0x0000ffff); | 6012 __ and_(temp, 0x0000ffff); |
6013 __ cmp(chars, temp); | 6013 __ cmp(chars, temp); |
6014 __ j(equal, &found_in_symbol_table); | 6014 __ j(equal, &found_in_symbol_table); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6273 | 6273 |
6274 __ bind(&sequential_string); | 6274 __ bind(&sequential_string); |
6275 // Stash away (adjusted) index and (underlying) string. | 6275 // Stash away (adjusted) index and (underlying) string. |
6276 __ push(edx); | 6276 __ push(edx); |
6277 __ push(edi); | 6277 __ push(edi); |
6278 __ SmiUntag(ecx); | 6278 __ SmiUntag(ecx); |
6279 STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0); | 6279 STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0); |
6280 __ test_b(ebx, kStringEncodingMask); | 6280 __ test_b(ebx, kStringEncodingMask); |
6281 __ j(zero, &two_byte_sequential); | 6281 __ j(zero, &two_byte_sequential); |
6282 | 6282 |
6283 // Sequential ascii string. Allocate the result. | 6283 // Sequential ASCII string. Allocate the result. |
6284 __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two); | 6284 __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two); |
6285 | 6285 |
6286 // eax: result string | 6286 // eax: result string |
6287 // ecx: result string length | 6287 // ecx: result string length |
6288 __ mov(edx, esi); // esi used by following code. | 6288 __ mov(edx, esi); // esi used by following code. |
6289 // Locate first character of result. | 6289 // Locate first character of result. |
6290 __ mov(edi, eax); | 6290 __ mov(edi, eax); |
6291 __ add(edi, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6291 __ add(edi, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
6292 // Load string argument and locate character of sub string start. | 6292 // Load string argument and locate character of sub string start. |
6293 __ pop(esi); | 6293 __ pop(esi); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6486 __ cmp(edx, eax); | 6486 __ cmp(edx, eax); |
6487 __ j(not_equal, ¬_same, Label::kNear); | 6487 __ j(not_equal, ¬_same, Label::kNear); |
6488 STATIC_ASSERT(EQUAL == 0); | 6488 STATIC_ASSERT(EQUAL == 0); |
6489 STATIC_ASSERT(kSmiTag == 0); | 6489 STATIC_ASSERT(kSmiTag == 0); |
6490 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 6490 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
6491 __ IncrementCounter(masm->isolate()->counters()->string_compare_native(), 1); | 6491 __ IncrementCounter(masm->isolate()->counters()->string_compare_native(), 1); |
6492 __ ret(2 * kPointerSize); | 6492 __ ret(2 * kPointerSize); |
6493 | 6493 |
6494 __ bind(¬_same); | 6494 __ bind(¬_same); |
6495 | 6495 |
6496 // Check that both objects are sequential ascii strings. | 6496 // Check that both objects are sequential ASCII strings. |
6497 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); | 6497 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); |
6498 | 6498 |
6499 // Compare flat ascii strings. | 6499 // Compare flat ASCII strings. |
6500 // Drop arguments from the stack. | 6500 // Drop arguments from the stack. |
6501 __ pop(ecx); | 6501 __ pop(ecx); |
6502 __ add(esp, Immediate(2 * kPointerSize)); | 6502 __ add(esp, Immediate(2 * kPointerSize)); |
6503 __ push(ecx); | 6503 __ push(ecx); |
6504 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 6504 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); |
6505 | 6505 |
6506 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 6506 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
6507 // tagged as a small integer. | 6507 // tagged as a small integer. |
6508 __ bind(&runtime); | 6508 __ bind(&runtime); |
6509 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 6509 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7345 false); | 7345 false); |
7346 __ pop(edx); | 7346 __ pop(edx); |
7347 __ ret(0); | 7347 __ ret(0); |
7348 } | 7348 } |
7349 | 7349 |
7350 #undef __ | 7350 #undef __ |
7351 | 7351 |
7352 } } // namespace v8::internal | 7352 } } // namespace v8::internal |
7353 | 7353 |
7354 #endif // V8_TARGET_ARCH_IA32 | 7354 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |