Always update raw pointers when handling interrupts inside RegExp code.
R=mstarzinger@chromium.org BUG=chromium:469480 LOG=N Review URL: https://codereview.chromium.org/1034173002 Cr-Commit-Position: refs/heads/master@{#27615}
This commit is contained in:
parent
146598f44a
commit
c67cb287a9
@ -1040,102 +1040,22 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
|
||||
int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid
|
||||
int delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an Latin1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
int start_index = frame_entry<int>(re_frame, kStartIndex);
|
||||
const byte* new_address = StringCharacterPosition(*subject_tmp,
|
||||
start_index + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
|
||||
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate),
|
||||
frame_entry<int>(re_frame, kStartIndex),
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInputString),
|
||||
frame_entry_address<const byte*>(re_frame, kInputStart),
|
||||
frame_entry_address<const byte*>(re_frame, kInputEnd));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1285,104 +1285,19 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
int RegExpMacroAssemblerARM64::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame,
|
||||
int start_offset,
|
||||
const byte** input_start,
|
||||
const byte** input_end) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInput));
|
||||
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid
|
||||
int delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an Latin1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = *input_start;
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
const byte* new_address = StringCharacterPosition(*subject_tmp,
|
||||
start_offset + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = *input_end;
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInput) = *subject;
|
||||
*input_start = new_address;
|
||||
*input_end = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInput) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInput) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
int RegExpMacroAssemblerARM64::CheckStackGuardState(
|
||||
Address* return_address, Code* re_code, Address re_frame, int start_index,
|
||||
const byte** input_start, const byte** input_end) {
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate), start_index,
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInput), input_start, input_end);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1072,102 +1072,22 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
|
||||
int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid
|
||||
int delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an LATIN1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
int start_index = frame_entry<int>(re_frame, kStartIndex);
|
||||
const byte* new_address = StringCharacterPosition(*subject_tmp,
|
||||
start_index + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
|
||||
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate),
|
||||
frame_entry<int>(re_frame, kStartIndex),
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInputString),
|
||||
frame_entry_address<const byte*>(re_frame, kInputStart),
|
||||
frame_entry_address<const byte*>(re_frame, kInputEnd));
|
||||
}
|
||||
|
||||
|
||||
|
@ -833,6 +833,12 @@ Object* Isolate::StackOverflow() {
|
||||
Throw(*exception, nullptr);
|
||||
|
||||
CaptureAndSetSimpleStackTrace(exception, factory()->undefined_value());
|
||||
#ifdef VERIFY_HEAP
|
||||
if (FLAG_verify_heap && FLAG_stress_compaction) {
|
||||
heap()->CollectAllAvailableGarbage("trigger compaction");
|
||||
}
|
||||
#endif // VERIFY_HEAP
|
||||
|
||||
return heap()->exception();
|
||||
}
|
||||
|
||||
|
@ -1100,101 +1100,22 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
|
||||
int RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid.
|
||||
int delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an Latin1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
int start_index = frame_entry<int>(re_frame, kStartIndex);
|
||||
const byte* new_address = StringCharacterPosition(*subject_tmp,
|
||||
start_index + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
|
||||
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate),
|
||||
frame_entry<int>(re_frame, kStartIndex),
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInputString),
|
||||
frame_entry_address<const byte*>(re_frame, kInputStart),
|
||||
frame_entry_address<const byte*>(re_frame, kInputEnd));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1146,101 +1146,22 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
int64_t RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
|
||||
int64 RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid.
|
||||
int delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an Latin1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
int start_index = frame_entry<int>(re_frame, kStartIndex);
|
||||
const byte* new_address = StringCharacterPosition(*subject_tmp,
|
||||
start_index + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
|
||||
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate),
|
||||
frame_entry<int>(re_frame, kStartIndex),
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInputString),
|
||||
frame_entry_address<const byte*>(re_frame, kInputStart),
|
||||
frame_entry_address<const byte*>(re_frame, kInputEnd));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1104,102 +1104,22 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
|
||||
int RegExpMacroAssemblerPPC::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid
|
||||
intptr_t delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an Latin1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
int start_index = frame_entry<intptr_t>(re_frame, kStartIndex);
|
||||
const byte* new_address =
|
||||
StringCharacterPosition(*subject_tmp, start_index + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = frame_entry<const byte*>(re_frame, kInputEnd);
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
|
||||
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate),
|
||||
frame_entry<int>(re_frame, kStartIndex),
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInputString),
|
||||
frame_entry_address<const byte*>(re_frame, kInputStart),
|
||||
frame_entry_address<const byte*>(re_frame, kInputEnd));
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,30 +42,82 @@ bool NativeRegExpMacroAssembler::CanReadUnaligned() {
|
||||
const byte* NativeRegExpMacroAssembler::StringCharacterPosition(
|
||||
String* subject,
|
||||
int start_index) {
|
||||
// Not just flat, but ultra flat.
|
||||
DCHECK(subject->IsExternalString() || subject->IsSeqString());
|
||||
if (subject->IsConsString()) {
|
||||
subject = ConsString::cast(subject)->first();
|
||||
} else if (subject->IsSlicedString()) {
|
||||
start_index += SlicedString::cast(subject)->offset();
|
||||
subject = SlicedString::cast(subject)->parent();
|
||||
}
|
||||
DCHECK(start_index >= 0);
|
||||
DCHECK(start_index <= subject->length());
|
||||
if (subject->IsOneByteRepresentation()) {
|
||||
const byte* address;
|
||||
if (StringShape(subject).IsExternal()) {
|
||||
const uint8_t* data = ExternalOneByteString::cast(subject)->GetChars();
|
||||
address = reinterpret_cast<const byte*>(data);
|
||||
if (subject->IsSeqOneByteString()) {
|
||||
return reinterpret_cast<const byte*>(
|
||||
SeqOneByteString::cast(subject)->GetChars() + start_index);
|
||||
} else if (subject->IsSeqTwoByteString()) {
|
||||
return reinterpret_cast<const byte*>(
|
||||
SeqTwoByteString::cast(subject)->GetChars() + start_index);
|
||||
} else if (subject->IsExternalOneByteString()) {
|
||||
return reinterpret_cast<const byte*>(
|
||||
ExternalOneByteString::cast(subject)->GetChars() + start_index);
|
||||
} else {
|
||||
DCHECK(subject->IsSeqOneByteString());
|
||||
const uint8_t* data = SeqOneByteString::cast(subject)->GetChars();
|
||||
address = reinterpret_cast<const byte*>(data);
|
||||
return reinterpret_cast<const byte*>(
|
||||
ExternalTwoByteString::cast(subject)->GetChars() + start_index);
|
||||
}
|
||||
return address + start_index;
|
||||
}
|
||||
const uc16* data;
|
||||
if (StringShape(subject).IsExternal()) {
|
||||
data = ExternalTwoByteString::cast(subject)->GetChars();
|
||||
|
||||
|
||||
int NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
Isolate* isolate, int start_index, bool is_direct_call,
|
||||
Address* return_address, Code* re_code, String** subject,
|
||||
const byte** input_start, const byte** input_end) {
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <= re_code->instruction_end());
|
||||
int return_value = 0;
|
||||
// Prepare for possible GC.
|
||||
HandleScope handles(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
Handle<String> subject_handle(*subject);
|
||||
bool is_one_byte = subject_handle->IsOneByteRepresentationUnderneath();
|
||||
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return_value = EXCEPTION;
|
||||
} else if (is_direct_call) {
|
||||
// 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.
|
||||
return_value = RETRY;
|
||||
} else {
|
||||
DCHECK(subject->IsSeqTwoByteString());
|
||||
data = SeqTwoByteString::cast(subject)->GetChars();
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
if (result->IsException()) return_value = EXCEPTION;
|
||||
}
|
||||
return reinterpret_cast<const byte*>(data + start_index);
|
||||
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid
|
||||
intptr_t delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
// If we continue, we need to update the subject string addresses.
|
||||
if (return_value == 0) {
|
||||
// String encoding might have changed.
|
||||
if (subject_handle->IsOneByteRepresentationUnderneath() != is_one_byte) {
|
||||
// If we changed between an LATIN1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return_value = RETRY;
|
||||
} else {
|
||||
*subject = *subject_handle;
|
||||
intptr_t byte_length = *input_end - *input_start;
|
||||
*input_start = StringCharacterPosition(*subject, start_index);
|
||||
*input_end = *input_start + byte_length;
|
||||
}
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
||||
|
@ -215,6 +215,12 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
|
||||
|
||||
static const byte* StringCharacterPosition(String* subject, int start_index);
|
||||
|
||||
static int CheckStackGuardState(Isolate* isolate, int start_index,
|
||||
bool is_direct_call, Address* return_address,
|
||||
Code* re_code, String** subject,
|
||||
const byte** input_start,
|
||||
const byte** input_end);
|
||||
|
||||
// Byte map of one byte characters with a 0xff if the character is a word
|
||||
// character (digit, letter or underscore) and 0x00 otherwise.
|
||||
// Used by generated RegExp code.
|
||||
|
@ -1176,102 +1176,22 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
|
||||
int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid
|
||||
intptr_t delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an Latin1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
int start_index = frame_entry<int>(re_frame, kStartIndex);
|
||||
const byte* new_address = StringCharacterPosition(*subject_tmp,
|
||||
start_index + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
|
||||
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate),
|
||||
frame_entry<int>(re_frame, kStartIndex),
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInputString),
|
||||
frame_entry_address<const byte*>(re_frame, kInputStart),
|
||||
frame_entry_address<const byte*>(re_frame, kInputEnd));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1071,102 +1071,22 @@ static T& frame_entry(Address re_frame, int frame_offset) {
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static T* frame_entry_address(Address re_frame, int frame_offset) {
|
||||
return reinterpret_cast<T*>(re_frame + frame_offset);
|
||||
}
|
||||
|
||||
|
||||
int RegExpMacroAssemblerX87::CheckStackGuardState(Address* return_address,
|
||||
Code* re_code,
|
||||
Address re_frame) {
|
||||
Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.JsHasOverflowed()) {
|
||||
isolate->StackOverflow();
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
// 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(isolate);
|
||||
Handle<Code> code_handle(re_code);
|
||||
|
||||
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
|
||||
|
||||
// Current string.
|
||||
bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
|
||||
|
||||
DCHECK(re_code->instruction_start() <= *return_address);
|
||||
DCHECK(*return_address <=
|
||||
re_code->instruction_start() + re_code->instruction_size());
|
||||
|
||||
Object* result = isolate->stack_guard()->HandleInterrupts();
|
||||
|
||||
if (*code_handle != re_code) { // Return address no longer valid
|
||||
int delta = code_handle->address() - re_code->address();
|
||||
// Overwrite the return address on the stack.
|
||||
*return_address += delta;
|
||||
}
|
||||
|
||||
if (result->IsException()) {
|
||||
return EXCEPTION;
|
||||
}
|
||||
|
||||
Handle<String> subject_tmp = subject;
|
||||
int slice_offset = 0;
|
||||
|
||||
// Extract the underlying string and the slice offset.
|
||||
if (StringShape(*subject_tmp).IsCons()) {
|
||||
subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
|
||||
} else if (StringShape(*subject_tmp).IsSliced()) {
|
||||
SlicedString* slice = SlicedString::cast(*subject_tmp);
|
||||
subject_tmp = Handle<String>(slice->parent());
|
||||
slice_offset = slice->offset();
|
||||
}
|
||||
|
||||
// String might have changed.
|
||||
if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
|
||||
// If we changed between an LATIN1 and an UC16 string, the specialized
|
||||
// code cannot be used, and we need to restart regexp matching from
|
||||
// scratch (including, potentially, compiling a new version of the code).
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
// Otherwise, the content of the string might have moved. It must still
|
||||
// be a sequential or external string with the same content.
|
||||
// Update the start and end pointers in the stack frame to the current
|
||||
// location (whether it has actually moved or not).
|
||||
DCHECK(StringShape(*subject_tmp).IsSequential() ||
|
||||
StringShape(*subject_tmp).IsExternal());
|
||||
|
||||
// The original start address of the characters to match.
|
||||
const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
|
||||
|
||||
// Find the current start address of the same character at the current string
|
||||
// position.
|
||||
int start_index = frame_entry<int>(re_frame, kStartIndex);
|
||||
const byte* new_address = StringCharacterPosition(*subject_tmp,
|
||||
start_index + slice_offset);
|
||||
|
||||
if (start_address != new_address) {
|
||||
// If there is a difference, update the object pointer and start and end
|
||||
// addresses in the RegExp stack frame to match the new value.
|
||||
const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
|
||||
int byte_length = static_cast<int>(end_address - start_address);
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
|
||||
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
|
||||
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
|
||||
// Subject string might have been a ConsString that underwent
|
||||
// short-circuiting during GC. That will not change start_address but
|
||||
// will change pointer inside the subject handle.
|
||||
frame_entry<const String*>(re_frame, kInputString) = *subject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NativeRegExpMacroAssembler::CheckStackGuardState(
|
||||
frame_entry<Isolate*>(re_frame, kIsolate),
|
||||
frame_entry<int>(re_frame, kStartIndex),
|
||||
frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
|
||||
frame_entry_address<String*>(re_frame, kInputString),
|
||||
frame_entry_address<const byte*>(re_frame, kInputStart),
|
||||
frame_entry_address<const byte*>(re_frame, kInputEnd));
|
||||
}
|
||||
|
||||
|
||||
|
13
test/mjsunit/regress/regress-crbug-469480.js
Normal file
13
test/mjsunit/regress/regress-crbug-469480.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --stress-compaction --verify-heap
|
||||
// Flags: --stack-size=100
|
||||
|
||||
// Load the debug context to fill up code space.
|
||||
%GetDebugContext();
|
||||
%GetDebugContext();
|
||||
|
||||
// Recurse and run regexp code.
|
||||
assertThrows(function f() { f(/./.test("a")); }, RangeError);
|
Loading…
Reference in New Issue
Block a user