Index: src/arm/ic-arm.cc |
=================================================================== |
--- src/arm/ic-arm.cc (revision 4542) |
+++ src/arm/ic-arm.cc (working copy) |
@@ -800,29 +800,68 @@ |
// -- sp[0] : key |
// -- sp[4] : receiver |
// ----------------------------------- |
+ Label miss; |
+ Label index_not_smi; |
+ Label index_out_of_range; |
+ Label slow_char_code; |
+ Label got_char_code; |
- Label miss, index_ok; |
- |
// Get the key and receiver object from the stack. |
__ ldm(ia, sp, r0.bit() | r1.bit()); |
- // Check that the receiver isn't a smi. |
- __ BranchOnSmi(r1, &miss); |
+ Register object = r1; |
+ Register index = r0; |
+ Register code = r2; |
+ Register scratch = r3; |
- // Check that the receiver is a string. |
- Condition is_string = masm->IsObjectStringType(r1, r2); |
- __ b(NegateCondition(is_string), &miss); |
+ StringHelper::GenerateFastCharCodeAt(masm, |
+ object, |
+ index, |
+ scratch, |
+ code, |
+ &miss, // When not a string. |
+ &index_not_smi, |
+ &index_out_of_range, |
+ &slow_char_code); |
- // Check if key is a smi or a heap number. |
- __ BranchOnSmi(r0, &index_ok); |
- __ CheckMap(r0, r2, Factory::heap_number_map(), &miss, false); |
+ // If we didn't bail out, code register contains smi tagged char |
+ // code. |
+ __ bind(&got_char_code); |
+ StringHelper::GenerateCharFromCode(masm, code, scratch, r0, JUMP_FUNCTION); |
+#ifdef DEBUG |
+ __ Abort("Unexpected fall-through from char from code tail call"); |
+#endif |
- __ bind(&index_ok); |
- // Duplicate receiver and key since they are expected on the stack after |
- // the KeyedLoadIC call. |
- __ Push(r1, r0); |
- __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_JS); |
+ // Check if key is a heap number. |
+ __ bind(&index_not_smi); |
+ __ CheckMap(index, scratch, Factory::heap_number_map(), &miss, true); |
+ // Push receiver and key on the stack (now that we know they are a |
+ // string and a number), and call runtime. |
+ __ bind(&slow_char_code); |
+ __ EnterInternalFrame(); |
+ __ Push(object, index); |
+ __ CallRuntime(Runtime::kStringCharCodeAt, 2); |
+ ASSERT(!code.is(r0)); |
+ __ mov(code, r0); |
+ __ LeaveInternalFrame(); |
+ |
+ // Check if the runtime call returned NaN char code. If yes, return |
+ // undefined. Otherwise, we can continue. |
+ if (FLAG_debug_code) { |
+ __ BranchOnSmi(code, &got_char_code); |
+ __ ldr(scratch, FieldMemOperand(code, HeapObject::kMapOffset)); |
+ __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
+ __ cmp(scratch, ip); |
+ __ Assert(eq, "StringCharCodeAt must return smi or heap number"); |
+ } |
+ __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
+ __ cmp(code, scratch); |
+ __ b(ne, &got_char_code); |
+ __ bind(&index_out_of_range); |
+ __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
+ __ Ret(); |
+ |
__ bind(&miss); |
GenerateGeneric(masm); |
} |