Chromium Code Reviews| Index: src/arm/codegen-arm.cc | 
| =================================================================== | 
| --- src/arm/codegen-arm.cc (revision 3319) | 
| +++ src/arm/codegen-arm.cc (working copy) | 
| @@ -3286,7 +3286,81 @@ | 
| void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 
| VirtualFrame::SpilledScope spilled_scope; | 
| ASSERT(args->length() == 2); | 
| + Comment(masm_, "[ GenerateFastCharCodeAt"); | 
| + | 
| + LoadAndSpill(args->at(0)); | 
| + LoadAndSpill(args->at(1)); | 
| + frame_->EmitPop(r0); // Index. | 
| + frame_->EmitPop(r1); // String. | 
| + | 
| + Label slow, end, not_a_flat_string, ascii_string, try_again_with_new_string; | 
| + | 
| + __ tst(r1, Operand(kSmiTagMask)); | 
| + __ b(eq, &slow); // The 'string' was a Smi. | 
| + | 
| + ASSERT(kSmiTag == 0); | 
| + __ tst(r0, Operand(kSmiTagMask | 0x80000000u)); | 
| + __ b(ne, &slow); // The index was negative or not a Smi. | 
| + | 
| + __ bind(&try_again_with_new_string); | 
| + __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE); | 
| + __ b(ge, &slow); | 
| + | 
| + // Now r2 has the string type. | 
| + __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); | 
| + __ and_(r4, r2, Operand(kStringSizeMask)); | 
| + __ add(r4, r4, Operand(String::kLongLengthShift)); | 
| + __ mov(r3, Operand(r3, LSR, r4)); | 
| + // Now r3 has the length of the string. Compare with the index. | 
| + __ cmp(r3, Operand(r0, LSR, kSmiTagSize)); | 
| + __ b(le, &slow); | 
| + | 
| + // Here we know the index is in range. Check that string is sequential. | 
| + ASSERT_EQ(0, kSeqStringTag); | 
| + __ tst(r2, Operand(kStringRepresentationMask)); | 
| + __ b(ne, ¬_a_flat_string); | 
| + | 
| + // Check whether it is an ASCII string. | 
| + ASSERT_EQ(0, kTwoByteStringTag); | 
| + __ tst(r2, Operand(kStringEncodingMask)); | 
| + __ b(ne, &ascii_string); | 
| + | 
| + // 2-byte string. We can add without shifting since the Smi tag size is the | 
| + // log2 of the number of bytes in a two-byte character. | 
| + ASSERT_EQ(1, kSmiTagSize); | 
| 
 
Lasse Reichstein
2009/11/18 10:04:08
Might also want to assert that kSmiShiftSize is ze
 
 | 
| + __ add(r1, r1, Operand(r0)); | 
| + __ ldrh(r0, FieldMemOperand(r1, SeqTwoByteString::kHeaderSize)); | 
| + __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 
| + __ jmp(&end); | 
| + | 
| + __ bind(&ascii_string); | 
| + __ add(r1, r1, Operand(r0, LSR, kSmiTagSize)); | 
| + __ ldrb(r0, FieldMemOperand(r1, SeqAsciiString::kHeaderSize)); | 
| + __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 
| + __ jmp(&end); | 
| + | 
| + __ bind(¬_a_flat_string); | 
| + __ and_(r2, r2, Operand(kStringRepresentationMask)); | 
| + __ cmp(r2, Operand(kConsStringTag)); | 
| + __ b(ne, &slow); | 
| + | 
| + // ConsString. | 
| + // Check that the right hand side is the empty string (ie 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. | 
| + __ ldr(r2, FieldMemOperand(r1, ConsString::kSecondOffset)); | 
| + __ LoadRoot(r3, Heap::kEmptyStringRootIndex); | 
| + __ cmp(r2, Operand(r3)); | 
| + __ b(ne, &slow); | 
| + | 
| + // Get the first of the two strings. | 
| + __ ldr(r1, FieldMemOperand(r1, ConsString::kFirstOffset)); | 
| + __ jmp(&try_again_with_new_string); | 
| + | 
| + __ bind(&slow); | 
| __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 
| + | 
| + __ bind(&end); | 
| frame_->EmitPush(r0); | 
| } |