Revision: 4812
Author: [email protected]
Date: Mon Jun  7 05:15:10 2010
Log: Improve generated code for string encoding tests on ia32.
Review URL: http://codereview.chromium.org/2673001
http://code.google.com/p/v8/source/detail?r=4812

Modified:
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc

=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Jun 7 01:27:32 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Jun 7 05:15:10 2010
@@ -11316,58 +11316,57 @@

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

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

   // 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 @@
   __ 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 @@
   __ 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 @@
   __ 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);

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to