Index: src/x64/code-stubs-x64.cc |
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
index bd842d9989612273cff5f90b4c04a51d41ccaebb..978e42fd5750200869665367cfd4750b1364d983 100644 |
--- a/src/x64/code-stubs-x64.cc |
+++ b/src/x64/code-stubs-x64.cc |
@@ -4070,11 +4070,10 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
__ 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,24 +4098,26 @@ 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); |
@@ -4127,18 +4128,18 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
// 2-byte string. |
// Load the 2-byte character code into the result register. |
- __ SmiToInteger32(scratch_, scratch_); |
+ __ SmiToInteger32(index_, index_); |
__ 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_); |
+ __ SmiToInteger32(index_, index_); |
__ movzxbl(result_, FieldOperand(object_, |
- scratch_, times_1, |
+ index_, times_1, |
SeqAsciiString::kHeaderSize)); |
__ bind(&got_char_code); |
__ Integer32ToSmi(result_, result_); |
@@ -4161,7 +4162,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 +4170,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_); |