Chromium Code Reviews| Index: src/ia32/codegen-ia32.cc |
| =================================================================== |
| --- src/ia32/codegen-ia32.cc (revision 4803) |
| +++ src/ia32/codegen-ia32.cc (working copy) |
| @@ -11303,58 +11303,58 @@ |
| // ecx: RegExp data (FixedArray) |
| // Check the representation and encoding of the subject string. |
| - Label seq_string, seq_two_byte_string, check_code; |
| - const int kStringRepresentationEncodingMask = |
| - kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| + Label seq_ascii_string, seq_two_byte_string, check_code; |
| __ mov(eax, Operand(esp, kSubjectOffset)); |
| __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| - __ and_(ebx, kStringRepresentationEncodingMask); |
| - // First check for sequential string. |
| - ASSERT_EQ(0, kStringTag); |
| - ASSERT_EQ(0, kSeqStringTag); |
| + // First check for flat two byte string. |
|
Lasse Reichstein
2010/06/07 09:29:06
"two-byte"?
William Hesse
2010/06/07 12:17:28
Done.
|
| + __ and_(ebx, |
|
Lasse Reichstein
2010/06/07 09:29:06
Would andb be enough? (Although I don't think it m
William Hesse
2010/06/07 12:17:28
All of these changed to test_b.
On 2010/06/07 09:
|
| + kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); |
| + ASSERT_EQ(0, kStringTag | kSeqStringTag | kTwoByteStringTag); |
| + __ j(zero, &seq_two_byte_string); |
| + // Any other flat string must be a flat ascii string. |
| __ test(Operand(ebx), |
| Immediate(kIsNotStringMask | kStringRepresentationMask)); |
| - __ j(zero, &seq_string); |
| + __ j(zero, &seq_ascii_string); |
| // Check for flat cons string. |
| // A flat cons string is a cons string where the second part is the empty |
| // string. In that case the subject string is just the first part of the cons |
| // string. Also in this case the first part of the cons string is known to be |
| // a sequential string or an external string. |
| - __ and_(ebx, kStringRepresentationMask); |
| - __ cmp(ebx, kConsStringTag); |
| - __ j(not_equal, &runtime); |
| + ASSERT(kExternalStringTag !=0); |
| + ASSERT_EQ(0, kConsStringTag & kExternalStringTag); |
| + __ test(Operand(ebx), |
| + Immediate(kIsNotStringMask | kExternalStringTag)); |
| + __ j(not_zero, &runtime); |
| + // String is a cons string. |
| __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); |
| __ cmp(Operand(edx), Factory::empty_string()); |
|
Lasse Reichstein
2010/06/07 09:29:06
Can you do a direct compare to memory? I.e.,
cmp(
William Hesse
2010/06/07 12:17:28
Done.
|
| __ j(not_equal, &runtime); |
| __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
| __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| - __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| - ASSERT_EQ(0, kSeqStringTag); |
| - __ test(ebx, Immediate(kStringRepresentationMask)); |
| + // String is a cons string with empty second part. |
| + // eax: first part of cons string. |
| + // ebx: map of first part of cons string. |
| + // Is first part a flat two byte string? |
| + __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), |
| + kStringRepresentationMask | kStringEncodingMask); |
| + ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag); |
| + __ j(zero, &seq_two_byte_string); |
| + // Any other flat string must be ascii. |
| + __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), |
| + kStringRepresentationMask); |
| __ j(not_zero, &runtime); |
| - __ and_(ebx, kStringRepresentationEncodingMask); |
| - __ bind(&seq_string); |
| - // eax: subject string (sequential either ascii to two byte) |
| - // ebx: suject string type & kStringRepresentationEncodingMask |
| + __ bind(&seq_ascii_string); |
| + // eax: subject string (flat ascii) |
| // ecx: RegExp data (FixedArray) |
| - // Check that the irregexp code has been generated for an ascii string. If |
| - // it has, the field contains a code object otherwise it contains the hole. |
| - const int kSeqTwoByteString = kStringTag | kSeqStringTag | kTwoByteStringTag; |
| - __ cmp(ebx, kSeqTwoByteString); |
| - __ j(equal, &seq_two_byte_string); |
| - if (FLAG_debug_code) { |
| - __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag); |
| - __ Check(equal, "Expected sequential ascii string"); |
| - } |
| __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
| __ Set(edi, Immediate(1)); // Type is ascii. |
| __ jmp(&check_code); |
| __ bind(&seq_two_byte_string); |
| - // eax: subject string |
| + // eax: subject string (flat two byte) |
| // ecx: RegExp data (FixedArray) |
| __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); |
| __ Set(edi, Immediate(0)); // Type is two byte. |
| @@ -12760,16 +12760,17 @@ |
| // Make sure that both arguments are strings if not known in advance. |
| if (string_check_) { |
| - __ test(eax, Immediate(kSmiTagMask)); |
| + __ mov(ecx, eax); |
| + __ and_(Operand(ecx), edx); |
| + __ test(ecx, Immediate(kSmiTagMask)); |
| __ j(zero, &string_add_runtime); |
| - __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); |
| - __ j(above_equal, &string_add_runtime); |
| - |
| - // First argument is a a string, test second. |
| - __ test(edx, Immediate(kSmiTagMask)); |
| - __ j(zero, &string_add_runtime); |
| - __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); |
| - __ j(above_equal, &string_add_runtime); |
| + __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| + __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| + __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| + __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| + __ or_(Operand(ecx), ebx); |
| + __ test_b(Operand(ecx), kIsNotStringMask); |
| + __ j(not_zero, &string_add_runtime); |
| } |
| // Both arguments are strings. |
| @@ -12800,7 +12801,8 @@ |
| // ecx: length of second string as a smi |
| // edx: second string |
| // Look at the length of the result of adding the two strings. |
| - Label string_add_flat_result, longer_than_two; |
| + Label make_two_character_string, longer_than_two, |
| + make_flat_string, make_flat_ascii_string, make_flat_non_ascii_string; |
| __ bind(&both_not_zero_length); |
| __ add(ebx, Operand(ecx)); |
| ASSERT(Smi::kMaxValue == String::kMaxLength); |
| @@ -12821,7 +12823,6 @@ |
| // Try to lookup two character string in symbol table. If it is not found |
| // just allocate a new one. |
| - Label make_two_character_string, make_flat_ascii_string; |
| StringHelper::GenerateTwoCharacterSymbolTableProbe( |
| masm, ebx, ecx, eax, edx, edi, &make_two_character_string); |
| __ IncrementCounter(&Counters::string_add_native, 1); |
| @@ -12834,7 +12835,7 @@ |
| __ bind(&longer_than_two); |
| // Check if resulting string will be flat. |
| __ cmp(Operand(ebx), Immediate(Smi::FromInt(String::kMinNonFlatLength))); |
| - __ j(below, &string_add_flat_result); |
| + __ j(below, &make_flat_string); |
| // If result is not supposed to be flat allocate a cons string object. If both |
| // strings are ascii the result is an ascii cons string. |
| @@ -12865,37 +12866,36 @@ |
| __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); |
| __ jmp(&allocated); |
| - // Handle creating a flat result. First check that both strings are not |
| - // external strings. |
| + // Handle creating a flat result. Branch to runtime if either string |
| + // is external or if they are not both ascii or both two-byte. |
| + // Otherwise branch to ascii case or two-byte case. |
| // eax: first string |
| // ebx: length of resulting flat string as a smi |
| // edx: second string |
| - __ bind(&string_add_flat_result); |
| + __ bind(&make_flat_string); |
| __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| - __ and_(ecx, kStringRepresentationMask); |
| - __ cmp(ecx, kExternalStringTag); |
| - __ j(equal, &string_add_runtime); |
| + __ movzx_b(edi, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| - __ and_(ecx, kStringRepresentationMask); |
| - __ cmp(ecx, kExternalStringTag); |
| - __ j(equal, &string_add_runtime); |
| - // Now check if both strings are ascii strings. |
| - // eax: first string |
| - // ebx: length of resulting flat string as a smi |
| - // edx: second string |
| - Label non_ascii_string_add_flat_result; |
| - ASSERT(kStringEncodingMask == kAsciiStringTag); |
| - __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
| - __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); |
| - __ j(zero, &non_ascii_string_add_flat_result); |
| + __ or_(ecx, Operand(edi)); |
| + ASSERT(kExternalStringTag !=0); |
| + ASSERT((kConsStringTag & kExternalStringTag) == 0); |
| + ASSERT((kSeqStringTag & kExternalStringTag) == 0); |
| + ASSERT(kTwoByteStringTag == 0); |
| + __ test_b(Operand(ecx), kExternalStringTag | kStringEncodingMask); |
| + __ j(zero, &make_flat_non_ascii_string); // Neither is ascii or external. |
| + __ test_b(Operand(ecx), kExternalStringTag); |
| + __ j(not_zero, &string_add_runtime); // One or both is external. |
| + // At this point, neither is external, and at least one is ascii. |
| + __ test(edi, Immediate(kStringEncodingMask)); |
|
Lasse Reichstein
2010/06/07 09:29:06
Could you do an xor (or just an and) here to check
William Hesse
2010/06/07 12:17:28
We can do a test with the other one and the mask,
|
| + __ j(zero, &string_add_runtime); // First string is two-byte, second ascii. |
| __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| - __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); |
| - __ j(zero, &string_add_runtime); |
| + __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask); |
| + __ j(zero, &string_add_runtime); // First string is ascii, second two-byte. |
| __ bind(&make_flat_ascii_string); |
| - // Both strings are ascii strings. As they are short they are both flat. |
| + // Both strings are ascii strings. As they are short they are both flat. |
| + // Create a flat ascii result. |
| // ebx: length of resulting flat string as a smi |
| __ SmiUntag(ebx); |
| __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); |
| @@ -12926,14 +12926,10 @@ |
| __ IncrementCounter(&Counters::string_add_native, 1); |
| __ ret(2 * kPointerSize); |
| - // Handle creating a flat two byte result. |
| - // eax: first string - known to be two byte |
| + // Both strings are two-byte strings. As they are short they are both flat. |
| + // Create a flat two byte result. |
| // ebx: length of resulting flat string as a smi |
| - // edx: second string |
| - __ bind(&non_ascii_string_add_flat_result); |
| - __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| - __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); |
| - __ j(not_zero, &string_add_runtime); |
| + __ bind(&make_flat_non_ascii_string); |
| // Both strings are two byte strings. As they are short they are both |
| // flat. |
| __ SmiUntag(ebx); |