Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Unified Diff: src/mips/code-stubs-mips.cc

Issue 2738413002: [regexp] Port RegExpExecStub to CSA (mostly) (Closed)
Patch Set: Rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/interface-descriptors.cc ('k') | src/mips/interface-descriptors-mips.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips/code-stubs-mips.cc
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index e29da4cb70421a9d1b280afbae5475c80a70887a..6c588c1918b21a02a39951877f085381c1195f01 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -1272,179 +1272,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));
- __ lw(a0, MemOperand(a0, 0));
- __ Branch(&runtime, eq, a0, Operand(zero_reg));
-
- // Check that the first argument is a JSRegExp object.
- __ lw(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).
- __ lw(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset));
- if (FLAG_debug_code) {
- __ SmiTst(regexp_data, t0);
- __ Check(nz,
- kUnexpectedTypeForRegExpDataFixedArrayExpected,
- t0,
- 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.
- __ lw(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.
- __ lw(a2,
- FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
- // Check (number_of_captures + 1) * 2 <= offsets vector size
- // Or number_of_captures * 2 <= offsets vector size - 2
- // Multiplying by 2 comes for free since a2 is smi-tagged.
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
- STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
- __ Branch(
- &runtime, hi, a2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
-
- // Reset offset for possibly sliced string.
- __ mov(t0, zero_reg);
- __ lw(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 seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
- not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
-
- __ bind(&check_underlying);
- __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ lbu(a0, FieldMemOperand(a0, 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 (5).
-
- // (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(&not_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
-
- // (3) Cons string. Check that it's flat.
- // Replace subject with first string and reload instance type.
- __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset));
- __ LoadRoot(a1, Heap::kempty_stringRootIndex);
- __ Branch(&runtime, ne, a0, Operand(a1));
- __ lw(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.
- __ lw(a1, MemOperand(sp, kPreviousIndexOffset));
- __ JumpIfNotSmi(a1, &runtime);
- __ lw(a3, FieldMemOperand(a3, String::kLengthOffset));
- __ Branch(&runtime, ls, a3, Operand(a1));
- __ sra(a1, a1, kSmiTagSize); // Untag the Smi.
-
- STATIC_ASSERT(kStringEncodingMask == 8);
- STATIC_ASSERT(kOneByteStringTag == 8);
- STATIC_ASSERT(kTwoByteStringTag == 0);
- __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for one-byte.
- __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset));
- __ sra(a3, a0, 3); // a3 is 1 for ASCII, 0 for UC16 (used below).
- __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
- __ Movz(t9, t1, 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 = 4;
@@ -1466,222 +1297,58 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Argument 9: Pass current isolate address.
// CFunctionArgumentOperand handles MIPS stack argument slots.
- __ li(a0, Operand(ExternalReference::isolate_address(isolate())));
- __ sw(a0, MemOperand(sp, 5 * kPointerSize));
+ __ li(t1, Operand(ExternalReference::isolate_address(isolate())));
+ __ sw(t1, MemOperand(sp, 5 * kPointerSize));
// Argument 8: Indicate that this is a direct call from JavaScript.
- __ li(a0, Operand(1));
- __ sw(a0, MemOperand(sp, 4 * kPointerSize));
+ __ li(t1, Operand(1));
+ __ sw(t1, MemOperand(sp, 4 * kPointerSize));
// Argument 7: Start (high end) of backtracking stack memory area.
- __ li(a0, Operand(address_of_regexp_stack_memory_address));
- __ lw(a0, MemOperand(a0, 0));
- __ li(a2, Operand(address_of_regexp_stack_memory_size));
- __ lw(a2, MemOperand(a2, 0));
- __ addu(a0, a0, a2);
- __ sw(a0, MemOperand(sp, 3 * kPointerSize));
+ 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));
+ __ lw(t1, MemOperand(t1, 0));
+ __ li(t2, Operand(address_of_regexp_stack_memory_size));
+ __ lw(t2, MemOperand(t2, 0));
+ __ addu(t1, t1, t2);
+ __ sw(t1, MemOperand(sp, 3 * kPointerSize));
// 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.
- __ mov(a0, zero_reg);
- __ sw(a0, MemOperand(sp, 2 * kPointerSize));
+ __ mov(t1, zero_reg);
+ __ sw(t1, MemOperand(sp, 2 * kPointerSize));
// Argument 5: static offsets vector buffer.
- __ li(a0, Operand(
- ExternalReference::address_of_static_offsets_vector(isolate())));
- __ sw(a0, MemOperand(sp, 1 * kPointerSize));
-
- // For arguments 4 and 3 get string length, calculate start of string data
- // calculate the shift of the index (0 for one-byte and 1 for two-byte).
- __ Addu(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.)
- __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
- // If slice offset is not 0, load the length from the original sliced string.
+ __ li(
+ t1,
+ Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
+ __ sw(t1, MemOperand(sp, 1 * kPointerSize));
+
// Argument 4, a3: End of string data
// Argument 3, a2: Start of string data
- // Prepare start and end index of the input.
- __ sllv(t1, t0, a3);
- __ addu(t0, t2, t1);
- __ sllv(t1, a1, a3);
- __ addu(a2, t0, t1);
-
- __ lw(t2, FieldMemOperand(subject, String::kLengthOffset));
- __ sra(t2, t2, kSmiTagSize);
- __ sllv(t1, t2, a3);
- __ addu(a3, t0, t1);
+ CHECK(a3.is(RegExpExecDescriptor::StringEndRegister()));
+ CHECK(a2.is(RegExpExecDescriptor::StringStartRegister()));
+
// 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.
- __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
+ Register code_reg = RegExpExecDescriptor::CodeRegister();
+ __ Addu(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())));
- __ lw(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,
- FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
- // Calculate number of capture registers (number_of_captures + 1) * 2.
- // Multiplying by 2 comes for free since r1 is smi-tagged.
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
- __ Addu(a1, a1, Operand(2)); // a1 was a smi.
-
- // Check that the last match info is a FixedArray.
- __ lw(last_match_info_elements, MemOperand(sp, kLastMatchInfoOffset));
- __ JumpIfSmi(last_match_info_elements, &runtime);
- // Check that the object has fast elements.
- __ lw(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.
- __ lw(a0,
- FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
- __ Addu(a2, a1, Operand(RegExpMatchInfo::kLastMatchOverhead));
- __ sra(at, a0, kSmiTagSize);
- __ Branch(&runtime, gt, a2, Operand(at));
-
- // a1: number of capture registers
- // subject: subject string
- // Store the capture count.
- __ sll(a2, a1, kSmiTagSize + kSmiShiftSize); // To smi.
- __ sw(a2, FieldMemOperand(last_match_info_elements,
- RegExpMatchInfo::kNumberOfCapturesOffset));
- // Store last subject and last input.
- __ sw(subject, FieldMemOperand(last_match_info_elements,
- RegExpMatchInfo::kLastSubjectOffset));
- __ mov(a2, subject);
- __ RecordWriteField(last_match_info_elements,
- RegExpMatchInfo::kLastSubjectOffset, subject, t3,
- kRAHasNotBeenSaved, kDontSaveFPRegs);
- __ mov(subject, a2);
- __ sw(subject, FieldMemOperand(last_match_info_elements,
- RegExpMatchInfo::kLastInputOffset));
- __ RecordWriteField(last_match_info_elements,
- RegExpMatchInfo::kLastInputOffset, subject, t3,
- 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.
- __ Addu(a0, last_match_info_elements,
- Operand(RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag));
- __ bind(&next_capture);
- __ Subu(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));
- __ addiu(a2, a2, kPointerSize);
- // Store the smi value in the last match info.
- __ sll(a3, a3, kSmiTagSize); // Convert to Smi.
- __ sw(a3, MemOperand(a0, 0));
- __ Branch(&next_capture, USE_DELAY_SLOT);
- __ addiu(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(&not_seq_nor_cons);
- // Go to (7).
- __ Branch(&not_long_external, gt, a1, Operand(kExternalStringTag));
-
- // (6) External string. Make it, offset-wise, look like a sequential string.
- __ bind(&external_string);
- __ lw(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));
- }
- __ lw(subject,
- FieldMemOperand(subject, ExternalString::kResourceDataOffset));
- // Move the pointer so that offset-wise, it looks like a sequential string.
- STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
- __ Subu(subject,
- subject,
- SeqTwoByteString::kHeaderSize - kHeapObjectTag);
- __ jmp(&seq_string); // Go to (5).
-
- // (7) Short external string or not a string? If yes, bail out to runtime.
- __ bind(&not_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.
- __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
- __ sra(t0, t0, kSmiTagSize);
- __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
- __ jmp(&check_underlying); // Go to (4).
-
- __ bind(&thin_string);
- __ lw(subject, FieldMemOperand(subject, ThinString::kActualOffset));
- __ jmp(&check_underlying); // Go to (4).
+ // Return the smi-tagged result.
+ __ SmiTag(v0);
+ __ Ret();
#endif // V8_INTERPRETED_REGEXP
}
« no previous file with comments | « src/interface-descriptors.cc ('k') | src/mips/interface-descriptors-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698