| Index: src/mips64/code-stubs-mips64.cc
 | 
| diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc
 | 
| index 645599a03a1d96ae4854eacbe78900e5f1a090c2..1738ef432e9a2d344dd298253295aa45865b3521 100644
 | 
| --- a/src/mips64/code-stubs-mips64.cc
 | 
| +++ b/src/mips64/code-stubs-mips64.cc
 | 
| @@ -1267,183 +1267,10 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
 | 
|  }
 | 
|  
 | 
|  void RegExpExecStub::Generate(MacroAssembler* masm) {
 | 
| -  // Just jump directly to runtime if native RegExp is not selected at compile
 | 
| -  // time or if regexp entry in generated code is turned off runtime switch or
 | 
| -  // at compilation.
 | 
|  #ifdef V8_INTERPRETED_REGEXP
 | 
| -  __ TailCallRuntime(Runtime::kRegExpExec);
 | 
| +  // This case is handled prior to the RegExpExecStub call.
 | 
| +  __ Abort(kUnexpectedRegExpExecCall);
 | 
|  #else  // V8_INTERPRETED_REGEXP
 | 
| -
 | 
| -  // Stack frame on entry.
 | 
| -  //  sp[0]: last_match_info (expected JSArray)
 | 
| -  //  sp[4]: previous index
 | 
| -  //  sp[8]: subject string
 | 
| -  //  sp[12]: JSRegExp object
 | 
| -
 | 
| -  const int kLastMatchInfoOffset = 0 * kPointerSize;
 | 
| -  const int kPreviousIndexOffset = 1 * kPointerSize;
 | 
| -  const int kSubjectOffset = 2 * kPointerSize;
 | 
| -  const int kJSRegExpOffset = 3 * kPointerSize;
 | 
| -
 | 
| -  Label runtime;
 | 
| -  // Allocation of registers for this function. These are in callee save
 | 
| -  // registers and will be preserved by the call to the native RegExp code, as
 | 
| -  // this code is called using the normal C calling convention. When calling
 | 
| -  // directly from generated code the native RegExp code will not do a GC and
 | 
| -  // therefore the content of these registers are safe to use after the call.
 | 
| -  // MIPS - using s0..s2, since we are not using CEntry Stub.
 | 
| -  Register subject = s0;
 | 
| -  Register regexp_data = s1;
 | 
| -  Register last_match_info_elements = s2;
 | 
| -
 | 
| -  // Ensure that a RegExp stack is allocated.
 | 
| -  ExternalReference address_of_regexp_stack_memory_address =
 | 
| -      ExternalReference::address_of_regexp_stack_memory_address(
 | 
| -          isolate());
 | 
| -  ExternalReference address_of_regexp_stack_memory_size =
 | 
| -      ExternalReference::address_of_regexp_stack_memory_size(isolate());
 | 
| -  __ li(a0, Operand(address_of_regexp_stack_memory_size));
 | 
| -  __ ld(a0, MemOperand(a0, 0));
 | 
| -  __ Branch(&runtime, eq, a0, Operand(zero_reg));
 | 
| -
 | 
| -  // Check that the first argument is a JSRegExp object.
 | 
| -  __ ld(a0, MemOperand(sp, kJSRegExpOffset));
 | 
| -  STATIC_ASSERT(kSmiTag == 0);
 | 
| -  __ JumpIfSmi(a0, &runtime);
 | 
| -  __ GetObjectType(a0, a1, a1);
 | 
| -  __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE));
 | 
| -
 | 
| -  // Check that the RegExp has been compiled (data contains a fixed array).
 | 
| -  __ ld(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset));
 | 
| -  if (FLAG_debug_code) {
 | 
| -    __ SmiTst(regexp_data, a4);
 | 
| -    __ Check(nz,
 | 
| -             kUnexpectedTypeForRegExpDataFixedArrayExpected,
 | 
| -             a4,
 | 
| -             Operand(zero_reg));
 | 
| -    __ GetObjectType(regexp_data, a0, a0);
 | 
| -    __ Check(eq,
 | 
| -             kUnexpectedTypeForRegExpDataFixedArrayExpected,
 | 
| -             a0,
 | 
| -             Operand(FIXED_ARRAY_TYPE));
 | 
| -  }
 | 
| -
 | 
| -  // regexp_data: RegExp data (FixedArray)
 | 
| -  // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
 | 
| -  __ ld(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
 | 
| -  __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
 | 
| -
 | 
| -  // regexp_data: RegExp data (FixedArray)
 | 
| -  // Check that the number of captures fit in the static offsets vector buffer.
 | 
| -  __ ld(a2,
 | 
| -         FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
 | 
| -  // Check (number_of_captures + 1) * 2 <= offsets vector size
 | 
| -  // Or          number_of_captures * 2 <= offsets vector size - 2
 | 
| -  // Or          number_of_captures     <= offsets vector size / 2 - 1
 | 
| -  // Multiplying by 2 comes for free since a2 is smi-tagged.
 | 
| -  STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
 | 
| -  int temp = Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1;
 | 
| -  __ Branch(&runtime, hi, a2, Operand(Smi::FromInt(temp)));
 | 
| -
 | 
| -  // Reset offset for possibly sliced string.
 | 
| -  __ mov(t0, zero_reg);
 | 
| -  __ ld(subject, MemOperand(sp, kSubjectOffset));
 | 
| -  __ JumpIfSmi(subject, &runtime);
 | 
| -  __ mov(a3, subject);  // Make a copy of the original subject string.
 | 
| -
 | 
| -  // subject: subject string
 | 
| -  // a3: subject string
 | 
| -  // regexp_data: RegExp data (FixedArray)
 | 
| -  // Handle subject string according to its encoding and representation:
 | 
| -  // (1) Sequential string?  If yes, go to (4).
 | 
| -  // (2) Sequential or cons?  If not, go to (5).
 | 
| -  // (3) Cons string.  If the string is flat, replace subject with first string
 | 
| -  //     and go to (1). Otherwise bail out to runtime.
 | 
| -  // (4) Sequential string.  Load regexp code according to encoding.
 | 
| -  // (E) Carry on.
 | 
| -  /// [...]
 | 
| -
 | 
| -  // Deferred code at the end of the stub:
 | 
| -  // (5) Long external string?  If not, go to (7).
 | 
| -  // (6) External string.  Make it, offset-wise, look like a sequential string.
 | 
| -  //     Go to (4).
 | 
| -  // (7) Short external string or not a string?  If yes, bail out to runtime.
 | 
| -  // (8) Sliced or thin string.  Replace subject with parent.  Go to (1).
 | 
| -
 | 
| -  Label check_underlying;   // (1)
 | 
| -  Label seq_string;         // (4)
 | 
| -  Label not_seq_nor_cons;   // (5)
 | 
| -  Label external_string;    // (6)
 | 
| -  Label not_long_external;  // (7)
 | 
| -
 | 
| -  __ bind(&check_underlying);
 | 
| -  __ ld(a2, FieldMemOperand(subject, HeapObject::kMapOffset));
 | 
| -  __ lbu(a0, FieldMemOperand(a2, Map::kInstanceTypeOffset));
 | 
| -
 | 
| -  // (1) Sequential string?  If yes, go to (4).
 | 
| -  __ And(a1,
 | 
| -         a0,
 | 
| -         Operand(kIsNotStringMask |
 | 
| -                 kStringRepresentationMask |
 | 
| -                 kShortExternalStringMask));
 | 
| -  STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
 | 
| -  __ Branch(&seq_string, eq, a1, Operand(zero_reg));  // Go to (4).
 | 
| -
 | 
| -  // (2) Sequential or cons?  If not, go to (5).
 | 
| -  STATIC_ASSERT(kConsStringTag < kExternalStringTag);
 | 
| -  STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
 | 
| -  STATIC_ASSERT(kThinStringTag > kExternalStringTag);
 | 
| -  STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
 | 
| -  STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
 | 
| -  // Go to (5).
 | 
| -  __ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
 | 
| -
 | 
| -  // (3) Cons string.  Check that it's flat.
 | 
| -  // Replace subject with first string and reload instance type.
 | 
| -  __ ld(a0, FieldMemOperand(subject, ConsString::kSecondOffset));
 | 
| -  __ LoadRoot(a1, Heap::kempty_stringRootIndex);
 | 
| -  __ Branch(&runtime, ne, a0, Operand(a1));
 | 
| -  __ ld(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
 | 
| -  __ jmp(&check_underlying);
 | 
| -
 | 
| -  // (4) Sequential string.  Load regexp code according to encoding.
 | 
| -  __ bind(&seq_string);
 | 
| -  // subject: sequential subject string (or look-alike, external string)
 | 
| -  // a3: original subject string
 | 
| -  // Load previous index and check range before a3 is overwritten.  We have to
 | 
| -  // use a3 instead of subject here because subject might have been only made
 | 
| -  // to look like a sequential string when it actually is an external string.
 | 
| -  __ ld(a1, MemOperand(sp, kPreviousIndexOffset));
 | 
| -  __ JumpIfNotSmi(a1, &runtime);
 | 
| -  __ ld(a3, FieldMemOperand(a3, String::kLengthOffset));
 | 
| -  __ Branch(&runtime, ls, a3, Operand(a1));
 | 
| -  __ SmiUntag(a1);
 | 
| -
 | 
| -  STATIC_ASSERT(kStringEncodingMask == 8);
 | 
| -  STATIC_ASSERT(kOneByteStringTag == 8);
 | 
| -  STATIC_ASSERT(kTwoByteStringTag == 0);
 | 
| -  __ And(a0, a0, Operand(kStringEncodingMask));  // Non-zero for one_byte.
 | 
| -  __ ld(t9, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset));
 | 
| -  __ dsra(a3, a0, 3);  // a3 is 1 for one_byte, 0 for UC16 (used below).
 | 
| -  __ ld(a5, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
 | 
| -  __ Movz(t9, a5, a0);  // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset.
 | 
| -
 | 
| -  // (E) Carry on.  String handling is done.
 | 
| -  // t9: irregexp code
 | 
| -  // Check that the irregexp code has been generated for the actual string
 | 
| -  // encoding. If it has, the field contains a code object otherwise it contains
 | 
| -  // a smi (code flushing support).
 | 
| -  __ JumpIfSmi(t9, &runtime);
 | 
| -
 | 
| -  // a1: previous index
 | 
| -  // a3: encoding of subject string (1 if one_byte, 0 if two_byte);
 | 
| -  // t9: code
 | 
| -  // subject: Subject string
 | 
| -  // regexp_data: RegExp data (FixedArray)
 | 
| -  // All checks done. Now push arguments for native regexp code.
 | 
| -  __ IncrementCounter(isolate()->counters()->regexp_entry_native(),
 | 
| -                      1, a0, a2);
 | 
| -
 | 
|    // Isolates: note we add an additional parameter here (isolate pointer).
 | 
|    const int kRegExpExecuteArguments = 9;
 | 
|    const int kParameterRegisters = 8;
 | 
| @@ -1468,18 +1295,22 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
 | 
|    //   [sp + 0] - saved ra
 | 
|  
 | 
|    // Argument 9: Pass current isolate address.
 | 
| -  __ li(a0, Operand(ExternalReference::isolate_address(isolate())));
 | 
| -  __ sd(a0, MemOperand(sp, 1 * kPointerSize));
 | 
| +  __ li(t1, Operand(ExternalReference::isolate_address(isolate())));
 | 
| +  __ sd(t1, MemOperand(sp, 1 * kPointerSize));
 | 
|  
 | 
|    // Argument 8: Indicate that this is a direct call from JavaScript.
 | 
|    __ li(a7, Operand(1));
 | 
|  
 | 
|    // Argument 7: Start (high end) of backtracking stack memory area.
 | 
| -  __ li(a0, Operand(address_of_regexp_stack_memory_address));
 | 
| -  __ ld(a0, MemOperand(a0, 0));
 | 
| -  __ li(a2, Operand(address_of_regexp_stack_memory_size));
 | 
| -  __ ld(a2, MemOperand(a2, 0));
 | 
| -  __ daddu(a6, a0, a2);
 | 
| +  ExternalReference address_of_regexp_stack_memory_address =
 | 
| +      ExternalReference::address_of_regexp_stack_memory_address(isolate());
 | 
| +  ExternalReference address_of_regexp_stack_memory_size =
 | 
| +      ExternalReference::address_of_regexp_stack_memory_size(isolate());
 | 
| +  __ li(t1, Operand(address_of_regexp_stack_memory_address));
 | 
| +  __ ld(t1, MemOperand(t1, 0));
 | 
| +  __ li(t2, Operand(address_of_regexp_stack_memory_size));
 | 
| +  __ ld(t2, MemOperand(t2, 0));
 | 
| +  __ daddu(a6, t1, t2);
 | 
|  
 | 
|    // Argument 6: Set the number of capture registers to zero to force global
 | 
|    // regexps to behave as non-global. This does not affect non-global regexps.
 | 
| @@ -1490,198 +1321,28 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
 | 
|        a4,
 | 
|        Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
 | 
|  
 | 
| -  // For arguments 4 and 3 get string length, calculate start of string data
 | 
| -  // and calculate the shift of the index (0 for one_byte and 1 for two byte).
 | 
| -  __ Daddu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
 | 
| -  __ Xor(a3, a3, Operand(1));  // 1 for 2-byte str, 0 for 1-byte.
 | 
| -  // Load the length from the original subject string from the previous stack
 | 
| -  // frame. Therefore we have to use fp, which points exactly to two pointer
 | 
| -  // sizes below the previous sp. (Because creating a new stack frame pushes
 | 
| -  // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
 | 
| -  __ ld(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
 | 
| -  // If slice offset is not 0, load the length from the original sliced string.
 | 
|    // Argument 4, a3: End of string data
 | 
|    // Argument 3, a2: Start of string data
 | 
| -  // Prepare start and end index of the input.
 | 
| -  __ dsllv(t1, t0, a3);
 | 
| -  __ daddu(t0, t2, t1);
 | 
| -  __ dsllv(t1, a1, a3);
 | 
| -  __ daddu(a2, t0, t1);
 | 
| +  CHECK(a3.is(RegExpExecDescriptor::StringEndRegister()));
 | 
| +  CHECK(a2.is(RegExpExecDescriptor::StringStartRegister()));
 | 
|  
 | 
| -  __ ld(t2, FieldMemOperand(subject, String::kLengthOffset));
 | 
| -
 | 
| -  __ SmiUntag(t2);
 | 
| -  __ dsllv(t1, t2, a3);
 | 
| -  __ daddu(a3, t0, t1);
 | 
|    // Argument 2 (a1): Previous index.
 | 
| -  // Already there
 | 
| +  CHECK(a1.is(RegExpExecDescriptor::LastIndexRegister()));
 | 
|  
 | 
|    // Argument 1 (a0): Subject string.
 | 
| -  __ mov(a0, subject);
 | 
| +  CHECK(a0.is(RegExpExecDescriptor::StringRegister()));
 | 
|  
 | 
|    // Locate the code entry and call it.
 | 
| -  __ Daddu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
 | 
| +  Register code_reg = RegExpExecDescriptor::CodeRegister();
 | 
| +  __ Daddu(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
 | 
|    DirectCEntryStub stub(isolate());
 | 
| -  stub.GenerateCall(masm, t9);
 | 
| +  stub.GenerateCall(masm, code_reg);
 | 
|  
 | 
|    __ LeaveExitFrame(false, no_reg, true);
 | 
|  
 | 
| -  // v0: result
 | 
| -  // subject: subject string (callee saved)
 | 
| -  // regexp_data: RegExp data (callee saved)
 | 
| -  // last_match_info_elements: Last match info elements (callee saved)
 | 
| -  // Check the result.
 | 
| -  Label success;
 | 
| -  __ Branch(&success, eq, v0, Operand(1));
 | 
| -  // We expect exactly one result since we force the called regexp to behave
 | 
| -  // as non-global.
 | 
| -  Label failure;
 | 
| -  __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE));
 | 
| -  // If not exception it can only be retry. Handle that in the runtime system.
 | 
| -  __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
 | 
| -  // Result must now be exception. If there is no pending exception already a
 | 
| -  // stack overflow (on the backtrack stack) was detected in RegExp code but
 | 
| -  // haven't created the exception yet. Handle that in the runtime system.
 | 
| -  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
 | 
| -  __ li(a1, Operand(isolate()->factory()->the_hole_value()));
 | 
| -  __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
 | 
| -                                      isolate())));
 | 
| -  __ ld(v0, MemOperand(a2, 0));
 | 
| -  __ Branch(&runtime, eq, v0, Operand(a1));
 | 
| -
 | 
| -  // For exception, throw the exception again.
 | 
| -  __ TailCallRuntime(Runtime::kRegExpExecReThrow);
 | 
| -
 | 
| -  __ bind(&failure);
 | 
| -  // For failure and exception return null.
 | 
| -  __ li(v0, Operand(isolate()->factory()->null_value()));
 | 
| -  __ DropAndRet(4);
 | 
| -
 | 
| -  // Process the result from the native regexp code.
 | 
| -  __ bind(&success);
 | 
| -
 | 
| -  __ lw(a1, UntagSmiFieldMemOperand(
 | 
| -      regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
 | 
| -  // Calculate number of capture registers (number_of_captures + 1) * 2.
 | 
| -  __ Daddu(a1, a1, Operand(1));
 | 
| -  __ dsll(a1, a1, 1);  // Multiply by 2.
 | 
| -
 | 
| -  // Check that the last match info is a FixedArray.
 | 
| -  __ ld(last_match_info_elements, MemOperand(sp, kLastMatchInfoOffset));
 | 
| -  __ JumpIfSmi(last_match_info_elements, &runtime);
 | 
| -  // Check that the object has fast elements.
 | 
| -  __ ld(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
 | 
| -  __ LoadRoot(at, Heap::kFixedArrayMapRootIndex);
 | 
| -  __ Branch(&runtime, ne, a0, Operand(at));
 | 
| -  // Check that the last match info has space for the capture registers and the
 | 
| -  // additional information.
 | 
| -  __ ld(a0,
 | 
| -        FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
 | 
| -  __ Daddu(a2, a1, Operand(RegExpMatchInfo::kLastMatchOverhead));
 | 
| -
 | 
| -  __ SmiUntag(at, a0);
 | 
| -  __ Branch(&runtime, gt, a2, Operand(at));
 | 
| -
 | 
| -  // a1: number of capture registers
 | 
| -  // subject: subject string
 | 
| -  // Store the capture count.
 | 
| -  __ SmiTag(a2, a1);  // To smi.
 | 
| -  __ sd(a2, FieldMemOperand(last_match_info_elements,
 | 
| -                            RegExpMatchInfo::kNumberOfCapturesOffset));
 | 
| -  // Store last subject and last input.
 | 
| -  __ sd(subject, FieldMemOperand(last_match_info_elements,
 | 
| -                                 RegExpMatchInfo::kLastSubjectOffset));
 | 
| -  __ mov(a2, subject);
 | 
| -  __ RecordWriteField(last_match_info_elements,
 | 
| -                      RegExpMatchInfo::kLastSubjectOffset, subject, a7,
 | 
| -                      kRAHasNotBeenSaved, kDontSaveFPRegs);
 | 
| -  __ mov(subject, a2);
 | 
| -  __ sd(subject, FieldMemOperand(last_match_info_elements,
 | 
| -                                 RegExpMatchInfo::kLastInputOffset));
 | 
| -  __ RecordWriteField(last_match_info_elements,
 | 
| -                      RegExpMatchInfo::kLastInputOffset, subject, a7,
 | 
| -                      kRAHasNotBeenSaved, kDontSaveFPRegs);
 | 
| -
 | 
| -  // Get the static offsets vector filled by the native regexp code.
 | 
| -  ExternalReference address_of_static_offsets_vector =
 | 
| -      ExternalReference::address_of_static_offsets_vector(isolate());
 | 
| -  __ li(a2, Operand(address_of_static_offsets_vector));
 | 
| -
 | 
| -  // a1: number of capture registers
 | 
| -  // a2: offsets vector
 | 
| -  Label next_capture, done;
 | 
| -  // Capture register counter starts from number of capture registers and
 | 
| -  // counts down until wrapping after zero.
 | 
| -  __ Daddu(a0, last_match_info_elements,
 | 
| -           Operand(RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag));
 | 
| -  __ bind(&next_capture);
 | 
| -  __ Dsubu(a1, a1, Operand(1));
 | 
| -  __ Branch(&done, lt, a1, Operand(zero_reg));
 | 
| -  // Read the value from the static offsets vector buffer.
 | 
| -  __ lw(a3, MemOperand(a2, 0));
 | 
| -  __ daddiu(a2, a2, kIntSize);
 | 
| -  // Store the smi value in the last match info.
 | 
| -  __ SmiTag(a3);
 | 
| -  __ sd(a3, MemOperand(a0, 0));
 | 
| -  __ Branch(&next_capture, USE_DELAY_SLOT);
 | 
| -  __ daddiu(a0, a0, kPointerSize);  // In branch delay slot.
 | 
| -
 | 
| -  __ bind(&done);
 | 
| -
 | 
| -  // Return last match info.
 | 
| -  __ mov(v0, last_match_info_elements);
 | 
| -  __ DropAndRet(4);
 | 
| -
 | 
| -  // Do the runtime call to execute the regexp.
 | 
| -  __ bind(&runtime);
 | 
| -  __ TailCallRuntime(Runtime::kRegExpExec);
 | 
| -
 | 
| -  // Deferred code for string handling.
 | 
| -  // (5) Long external string?  If not, go to (7).
 | 
| -  __ bind(¬_seq_nor_cons);
 | 
| -  // Go to (7).
 | 
| -  __ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
 | 
| -
 | 
| -  // (6) External string.  Make it, offset-wise, look like a sequential string.
 | 
| -  __ bind(&external_string);
 | 
| -  __ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
 | 
| -  __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
 | 
| -  if (FLAG_debug_code) {
 | 
| -    // Assert that we do not have a cons or slice (indirect strings) here.
 | 
| -    // Sequential strings have already been ruled out.
 | 
| -    __ And(at, a0, Operand(kIsIndirectStringMask));
 | 
| -    __ Assert(eq,
 | 
| -              kExternalStringExpectedButNotFound,
 | 
| -              at,
 | 
| -              Operand(zero_reg));
 | 
| -  }
 | 
| -  __ ld(subject,
 | 
| -        FieldMemOperand(subject, ExternalString::kResourceDataOffset));
 | 
| -  // Move the pointer so that offset-wise, it looks like a sequential string.
 | 
| -  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
 | 
| -  __ Dsubu(subject,
 | 
| -          subject,
 | 
| -          SeqTwoByteString::kHeaderSize - kHeapObjectTag);
 | 
| -  __ jmp(&seq_string);  // Go to (4).
 | 
| -
 | 
| -  // (7) Short external string or not a string?  If yes, bail out to runtime.
 | 
| -  __ bind(¬_long_external);
 | 
| -  STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
 | 
| -  __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
 | 
| -  __ Branch(&runtime, ne, at, Operand(zero_reg));
 | 
| -
 | 
| -  // (8) Sliced or thin string.  Replace subject with parent.  Go to (4).
 | 
| -  Label thin_string;
 | 
| -  __ Branch(&thin_string, eq, a1, Operand(kThinStringTag));
 | 
| -  // Load offset into t0 and replace subject string with parent.
 | 
| -  __ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
 | 
| -  __ SmiUntag(t0);
 | 
| -  __ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
 | 
| -  __ jmp(&check_underlying);  // Go to (1).
 | 
| -
 | 
| -  __ bind(&thin_string);
 | 
| -  __ ld(subject, FieldMemOperand(subject, ThinString::kActualOffset));
 | 
| -  __ jmp(&check_underlying);  // Go to (1).
 | 
| +  // Return the smi-tagged result.
 | 
| +  __ SmiTag(v0);
 | 
| +  __ Ret();
 | 
|  #endif  // V8_INTERPRETED_REGEXP
 | 
|  }
 | 
|  
 | 
| 
 |