Chromium Code Reviews| Index: src/ia32/ic-ia32.cc |
| diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc |
| index cf521a249ccce1d4b81b19f07e28953233648e9e..34b32be74a8f5a236640834306b627ccea4e3b51 100644 |
| --- a/src/ia32/ic-ia32.cc |
| +++ b/src/ia32/ic-ia32.cc |
| @@ -491,39 +491,72 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| // ----------- S t a t e ------------- |
| - // -- eax : key |
| + // -- eax : key (index) |
| // -- edx : receiver |
| // -- esp[0] : return address |
| // ----------------------------------- |
| - Label miss, index_ok; |
| - |
| - // Pop return address. |
| - // Performing the load early is better in the common case. |
| - __ pop(ebx); |
| + Label miss; |
| + Label not_positive_smi; |
| + Label slow_char_code; |
| + Label got_char_code; |
| - __ test(edx, Immediate(kSmiTagMask)); |
| - __ j(zero, &miss); |
| - __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| - __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| - __ test(ecx, Immediate(kIsNotStringMask)); |
| - __ j(not_zero, &miss); |
| + Register receiver = edx; |
| + Register index = eax; |
| + Register code = ebx; |
| + Register scratch = ecx; |
| + |
| + StringHelper::GenerateFastCharCodeAt(masm, |
| + receiver, |
| + index, |
| + scratch, |
| + code, |
| + &miss, // When not a string. |
| + ¬_positive_smi, |
| + &slow_char_code); |
| + // If we didn't bail out, code register contains smi tagged char |
| + // code. |
| + __ bind(&got_char_code); |
| + StringHelper::GenerateCharFromCode(masm, code, eax, 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. |
| - __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &index_ok); |
| + __ bind(¬_positive_smi); |
| + ASSERT(kSmiTag == 0); |
| + __ test(index, Immediate(kSmiTagMask)); |
| + __ j(zero, &slow_char_code); |
| __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
| __ cmp(ecx, Factory::heap_number_map()); |
| __ j(not_equal, &miss); |
| - __ bind(&index_ok); |
| - // Push receiver and key on the stack, and make a tail call. |
| - __ push(edx); // receiver |
| - __ push(eax); // key |
| - __ push(ebx); // 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(eax)); |
| + __ mov(code, eax); |
| + __ LeaveInternalFrame(); |
| + |
| + // Check if the runtime call returned NaN char code. If yes, return |
| + // undefined. Otherwise, we can continue. |
| + if (FLAG_debug_code) { |
|
Mads Ager (chromium)
2010/04/20 10:36:50
I'm not sure this debug_code code adds much?
|
| + ASSERT(kSmiTag == 0); |
| + __ test(code, Immediate(kSmiTagMask)); |
| + __ j(zero, &got_char_code); |
| + __ mov(scratch, FieldOperand(code, HeapObject::kMapOffset)); |
| + __ cmp(scratch, Factory::heap_number_map()); |
| + __ Assert(equal, "StringCharCodeAt must return smi or heap number"); |
| + } |
| + __ cmp(code, Factory::nan_value()); |
| + __ j(not_equal, &got_char_code); |
| + __ Set(eax, Immediate(Factory::undefined_value())); |
| + __ ret(0); |
| __ bind(&miss); |
| - __ push(ebx); |
| GenerateMiss(masm); |
| } |