Simplify StringCharCodeAt in non-crankshaft codegen.

TEST=test/mjsunit/string-slices.js

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2011-11-09 14:32:51 +00:00
parent 8b7bcc4e80
commit 6157562994
18 changed files with 99 additions and 139 deletions

View File

@ -5056,14 +5056,11 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// If the index is non-smi trigger the non-smi case.
__ JumpIfNotSmi(index_, &index_not_smi_);
// Put smi-tagged index into scratch register.
__ mov(scratch_, index_);
__ bind(&got_smi_index_);
// Check for index out of range.
__ ldr(ip, FieldMemOperand(object_, String::kLengthOffset));
__ cmp(ip, Operand(scratch_));
__ cmp(ip, Operand(index_));
__ b(ls, index_out_of_range_);
// We need special handling for non-flat strings.
@ -5089,27 +5086,27 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
__ LoadRoot(ip, Heap::kEmptyStringRootIndex);
__ cmp(result_, Operand(ip));
__ b(ne, &call_runtime_);
// Get the first of the two strings and load its instance type.
__ ldr(result_, FieldMemOperand(object_, ConsString::kFirstOffset));
// Get the first of the two parts.
__ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset));
__ jmp(&assure_seq_string);
// SlicedString, unpack and add offset.
__ bind(&sliced_string);
__ ldr(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset));
__ add(scratch_, scratch_, result_);
__ ldr(result_, FieldMemOperand(object_, SlicedString::kParentOffset));
__ add(index_, index_, result_);
__ ldr(object_, FieldMemOperand(object_, SlicedString::kParentOffset));
// Assure that we are dealing with a sequential string. Go to runtime if not.
__ bind(&assure_seq_string);
__ ldr(result_, FieldMemOperand(result_, HeapObject::kMapOffset));
__ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
__ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
// Check that parent is not an external string. Go to runtime otherwise.
// Note that if the original string is a cons or slice with an external
// string as underlying string, we pass that unpacked underlying string with
// the updated index to the runtime function.
STATIC_ASSERT(kSeqStringTag == 0);
__ tst(result_, Operand(kStringRepresentationMask));
__ b(ne, &call_runtime_);
// Actually fetch the parent string if it is confirmed to be sequential.
STATIC_ASSERT(SlicedString::kParentOffset == ConsString::kFirstOffset);
__ ldr(object_, FieldMemOperand(object_, SlicedString::kParentOffset));
// Check for 1-byte or 2-byte string.
__ bind(&flat_string);
@ -5123,15 +5120,15 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// add without shifting since the smi tag size is the log2 of the
// number of bytes in a two-byte character.
STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0);
__ add(scratch_, object_, Operand(scratch_));
__ ldrh(result_, FieldMemOperand(scratch_, SeqTwoByteString::kHeaderSize));
__ add(index_, object_, Operand(index_));
__ ldrh(result_, FieldMemOperand(index_, SeqTwoByteString::kHeaderSize));
__ jmp(&got_char_code);
// ASCII string.
// Load the byte into the result register.
__ bind(&ascii_string);
__ add(scratch_, object_, Operand(scratch_, LSR, kSmiTagSize));
__ ldrb(result_, FieldMemOperand(scratch_, SeqAsciiString::kHeaderSize));
__ add(index_, object_, Operand(index_, LSR, kSmiTagSize));
__ ldrb(result_, FieldMemOperand(index_, SeqAsciiString::kHeaderSize));
__ bind(&got_char_code);
__ mov(result_, Operand(result_, LSL, kSmiTagSize));
@ -5148,12 +5145,12 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ bind(&index_not_smi_);
// If index is a heap number, try converting it to an integer.
__ CheckMap(index_,
scratch_,
result_,
Heap::kHeapNumberMapRootIndex,
index_not_number_,
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
__ Push(object_, index_);
__ push(object_);
__ push(index_); // Consumed by runtime conversion function.
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
@ -5164,15 +5161,14 @@ void StringCharCodeAtGenerator::GenerateSlow(
}
// Save the conversion result before the pop instructions below
// have a chance to overwrite it.
__ Move(scratch_, r0);
__ pop(index_);
__ Move(index_, r0);
__ pop(object_);
// Reload the instance type.
__ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
__ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
call_helper.AfterCall(masm);
// If index is still not a smi, it must be out of range.
__ JumpIfNotSmi(scratch_, index_out_of_range_);
__ JumpIfNotSmi(index_, index_out_of_range_);
// Otherwise, return to the fast path.
__ jmp(&got_smi_index_);

View File

@ -3033,7 +3033,6 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
Register object = r1;
Register index = r0;
Register scratch = r2;
Register result = r3;
__ pop(object);
@ -3043,7 +3042,6 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
Label done;
StringCharCodeAtGenerator generator(object,
index,
scratch,
result,
&need_conversion,
&need_conversion,
@ -3080,8 +3078,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
Register object = r1;
Register index = r0;
Register scratch1 = r2;
Register scratch2 = r3;
Register scratch = r3;
Register result = r0;
__ pop(object);
@ -3091,8 +3088,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
Label done;
StringCharAtGenerator generator(object,
index,
scratch1,
scratch2,
scratch,
result,
&need_conversion,
&need_conversion,

View File

@ -1109,14 +1109,12 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
Register receiver = r1;
Register index = r0;
Register scratch1 = r2;
Register scratch2 = r3;
Register scratch = r3;
Register result = r0;
StringCharAtGenerator char_at_generator(receiver,
index,
scratch1,
scratch2,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.

View File

@ -3647,6 +3647,9 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Check whether the string is sequential. The only non-sequential
// shapes we support have just been unwrapped above.
// Note that if the original string is a cons or slice with an external
// string as underlying string, we pass that unpacked underlying string with
// the updated index to the runtime function.
__ bind(&check_sequential);
STATIC_ASSERT(kSeqStringTag == 0);
__ tst(result, Operand(kStringRepresentationMask));

View File

@ -1727,7 +1727,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Register receiver = r1;
Register index = r4;
Register scratch = r3;
Register result = r0;
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
if (argc > 0) {
@ -1738,7 +1737,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
StringCharCodeAtGenerator generator(receiver,
index,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.
@ -1809,8 +1807,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Register receiver = r0;
Register index = r4;
Register scratch1 = r1;
Register scratch2 = r3;
Register scratch = r3;
Register result = r0;
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
if (argc > 0) {
@ -1821,8 +1818,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
StringCharAtGenerator generator(receiver,
index,
scratch1,
scratch2,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.

View File

@ -771,7 +771,6 @@ class StringCharCodeAtGenerator {
public:
StringCharCodeAtGenerator(Register object,
Register index,
Register scratch,
Register result,
Label* receiver_not_string,
Label* index_not_number,
@ -779,7 +778,6 @@ class StringCharCodeAtGenerator {
StringIndexFlags index_flags)
: object_(object),
index_(index),
scratch_(scratch),
result_(result),
receiver_not_string_(receiver_not_string),
index_not_number_(index_not_number),
@ -805,7 +803,6 @@ class StringCharCodeAtGenerator {
private:
Register object_;
Register index_;
Register scratch_;
Register result_;
Label* receiver_not_string_;
@ -868,8 +865,7 @@ class StringCharAtGenerator {
public:
StringCharAtGenerator(Register object,
Register index,
Register scratch1,
Register scratch2,
Register scratch,
Register result,
Label* receiver_not_string,
Label* index_not_number,
@ -877,13 +873,12 @@ class StringCharAtGenerator {
StringIndexFlags index_flags)
: char_code_at_generator_(object,
index,
scratch1,
scratch2,
scratch,
receiver_not_string,
index_not_number,
index_out_of_range,
index_flags),
char_from_code_generator_(scratch2, result) {}
char_from_code_generator_(scratch, result) {}
// Generates the fast case code. On the fallthrough path |result|
// register contains the result.

View File

@ -5106,13 +5106,10 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// If the index is non-smi trigger the non-smi case.
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfNotSmi(index_, &index_not_smi_);
// Put smi-tagged index into scratch register.
__ mov(scratch_, index_);
__ bind(&got_smi_index_);
// Check for index out of range.
__ cmp(scratch_, FieldOperand(object_, String::kLengthOffset));
__ cmp(index_, FieldOperand(object_, String::kLengthOffset));
__ j(above_equal, index_out_of_range_);
// We need special handling for non-flat strings.
@ -5137,25 +5134,25 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
__ cmp(FieldOperand(object_, ConsString::kSecondOffset),
Immediate(masm->isolate()->factory()->empty_string()));
__ j(not_equal, &call_runtime_);
// Get the first of the two strings and load its instance type.
__ mov(result_, FieldOperand(object_, ConsString::kFirstOffset));
// Get the first of the two parts.
__ mov(object_, FieldOperand(object_, ConsString::kFirstOffset));
__ jmp(&assure_seq_string, Label::kNear);
// SlicedString, unpack and add offset.
__ bind(&sliced_string);
__ add(scratch_, FieldOperand(object_, SlicedString::kOffsetOffset));
__ mov(result_, FieldOperand(object_, SlicedString::kParentOffset));
__ add(index_, FieldOperand(object_, SlicedString::kOffsetOffset));
__ mov(object_, FieldOperand(object_, SlicedString::kParentOffset));
// Assure that we are dealing with a sequential string. Go to runtime if not.
// Note that if the original string is a cons or slice with an external
// string as underlying string, we pass that unpacked underlying string with
// the updated index to the runtime function.
__ bind(&assure_seq_string);
__ mov(result_, FieldOperand(result_, HeapObject::kMapOffset));
__ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
__ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
STATIC_ASSERT(kSeqStringTag == 0);
__ test(result_, Immediate(kStringRepresentationMask));
__ j(not_zero, &call_runtime_);
// Actually fetch the parent string if it is confirmed to be sequential.
STATIC_ASSERT(SlicedString::kParentOffset == ConsString::kFirstOffset);
__ mov(object_, FieldOperand(object_, SlicedString::kParentOffset));
// Check for 1-byte or 2-byte string.
__ bind(&flat_string);
@ -5168,16 +5165,16 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Load the 2-byte character code into the result register.
STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
__ movzx_w(result_, FieldOperand(object_,
scratch_, times_1, // Scratch is smi-tagged.
index_, times_1, // Scratch is smi-tagged.
SeqTwoByteString::kHeaderSize));
__ jmp(&got_char_code, Label::kNear);
// ASCII string.
// Load the byte into the result register.
__ bind(&ascii_string);
__ SmiUntag(scratch_);
__ SmiUntag(index_);
__ movzx_b(result_, FieldOperand(object_,
scratch_, times_1,
index_, times_1,
SeqAsciiString::kHeaderSize));
__ bind(&got_char_code);
__ SmiTag(result_);
@ -5199,7 +5196,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
__ push(object_);
__ push(index_);
__ push(index_); // Consumed by runtime conversion function.
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
@ -5208,12 +5204,11 @@ void StringCharCodeAtGenerator::GenerateSlow(
// NumberToSmi discards numbers that are not exact integers.
__ CallRuntime(Runtime::kNumberToSmi, 1);
}
if (!scratch_.is(eax)) {
if (!index_.is(eax)) {
// Save the conversion result before the pop instructions below
// have a chance to overwrite it.
__ mov(scratch_, eax);
__ mov(index_, eax);
}
__ pop(index_);
__ pop(object_);
// Reload the instance type.
__ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
@ -5221,7 +5216,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
call_helper.AfterCall(masm);
// If index is still not a smi, it must be out of range.
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfNotSmi(scratch_, index_out_of_range_);
__ JumpIfNotSmi(index_, index_out_of_range_);
// Otherwise, return to the fast path.
__ jmp(&got_smi_index_);

View File

@ -2936,7 +2936,6 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
Register object = ebx;
Register index = eax;
Register scratch = ecx;
Register result = edx;
__ pop(object);
@ -2946,7 +2945,6 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
Label done;
StringCharCodeAtGenerator generator(object,
index,
scratch,
result,
&need_conversion,
&need_conversion,
@ -2984,8 +2982,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
Register object = ebx;
Register index = eax;
Register scratch1 = ecx;
Register scratch2 = edx;
Register scratch = edx;
Register result = eax;
__ pop(object);
@ -2995,8 +2992,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
Label done;
StringCharAtGenerator generator(object,
index,
scratch1,
scratch2,
scratch,
result,
&need_conversion,
&need_conversion,

View File

@ -606,14 +606,12 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
Register receiver = edx;
Register index = eax;
Register scratch1 = ebx;
Register scratch2 = ecx;
Register scratch = ecx;
Register result = eax;
StringCharAtGenerator char_at_generator(receiver,
index,
scratch1,
scratch2,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.

View File

@ -3451,6 +3451,9 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Check whether the string is sequential. The only non-sequential
// shapes we support have just been unwrapped above.
// Note that if the original string is a cons or slice with an external
// string as underlying string, we pass that unpacked underlying string with
// the updated index to the runtime function.
__ bind(&check_sequential);
STATIC_ASSERT(kSeqStringTag == 0);
__ test(result, Immediate(kStringRepresentationMask));

View File

@ -1624,7 +1624,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Register receiver = ebx;
Register index = edi;
Register scratch = edx;
Register result = eax;
__ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
if (argc > 0) {
@ -1635,7 +1634,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
StringCharCodeAtGenerator generator(receiver,
index,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.
@ -1709,8 +1707,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Register receiver = eax;
Register index = edi;
Register scratch1 = ebx;
Register scratch2 = edx;
Register scratch = edx;
Register result = eax;
__ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
if (argc > 0) {
@ -1721,8 +1718,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
StringCharAtGenerator generator(receiver,
index,
scratch1,
scratch2,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.

View File

@ -4068,13 +4068,10 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// If the index is non-smi trigger the non-smi case.
__ JumpIfNotSmi(index_, &index_not_smi_);
// Put smi-tagged index into scratch register.
__ movq(scratch_, index_);
__ bind(&got_smi_index_);
// Check for index out of range.
__ SmiCompare(scratch_, FieldOperand(object_, String::kLengthOffset));
__ SmiCompare(index_, FieldOperand(object_, String::kLengthOffset));
__ j(above_equal, index_out_of_range_);
// We need special handling for non-flat strings.
@ -4099,46 +4096,47 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
__ CompareRoot(FieldOperand(object_, ConsString::kSecondOffset),
Heap::kEmptyStringRootIndex);
__ j(not_equal, &call_runtime_);
// Get the first of the two strings and load its instance type.
// Get the first of the two parts.
ASSERT(!kScratchRegister.is(scratch_));
__ movq(kScratchRegister, FieldOperand(object_, ConsString::kFirstOffset));
__ movq(object_, FieldOperand(object_, ConsString::kFirstOffset));
__ jmp(&assure_seq_string, Label::kNear);
// SlicedString, unpack and add offset.
__ bind(&sliced_string);
__ addq(scratch_, FieldOperand(object_, SlicedString::kOffsetOffset));
__ movq(kScratchRegister, FieldOperand(object_, SlicedString::kParentOffset));
__ addq(index_, FieldOperand(object_, SlicedString::kOffsetOffset));
__ movq(object_, FieldOperand(object_, SlicedString::kParentOffset));
// Assure that we are dealing with a sequential string. Go to runtime if not.
// Note that if the original string is a cons or slice with an external
// string as underlying string, we pass that unpacked underlying string with
// the updated index to the runtime function.
__ bind(&assure_seq_string);
__ movq(result_, FieldOperand(kScratchRegister, HeapObject::kMapOffset));
__ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
__ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
// If the first cons component is also non-flat, then go to runtime.
STATIC_ASSERT(kSeqStringTag == 0);
__ testb(result_, Immediate(kStringRepresentationMask));
__ j(not_zero, &call_runtime_);
__ movq(object_, kScratchRegister);
// Check for 1-byte or 2-byte string.
__ bind(&flat_string);
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ SmiToInteger32(index_, index_);
__ testb(result_, Immediate(kStringEncodingMask));
__ j(not_zero, &ascii_string);
// 2-byte string.
// Load the 2-byte character code into the result register.
__ SmiToInteger32(scratch_, scratch_);
__ movzxwl(result_, FieldOperand(object_,
scratch_, times_2,
index_, times_2,
SeqTwoByteString::kHeaderSize));
__ jmp(&got_char_code);
// ASCII string.
// Load the byte into the result register.
__ bind(&ascii_string);
__ SmiToInteger32(scratch_, scratch_);
__ movzxbl(result_, FieldOperand(object_,
scratch_, times_1,
index_, times_1,
SeqAsciiString::kHeaderSize));
__ bind(&got_char_code);
__ Integer32ToSmi(result_, result_);
@ -4161,7 +4159,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
DONT_DO_SMI_CHECK);
call_helper.BeforeCall(masm);
__ push(object_);
__ push(index_);
__ push(index_); // Consumed by runtime conversion function.
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
@ -4170,19 +4167,18 @@ void StringCharCodeAtGenerator::GenerateSlow(
// NumberToSmi discards numbers that are not exact integers.
__ CallRuntime(Runtime::kNumberToSmi, 1);
}
if (!scratch_.is(rax)) {
if (!index_.is(rax)) {
// Save the conversion result before the pop instructions below
// have a chance to overwrite it.
__ movq(scratch_, rax);
__ movq(index_, rax);
}
__ pop(index_);
__ pop(object_);
// Reload the instance type.
__ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
__ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
call_helper.AfterCall(masm);
// If index is still not a smi, it must be out of range.
__ JumpIfNotSmi(scratch_, index_out_of_range_);
__ JumpIfNotSmi(index_, index_out_of_range_);
// Otherwise, return to the fast path.
__ jmp(&got_smi_index_);

View File

@ -2865,7 +2865,6 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
Register object = rbx;
Register index = rax;
Register scratch = rcx;
Register result = rdx;
__ pop(object);
@ -2875,7 +2874,6 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
Label done;
StringCharCodeAtGenerator generator(object,
index,
scratch,
result,
&need_conversion,
&need_conversion,
@ -2913,8 +2911,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
Register object = rbx;
Register index = rax;
Register scratch1 = rcx;
Register scratch2 = rdx;
Register scratch = rdx;
Register result = rax;
__ pop(object);
@ -2924,8 +2921,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
Label done;
StringCharAtGenerator generator(object,
index,
scratch1,
scratch2,
scratch,
result,
&need_conversion,
&need_conversion,

View File

@ -531,14 +531,12 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
Register receiver = rdx;
Register index = rax;
Register scratch1 = rbx;
Register scratch2 = rcx;
Register scratch = rcx;
Register result = rax;
StringCharAtGenerator char_at_generator(receiver,
index,
scratch1,
scratch2,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.

View File

@ -3380,6 +3380,9 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Check whether the string is sequential. The only non-sequential
// shapes we support have just been unwrapped above.
// Note that if the original string is a cons or slice with an external
// string as underlying string, we pass that unpacked underlying string with
// the updated index to the runtime function.
__ bind(&check_sequential);
STATIC_ASSERT(kSeqStringTag == 0);
__ testb(result, Immediate(kStringRepresentationMask));

View File

@ -1600,7 +1600,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Register receiver = rbx;
Register index = rdi;
Register scratch = rdx;
Register result = rax;
__ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
if (argc > 0) {
@ -1611,7 +1610,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
StringCharCodeAtGenerator generator(receiver,
index,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.
@ -1680,8 +1678,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Register receiver = rax;
Register index = rdi;
Register scratch1 = rbx;
Register scratch2 = rdx;
Register scratch = rdx;
Register result = rax;
__ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
if (argc > 0) {
@ -1692,8 +1689,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
StringCharAtGenerator generator(receiver,
index,
scratch1,
scratch2,
scratch,
result,
&miss, // When not a string.
&miss, // When not a number.

View File

@ -24,11 +24,6 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Flags: --string-slices
//assertEquals('345"12345 6"1234567"123',
// '12345""12345 6""1234567""1234'.slice(2,-1).replace(/""/g, '"'));
var foo = "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl";
for(var i = 0; i < 1000; i++) {

View File

@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --string-slices --expose-externalize-string
// Flags: --expose-externalize-string --allow-natives-syntax
var s = 'abcdefghijklmn';
assertEquals(s, s.substr());
@ -100,14 +100,7 @@ for (var i = 5; i < 25; i++) {
// Keep creating strings to to force allocation failure on substring creation.
var x = "0123456789ABCDEF";
x += x; // 2^5
x += x;
x += x;
x += x;
x += x;
x += x; // 2^10
x += x;
x += x;
for (var i = 0; i < 8; i++) x += x;
var xl = x.length;
var cache = [];
for (var i = 0; i < 1000; i++) {
@ -119,14 +112,7 @@ for (var i = 0; i < 1000; i++) {
// Same with two-byte strings
var x = "\u2028123456789ABCDEF";
x += x; // 2^5
x += x;
x += x;
x += x;
x += x;
x += x; // 2^10
x += x;
x += x;
for (var i = 0; i < 8; i++) x += x;
var xl = x.length;
var cache = [];
for (var i = 0; i < 1000; i++) {
@ -202,3 +188,21 @@ assertEquals(a.slice(1,-1), b);
assertTrue(/3456789qwe/.test(a));
assertEquals(5, a.indexOf("678"));
assertEquals("12345", a.split("6")[0]);
// Create a slice with an external string as parent string.
var c = a.slice(1,-1);
function test_crankshaft() {
for (var i = 0; i < 20; i++) {
assertEquals(b.charAt(i), a.charAt(i + 1));
assertEquals(b.charAt(i), c.charAt(i));
assertEquals(b.charAt(4), c.charAt(4));
assertTrue(/3456789qwe/.test(c));
assertEquals(4, c.indexOf("678"));
assertEquals("2345", c.split("6")[0]);
}
}
test_crankshaft();
%OptimizeFunctionOnNextCall(test_crankshaft);
test_crankshaft();