Version 5.0.71.40 (cherry-pick)
Merged 3518e492c0939759ae1a2623bbd606646ee172f1
Merged 7d8e279a7b11cb3c1cbeb424118a20210f9b8eea
Merged 644bade748fafb1f2e8ab25ca33473a4c77c006d
Merged b4697727e946e8d96d5345a4db7ff72842d60466
Merged 71dd5c4380e191f0a4cd1d5b6b044bdf1c04f0f9
[regexp] do not assume short external strings have a minimum size.
PPC: [regexp] do not assume short external strings have a minimum size.
X87: [regexp] do not assume short external strings have a minimum size.
MIPS64: [regexp] do not assume short external strings have a minimum size.
MIPS64: [regexp] do not assume short external strings have a minimum size.
BUG=chromium:604897,chromium:604897,chromium:604897,v8:4923,v8:4923,v8:4923
LOG=N
R=hablich@chromium.org
Review URL: https://codereview.chromium.org/1927003003 .
Cr-Commit-Position: refs/branch-heads/5.0@{#47}
Cr-Branched-From: ad16e6c2cbd2c6b0f2e8ff944ac245561c682ac2-refs/heads/5.0.71@{#1}
Cr-Branched-From: bd9df50d75125ee2ad37b3d92c8f50f0a8b5f030-refs/heads/master@{#34215}
diff --git a/include/v8-version.h b/include/v8-version.h
index ecf2daf..f656daf 100644
--- a/include/v8-version.h
+++ b/include/v8-version.h
@@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 5
#define V8_MINOR_VERSION 0
#define V8_BUILD_NUMBER 71
-#define V8_PATCH_LEVEL 39
+#define V8_PATCH_LEVEL 40
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 9e8364f..82fb51d 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -1581,34 +1581,33 @@
__ ldr(subject, MemOperand(sp, kSubjectOffset));
__ JumpIfSmi(subject, &runtime);
__ mov(r3, subject); // Make a copy of the original subject string.
- __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
// subject: subject string
// r3: subject string
- // r0: subject string instance type
// regexp_data: RegExp data (FixedArray)
// Handle subject string according to its encoding and representation:
- // (1) Sequential string? If yes, go to (5).
- // (2) Anything but sequential or cons? If yes, go to (6).
- // (3) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (4) Is subject external? If yes, go to (7).
- // (5) Sequential string. Load regexp code according to encoding.
+ // (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:
- // (6) Not a long external string? If yes, go to (8).
- // (7) External string. Make it, offset-wise, look like a sequential string.
- // Go to (5).
- // (8) Short external string or not a string? If yes, bail out to runtime.
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (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 string. Replace subject with parent. Go to (1).
- Label seq_string /* 5 */, external_string /* 7 */,
- check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
- not_long_external /* 8 */;
+ Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
+ not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
- // (1) Sequential string? If yes, go to (5).
+ __ bind(&check_underlying);
+ __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
+ __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+
+ // (1) Sequential string? If yes, go to (4).
__ and_(r1,
r0,
Operand(kIsNotStringMask |
@@ -1616,15 +1615,15 @@
kShortExternalStringMask),
SetCC);
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
- __ b(eq, &seq_string); // Go to (5).
+ __ b(eq, &seq_string); // Go to (4).
- // (2) Anything but sequential or cons? If yes, go to (6).
+ // (2) Sequential or cons? If not, go to (5).
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
__ cmp(r1, Operand(kExternalStringTag));
- __ b(ge, ¬_seq_nor_cons); // Go to (6).
+ __ b(ge, ¬_seq_nor_cons); // Go to (5).
// (3) Cons string. Check that it's flat.
// Replace subject with first string and reload instance type.
@@ -1632,19 +1631,9 @@
__ CompareRoot(r0, Heap::kempty_stringRootIndex);
__ b(ne, &runtime);
__ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
+ __ jmp(&check_underlying);
- // (4) Is subject external? If yes, go to (7).
- __ bind(&check_underlying);
- __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kSeqStringTag == 0);
- __ tst(r0, Operand(kStringRepresentationMask));
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ b(ne, &external_string); // Go to (7).
-
- // (5) Sequential string. Load regexp code according to encoding.
+ // (4) Sequential string. Load regexp code according to encoding.
__ bind(&seq_string);
// subject: sequential subject string (or look-alike, external string)
// r3: original subject string
@@ -1877,12 +1866,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (6) Not a long external string? If yes, go to (8).
+ // (5) Long external string? If not, go to (7).
__ bind(¬_seq_nor_cons);
// Compare flags are still set.
- __ b(gt, ¬_long_external); // Go to (8).
+ __ b(gt, ¬_long_external); // Go to (7).
- // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (6) External string. Make it, offset-wise, look like a sequential string.
__ bind(&external_string);
__ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
@@ -1899,15 +1888,15 @@
__ sub(subject,
subject,
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
- __ jmp(&seq_string); // Go to (5).
+ __ jmp(&seq_string); // Go to (4).
- // (8) Short external string or not a string? If yes, bail out to runtime.
+ // (7) Short external string or not a string? If yes, bail out to runtime.
__ bind(¬_long_external);
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
__ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
__ b(ne, &runtime);
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (8) Sliced string. Replace subject with parent. Go to (4).
// Load offset into r9 and replace subject string with parent.
__ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
__ SmiUntag(r9);
diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc
index 32250a8..ad566e6 100644
--- a/src/arm64/code-stubs-arm64.cc
+++ b/src/arm64/code-stubs-arm64.cc
@@ -1747,35 +1747,35 @@
__ Peek(subject, kSubjectOffset);
__ JumpIfSmi(subject, &runtime);
- __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
-
__ Ldr(jsstring_length, FieldMemOperand(subject, String::kLengthOffset));
// Handle subject string according to its encoding and representation:
- // (1) Sequential string? If yes, go to (5).
- // (2) Anything but sequential or cons? If yes, go to (6).
- // (3) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (4) Is subject external? If yes, go to (7).
- // (5) Sequential string. Load regexp code according to encoding.
+ // (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:
- // (6) Not a long external string? If yes, go to (8).
- // (7) External string. Make it, offset-wise, look like a sequential string.
- // Go to (5).
- // (8) Short external string or not a string? If yes, bail out to runtime.
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (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 string. Replace subject with parent. Go to (1).
- Label check_underlying; // (4)
- Label seq_string; // (5)
- Label not_seq_nor_cons; // (6)
- Label external_string; // (7)
- Label not_long_external; // (8)
+ Label check_underlying; // (1)
+ Label seq_string; // (4)
+ Label not_seq_nor_cons; // (5)
+ Label external_string; // (6)
+ Label not_long_external; // (7)
- // (1) Sequential string? If yes, go to (5).
+ __ Bind(&check_underlying);
+ __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
+ __ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
+
+ // (1) Sequential string? If yes, go to (4).
__ And(string_representation,
string_type,
kIsNotStringMask |
@@ -1792,36 +1792,24 @@
// is a String
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
STATIC_ASSERT(kShortExternalStringTag != 0);
- __ Cbz(string_representation, &seq_string); // Go to (5).
+ __ Cbz(string_representation, &seq_string); // Go to (4).
- // (2) Anything but sequential or cons? If yes, go to (6).
+ // (2) Sequential or cons? If not, go to (5).
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
__ Cmp(string_representation, kExternalStringTag);
- __ B(ge, ¬_seq_nor_cons); // Go to (6).
+ __ B(ge, ¬_seq_nor_cons); // Go to (5).
// (3) Cons string. Check that it's flat.
__ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset));
__ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime);
// Replace subject with first string.
__ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
+ __ B(&check_underlying);
- // (4) Is subject external? If yes, go to (7).
- __ Bind(&check_underlying);
- // Reload the string type.
- __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kSeqStringTag == 0);
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ TestAndBranchIfAnySet(string_type.X(),
- kStringRepresentationMask,
- &external_string); // Go to (7).
-
- // (5) Sequential string. Load regexp code according to encoding.
+ // (4) Sequential string. Load regexp code according to encoding.
__ Bind(&seq_string);
// Check that the third argument is a positive smi less than the subject
@@ -2091,12 +2079,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (6) Not a long external string? If yes, go to (8).
+ // (5) Long external string? If not, go to (7).
__ Bind(¬_seq_nor_cons);
// Compare flags are still set.
- __ B(ne, ¬_long_external); // Go to (8).
+ __ B(ne, ¬_long_external); // Go to (7).
- // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (6) External string. Make it, offset-wise, look like a sequential string.
__ Bind(&external_string);
if (masm->emit_debug_code()) {
// Assert that we do not have a cons or slice (indirect strings) here.
@@ -2114,9 +2102,9 @@
// Move the pointer so that offset-wise, it looks like a sequential string.
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
__ Sub(subject, subject, SeqTwoByteString::kHeaderSize - kHeapObjectTag);
- __ B(&seq_string); // Go to (5).
+ __ B(&seq_string); // Go to (4).
- // (8) If this is a short external string or not a string, bail out to
+ // (7) If this is a short external string or not a string, bail out to
// runtime.
__ Bind(¬_long_external);
STATIC_ASSERT(kShortExternalStringTag != 0);
@@ -2124,11 +2112,11 @@
kShortExternalStringMask | kIsNotStringMask,
&runtime);
- // (9) Sliced string. Replace subject with parent.
+ // (8) Sliced string. Replace subject with parent.
__ Ldr(sliced_string_offset,
UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset));
__ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
- __ B(&check_underlying); // Go to (4).
+ __ B(&check_underlying); // Go to (1).
#endif
}
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 79f75fa..510b58e 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -798,39 +798,37 @@
__ mov(eax, Operand(esp, kSubjectOffset));
__ JumpIfSmi(eax, &runtime);
__ mov(edx, eax); // Make a copy of the original subject string.
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
// eax: subject string
// edx: subject string
- // ebx: subject string instance type
// ecx: RegExp data (FixedArray)
// Handle subject string according to its encoding and representation:
// (1) Sequential two byte? If yes, go to (9).
- // (2) Sequential one byte? If yes, go to (6).
- // (3) Anything but sequential or cons? If yes, go to (7).
- // (4) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (5a) Is subject sequential two byte? If yes, go to (9).
- // (5b) Is subject external? If yes, go to (8).
- // (6) One byte sequential. Load regexp code for one byte.
+ // (2) Sequential one byte? If yes, go to (5).
+ // (3) Sequential or cons? If not, go to (6).
+ // (4) Cons string. If the string is flat, replace subject with first string
+ // and go to (1). Otherwise bail out to runtime.
+ // (5) One byte sequential. Load regexp code for one byte.
// (E) Carry on.
/// [...]
// Deferred code at the end of the stub:
- // (7) Not a long external string? If yes, go to (10).
- // (8) External string. Make it, offset-wise, look like a sequential string.
- // (8a) Is the external string one byte? If yes, go to (6).
- // (9) Two byte sequential. Load regexp code for one byte. Go to (E).
+ // (6) Long external string? If not, go to (10).
+ // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (8) Is the external string one byte? If yes, go to (5).
+ // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
// (10) Short external string or not a string? If yes, bail out to runtime.
- // (11) Sliced string. Replace subject with parent. Go to (5a).
+ // (11) Sliced string. Replace subject with parent. Go to (1).
- Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
- external_string /* 8 */, check_underlying /* 5a */,
- not_seq_nor_cons /* 7 */, check_code /* E */,
- not_long_external /* 10 */;
+ Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
+ external_string /* 7 */, check_underlying /* 1 */,
+ not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
+ __ bind(&check_underlying);
// (1) Sequential two byte? If yes, go to (9).
+ __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+ __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+
__ and_(ebx, kIsNotStringMask |
kStringRepresentationMask |
kStringEncodingMask |
@@ -838,14 +836,14 @@
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
__ j(zero, &seq_two_byte_string); // Go to (9).
- // (2) Sequential one byte? If yes, go to (6).
+ // (2) Sequential one byte? If yes, go to (5).
// Any other sequential string must be one byte.
__ and_(ebx, Immediate(kIsNotStringMask |
kStringRepresentationMask |
kShortExternalStringMask));
- __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
+ __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
- // (3) Anything but sequential or cons? If yes, go to (7).
+ // (3) Sequential or cons? If not, go to (6).
// We check whether the subject string is a cons, since sequential strings
// have already been covered.
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
@@ -853,32 +851,19 @@
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
__ cmp(ebx, Immediate(kExternalStringTag));
- __ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
+ __ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
// (4) Cons string. Check that it's flat.
// Replace subject with first string and reload instance type.
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
__ j(not_equal, &runtime);
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
- __ bind(&check_underlying);
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
-
- // (5a) Is subject sequential two byte? If yes, go to (9).
- __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
- STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
- __ j(zero, &seq_two_byte_string); // Go to (9).
- // (5b) Is subject external? If yes, go to (8).
- __ test_b(ebx, kStringRepresentationMask);
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ j(not_zero, &external_string); // Go to (8).
+ __ jmp(&check_underlying);
// eax: sequential subject string (or look-alike, external string)
// edx: original subject string
// ecx: RegExp data (FixedArray)
- // (6) One byte sequential. Load regexp code for one byte.
+ // (5) One byte sequential. Load regexp code for one byte.
__ bind(&seq_one_byte_string);
// Load previous index and check range before edx is overwritten. We have
// to use edx instead of eax here because it might have been only made to
@@ -1105,12 +1090,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (7) Not a long external string? If yes, go to (10).
+ // (6) Long external string? If not, go to (10).
__ bind(¬_seq_nor_cons);
// Compare flags are still set from (3).
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
- // (8) External string. Short external strings have been ruled out.
+ // (7) External string. Short external strings have been ruled out.
__ bind(&external_string);
// Reload instance type.
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
@@ -1126,14 +1111,14 @@
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
STATIC_ASSERT(kTwoByteStringTag == 0);
- // (8a) Is the external string one byte? If yes, go to (6).
+ // (8) Is the external string one byte? If yes, go to (5).
__ test_b(ebx, kStringEncodingMask);
- __ j(not_zero, &seq_one_byte_string); // Goto (6).
+ __ j(not_zero, &seq_one_byte_string); // Go to (5).
// eax: sequential subject string (or look-alike, external string)
// edx: original subject string
// ecx: RegExp data (FixedArray)
- // (9) Two byte sequential. Load regexp code for one byte. Go to (E).
+ // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
__ bind(&seq_two_byte_string);
// Load previous index and check range before edx is overwritten. We have
// to use edx instead of eax here because it might have been only made to
@@ -1153,11 +1138,11 @@
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
__ j(not_zero, &runtime);
- // (11) Sliced string. Replace subject with parent. Go to (5a).
+ // (11) Sliced string. Replace subject with parent. Go to (1).
// Load offset into edi and replace subject string with parent.
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
- __ jmp(&check_underlying); // Go to (5a).
+ __ jmp(&check_underlying); // Go to (1).
#endif // V8_INTERPRETED_REGEXP
}
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index ae08eb6..541e73e 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -1605,7 +1605,6 @@
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
-
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
@@ -1638,8 +1637,7 @@
// 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_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));
@@ -1691,34 +1689,33 @@
__ lw(subject, MemOperand(sp, kSubjectOffset));
__ JumpIfSmi(subject, &runtime);
__ mov(a3, subject); // Make a copy of the original subject string.
- __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
// subject: subject string
// a3: subject string
- // a0: subject string instance type
// regexp_data: RegExp data (FixedArray)
// Handle subject string according to its encoding and representation:
- // (1) Sequential string? If yes, go to (5).
- // (2) Anything but sequential or cons? If yes, go to (6).
- // (3) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (4) Is subject external? If yes, go to (7).
- // (5) Sequential string. Load regexp code according to encoding.
+ // (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:
- // (6) Not a long external string? If yes, go to (8).
- // (7) External string. Make it, offset-wise, look like a sequential string.
- // Go to (5).
- // (8) Short external string or not a string? If yes, bail out to runtime.
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (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 string. Replace subject with parent. Go to (1).
- Label seq_string /* 5 */, external_string /* 7 */,
- check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
- not_long_external /* 8 */;
+ Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
+ not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
- // (1) Sequential string? If yes, go to (5).
+ __ 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 |
@@ -1727,12 +1724,12 @@
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
__ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
- // (2) Anything but sequential or cons? If yes, go to (6).
+ // (2) Sequential or cons? If not, go to (5).
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
- // Go to (6).
+ // Go to (5).
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
// (3) Cons string. Check that it's flat.
@@ -1741,19 +1738,9 @@
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
__ Branch(&runtime, ne, a0, Operand(a1));
__ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
+ __ jmp(&check_underlying);
- // (4) Is subject external? If yes, go to (7).
- __ bind(&check_underlying);
- __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kSeqStringTag == 0);
- __ And(at, a0, Operand(kStringRepresentationMask));
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
-
- // (5) Sequential string. Load regexp code according to encoding.
+ // (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
@@ -1995,12 +1982,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (6) Not a long external string? If yes, go to (8).
+ // (5) Long external string? If not, go to (7).
__ bind(¬_seq_nor_cons);
- // Go to (8).
+ // Go to (7).
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
- // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (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));
@@ -2022,13 +2009,13 @@
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
__ jmp(&seq_string); // Go to (5).
- // (8) Short external string or not a string? If yes, bail out to runtime.
+ // (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));
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (8) Sliced string. Replace subject with parent. Go to (4).
// Load offset into t0 and replace subject string with parent.
__ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
__ sra(t0, t0, kSmiTagSize);
diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc
index dac3d4f..28812ad 100644
--- a/src/mips64/code-stubs-mips64.cc
+++ b/src/mips64/code-stubs-mips64.cc
@@ -1686,50 +1686,51 @@
__ ld(subject, MemOperand(sp, kSubjectOffset));
__ JumpIfSmi(subject, &runtime);
__ mov(a3, subject); // Make a copy of the original subject string.
- __ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
+
// subject: subject string
// a3: subject string
- // a0: subject string instance type
// regexp_data: RegExp data (FixedArray)
// Handle subject string according to its encoding and representation:
- // (1) Sequential string? If yes, go to (5).
- // (2) Anything but sequential or cons? If yes, go to (6).
- // (3) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (4) Is subject external? If yes, go to (7).
- // (5) Sequential string. Load regexp code according to encoding.
+ // (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:
- // (6) Not a long external string? If yes, go to (8).
- // (7) External string. Make it, offset-wise, look like a sequential string.
- // Go to (5).
- // (8) Short external string or not a string? If yes, bail out to runtime.
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (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 string. Replace subject with parent. Go to (1).
- Label check_underlying; // (4)
- Label seq_string; // (5)
- Label not_seq_nor_cons; // (6)
- Label external_string; // (7)
- Label not_long_external; // (8)
+ Label check_underlying; // (1)
+ Label seq_string; // (4)
+ Label not_seq_nor_cons; // (5)
+ Label external_string; // (6)
+ Label not_long_external; // (7)
- // (1) Sequential string? If yes, go to (5).
+ __ 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 (5).
+ __ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (4).
- // (2) Anything but sequential or cons? If yes, go to (6).
+ // (2) Sequential or cons? If not, go to (5).
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
- // Go to (6).
+ // Go to (5).
__ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
// (3) Cons string. Check that it's flat.
@@ -1738,19 +1739,9 @@
__ LoadRoot(a1, Heap::kempty_stringRootIndex);
__ Branch(&runtime, ne, a0, Operand(a1));
__ ld(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
+ __ jmp(&check_underlying);
- // (4) Is subject external? If yes, go to (7).
- __ bind(&check_underlying);
- __ ld(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kSeqStringTag == 0);
- __ And(at, a0, Operand(kStringRepresentationMask));
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7).
-
- // (5) Sequential string. Load regexp code according to encoding.
+ // (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
@@ -1993,12 +1984,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (6) Not a long external string? If yes, go to (8).
+ // (5) Long external string? If not, go to (7).
__ bind(¬_seq_nor_cons);
- // Go to (8).
+ // Go to (7).
__ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag));
- // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (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));
@@ -2018,20 +2009,20 @@
__ Dsubu(subject,
subject,
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
- __ jmp(&seq_string); // Go to (5).
+ __ jmp(&seq_string); // Go to (4).
- // (8) Short external string or not a string? If yes, bail out to runtime.
+ // (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));
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (8) Sliced string. Replace subject with parent. Go to (4).
// 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 (4).
+ __ jmp(&check_underlying); // Go to (1).
#endif // V8_INTERPRETED_REGEXP
}
diff --git a/src/objects.h b/src/objects.h
index a3d6a72..61c6e5e 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -9292,9 +9292,6 @@
static const int kResourceDataOffset = kResourceOffset + kPointerSize;
static const int kSize = kResourceDataOffset + kPointerSize;
- static const int kMaxShortLength =
- (kShortSize - SeqString::kHeaderSize) / kCharSize;
-
// Return whether external string is short (data pointer is not cached).
inline bool is_short();
diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc
index c5ed7c5..03c73af 100644
--- a/src/ppc/code-stubs-ppc.cc
+++ b/src/ppc/code-stubs-ppc.cc
@@ -1641,48 +1641,49 @@
__ LoadP(subject, MemOperand(sp, kSubjectOffset));
__ JumpIfSmi(subject, &runtime);
__ mr(r6, subject); // Make a copy of the original subject string.
- __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
// subject: subject string
// r6: subject string
- // r3: subject string instance type
// regexp_data: RegExp data (FixedArray)
// Handle subject string according to its encoding and representation:
- // (1) Sequential string? If yes, go to (5).
- // (2) Anything but sequential or cons? If yes, go to (6).
- // (3) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (4) Is subject external? If yes, go to (7).
- // (5) Sequential string. Load regexp code according to encoding.
+ // (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:
- // (6) Not a long external string? If yes, go to (8).
- // (7) External string. Make it, offset-wise, look like a sequential string.
- // Go to (5).
- // (8) Short external string or not a string? If yes, bail out to runtime.
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (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 string. Replace subject with parent. Go to (1).
- Label seq_string /* 5 */, external_string /* 7 */, check_underlying /* 4 */,
- not_seq_nor_cons /* 6 */, not_long_external /* 8 */;
+ Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
+ not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
- // (1) Sequential string? If yes, go to (5).
+ __ bind(&check_underlying);
+ __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
+ __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+
+ // (1) Sequential string? If yes, go to (4).
+
STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask |
kShortExternalStringMask) == 0x93);
__ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask |
kShortExternalStringMask));
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
- __ beq(&seq_string, cr0); // Go to (5).
+ __ beq(&seq_string, cr0); // Go to (4).
- // (2) Anything but sequential or cons? If yes, go to (6).
+ // (2) Sequential or cons? If not, go to (5).
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
STATIC_ASSERT(kExternalStringTag < 0xffffu);
__ cmpi(r4, Operand(kExternalStringTag));
- __ bge(¬_seq_nor_cons); // Go to (6).
+ __ bge(¬_seq_nor_cons); // Go to (5).
// (3) Cons string. Check that it's flat.
// Replace subject with first string and reload instance type.
@@ -1690,20 +1691,9 @@
__ CompareRoot(r3, Heap::kempty_stringRootIndex);
__ bne(&runtime);
__ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
+ __ b(&check_underlying);
- // (4) Is subject external? If yes, go to (7).
- __ bind(&check_underlying);
- __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
- __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kSeqStringTag == 0);
- STATIC_ASSERT(kStringRepresentationMask == 3);
- __ andi(r0, r3, Operand(kStringRepresentationMask));
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ bne(&external_string, cr0); // Go to (7).
-
- // (5) Sequential string. Load regexp code according to encoding.
+ // (4) Sequential string. Load regexp code according to encoding.
__ bind(&seq_string);
// subject: sequential subject string (or look-alike, external string)
// r6: original subject string
@@ -1936,12 +1926,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (6) Not a long external string? If yes, go to (8).
+ // (5) Long external string? If not, go to (7).
__ bind(¬_seq_nor_cons);
// Compare flags are still set.
- __ bgt(¬_long_external); // Go to (8).
+ __ bgt(¬_long_external); // Go to (7).
- // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (6) External string. Make it, offset-wise, look like a sequential string.
__ bind(&external_string);
__ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
__ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
@@ -1958,15 +1948,15 @@
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
__ subi(subject, subject,
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
- __ b(&seq_string); // Go to (5).
+ __ b(&seq_string); // Go to (4).
- // (8) Short external string or not a string? If yes, bail out to runtime.
+ // (7) Short external string or not a string? If yes, bail out to runtime.
__ bind(¬_long_external);
STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0);
__ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask));
__ bne(&runtime, cr0);
- // (9) Sliced string. Replace subject with parent. Go to (4).
+ // (8) Sliced string. Replace subject with parent. Go to (4).
// Load offset into r11 and replace subject string with parent.
__ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset));
__ SmiUntag(r11);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 3dd2f45..f314b9c 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -667,35 +667,34 @@
__ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
__ JumpIfSmi(rdi, &runtime);
__ movp(r15, rdi); // Make a copy of the original subject string.
- __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
- __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
// rax: RegExp data (FixedArray)
// rdi: subject string
// r15: subject string
// Handle subject string according to its encoding and representation:
// (1) Sequential two byte? If yes, go to (9).
- // (2) Sequential one byte? If yes, go to (6).
- // (3) Anything but sequential or cons? If yes, go to (7).
- // (4) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (5a) Is subject sequential two byte? If yes, go to (9).
- // (5b) Is subject external? If yes, go to (8).
- // (6) One byte sequential. Load regexp code for one byte.
+ // (2) Sequential one byte? If yes, go to (5).
+ // (3) Sequential or cons? If not, go to (6).
+ // (4) Cons string. If the string is flat, replace subject with first string
+ // and go to (1). Otherwise bail out to runtime.
+ // (5) One byte sequential. Load regexp code for one byte.
// (E) Carry on.
/// [...]
// Deferred code at the end of the stub:
- // (7) Not a long external string? If yes, go to (10).
- // (8) External string. Make it, offset-wise, look like a sequential string.
- // (8a) Is the external string one byte? If yes, go to (6).
- // (9) Two byte sequential. Load regexp code for one byte. Go to (E).
+ // (6) Long external string? If not, go to (10).
+ // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (8) Is the external string one byte? If yes, go to (5).
+ // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
// (10) Short external string or not a string? If yes, bail out to runtime.
- // (11) Sliced string. Replace subject with parent. Go to (5a).
+ // (11) Sliced string. Replace subject with parent. Go to (1).
- Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
- external_string /* 8 */, check_underlying /* 5a */,
- not_seq_nor_cons /* 7 */, check_code /* E */,
- not_long_external /* 10 */;
+ Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
+ external_string /* 7 */, check_underlying /* 1 */,
+ not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
+
+ __ bind(&check_underlying);
+ __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
+ __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
// (1) Sequential two byte? If yes, go to (9).
__ andb(rbx, Immediate(kIsNotStringMask |
@@ -705,14 +704,14 @@
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
__ j(zero, &seq_two_byte_string); // Go to (9).
- // (2) Sequential one byte? If yes, go to (6).
+ // (2) Sequential one byte? If yes, go to (5).
// Any other sequential string must be one byte.
__ andb(rbx, Immediate(kIsNotStringMask |
kStringRepresentationMask |
kShortExternalStringMask));
- __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
+ __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
- // (3) Anything but sequential or cons? If yes, go to (7).
+ // (3) Sequential or cons? If not, go to (6).
// We check whether the subject string is a cons, since sequential strings
// have already been covered.
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
@@ -720,7 +719,7 @@
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
__ cmpp(rbx, Immediate(kExternalStringTag));
- __ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
+ __ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
// (4) Cons string. Check that it's flat.
// Replace subject with first string and reload instance type.
@@ -728,22 +727,9 @@
Heap::kempty_stringRootIndex);
__ j(not_equal, &runtime);
__ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
- __ bind(&check_underlying);
- __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
- __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
+ __ jmp(&check_underlying);
- // (5a) Is subject sequential two byte? If yes, go to (9).
- __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask));
- STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
- __ j(zero, &seq_two_byte_string); // Go to (9).
- // (5b) Is subject external? If yes, go to (8).
- __ testb(rbx, Immediate(kStringRepresentationMask));
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ j(not_zero, &external_string); // Go to (8)
-
- // (6) One byte sequential. Load regexp code for one byte.
+ // (5) One byte sequential. Load regexp code for one byte.
__ bind(&seq_one_byte_string);
// rax: RegExp data (FixedArray)
__ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset));
@@ -990,12 +976,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (7) Not a long external string? If yes, go to (10).
+ // (6) Long external string? If not, go to (10).
__ bind(¬_seq_nor_cons);
// Compare flags are still set from (3).
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
- // (8) External string. Short external strings have been ruled out.
+ // (7) External string. Short external strings have been ruled out.
__ bind(&external_string);
__ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
@@ -1010,13 +996,13 @@
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
__ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
STATIC_ASSERT(kTwoByteStringTag == 0);
- // (8a) Is the external string one byte? If yes, go to (6).
+ // (8) Is the external string one byte? If yes, go to (5).
__ testb(rbx, Immediate(kStringEncodingMask));
- __ j(not_zero, &seq_one_byte_string); // Goto (6).
+ __ j(not_zero, &seq_one_byte_string); // Go to (5).
// rdi: subject string (flat two-byte)
// rax: RegExp data (FixedArray)
- // (9) Two byte sequential. Load regexp code for one byte. Go to (E).
+ // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
__ bind(&seq_two_byte_string);
__ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
__ Set(rcx, 0); // Type is two byte.
@@ -1029,7 +1015,7 @@
__ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
__ j(not_zero, &runtime);
- // (11) Sliced string. Replace subject with parent. Go to (5a).
+ // (11) Sliced string. Replace subject with parent. Go to (1).
// Load offset into r14 and replace subject string with parent.
__ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
__ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc
index e1ad6a7..c54f428 100644
--- a/src/x87/code-stubs-x87.cc
+++ b/src/x87/code-stubs-x87.cc
@@ -500,39 +500,37 @@
__ mov(eax, Operand(esp, kSubjectOffset));
__ JumpIfSmi(eax, &runtime);
__ mov(edx, eax); // Make a copy of the original subject string.
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
// eax: subject string
// edx: subject string
- // ebx: subject string instance type
// ecx: RegExp data (FixedArray)
// Handle subject string according to its encoding and representation:
// (1) Sequential two byte? If yes, go to (9).
- // (2) Sequential one byte? If yes, go to (6).
- // (3) Anything but sequential or cons? If yes, go to (7).
- // (4) Cons string. If the string is flat, replace subject with first string.
- // Otherwise bailout.
- // (5a) Is subject sequential two byte? If yes, go to (9).
- // (5b) Is subject external? If yes, go to (8).
- // (6) One byte sequential. Load regexp code for one byte.
+ // (2) Sequential one byte? If yes, go to (5).
+ // (3) Sequential or cons? If not, go to (6).
+ // (4) Cons string. If the string is flat, replace subject with first string
+ // and go to (1). Otherwise bail out to runtime.
+ // (5) One byte sequential. Load regexp code for one byte.
// (E) Carry on.
/// [...]
// Deferred code at the end of the stub:
- // (7) Not a long external string? If yes, go to (10).
- // (8) External string. Make it, offset-wise, look like a sequential string.
- // (8a) Is the external string one byte? If yes, go to (6).
- // (9) Two byte sequential. Load regexp code for one byte. Go to (E).
+ // (6) Long external string? If not, go to (10).
+ // (7) External string. Make it, offset-wise, look like a sequential string.
+ // (8) Is the external string one byte? If yes, go to (5).
+ // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
// (10) Short external string or not a string? If yes, bail out to runtime.
- // (11) Sliced string. Replace subject with parent. Go to (5a).
+ // (11) Sliced string. Replace subject with parent. Go to (1).
- Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
- external_string /* 8 */, check_underlying /* 5a */,
- not_seq_nor_cons /* 7 */, check_code /* E */,
- not_long_external /* 10 */;
+ Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
+ external_string /* 7 */, check_underlying /* 1 */,
+ not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
+ __ bind(&check_underlying);
// (1) Sequential two byte? If yes, go to (9).
+ __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+ __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+
__ and_(ebx, kIsNotStringMask |
kStringRepresentationMask |
kStringEncodingMask |
@@ -540,14 +538,14 @@
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
__ j(zero, &seq_two_byte_string); // Go to (9).
- // (2) Sequential one byte? If yes, go to (6).
+ // (2) Sequential one byte? If yes, go to (5).
// Any other sequential string must be one byte.
__ and_(ebx, Immediate(kIsNotStringMask |
kStringRepresentationMask |
kShortExternalStringMask));
- __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6).
+ __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
- // (3) Anything but sequential or cons? If yes, go to (7).
+ // (3) Sequential or cons? If not, go to (6).
// We check whether the subject string is a cons, since sequential strings
// have already been covered.
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
@@ -555,32 +553,19 @@
STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
__ cmp(ebx, Immediate(kExternalStringTag));
- __ j(greater_equal, ¬_seq_nor_cons); // Go to (7).
+ __ j(greater_equal, ¬_seq_nor_cons); // Go to (6).
// (4) Cons string. Check that it's flat.
// Replace subject with first string and reload instance type.
__ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
__ j(not_equal, &runtime);
__ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
- __ bind(&check_underlying);
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
-
- // (5a) Is subject sequential two byte? If yes, go to (9).
- __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
- STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
- __ j(zero, &seq_two_byte_string); // Go to (9).
- // (5b) Is subject external? If yes, go to (8).
- __ test_b(ebx, kStringRepresentationMask);
- // The underlying external string is never a short external string.
- STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
- STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
- __ j(not_zero, &external_string); // Go to (8).
+ __ jmp(&check_underlying);
// eax: sequential subject string (or look-alike, external string)
// edx: original subject string
// ecx: RegExp data (FixedArray)
- // (6) One byte sequential. Load regexp code for one byte.
+ // (5) One byte sequential. Load regexp code for one byte.
__ bind(&seq_one_byte_string);
// Load previous index and check range before edx is overwritten. We have
// to use edx instead of eax here because it might have been only made to
@@ -801,12 +786,12 @@
__ TailCallRuntime(Runtime::kRegExpExec);
// Deferred code for string handling.
- // (7) Not a long external string? If yes, go to (10).
+ // (6) Long external string? If not, go to (10).
__ bind(¬_seq_nor_cons);
// Compare flags are still set from (3).
__ j(greater, ¬_long_external, Label::kNear); // Go to (10).
- // (8) External string. Short external strings have been ruled out.
+ // (7) External string. Short external strings have been ruled out.
__ bind(&external_string);
// Reload instance type.
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
@@ -822,14 +807,14 @@
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
__ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
STATIC_ASSERT(kTwoByteStringTag == 0);
- // (8a) Is the external string one byte? If yes, go to (6).
+ // (8) Is the external string one byte? If yes, go to (5).
__ test_b(ebx, kStringEncodingMask);
- __ j(not_zero, &seq_one_byte_string); // Goto (6).
+ __ j(not_zero, &seq_one_byte_string); // Go to (5).
// eax: sequential subject string (or look-alike, external string)
// edx: original subject string
// ecx: RegExp data (FixedArray)
- // (9) Two byte sequential. Load regexp code for one byte. Go to (E).
+ // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
__ bind(&seq_two_byte_string);
// Load previous index and check range before edx is overwritten. We have
// to use edx instead of eax here because it might have been only made to
@@ -849,11 +834,11 @@
__ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
__ j(not_zero, &runtime);
- // (11) Sliced string. Replace subject with parent. Go to (5a).
+ // (11) Sliced string. Replace subject with parent. Go to (1).
// Load offset into edi and replace subject string with parent.
__ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
__ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
- __ jmp(&check_underlying); // Go to (5a).
+ __ jmp(&check_underlying); // Go to (1).
#endif // V8_INTERPRETED_REGEXP
}
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index 14ec12f..22321c3 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -1967,3 +1967,26 @@
CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]);
CHECK(resultToStringError->IsObject());
}
+
+class UncachedExternalString
+ : public v8::String::ExternalOneByteStringResource {
+ public:
+ const char* data() const override { return "abcdefghijklmnopqrstuvwxyz"; }
+ size_t length() const override { return 26; }
+ bool IsCompressible() const override { return true; }
+};
+
+TEST(UncachedExternalString) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ LocalContext env;
+ v8::Local<v8::String> external =
+ v8::String::NewExternalOneByte(isolate, new UncachedExternalString())
+ .ToLocalChecked();
+ CHECK(v8::Utils::OpenHandle(*external)->map() ==
+ CcTest::i_isolate()->heap()->short_external_one_byte_string_map());
+ v8::Local<v8::Object> global = env->Global();
+ global->Set(env.local(), v8_str("external"), external).FromJust();
+ CompileRun("var re = /y(.)/; re.test('ab');");
+ ExpectString("external.substring(1).match(re)[1]", "z");
+}