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 |