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, |