Index: src/x64/code-stubs-x64.cc |
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
index b8f820d7f5581e9727731f61fa8481a751258aa0..e98d0da99a35b8f403b11e57affbc3170d2326a1 100644 |
--- a/src/x64/code-stubs-x64.cc |
+++ b/src/x64/code-stubs-x64.cc |
@@ -2660,12 +2660,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
// string. Also in this case the first part of the cons string is known to be |
// a sequential string or an external string. |
// In the case of a sliced string its offset has to be taken into account. |
- Label cons_string, check_encoding; |
+ Label cons_string, external_string, check_encoding; |
STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
__ cmpq(rbx, Immediate(kExternalStringTag)); |
__ j(less, &cons_string, Label::kNear); |
- __ j(equal, &runtime); |
+ __ j(equal, &external_string); |
// String is sliced. |
__ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |
@@ -2689,10 +2689,10 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
Immediate(kStringRepresentationMask | kStringEncodingMask)); |
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
__ j(zero, &seq_two_byte_string, Label::kNear); |
- // Any other flat string must be ascii. |
+ // Any other flat string must be sequential ascii or external. |
__ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), |
Immediate(kStringRepresentationMask)); |
- __ j(not_zero, &runtime); |
+ __ j(not_zero, &external_string); |
__ bind(&seq_ascii_string); |
// rdi: subject string (sequential ascii) |
@@ -2926,6 +2926,31 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
__ bind(&termination_exception); |
__ ThrowUncatchable(TERMINATION, rax); |
+ // String is external. |
+ // rdi: subject string (expected to be external) |
+ // rbx: scratch |
+ __ bind(&external_string); |
+ __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
+ __ movzxbl(rbx, FieldOperand(rbx, 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. |
+ __ testb(rbx, Immediate(kIsIndirectStringMask)); |
+ __ Assert(zero, "external string expected, but not found"); |
+ } |
+ // Rule out short external strings. |
+ STATIC_CHECK(kShortExternalStringTag != 0); |
+ __ testb(rbx, Immediate(kShortExternalStringMask)); |
+ __ j(not_zero, &runtime); |
+ __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |
+ // Move the pointer so that offset-wise, it looks like a sequential string. |
+ STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
+ __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
+ STATIC_ASSERT(kTwoByteStringTag == 0); |
+ __ testb(rbx, Immediate(kStringEncodingMask)); |
+ __ j(not_zero, &seq_ascii_string); |
+ __ jmp(&seq_two_byte_string); |
+ |
// Do the runtime call to execute the regexp. |
__ bind(&runtime); |
__ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |