| Index: src/x64/lithium-codegen-x64.cc
|
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
|
| index 667d78131d4500605fa95ecd336fbb1aeff87911..9bd23b5cc3a4939b2c2b729ed8e29a871c6811a6 100644
|
| --- a/src/x64/lithium-codegen-x64.cc
|
| +++ b/src/x64/lithium-codegen-x64.cc
|
| @@ -3148,6 +3148,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
|
|
| Register string = ToRegister(instr->string());
|
| Register index = no_reg;
|
| + Register offset = ToRegister(instr->TempAt(0));
|
| int const_index = -1;
|
| if (instr->index()->IsConstantOperand()) {
|
| const_index = ToInteger32(LConstantOperand::cast(instr->index()));
|
| @@ -3170,7 +3171,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
| DeferredStringCharCodeAt* deferred =
|
| new DeferredStringCharCodeAt(this, instr);
|
|
|
| - Label flat_string, ascii_string, done;
|
| + Label flat_string, ascii_string, cons_string, two_byte_string, done;
|
|
|
| // Fetch the instance type of the receiver into result register.
|
| __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
|
| @@ -3181,15 +3182,34 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
| __ testb(result, Immediate(kStringRepresentationMask));
|
| __ j(zero, &flat_string, Label::kNear);
|
|
|
| - // Handle cons strings and go to deferred code for the rest.
|
| - __ testb(result, Immediate(kIsConsStringMask));
|
| - __ j(zero, deferred->entry());
|
| + // Handle non-flat strings.
|
| + __ and_(result, Immediate(kStringRepresentationMask));
|
| + __ cmpb(result, Immediate(kConsStringTag));
|
| + __ j(equal, &cons_string, Label::kNear);
|
| + __ cmpb(result, Immediate(kExternalStringTag));
|
| + __ j(equal, deferred->entry());
|
| +
|
| + // SlicedString.
|
| + // Unpack slice, add offset and retrieve the result char.
|
| + __ movq(offset, FieldOperand(string, SlicedString::kOffsetOffset));
|
| + __ SmiToInteger32(offset, offset);
|
| + __ movq(string, FieldOperand(string, SlicedString::kParentOffset));
|
| + __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
|
| + __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
|
| + __ addq(string, offset);
|
| + // Check for ASCII or two-byte string.
|
| + STATIC_ASSERT(kAsciiStringTag != 0);
|
| + __ testb(result, Immediate(kStringEncodingMask));
|
| + __ j(not_zero, &ascii_string, Label::kNear);
|
| + __ addq(string, offset);
|
| + __ jmp(&two_byte_string, Label::kNear);
|
|
|
| // ConsString.
|
| // Check whether the right hand side is the empty string (i.e. if
|
| // this is really a flat string in a cons string). If that is not
|
| // the case we would rather go to the runtime system now to flatten
|
| // the string.
|
| + __ bind(&cons_string);
|
| __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
|
| Heap::kEmptyStringRootIndex);
|
| __ j(not_equal, deferred->entry());
|
| @@ -3210,6 +3230,7 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
|
|
| // Two-byte string.
|
| // Load the two-byte character code into the result register.
|
| + __ bind(&two_byte_string);
|
| STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
| if (instr->index()->IsConstantOperand()) {
|
| __ movzxwl(result,
|
|
|