Chromium Code Reviews| Index: src/arm/codegen-arm.cc |
| diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc |
| index 6b111ff5c55db34aff3b6a44fecf7bae971c1077..95f0d6e5c452b82fc6f3f7bc58f66f51e2c0a1be 100644 |
| --- a/src/arm/codegen-arm.cc |
| +++ b/src/arm/codegen-arm.cc |
| @@ -302,6 +302,112 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( |
| __ pop(lr); |
| } |
| + |
| +void StringCharLoadGenerator::Generate(MacroAssembler* masm, |
| + Register string, |
| + Register index, |
| + Register result, |
| + Label* call_runtime) { |
| + // Fetch the instance type of the receiver into result register. |
| + __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset)); |
| + __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); |
| + |
| + // We need special handling for indirect strings. |
| + Label check_sequential; |
| + __ tst(result, Operand(kIsIndirectStringMask)); |
| + __ b(eq, &check_sequential); |
| + |
| + // Dispatch on the indirect string shape: slice or cons. |
| + Label cons_string; |
| + __ tst(result, Operand(kSlicedNotConsMask)); |
| + __ b(eq, &cons_string); |
| + |
| + // Handle slices. |
| + Label indirect_string_loaded; |
| + __ ldr(result, FieldMemOperand(string, SlicedString::kOffsetOffset)); |
| + __ add(index, index, Operand(result, ASR, kSmiTagSize)); |
| + __ ldr(string, FieldMemOperand(string, SlicedString::kParentOffset)); |
| + __ jmp(&indirect_string_loaded); |
| + |
| + // Handle external strings. |
|
Rico
2011/11/24 06:55:15
Any reason for not just having this be fall-throug
Yang
2011/11/24 11:15:11
Done.
|
| + 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. |
| + __ tst(result, Operand(kIsIndirectStringMask)); |
| + __ Assert(eq, "external string expected, but not found"); |
| + } |
| + // Rule out short external strings. |
| + STATIC_CHECK(kShortExternalStringTag != 0); |
| + __ tst(result, Operand(kShortExternalStringMask)); |
| + __ b(ne, call_runtime); |
| + // Check encoding. |
| + STATIC_ASSERT(kTwoByteStringTag == 0); |
| + __ tst(result, Operand(kStringEncodingMask)); |
| + __ ldr(result, FieldMemOperand(string, ExternalString::kResourceDataOffset)); |
| + __ b(ne, &ascii_external); |
| + // Two-byte string. |
| + __ ldrh(result, MemOperand(result, index, LSL, 1)); |
| + __ jmp(&done); |
| + __ bind(&ascii_external); |
| + // Ascii string. |
| + __ ldrb(result, MemOperand(result, index)); |
| + __ jmp(&done); |
| + |
| + // Handle conses. |
|
Rico
2011/11/24 06:55:15
Handle cons strings?
Yang
2011/11/24 11:15:11
Done.
|
| + // 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); |
| + __ ldr(result, FieldMemOperand(string, ConsString::kSecondOffset)); |
| + __ LoadRoot(ip, Heap::kEmptyStringRootIndex); |
| + __ cmp(result, ip); |
| + __ b(ne, call_runtime); |
| + // Get the first of the two strings and load its instance type. |
| + __ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset)); |
| + |
| + __ bind(&indirect_string_loaded); |
| + __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset)); |
| + __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); |
| + |
| + // Check whether the string is sequential. The only non-sequential |
| + // 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. |
|
Rico
2011/11/24 06:55:15
Please fix comment, we don't do this anymore. Plea
Yang
2011/11/24 11:15:11
Done.
|
| + __ bind(&check_sequential); |
| + STATIC_ASSERT(kSeqStringTag == 0); |
| + __ tst(result, Operand(kStringRepresentationMask)); |
| + __ b(ne, &external_string); |
| + |
| + // Dispatch on the encoding: ASCII or two-byte. |
| + Label ascii_string; |
| + STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
| + STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| + __ tst(result, Operand(kStringEncodingMask)); |
| + __ b(ne, &ascii_string); |
| + |
| + // Two-byte string. |
| + // Load the two-byte character code into the result register. |
| + __ add(result, |
| + string, |
| + Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| + __ ldrh(result, MemOperand(result, index, LSL, 1)); |
| + __ jmp(&done); |
| + |
| + // ASCII string. |
| + // Load the byte into the result register. |
| + __ bind(&ascii_string); |
| + __ add(result, |
| + string, |
| + Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| + __ ldrb(result, MemOperand(result, index)); |
| + |
| + __ bind(&done); |
| +} |
| + |
| #undef __ |
| } } // namespace v8::internal |