Revision: 9064
Author: [email protected]
Date: Tue Aug 30 01:22:41 2011
Log: Generated code for substring slices in ia32.
Review URL: http://codereview.chromium.org/7744052
http://code.google.com/p/v8/source/detail?r=9064
Modified:
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/test/mjsunit/string-slices.js
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Aug 29
06:02:35 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Aug 30
01:22:41 2011
@@ -3473,8 +3473,6 @@
// Dispatch on the indirect string shape: slice or cons.
Label cons_string;
- const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
- ASSERT(IsPowerOf2(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
__ tst(result, Operand(kSlicedNotConsMask));
__ b(eq, &cons_string);
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Mon Aug 29 04:41:23
2011
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Tue Aug 30 01:22:41
2011
@@ -5642,9 +5642,6 @@
void SubStringStub::Generate(MacroAssembler* masm) {
Label runtime;
- if (FLAG_string_slices) {
- __ jmp(&runtime);
- }
// Stack frame on entry.
// esp[0]: return address
// esp[4]: to
@@ -5706,7 +5703,83 @@
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
__ Set(ecx, Immediate(2));
- __ bind(&result_longer_than_two);
+ if (FLAG_string_slices) {
+ Label copy_rountine;
+ // If coming from the make_two_character_string path, the string
+ // is too short to be sliced anyways.
+ STATIC_ASSERT(2 < SlicedString::kMinLength);
+ __ jmp(©_routine);
+ __ bind(&result_longer_than_two);
+
+ // eax: string
+ // ebx: instance type
+ // ecx: sub string length
+ // edx: from index (smi)
+ Label allocate_slice, sliced_string, seq_string;
+ __ cmp(ecx, SlicedString::kMinLength);
+ // Short slice. Copy instead of slicing.
+ __ j(less, ©_routine);
+ STATIC_ASSERT(kSeqStringTag == 0);
+ __ test(ebx, Immediate(kStringRepresentationMask));
+ __ j(zero, &seq_string, Label::kNear);
+ STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag &
kConsStringTag));
+ STATIC_ASSERT(kIsIndirectStringMask != 0);
+ __ test(ebx, Immediate(kIsIndirectStringMask));
+ // External string. Jump to runtime.
+ __ j(zero, &runtime);
+
+ Factory* factory = masm->isolate()->factory();
+ __ test(ebx, Immediate(kSlicedNotConsMask));
+ __ j(not_zero, &sliced_string, Label::kNear);
+ // Cons string. Check whether it is flat, then fetch first part.
+ __ cmp(FieldOperand(eax, ConsString::kSecondOffset),
+ factory->empty_string());
+ __ j(not_equal, &runtime);
+ __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset));
+ __ jmp(&allocate_slice, Label::kNear);
+
+ __ bind(&sliced_string);
+ // Sliced string. Fetch parent and correct start index by offset.
+ __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset));
+ __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset));
+ __ jmp(&allocate_slice, Label::kNear);
+
+ __ bind(&seq_string);
+ // Sequential string. Just move string to the right register.
+ __ mov(edi, eax);
+
+ __ bind(&allocate_slice);
+ // edi: underlying subject string
+ // ebx: instance type of original subject string
+ // edx: offset
+ // ecx: length
+ // Allocate new sliced string. At this point we do not reload the
instance
+ // type including the string encoding because we simply rely on the
info
+ // provided by the original string. It does not matter if the original
+ // string's encoding is wrong because we always have to recheck
encoding of
+ // the newly created string's parent anyways due to externalized
strings.
+ Label two_byte_slice, set_slice_header;
+ STATIC_ASSERT(kAsciiStringTag != 0);
+ __ test(ebx, Immediate(kAsciiStringTag));
+ __ j(zero, &two_byte_slice, Label::kNear);
+ __ AllocateAsciiSlicedString(eax, ebx, no_reg, &runtime);
+ __ jmp(&set_slice_header, Label::kNear);
+ __ bind(&two_byte_slice);
+ __ AllocateSlicedString(eax, ebx, no_reg, &runtime);
+ __ bind(&set_slice_header);
+ __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx);
+ __ SmiTag(ecx);
+ __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx);
+ __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi);
+ __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset),
+ Immediate(String::kEmptyHashField));
+ __ jmp(&return_eax);
+
+ __ bind(©_routine);
+ } else {
+ __ bind(&result_longer_than_two);
+ }
+
// eax: string
// ebx: instance type
// ecx: result string length
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Aug 26
06:03:30 2011
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Aug 30
01:22:41 2011
@@ -3234,8 +3234,6 @@
// Dispatch on the indirect string shape: slice or cons.
Label cons_string;
- const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
- ASSERT(IsPowerOf2(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
__ test(result, Immediate(kSlicedNotConsMask));
__ j(zero, &cons_string, Label::kNear);
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Aug 29
06:02:35 2011
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Aug 30
01:22:41 2011
@@ -1206,6 +1206,42 @@
mov(FieldOperand(result, HeapObject::kMapOffset),
Immediate(isolate()->factory()->cons_ascii_string_map()));
}
+
+
+void MacroAssembler::AllocateSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ // Allocate heap number in new space.
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ // Set the map. The other fields are left uninitialized.
+ mov(FieldOperand(result, HeapObject::kMapOffset),
+ Immediate(isolate()->factory()->sliced_string_map()));
+}
+
+
+void MacroAssembler::AllocateAsciiSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ // Allocate heap number in new space.
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ // Set the map. The other fields are left uninitialized.
+ mov(FieldOperand(result, HeapObject::kMapOffset),
+ Immediate(isolate()->factory()->sliced_ascii_string_map()));
+}
// Copy memory, byte-by-byte, from source to destination. Not optimized
for
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Mon Aug 29
06:02:35 2011
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Tue Aug 30
01:22:41 2011
@@ -446,6 +446,17 @@
Register scratch2,
Label* gc_required);
+ // Allocate a raw sliced string object. Only the map field of the result
is
+ // initialized.
+ void AllocateSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+ void AllocateAsciiSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+
// Copy memory, byte-by-byte, from source to destination. Not optimized
for
// long or aligned copies.
// The contents of index and scratch are destroyed.
=======================================
--- /branches/bleeding_edge/src/objects.h Fri Aug 26 06:03:30 2011
+++ /branches/bleeding_edge/src/objects.h Tue Aug 30 01:22:41 2011
@@ -496,6 +496,11 @@
STATIC_ASSERT(
(kSlicedStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
+// Use this mask to distinguish between cons and slice only after making
+// sure that the string is one of the two (an indirect string).
+const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
+STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask) && kSlicedNotConsMask !=
0);
+
// If bit 7 is clear, then bit 3 indicates whether this two-byte
// string actually contains ascii data.
const uint32_t kAsciiDataHintMask = 0x08;
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Aug 26
06:03:30 2011
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Aug 30
01:22:41 2011
@@ -3217,8 +3217,6 @@
// Dispatch on the indirect string shape: slice or cons.
Label cons_string;
- const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
- ASSERT(IsPowerOf2(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
__ testb(result, Immediate(kSlicedNotConsMask));
__ j(zero, &cons_string, Label::kNear);
=======================================
--- /branches/bleeding_edge/test/mjsunit/string-slices.js Fri Aug 26
06:03:30 2011
+++ /branches/bleeding_edge/test/mjsunit/string-slices.js Tue Aug 30
01:22:41 2011
@@ -72,7 +72,7 @@
}
/x/.exec(x); // Try to force a flatten.
for (var i = 5; i < 25; i++) {
- for (var j = 12; j < 25; j++) {
+ for (var j = 0; j < 25; j++) {
var z = x.substring(i, i+j);
var w = Math.random() * 42; // Allocate something new in new-space.
assertEquals(j, z.length);
@@ -110,7 +110,7 @@
x += x;
var xl = x.length;
var cache = [];
-for (var i = 0; i < 10000; i++) {
+for (var i = 0; i < 1000; i++) {
var z = x.substring(i % xl);
assertEquals(xl - (i % xl), z.length);
cache.push(z);
@@ -129,7 +129,7 @@
x += x;
var xl = x.length;
var cache = [];
-for (var i = 0; i < 10000; i++) {
+for (var i = 0; i < 1000; i++) {
var z = x.substring(i % xl);
assertEquals(xl - (i % xl), z.length);
cache.push(z);
@@ -149,6 +149,7 @@
var z = cache.pop();
assertTrue(/\u2028123456789ABCDEF/.test(z));
assertEquals(xl - offset, z.length);
+ assertEquals(x.charAt(i*(i+1)/2), z.charAt(0));
offset -= i;
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev