Revision: 4409
Author: [email protected]
Date: Wed Apr 14 02:25:33 2010
Log: Port direct call to native RegExp from JavaScript to ARM
The ia32 version was implemented in r3542 and r3543. The x64 was
implementeed in r3740, r3741 and r3742.
Minor tweaks to the is32 and x64 code as well.
Review URL: http://codereview.chromium.org/1575035
http://code.google.com/p/v8/source/detail?r=4409
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/x64/codegen-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Tue Apr 13 02:31:03 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Wed Apr 14 02:25:33 2010
@@ -32,7 +32,10 @@
#include "compiler.h"
#include "debug.h"
#include "ic-inl.h"
+#include "jsregexp.h"
#include "parser.h"
+#include "regexp-macro-assembler.h"
+#include "regexp-stack.h"
#include "register-allocator-inl.h"
#include "runtime.h"
#include "scopes.h"
@@ -4015,8 +4018,8 @@
Load(args->at(1));
Load(args->at(2));
Load(args->at(3));
-
- frame_->CallRuntime(Runtime::kRegExpExec, 4);
+ RegExpExecStub stub;
+ frame_->CallStub(&stub, 4);
frame_->EmitPush(r0);
}
@@ -7500,6 +7503,345 @@
__ bind(&runtime);
__ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
}
+
+
+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.
+#ifndef V8_NATIVE_REGEXP
+ __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
+#else // V8_NATIVE_REGEXP
+ if (!FLAG_regexp_entry_native) {
+ __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
+ return;
+ }
+
+ // Stack frame on entry.
+ // sp[0]: last_match_info (expected JSArray)
+ // sp[4]: previous index
+ // sp[8]: subject string
+ // sp[12]: JSRegExp object
+
+ static const int kLastMatchInfoOffset = 0 * kPointerSize;
+ static const int kPreviousIndexOffset = 1 * kPointerSize;
+ static const int kSubjectOffset = 2 * kPointerSize;
+ static const int kJSRegExpOffset = 3 * kPointerSize;
+
+ Label runtime, invoke_regexp;
+
+ // 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.
+ Register subject = r4;
+ Register regexp_data = r5;
+ Register last_match_info_elements = r6;
+
+ // 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(r0, Operand(address_of_regexp_stack_memory_size));
+ __ ldr(r0, MemOperand(r0, 0));
+ __ tst(r0, Operand(r0));
+ __ b(eq, &runtime);
+
+ // Check that the first argument is a JSRegExp object.
+ __ ldr(r0, MemOperand(sp, kJSRegExpOffset));
+ ASSERT_EQ(0, kSmiTag);
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(eq, &runtime);
+ __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
+ __ b(ne, &runtime);
+
+ // Check that the RegExp has been compiled (data contains a fixed array).
+ __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset));
+ if (FLAG_debug_code) {
+ __ tst(regexp_data, Operand(kSmiTagMask));
+ __ Check(nz, "Unexpected type for RegExp data, FixedArray expected");
+ __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE);
+ __ Check(eq, "Unexpected type for RegExp data, FixedArray expected");
+ }
+
+ // regexp_data: RegExp data (FixedArray)
+ // Check the type of the RegExp. Only continue if type is
JSRegExp::IRREGEXP.
+ __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
+ __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
+ __ b(ne, &runtime);
+
+ // regexp_data: RegExp data (FixedArray)
+ // Check that the number of captures fit in the static offsets vector
buffer.
+ __ ldr(r2,
+ FieldMemOperand(regexp_data,
JSRegExp::kIrregexpCaptureCountOffset));
+ // Calculate number of capture registers (number_of_captures + 1) * 2.
This
+ // uses the asumption that smis are 2 * their untagged value.
+ ASSERT_EQ(0, kSmiTag);
+ ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
+ __ add(r2, r2, Operand(2)); // r2 was a smi.
+ // Check that the static offsets vector buffer is large enough.
+ __ cmp(r2, Operand(OffsetsVector::kStaticOffsetsVectorSize));
+ __ b(hi, &runtime);
+
+ // r2: Number of capture registers
+ // regexp_data: RegExp data (FixedArray)
+ // Check that the second argument is a string.
+ __ ldr(subject, MemOperand(sp, kSubjectOffset));
+ __ tst(subject, Operand(kSmiTagMask));
+ __ b(eq, &runtime);
+ Condition is_string = masm->IsObjectStringType(subject, r0);
+ __ b(NegateCondition(is_string), &runtime);
+ // Get the length of the string to r3.
+ __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset));
+
+ // r2: Number of capture registers
+ // r3: Length of subject string
+ // subject: Subject string
+ // regexp_data: RegExp data (FixedArray)
+ // Check that the third argument is a positive smi less than the subject
+ // string length. A negative value will be greater (unsigned comparison).
+ __ ldr(r0, MemOperand(sp, kPreviousIndexOffset));
+ __ cmp(r3, Operand(r0, ASR, kSmiTagSize + kSmiShiftSize));
+ __ b(ls, &runtime);
+
+ // r2: Number of capture registers
+ // subject: Subject string
+ // regexp_data: RegExp data (FixedArray)
+ // Check that the fourth object is a JSArray object.
+ __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(eq, &runtime);
+ __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
+ __ b(ne, &runtime);
+ // Check that the JSArray is in fast case.
+ __ ldr(last_match_info_elements,
+ FieldMemOperand(r0, JSArray::kElementsOffset));
+ __ ldr(r0, FieldMemOperand(last_match_info_elements,
HeapObject::kMapOffset));
+ __ cmp(r0, Operand(Factory::fixed_array_map()));
+ __ b(ne, &runtime);
+ // Check that the last match info has space for the capture registers
and the
+ // additional information.
+ __ ldr(r0,
+ FieldMemOperand(last_match_info_elements,
FixedArray::kLengthOffset));
+ __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead));
+ __ cmp(r2, r0);
+ __ b(gt, &runtime);
+
+ // subject: Subject string
+ // regexp_data: RegExp data (FixedArray)
+ // Check the representation and encoding of the subject string.
+ Label seq_string;
+ const int kStringRepresentationEncodingMask =
+ kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
+ __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
+ __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+ __ and_(r1, r0, Operand(kStringRepresentationEncodingMask));
+ // First check for sequential string.
+ ASSERT_EQ(0, kStringTag);
+ ASSERT_EQ(0, kSeqStringTag);
+ __ tst(r1, Operand(kIsNotStringMask | kStringRepresentationMask));
+ __ b(eq, &seq_string);
+
+ // subject: Subject string
+ // regexp_data: RegExp data (FixedArray)
+ // 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 or an external string.
+ __ and_(r0, r0, Operand(kStringRepresentationMask));
+ __ cmp(r0, Operand(kConsStringTag));
+ __ b(ne, &runtime);
+ __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset));
+ __ LoadRoot(r1, Heap::kEmptyStringRootIndex);
+ __ cmp(r0, r1);
+ __ b(ne, &runtime);
+ __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
+ __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
+ __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+ ASSERT_EQ(0, kSeqStringTag);
+ __ tst(r0, Operand(kStringRepresentationMask));
+ __ b(nz, &runtime);
+ __ and_(r1, r0, Operand(kStringRepresentationEncodingMask));
+
+ __ bind(&seq_string);
+ // r1: suject string type & kStringRepresentationEncodingMask
+ // subject: Subject string
+ // regexp_data: 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.
+#ifdef DEBUG
+ const int kSeqAsciiString = kStringTag | kSeqStringTag | kAsciiStringTag;
+ const int kSeqTwoByteString = kStringTag | kSeqStringTag |
kTwoByteStringTag;
+ CHECK_EQ(4, kSeqAsciiString);
+ CHECK_EQ(0, kSeqTwoByteString);
+#endif
+ // Find the code object based on the assumptions above.
+ __ mov(r3, Operand(r1, ASR, 2), SetCC);
+ __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset),
ne);
+ __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset),
eq);
+
+ // 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
+ // the hole.
+ __ CompareObjectType(r7, r0, r0, CODE_TYPE);
+ __ b(ne, &runtime);
+
+ // r3: encoding of subject string (1 if ascii, 0 if two_byte);
+ // r7: code
+ // subject: Subject string
+ // regexp_data: RegExp data (FixedArray)
+ // Load used arguments before starting to push arguments for call to
native
+ // RegExp code to avoid handling changing stack height.
+ __ ldr(r1, MemOperand(sp, kPreviousIndexOffset));
+ __ mov(r1, Operand(r1, ASR, kSmiTagSize));
+
+ // r1: previous index
+ // r3: encoding of subject string (1 if ascii, 0 if two_byte);
+ // r7: code
+ // subject: Subject string
+ // regexp_data: RegExp data (FixedArray)
+ // All checks done. Now push arguments for native regexp code.
+ __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2);
+
+ static const int kRegExpExecuteArguments = 7;
+ __ push(lr);
+ __ PrepareCallCFunction(kRegExpExecuteArguments, r0);
+
+ // Argument 7 (sp[8]): Indicate that this is a direct call from
JavaScript.
+ __ mov(r0, Operand(1));
+ __ str(r0, MemOperand(sp, 2 * kPointerSize));
+
+ // Argument 6 (sp[4]): Start (high end) of backtracking stack memory
area.
+ __ mov(r0, Operand(address_of_regexp_stack_memory_address));
+ __ ldr(r0, MemOperand(r0, 0));
+ __ mov(r2, Operand(address_of_regexp_stack_memory_size));
+ __ ldr(r2, MemOperand(r2, 0));
+ __ add(r0, r0, Operand(r2));
+ __ str(r0, MemOperand(sp, 1 * kPointerSize));
+
+ // Argument 5 (sp[0]): static offsets vector buffer.
+ __ mov(r0,
Operand(ExternalReference::address_of_static_offsets_vector()));
+ __ str(r0, MemOperand(sp, 0 * kPointerSize));
+
+ // For arguments 4 and 3 get string length, calculate start of string
data and
+ // calculate the shift of the index (0 for ASCII and 1 for two byte).
+ __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset));
+ ASSERT_EQ(SeqAsciiString::kHeaderSize, SeqTwoByteString::kHeaderSize);
+ __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize -
kHeapObjectTag));
+ __ eor(r3, r3, Operand(1));
+ // Argument 4 (r3): End of string data
+ // Argument 3 (r2): Start of string data
+ __ add(r2, r9, Operand(r1, LSL, r3));
+ __ add(r3, r9, Operand(r0, LSL, r3));
+
+ // Argument 2 (r1): Previous index.
+ // Already there
+
+ // Argument 1 (r0): Subject string.
+ __ mov(r0, subject);
+
+ // Locate the code entry and call it.
+ __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
+ __ CallCFunction(r7, kRegExpExecuteArguments);
+ __ pop(lr);
+
+ // r0: 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;
+ __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS));
+ __ b(eq, &success);
+ Label failure;
+ __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE));
+ __ b(eq, &failure);
+ __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
+ // If not exception it can only be retry. Handle that in the runtime
system.
+ __ b(ne, &runtime);
+ // 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.
+ __ mov(r0, Operand(ExternalReference::the_hole_value_location()));
+ __ ldr(r0, MemOperand(r0, 0));
+ __ mov(r1, Operand(ExternalReference(Top::k_pending_exception_address)));
+ __ ldr(r1, MemOperand(r1, 0));
+ __ cmp(r0, r1);
+ __ b(eq, &runtime);
+ __ bind(&failure);
+ // For failure and exception return null.
+ __ mov(r0, Operand(Factory::null_value()));
+ __ add(sp, sp, Operand(4 * kPointerSize));
+ __ Ret();
+
+ // Process the result from the native regexp code.
+ __ bind(&success);
+ __ ldr(r1,
+ FieldMemOperand(regexp_data,
JSRegExp::kIrregexpCaptureCountOffset));
+ // Calculate number of capture registers (number_of_captures + 1) * 2.
+ ASSERT_EQ(0, kSmiTag);
+ ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
+ __ add(r1, r1, Operand(2)); // r1 was a smi.
+
+ // r1: number of capture registers
+ // r4: subject string
+ // Store the capture count.
+ __ mov(r2, Operand(r1, LSL, kSmiTagSize + kSmiShiftSize)); // To smi.
+ __ str(r2, FieldMemOperand(last_match_info_elements,
+ RegExpImpl::kLastCaptureCountOffset));
+ // Store last subject and last input.
+ __ mov(r3, last_match_info_elements); // Moved up to reduce latency.
+ __ mov(r2, Operand(RegExpImpl::kLastSubjectOffset)); // Ditto.
+ __ str(subject,
+ FieldMemOperand(last_match_info_elements,
+ RegExpImpl::kLastSubjectOffset));
+ __ RecordWrite(r3, r2, r7);
+ __ str(subject,
+ FieldMemOperand(last_match_info_elements,
+ RegExpImpl::kLastInputOffset));
+ __ mov(r3, last_match_info_elements);
+ __ mov(r2, Operand(RegExpImpl::kLastInputOffset));
+ __ RecordWrite(r3, r2, r7);
+
+ // Get the static offsets vector filled by the native regexp code.
+ ExternalReference address_of_static_offsets_vector =
+ ExternalReference::address_of_static_offsets_vector();
+ __ mov(r2, Operand(address_of_static_offsets_vector));
+
+ // r1: number of capture registers
+ // r2: offsets vector
+ Label next_capture, done;
+ // Capture register counter starts from number of capture registers and
+ // counts down until wraping after zero.
+ __ add(r0,
+ last_match_info_elements,
+ Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag));
+ __ bind(&next_capture);
+ __ sub(r1, r1, Operand(1), SetCC);
+ __ b(mi, &done);
+ // Read the value from the static offsets vector buffer.
+ __ ldr(r3, MemOperand(r2, kPointerSize, PostIndex));
+ // Store the smi value in the last match info.
+ __ mov(r3, Operand(r3, LSL, kSmiTagSize));
+ __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
+ __ jmp(&next_capture);
+ __ bind(&done);
+
+ // Return last match info.
+ __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
+ __ add(sp, sp, Operand(4 * kPointerSize));
+ __ Ret();
+
+ // Do the runtime call to execute the regexp.
+ __ bind(&runtime);
+ __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
+#endif // V8_NATIVE_REGEXP
+}
void CallFunctionStub::Generate(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc Fri Apr
9 04:25:52 2010
+++ /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc Wed Apr
14 02:25:33 2010
@@ -611,7 +611,6 @@
__ add(frame_pointer(), sp, Operand(4 * kPointerSize));
__ push(r0); // Make room for "position - 1" constant (value is
irrelevant).
__ push(r0); // Make room for "at start" constant (value is irrelevant).
-
// Check if we have space on the stack for registers.
Label stack_limit_hit;
Label stack_ok;
@@ -1000,6 +999,12 @@
// If not real stack overflow the stack guard was used to interrupt
// execution for another purpose.
+
+ // If this is a direct call from JavaScript retry the RegExp forcing the
call
+ // through the runtime system. Currently the direct call cannot handle a
GC.
+ if (frame_entry<int>(re_frame, kDirectCall) == 1) {
+ return RETRY;
+ }
// Prepare for possible GC.
HandleScope handles;
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Apr 13 06:42:45
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed Apr 14 02:25:33
2010
@@ -10811,9 +10811,8 @@
// ebx: Length of subject string
// ecx: RegExp data (FixedArray)
// edx: Number of capture registers
- // Check that the third argument is a positive smi.
// Check that the third argument is a positive smi less than the subject
- // string length. A negative value will be greater (usigned comparison).
+ // string length. A negative value will be greater (unsigned comparison).
__ mov(eax, Operand(esp, kPreviousIndexOffset));
__ SmiUntag(eax);
__ cmp(eax, Operand(ebx));
@@ -10860,9 +10859,8 @@
// 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.
- __ mov(edx, ebx);
- __ and_(edx, kStringRepresentationMask);
- __ cmp(edx, kConsStringTag);
+ __ and_(ebx, kStringRepresentationMask);
+ __ cmp(ebx, kConsStringTag);
__ j(not_equal, &runtime);
__ mov(edx, FieldOperand(eax, ConsString::kSecondOffset));
__ cmp(Operand(edx), Factory::empty_string());
@@ -10881,7 +10879,8 @@
// 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.
- __ cmp(ebx, kStringTag | kSeqStringTag | kTwoByteStringTag);
+ const int kSeqTwoByteString = kStringTag | kSeqStringTag |
kTwoByteStringTag;
+ __ cmp(ebx, kSeqTwoByteString);
__ j(equal, &seq_two_byte_string);
if (FLAG_debug_code) {
__ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag);
@@ -10977,7 +10976,7 @@
// 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.
+ // TODO(592): Rerunning the RegExp to get the stack overflow exception.
ExternalReference pending_exception(Top::k_pending_exception_address);
__ mov(eax,
Operand::StaticVariable(ExternalReference::the_hole_value_location()));
@@ -11028,7 +11027,6 @@
// ecx: offsets vector
// edx: number of capture registers
Label next_capture, done;
- __ mov(eax, Operand(esp, kPreviousIndexOffset));
// Capture register counter starts from number of capture registers and
// counts down until wraping after zero.
__ bind(&next_capture);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Tue Apr 13 06:42:45 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Wed Apr 14 02:25:33 2010
@@ -7318,7 +7318,7 @@
// rcx: RegExp data (FixedArray)
// rdx: Number of capture registers
// Check that the third argument is a positive smi less than the string
- // length. A negative value will be greater (usigned comparison).
+ // length. A negative value will be greater (unsigned comparison).
__ movq(rax, Operand(rsp, kPreviousIndexOffset));
__ SmiToInteger32(rax, rax);
__ cmpl(rax, rbx);
@@ -7364,9 +7364,8 @@
// 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.
- __ movl(rdx, rbx);
- __ andb(rdx, Immediate(kStringRepresentationMask));
- __ cmpb(rdx, Immediate(kConsStringTag));
+ __ andb(rbx, Immediate(kStringRepresentationMask));
+ __ cmpb(rbx, Immediate(kConsStringTag));
__ j(not_equal, &runtime);
__ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset));
__ Cmp(rdx, Factory::empty_string());
@@ -7385,7 +7384,8 @@
// rcx: 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.
- __ cmpb(rbx, Immediate(kStringTag | kSeqStringTag | kTwoByteStringTag));
+ const int kSeqTwoByteString = kStringTag | kSeqStringTag |
kTwoByteStringTag;
+ __ cmpb(rbx, Immediate(kSeqTwoByteString));
__ j(equal, &seq_two_byte_string);
if (FLAG_debug_code) {
__ cmpb(rbx, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
@@ -7511,7 +7511,7 @@
// 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.
+ // TODO(592): Rerunning the RegExp to get the stack overflow exception.
ExternalReference
pending_exception_address(Top::k_pending_exception_address);
__ movq(kScratchRegister, pending_exception_address);
__ Cmp(kScratchRegister, Factory::the_hole_value());
@@ -7558,7 +7558,6 @@
// rcx: offsets vector
// rdx: number of capture registers
Label next_capture, done;
- __ movq(rax, Operand(rsp, kPreviousIndexOffset));
// Capture register counter starts from number of capture registers and
// counts down until wraping after zero.
__ bind(&next_capture);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
To unsubscribe, reply using "remove me" as the subject.