Chromium Code Reviews| Index: src/x64/codegen-x64.cc |
| diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc |
| index 4090ce40c4b54bcea4dd6b042adeb46d8a8f330f..3ced9a663c1fe00a5eafae4c810717258823b0ba 100644 |
| --- a/src/x64/codegen-x64.cc |
| +++ b/src/x64/codegen-x64.cc |
| @@ -367,6 +367,110 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( |
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| } |
| + |
| +void StringCharLoadGenerator::Generate(MacroAssembler* masm, |
| + Register string, |
| + Register index, |
| + Register result, |
| + Label* call_runtime) { |
| + // Fetch the instance type of the receiver into result register. |
| + __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
| + __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| + |
| + // We need special handling for indirect strings. |
| + Label check_sequential; |
| + __ testb(result, Immediate(kIsIndirectStringMask)); |
| + __ j(zero, &check_sequential); |
| + |
| + // Dispatch on the indirect string shape: slice or cons. |
| + Label cons_string; |
| + __ testb(result, Immediate(kSlicedNotConsMask)); |
| + __ j(zero, &cons_string, Label::kNear); |
| + |
| + // Handle slices. |
| + Label indirect_string_loaded; |
| + __ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset)); |
| + __ addq(index, result); |
| + __ movq(string, FieldOperand(string, SlicedString::kParentOffset)); |
| + __ jmp(&indirect_string_loaded, Label::kNear); |
| + |
| + // Handle external strings. |
|
Yang
2011/11/23 14:04:07
The interesting part starts here.
|
| + Label external_string, ascii_external, done; |
| + __ bind(&external_string); |
| + if (FLAG_debug_code) { |
| + // Assert that we do not have a cons or slice (indirect strings) here. |
| + // Sequential strings have already been ruled out. |
| + __ testb(result, Immediate(kIsIndirectStringMask)); |
| + __ Assert(zero, "external string expected, but not found"); |
| + } |
| + // Rule out short external strings. |
| + STATIC_CHECK(kShortExternalStringTag != 0); |
| + __ testb(result, Immediate(kShortExternalStringTag)); |
|
Lasse Reichstein
2011/11/24 09:52:55
kShortExternalStringMask
|
| + __ j(not_zero, call_runtime); |
| + // Check encoding. |
| + STATIC_ASSERT(kTwoByteStringTag == 0); |
| + __ testb(result, Immediate(kStringEncodingMask)); |
| + __ movq(result, FieldOperand(string, ExternalString::kResourceDataOffset)); |
| + __ j(not_equal, &ascii_external, Label::kNear); |
| + // Two-byte string. |
| + __ movzxwl(result, Operand(result, index, times_2, 0)); |
| + __ jmp(&done); |
| + __ bind(&ascii_external); |
| + // Ascii string. |
| + __ movzxbl(result, Operand(result, index, times_1, 0)); |
| + __ jmp(&done); |
| + |
| + // Handle conses. |
| + // 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, call_runtime); |
| + __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); |
| + |
| + __ bind(&indirect_string_loaded); |
| + __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
| + __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| + |
| + // Check whether the string is sequential. The only non-sequential |
|
Lasse Reichstein
2011/11/24 09:52:55
Slightly confusing comment. How about something li
|
| + // 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 adjusted index to the runtime function. |
| + __ bind(&check_sequential); |
| + STATIC_ASSERT(kSeqStringTag == 0); |
| + __ testb(result, Immediate(kStringRepresentationMask)); |
| + __ j(not_zero, &external_string); |
| + |
| + // Dispatch on the encoding: ASCII or two-byte. |
| + Label ascii_string; |
| + STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
| + STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| + __ testb(result, Immediate(kStringEncodingMask)); |
| + __ j(not_zero, &ascii_string, Label::kNear); |
| + |
| + // Two-byte string. |
| + // Load the two-byte character code into the result register. |
| + STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| + __ movzxwl(result, FieldOperand(string, |
| + index, |
| + times_2, |
| + SeqTwoByteString::kHeaderSize)); |
| + __ jmp(&done, Label::kNear); |
| + |
| + // ASCII string. |
| + // Load the byte into the result register. |
| + __ bind(&ascii_string); |
| + __ movzxbl(result, FieldOperand(string, |
| + index, |
| + times_1, |
| + SeqAsciiString::kHeaderSize)); |
| + __ bind(&done); |
| +} |
| + |
| #undef __ |
| } } // namespace v8::internal |