Index: src/ia32/codegen-ia32.cc |
=================================================================== |
--- src/ia32/codegen-ia32.cc (revision 3670) |
+++ src/ia32/codegen-ia32.cc (working copy) |
@@ -8107,10 +8107,24 @@ |
// esp[12]: subject string |
// esp[16]: JSRegExp object |
- Label runtime; |
+ static const int kLastMatchInfoOffset = 1 * kPointerSize; |
+ static const int kPreviousIndexOffset = 2 * kPointerSize; |
+ static const int kSubjectOffset = 3 * kPointerSize; |
+ static const int kJSRegExpOffset = 4 * kPointerSize; |
+ Label runtime, invoke_regexp; |
+ |
+ // Ensure that a RegExp stack is allocated. |
+ ExternalReference address_of_regexp_stack_memory_address = |
+ ExternalReference::address_of_regexp_stack_memory_address(); |
+ ExternalReference address_of_regexp_stack_memory_size = |
+ ExternalReference::address_of_regexp_stack_memory_size(); |
+ __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
+ __ test(ebx, Operand(ebx)); |
+ __ j(zero, &runtime, not_taken); |
+ |
// Check that the first argument is a JSRegExp object. |
- __ mov(eax, Operand(esp, 4 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kJSRegExpOffset)); |
ASSERT_EQ(0, kSmiTag); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, &runtime); |
@@ -8146,7 +8160,7 @@ |
// ecx: RegExp data (FixedArray) |
// edx: Number of capture registers |
// Check that the second argument is a string. |
- __ mov(eax, Operand(esp, 3 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kSubjectOffset)); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, &runtime); |
Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); |
@@ -8158,7 +8172,7 @@ |
// ecx: RegExp data (FixedArray) |
// edx: Number of capture registers |
// Check that the third argument is a positive smi. |
- __ mov(eax, Operand(esp, 2 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kPreviousIndexOffset)); |
__ test(eax, Immediate(kSmiTagMask | 0x80000000)); |
__ j(not_zero, &runtime); |
// Check that it is not greater than the subject string length. |
@@ -8169,7 +8183,7 @@ |
// ecx: RegExp data (FixedArray) |
// edx: Number of capture registers |
// Check that the fourth object is a JSArray object. |
- __ mov(eax, Operand(esp, 1 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
__ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, &runtime); |
__ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
@@ -8187,38 +8201,74 @@ |
__ j(greater, &runtime); |
// ecx: RegExp data (FixedArray) |
- // Check the representation and encoding of the subject string (only support |
- // flat ascii strings). |
- __ mov(eax, Operand(esp, 3 * kPointerSize)); |
+ // Check the representation and encoding of the subject string. |
+ Label seq_string, seq_two_byte_string, check_code; |
+ const int kStringRepresentationEncodingMask = |
+ kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
+ __ mov(eax, Operand(esp, kSubjectOffset)); |
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
- __ and_(ebx, kStringRepresentationMask | kStringEncodingMask); |
- __ cmp(ebx, kSeqStringTag | kAsciiStringTag); |
+ __ 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); |
+ |
+ // 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. |
+ __ mov(edx, ebx); |
+ __ and_(edx, kStringRepresentationMask); |
+ __ cmp(edx, kConsStringTag); |
__ j(not_equal, &runtime); |
+ __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); |
+ __ cmp(Operand(edx), Immediate(Handle<String>(Heap::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)); |
+ __ and_(ebx, kStringRepresentationEncodingMask); |
+ __ bind(&seq_string); |
+ // eax: subject string (sequential either ascii to two byte) |
+ // ebx: suject string type & kStringRepresentationEncodingMask |
// ecx: RegExp data (FixedArray) |
- // Ensure that a RegExp stack is allocated. |
- ExternalReference address_of_regexp_stack_memory_address = |
- ExternalReference::address_of_regexp_stack_memory_address(); |
- ExternalReference address_of_regexp_stack_memory_size = |
- ExternalReference::address_of_regexp_stack_memory_size(); |
- __ mov(eax, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
- __ test(eax, Operand(eax)); |
- __ j(zero, &runtime, not_taken); |
+ // 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. |
+ __ cmp(ebx, kStringTag | kSeqStringTag | kTwoByteStringTag); |
+ __ j(equal, &seq_two_byte_string); |
+#ifdef DEBUG |
+ __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag); |
+ __ Check(equal, "Expected sequential ascii string"); |
+#endif |
+ __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
+ __ Set(edi, Immediate(1)); // Type is ascii. |
+ __ jmp(&check_code); |
+ __ bind(&seq_two_byte_string); |
+ // eax: subject string |
// 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. |
- __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
+ __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); |
+ __ Set(edi, Immediate(0)); // Type is two byte. |
+ |
+ __ bind(&check_code); |
+ // Check that the irregexp code has been generated for If it has, the field |
+ // contains a code object otherwise it contains the hole. |
__ CmpObjectType(edx, CODE_TYPE, ebx); |
__ j(not_equal, &runtime); |
+ // eax: subject string |
+ // edx: code |
+ // edi: encoding of subject string (1 if ascii 0 if two_byte); |
// Load used arguments before starting to push arguments for call to native |
// RegExp code to avoid handling changing stack height. |
- __ mov(eax, Operand(esp, 3 * kPointerSize)); // Subject string. |
- __ mov(ebx, Operand(esp, 2 * kPointerSize)); // Previous index. |
- __ mov(ecx, Operand(esp, 4 * kPointerSize)); // JSRegExp object. |
- __ SmiUntag(ebx); // Previous index from sim. |
+ __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
+ __ mov(ecx, Operand(esp, kJSRegExpOffset)); |
+ __ SmiUntag(ebx); // Previous index from smi. |
// eax: subject string |
// ebx: previous index |
@@ -8243,20 +8293,29 @@ |
// Argument 5: static offsets vector buffer. |
__ push(Immediate(ExternalReference::address_of_static_offsets_vector())); |
- // Argument 4: End of string data. |
- __ mov(ecx, FieldOperand(eax, String::kLengthOffset)); |
- __ add(ecx, Operand(eax)); |
- __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
- __ push(ecx); |
+ // Argument 4: End of string data |
+ // Argument 3: Start of string data |
+ Label push_two_byte, push_rest; |
+ __ test(edi, Operand(edi)); |
+ __ mov(edi, FieldOperand(eax, String::kLengthOffset)); |
+ __ j(zero, &push_two_byte); |
+ __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); |
+ __ push(ecx); // Argument 4. |
+ __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); |
+ __ push(ecx); // Argument 3. |
+ __ jmp(&push_rest); |
- // Argument 3: Start of string data. |
- __ mov(ecx, ebx); |
- __ add(ebx, Operand(eax)); // String is ASCII. |
- __ add(Operand(ebx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
- __ push(ebx); |
+ __ bind(&push_two_byte); |
+ ASSERT(kShortSize == 2); |
+ __ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize)); |
+ __ push(ecx); // Argument 4. |
+ __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); |
+ __ push(ecx); // Argument 3. |
+ __ bind(&push_rest); |
+ |
// Argument 2: Previous index. |
- __ push(ecx); |
+ __ push(ebx); |
// Argument 1: Subject string. |
__ push(eax); |
@@ -8292,7 +8351,7 @@ |
// Load RegExp data. |
__ bind(&success); |
- __ mov(eax, Operand(esp, 4 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kJSRegExpOffset)); |
__ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
__ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
// Calculate number of capture registers (number_of_captures + 1) * 2. |
@@ -8300,7 +8359,7 @@ |
// edx: Number of capture registers |
// Load last_match_info which is still known to be a fast case JSArray. |
- __ mov(eax, Operand(esp, 1 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
__ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); |
// ebx: last_match_info backing store (FixedArray) |
@@ -8310,11 +8369,11 @@ |
__ mov(FieldOperand(ebx, RegExpImpl::kLastCaptureCountOffset), edx); |
__ SmiUntag(edx); // Number of capture registers back from smi. |
// Store last subject and last input. |
- __ mov(eax, Operand(esp, 3 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kSubjectOffset)); |
__ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax); |
__ mov(ecx, ebx); |
__ RecordWrite(ecx, RegExpImpl::kLastSubjectOffset, eax, edi); |
- __ mov(eax, Operand(esp, 3 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kSubjectOffset)); |
__ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax); |
__ mov(ecx, ebx); |
__ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi); |
@@ -8328,7 +8387,7 @@ |
// ecx: offsets vector |
// edx: number of capture registers |
Label next_capture, done; |
- __ mov(eax, Operand(esp, 2 * kPointerSize)); // Read previous index. |
+ __ mov(eax, Operand(esp, kPreviousIndexOffset)); |
// Capture register counter starts from number of capture registers and |
// counts down until wraping after zero. |
__ bind(&next_capture); |
@@ -8355,7 +8414,7 @@ |
__ bind(&done); |
// Return last match info. |
- __ mov(eax, Operand(esp, 1 * kPointerSize)); |
+ __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
__ ret(4 * kPointerSize); |
// Do the runtime call to execute the regexp. |