Chromium Code Reviews| Index: src/ia32/builtins-ia32.cc |
| diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc |
| index 1c2eb94cf583a3a236c829a982a32c2143276bc3..b133290b4d07488655d70ceb5bbd3bca60943610 100644 |
| --- a/src/ia32/builtins-ia32.cc |
| +++ b/src/ia32/builtins-ia32.cc |
| @@ -29,6 +29,7 @@ |
| #if defined(V8_TARGET_ARCH_IA32) |
| +#include "code-stubs-ia32.h" |
| #include "codegen-inl.h" |
| namespace v8 { |
| @@ -695,17 +696,6 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| } |
| -// Load the built-in Array function from the current context. |
| -static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { |
| - // Load the global context. |
| - __ mov(result, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| - __ mov(result, FieldOperand(result, GlobalObject::kGlobalContextOffset)); |
| - // Load the Array function from the global context. |
| - __ mov(result, |
| - Operand(result, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| -} |
| - |
| - |
| // Number of empty elements to allocate for an empty array. |
| static const int kPreallocatedArrayElements = 4; |
| @@ -1095,7 +1085,7 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { |
| Label generic_array_code; |
| // Get the Array function. |
| - GenerateLoadArrayFunction(masm, edi); |
| + __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); |
| if (FLAG_debug_code) { |
| // Initial map for the builtin Array function shoud be a map. |
| @@ -1131,7 +1121,7 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { |
| if (FLAG_debug_code) { |
| // The array construct code is only set for the builtin Array function which |
| // does always have a map. |
| - GenerateLoadArrayFunction(masm, ebx); |
| + __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ebx); |
| __ cmp(edi, Operand(ebx)); |
| __ Assert(equal, "Unexpected Array function"); |
| // Initial map for the builtin Array function should be a map. |
| @@ -1155,6 +1145,131 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { |
| } |
| +void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
| + // ----------- S t a t e ------------- |
| + // -- eax : number of arguments |
| + // -- edi : constructor function |
| + // -- esp[0] : return address |
| + // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| + // -- esp[(argc + 1) * 4] : receiver |
| + // ----------------------------------- |
| + __ IncrementCounter(&Counters::string_ctor_calls, 1); |
| + |
| + if (FLAG_debug_code) { |
| + __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); |
| + __ cmp(edi, Operand(ecx)); |
| + __ Assert(equal, "Unexpected String function"); |
| + } |
| + |
| + // Load the first argument and get rid of the rest (including the |
| + // receiver). |
| + Label no_arguments; |
| + __ test(eax, Operand(eax)); |
| + __ j(zero, &no_arguments); |
| + __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); |
| + __ pop(ecx); |
| + __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |
| + __ push(ecx); |
| + __ mov(eax, ebx); |
| + |
| + // Lookup the argument in the number to string cache. |
| + Label not_cached, argument_is_string; |
| + NumberToStringStub::GenerateLookupNumberStringCache( |
| + masm, |
| + eax, // Input. |
| + ebx, // Result. |
| + ecx, // Scratch 1. |
| + edx, // Scratch 2. |
| + false, // Input is known to be smi? |
| + ¬_cached); |
| + __ IncrementCounter(&Counters::string_ctor_cached_number, 1); |
| + __ bind(&argument_is_string); |
| + // ----------- S t a t e ------------- |
| + // -- ebx : argument converted to string |
| + // -- edi : constructor function |
| + // -- esp[0] : return address |
| + // ----------------------------------- |
| + |
| + // Allocate a JSValue and put the tagged pointer into eax. |
| + Label gc_required; |
| + __ AllocateInNewSpace(JSValue::kSize, |
| + eax, // Result. |
| + ecx, // New allocation top (we ignore it). |
| + no_reg, |
| + &gc_required, |
| + TAG_OBJECT); |
| + |
| + // Set the map. |
| + __ LoadGlobalFunctionInitialMap(edi, ecx); |
|
antonm
2010/08/26 13:51:16
maybe add a check under FLAG_debug_code above this
|
| + if (FLAG_debug_code) { |
| + __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), |
| + JSValue::kSize >> kPointerSizeLog2); |
| + __ Assert(equal, "Unexpected string wrapper instance size"); |
| + __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); |
| + __ Assert(equal, "Unexpected unused properties of string wrapper"); |
| + } |
| + __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); |
| + |
| + // Set properties and elements. |
| + __ Set(ecx, Immediate(Factory::empty_fixed_array())); |
| + __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); |
| + __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); |
| + |
| + // Set the value. |
| + __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); |
| + |
| + // Ensure the object is fully initialized. |
| + STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
| + |
| + // We're done. Return. |
| + __ ret(0); |
| + |
| + // The argument was not found in the number to string cache. Check |
| + // if it's a string already before calling the conversion builtin. |
| + Label convert_argument; |
| + __ bind(¬_cached); |
| + STATIC_ASSERT(kSmiTag == 0); |
| + __ test(eax, Immediate(kSmiTagMask)); |
| + __ j(zero, &convert_argument); |
| + Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); |
| + __ j(NegateCondition(is_string), &convert_argument); |
| + __ mov(ebx, eax); |
| + __ IncrementCounter(&Counters::string_ctor_string_value, 1); |
| + __ jmp(&argument_is_string); |
| + |
| + // Invoke the conversion builtin and put the result into ebx. |
| + __ bind(&convert_argument); |
| + __ IncrementCounter(&Counters::string_ctor_conversions, 1); |
| + __ EnterInternalFrame(); |
| + __ push(edi); // Preserve the function. |
| + __ push(eax); |
| + __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); |
| + __ pop(edi); |
| + __ LeaveInternalFrame(); |
| + __ mov(ebx, eax); |
| + __ jmp(&argument_is_string); |
| + |
| + // Load the empty string into ebx, remove the receiver from the |
| + // stack, and jump back to the case where the argument is a string. |
| + __ bind(&no_arguments); |
| + __ Set(ebx, Immediate(Factory::empty_string())); |
| + __ pop(ecx); |
| + __ lea(esp, Operand(esp, kPointerSize)); |
| + __ push(ecx); |
| + __ jmp(&argument_is_string); |
| + |
| + // At this point the argument is already a string. Call runtime to |
| + // create a string wrapper. |
| + __ bind(&gc_required); |
| + __ IncrementCounter(&Counters::string_ctor_gc_required, 1); |
| + __ EnterInternalFrame(); |
| + __ push(ebx); |
| + __ CallRuntime(Runtime::kNewStringWrapper, 1); |
| + __ LeaveInternalFrame(); |
| + __ ret(0); |
| +} |
| + |
| + |
| static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
| __ push(ebp); |
| __ mov(ebp, Operand(esp)); |