Chromium Code Reviews| Index: src/ic-arm.cc |
| =================================================================== |
| --- src/ic-arm.cc (revision 606) |
| +++ src/ic-arm.cc (working copy) |
| @@ -156,6 +156,28 @@ |
| } |
| +// Generate code to check is an object is a string. If the object is |
| +// a string, the map's instance type is left in the scratch1 register. |
| +static void GenerateStringCheck(MacroAssembler* masm, |
| + Register receiver, |
| + Register scratch1, |
|
Erik Corry
2008/10/27 14:41:23
This shouldn't be called scratch, since we are goi
|
| + Register scratch2, |
| + Label* smi, |
| + Label* non_string_object) { |
| + // Check that the receiver isn't a smi. |
| + __ tst(receiver, Operand(kSmiTagMask)); |
| + __ b(eq, smi); |
| + |
| + // Check that the object is a string. |
| + __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| + __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| + __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); |
| + // The cast is to resolve the overload for the argument of 0x0. |
| + __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); |
| + __ b(ne, non_string_object); |
| +} |
| + |
| + |
| void LoadIC::GenerateStringLength(MacroAssembler* masm) { |
| // ----------- S t a t e ------------- |
| // -- r2 : name |
| @@ -163,30 +185,33 @@ |
| // -- [sp] : receiver |
| // ----------------------------------- |
| - Label miss; |
| + Label miss, load_length, check_wrapper; |
| __ ldr(r0, MemOperand(sp, 0)); |
| - // Check that the receiver isn't a smi. |
| - __ tst(r0, Operand(kSmiTagMask)); |
| - __ b(eq, &miss); |
| + // Check if the object is a string. |
| + GenerateStringCheck(masm, r0, r1, r3, &miss, &check_wrapper); |
| - // Check that the object is a string. |
| - __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| - __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
| - __ and_(r3, r1, Operand(kIsNotStringMask)); |
| - // The cast is to resolve the overload for the argument of 0x0. |
| - __ cmp(r3, Operand(static_cast<int32_t>(kStringTag))); |
| - __ b(ne, &miss); |
| - |
| + // Load length directly from the string. |
| + __ bind(&load_length); |
| __ and_(r1, r1, Operand(kStringSizeMask)); |
| __ add(r1, r1, Operand(String::kHashShift)); |
| - // Load length directly from the string. |
| __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset)); |
| __ mov(r0, Operand(r0, LSR, r1)); |
| __ mov(r0, Operand(r0, LSL, kSmiTagSize)); |
| __ Ret(); |
| + // Check if the object is a JSValue wrapper. |
| + __ bind(&check_wrapper); |
| + __ cmp(r0, Operand(JS_VALUE_TYPE)); |
| + __ b(ne, &miss); |
| + |
| + // Check if the wrapped value is a string and load the length |
| + // directly if it is. |
| + __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); |
| + GenerateStringCheck(masm, r0, r1, r3, &miss, &miss); |
| + __ b(&load_length); |
| + |
| // Cache miss: Jump to runtime. |
| __ bind(&miss); |
| Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss)); |