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