From: yangguo@chromium.org Date: Wed, 9 Nov 2011 14:32:51 +0000 (+0000) Subject: Simplify StringCharCodeAt in non-crankshaft codegen. X-Git-Tag: upstream/4.7.83~17959 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6157562994e51ebf4d559142e0326bdc8c91592b;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 023312f..0d82682 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -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_); diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 9507717..8a333ee 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -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, diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc index 18d4a9f..f8e4bbb 100644 --- a/src/arm/ic-arm.cc +++ b/src/arm/ic-arm.cc @@ -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. diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 59f9ea0..880a34d 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -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)); diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index bf6f085..f073d09 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -1727,7 +1727,6 @@ Handle 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 CallStubCompiler::CompileStringCharCodeAtCall( StringCharCodeAtGenerator generator(receiver, index, - scratch, result, &miss, // When not a string. &miss, // When not a number. @@ -1809,8 +1807,7 @@ Handle 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 CallStubCompiler::CompileStringCharAtCall( StringCharAtGenerator generator(receiver, index, - scratch1, - scratch2, + scratch, result, &miss, // When not a string. &miss, // When not a number. diff --git a/src/code-stubs.h b/src/code-stubs.h index d49ff1d..1af4fa9 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -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. diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 432c10c..2b18af0 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -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_); diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 5b03056..bd5df17 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -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, diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index 1168932..e93353e 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -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. diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index f8459fc..8eec9c4 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -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)); diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 3089a69..6b28fe6 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -1624,7 +1624,6 @@ Handle 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 CallStubCompiler::CompileStringCharCodeAtCall( StringCharCodeAtGenerator generator(receiver, index, - scratch, result, &miss, // When not a string. &miss, // When not a number. @@ -1709,8 +1707,7 @@ Handle 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 CallStubCompiler::CompileStringCharAtCall( StringCharAtGenerator generator(receiver, index, - scratch1, - scratch2, + scratch, result, &miss, // When not a string. &miss, // When not a number. diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index bd842d9..1d1c6f0 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -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_); diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index aeff76a..b64aeb4 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -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, diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc index e8ab06c..3a57753 100644 --- a/src/x64/ic-x64.cc +++ b/src/x64/ic-x64.cc @@ -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. diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index d4875da..3b71234 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -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)); diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index 867c71a..6cee05c 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -1600,7 +1600,6 @@ Handle 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 CallStubCompiler::CompileStringCharCodeAtCall( StringCharCodeAtGenerator generator(receiver, index, - scratch, result, &miss, // When not a string. &miss, // When not a number. @@ -1680,8 +1678,7 @@ Handle 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 CallStubCompiler::CompileStringCharAtCall( StringCharAtGenerator generator(receiver, index, - scratch1, - scratch2, + scratch, result, &miss, // When not a string. &miss, // When not a number. diff --git a/test/mjsunit/string-slices-regexp.js b/test/mjsunit/string-slices-regexp.js index df01574..98b8ef9 100644 --- a/test/mjsunit/string-slices-regexp.js +++ b/test/mjsunit/string-slices-regexp.js @@ -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++) { diff --git a/test/mjsunit/string-slices.js b/test/mjsunit/string-slices.js index 7c40229..3eb30f1 100755 --- a/test/mjsunit/string-slices.js +++ b/test/mjsunit/string-slices.js @@ -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(); \ No newline at end of file