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