Improve generated code for string encoding tests on ia32.

Review URL: http://codereview.chromium.org/2673001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4812 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2010-06-07 12:15:10 +00:00
parent 68b8a50843
commit dd278e634e

View File

@ -11316,58 +11316,57 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// 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);
__ test(Operand(ebx),
Immediate(kIsNotStringMask | kStringRepresentationMask));
__ j(zero, &seq_string);
// First check for flat two-byte string.
__ test_b(Operand(ebx),
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_b(Operand(ebx), kIsNotStringMask | kStringRepresentationMask);
__ j(zero, &seq_ascii_string);
// Check for flat cons string.
// If this is a string, and not an external string, it is a 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);
__ mov(edx, FieldOperand(eax, ConsString::kSecondOffset));
__ cmp(Operand(edx), Factory::empty_string());
ASSERT(kExternalStringTag !=0);
ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
__ test_b(Operand(ebx), kIsNotStringMask | kExternalStringTag);
__ j(not_zero, &runtime);
// String is a cons string.
__ cmp(FieldOperand(eax, ConsString::kSecondOffset),
Factory::empty_string());
__ 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.
@ -12773,16 +12772,17 @@ void StringAddStub::Generate(MacroAssembler* masm) {
// 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.
@ -12813,7 +12813,8 @@ void StringAddStub::Generate(MacroAssembler* masm) {
// 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);
@ -12834,7 +12835,6 @@ void StringAddStub::Generate(MacroAssembler* masm) {
// 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);
@ -12847,7 +12847,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ 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.
@ -12878,37 +12878,38 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ 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_EQ(0, kConsStringTag & kExternalStringTag);
ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
ASSERT_EQ(0, kTwoByteStringTag);
__ 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.
// Check that both are ascii, by computing mask & first type & second type.
__ and_(edi, kStringEncodingMask);
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
__ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
__ test_b(edi, FieldOperand(ecx, Map::kInstanceTypeOffset));
ASSERT(kAsciiStringTag != 0);
__ j(zero, &string_add_runtime);
__ 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);
@ -12939,14 +12940,10 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ 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);