Commit 3077e8aa authored by yangguo@chromium.org's avatar yangguo@chromium.org

Generated code for substring slices in ia32.

Review URL: http://codereview.chromium.org/7744052

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9064 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4084e698
......@@ -3473,8 +3473,6 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// 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);
......
......@@ -5642,9 +5642,6 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
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 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ 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(&copy_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, &copy_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(&copy_routine);
} else {
__ bind(&result_longer_than_two);
}
// eax: string
// ebx: instance type
// ecx: result string length
......
......@@ -3234,8 +3234,6 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// 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);
......
......@@ -1208,6 +1208,42 @@ void MacroAssembler::AllocateAsciiConsString(Register result,
}
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
// long or aligned copies. The contents of scratch and length are destroyed.
// Source and destination are incremented by length.
......
......@@ -446,6 +446,17 @@ class MacroAssembler: public Assembler {
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.
......
......@@ -496,6 +496,11 @@ STATIC_ASSERT(
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;
......
......@@ -3217,8 +3217,6 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// 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);
......
......@@ -72,7 +72,7 @@ for (var i = 0; i < 25; i++) {
}
/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;
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;
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 @@ for (var i = 63; i >= 0; i--) {
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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment