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); |
| } |