Index: src/x64/ic-x64.cc |
=================================================================== |
--- src/x64/ic-x64.cc (revision 4526) |
+++ src/x64/ic-x64.cc (working copy) |
@@ -523,31 +523,70 @@ |
// -- rsp[8] : name |
// -- rsp[16] : receiver |
// ----------------------------------- |
+ Label miss; |
+ Label index_not_smi; |
+ Label index_out_of_range; |
+ Label slow_char_code; |
+ Label got_char_code; |
- Label miss, index_ok; |
+ Register receiver = rdx; |
+ Register index = rax; |
+ Register code = rbx; |
+ Register scratch = rcx; |
- // Check that the receiver isn't a smi. |
- __ movq(rcx, Operand(rsp, 2 * kPointerSize)); |
- __ JumpIfSmi(rcx, &miss); |
+ __ movq(index, Operand(rsp, 1 * kPointerSize)); |
+ __ movq(receiver, Operand(rsp, 2 * kPointerSize)); |
- // Check that the receiver is a string. |
- Condition is_string = masm->IsObjectStringType(rcx, rax, rbx); |
- __ j(NegateCondition(is_string), &miss); |
+ StringHelper::GenerateFastCharCodeAt(masm, |
+ receiver, |
+ index, |
+ scratch, |
+ code, |
+ &miss, // When not a string. |
+ &index_not_smi, |
+ &index_out_of_range, |
+ &slow_char_code); |
+ // If we didn't bail out, code register contains smi tagged char |
+ // code. |
+ __ bind(&got_char_code); |
+ StringHelper::GenerateCharFromCode(masm, code, rax, scratch, JUMP_FUNCTION); |
+#ifdef DEBUG |
+ __ Abort("Unexpected fall-through from char from code tail call"); |
+#endif |
- // Check if key is a smi or a heap number. |
- __ movq(rax, Operand(rsp, kPointerSize)); |
- __ JumpIfSmi(rax, &index_ok); |
- __ CheckMap(rax, Factory::heap_number_map(), &miss, false); |
+ // Check if key is a heap number. |
+ __ bind(&index_not_smi); |
+ __ CompareRoot(FieldOperand(index, HeapObject::kMapOffset), |
+ Heap::kHeapNumberMapRootIndex); |
+ __ j(not_equal, &miss); |
- __ bind(&index_ok); |
- // Duplicate receiver and key since they are expected on the stack after |
- // the KeyedLoadIC call. |
- __ pop(rbx); // return address |
- __ push(rcx); // receiver |
- __ push(rax); // key |
- __ push(rbx); // return address |
- __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION); |
+ // 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(receiver); |
+ __ push(index); |
+ __ CallRuntime(Runtime::kStringCharCodeAt, 2); |
+ ASSERT(!code.is(rax)); |
+ __ movq(code, rax); |
+ __ LeaveInternalFrame(); |
+ // Check if the runtime call returned NaN char code. If yes, return |
+ // undefined. Otherwise, we can continue. |
+ if (FLAG_debug_code) { |
+ ASSERT(kSmiTag == 0); |
+ __ JumpIfSmi(code, &got_char_code); |
+ __ CompareRoot(FieldOperand(code, HeapObject::kMapOffset), |
+ Heap::kHeapNumberMapRootIndex); |
+ __ Assert(equal, "StringCharCodeAt must return smi or heap number"); |
+ } |
+ __ CompareRoot(code, Heap::kNanValueRootIndex); |
+ __ j(not_equal, &got_char_code); |
+ |
+ __ bind(&index_out_of_range); |
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
+ __ ret(0); |
+ |
__ bind(&miss); |
GenerateMiss(masm); |
} |