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..2f6374dfafc736ca4d65e03960e6844f158ce1aa 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, sliced_ascii_string, done; |
// Fetch the instance type of the receiver into result register. |
__ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
@@ -3181,15 +3182,47 @@ 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); |
+ if (instr->index()->IsConstantOperand()) { |
+ __ addq(offset, Immediate(const_index)); |
+ } else { |
+ __ addq(offset, index); |
+ } |
+ __ movq(string, FieldOperand(string, SlicedString::kParentOffset)); |
+ __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
+ __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
+ // Check for ASCII or two-byte string. |
+ STATIC_ASSERT(kAsciiStringTag != 0); |
+ __ testb(result, Immediate(kStringEncodingMask)); |
+ __ j(not_zero, &sliced_ascii_string, Label::kNear); |
+ __ movzxwl(result, FieldOperand(string, |
+ offset, |
+ times_2, |
+ SeqTwoByteString::kHeaderSize)); |
+ __ jmp(&done, Label::kNear); |
+ __ bind(&sliced_ascii_string); |
+ __ movzxbl(result, FieldOperand(string, |
+ offset, |
+ times_1, |
+ SeqAsciiString::kHeaderSize)); |
+ __ jmp(&done, 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()); |