| 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 |