diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2013-07-02 17:11:31 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2013-07-06 16:53:06 +0200 |
commit | 704fd8f3745527fc080f96e54e5ec1857c505399 (patch) | |
tree | bff68e8a731f3618d3e8f1708aa9de194bc1f612 /deps/v8/src/ia32/builtins-ia32.cc | |
parent | eec43351c44c0bec31a83e1a28be15e30722936a (diff) | |
download | node-704fd8f3745527fc080f96e54e5ec1857c505399.tar.gz |
v8: upgrade to v3.20.2
Diffstat (limited to 'deps/v8/src/ia32/builtins-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/builtins-ia32.cc | 501 |
1 files changed, 13 insertions, 488 deletions
diff --git a/deps/v8/src/ia32/builtins-ia32.cc b/deps/v8/src/ia32/builtins-ia32.cc index bf4ee949e..8aa6e4a60 100644 --- a/deps/v8/src/ia32/builtins-ia32.cc +++ b/deps/v8/src/ia32/builtins-ia32.cc @@ -27,7 +27,7 @@ #include "v8.h" -#if defined(V8_TARGET_ARCH_IA32) +#if V8_TARGET_ARCH_IA32 #include "codegen.h" #include "deoptimizer.h" @@ -447,6 +447,8 @@ void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, bool is_construct) { + ProfileEntryHookStub::MaybeCallEntryHook(masm); + // Clear the context before we push it when entering the internal frame. __ Set(esi, Immediate(0)); @@ -1015,427 +1017,6 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { } -// Allocate an empty JSArray. The allocated array is put into the result -// register. If the parameter initial_capacity is larger than zero an elements -// backing store is allocated with this size and filled with the hole values. -// Otherwise the elements backing store is set to the empty FixedArray. -static void AllocateEmptyJSArray(MacroAssembler* masm, - Register array_function, - Register result, - Register scratch1, - Register scratch2, - Register scratch3, - Label* gc_required) { - const int initial_capacity = JSArray::kPreallocatedArrayElements; - STATIC_ASSERT(initial_capacity >= 0); - - __ LoadInitialArrayMap(array_function, scratch2, scratch1, false); - - // Allocate the JSArray object together with space for a fixed array with the - // requested elements. - int size = JSArray::kSize; - if (initial_capacity > 0) { - size += FixedArray::SizeFor(initial_capacity); - } - __ Allocate(size, result, scratch2, scratch3, gc_required, TAG_OBJECT); - - // Allocated the JSArray. Now initialize the fields except for the elements - // array. - // result: JSObject - // scratch1: initial map - // scratch2: start of next object - __ mov(FieldOperand(result, JSObject::kMapOffset), scratch1); - Factory* factory = masm->isolate()->factory(); - __ mov(FieldOperand(result, JSArray::kPropertiesOffset), - factory->empty_fixed_array()); - // Field JSArray::kElementsOffset is initialized later. - __ mov(FieldOperand(result, JSArray::kLengthOffset), Immediate(0)); - - // If no storage is requested for the elements array just set the empty - // fixed array. - if (initial_capacity == 0) { - __ mov(FieldOperand(result, JSArray::kElementsOffset), - factory->empty_fixed_array()); - return; - } - - // Calculate the location of the elements array and set elements array member - // of the JSArray. - // result: JSObject - // scratch2: start of next object - __ lea(scratch1, Operand(result, JSArray::kSize)); - __ mov(FieldOperand(result, JSArray::kElementsOffset), scratch1); - - // Initialize the FixedArray and fill it with holes. FixedArray length is - // stored as a smi. - // result: JSObject - // scratch1: elements array - // scratch2: start of next object - __ mov(FieldOperand(scratch1, FixedArray::kMapOffset), - factory->fixed_array_map()); - __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset), - Immediate(Smi::FromInt(initial_capacity))); - - // Fill the FixedArray with the hole value. Inline the code if short. - // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. - static const int kLoopUnfoldLimit = 4; - if (initial_capacity <= kLoopUnfoldLimit) { - // Use a scratch register here to have only one reloc info when unfolding - // the loop. - __ mov(scratch3, factory->the_hole_value()); - for (int i = 0; i < initial_capacity; i++) { - __ mov(FieldOperand(scratch1, - FixedArray::kHeaderSize + i * kPointerSize), - scratch3); - } - } else { - Label loop, entry; - __ mov(scratch2, Immediate(initial_capacity)); - __ jmp(&entry); - __ bind(&loop); - __ mov(FieldOperand(scratch1, - scratch2, - times_pointer_size, - FixedArray::kHeaderSize), - factory->the_hole_value()); - __ bind(&entry); - __ dec(scratch2); - __ j(not_sign, &loop); - } -} - - -// Allocate a JSArray with the number of elements stored in a register. The -// register array_function holds the built-in Array function and the register -// array_size holds the size of the array as a smi. The allocated array is put -// into the result register and beginning and end of the FixedArray elements -// storage is put into registers elements_array and elements_array_end (see -// below for when that is not the case). If the parameter fill_with_holes is -// true the allocated elements backing store is filled with the hole values -// otherwise it is left uninitialized. When the backing store is filled the -// register elements_array is scratched. -static void AllocateJSArray(MacroAssembler* masm, - Register array_function, // Array function. - Register array_size, // As a smi, cannot be 0. - Register result, - Register elements_array, - Register elements_array_end, - Register scratch, - bool fill_with_hole, - Label* gc_required) { - ASSERT(scratch.is(edi)); // rep stos destination - ASSERT(!fill_with_hole || array_size.is(ecx)); // rep stos count - ASSERT(!fill_with_hole || !result.is(eax)); // result is never eax - - __ LoadInitialArrayMap(array_function, scratch, - elements_array, fill_with_hole); - - // Allocate the JSArray object together with space for a FixedArray with the - // requested elements. - STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); - __ Allocate(JSArray::kSize + FixedArray::kHeaderSize, - times_pointer_size, - array_size, - REGISTER_VALUE_IS_SMI, - result, - elements_array_end, - scratch, - gc_required, - TAG_OBJECT); - - // Allocated the JSArray. Now initialize the fields except for the elements - // array. - // result: JSObject - // elements_array: initial map - // elements_array_end: start of next object - // array_size: size of array (smi) - __ mov(FieldOperand(result, JSObject::kMapOffset), elements_array); - Factory* factory = masm->isolate()->factory(); - __ mov(elements_array, factory->empty_fixed_array()); - __ mov(FieldOperand(result, JSArray::kPropertiesOffset), elements_array); - // Field JSArray::kElementsOffset is initialized later. - __ mov(FieldOperand(result, JSArray::kLengthOffset), array_size); - - // Calculate the location of the elements array and set elements array member - // of the JSArray. - // result: JSObject - // elements_array_end: start of next object - // array_size: size of array (smi) - __ lea(elements_array, Operand(result, JSArray::kSize)); - __ mov(FieldOperand(result, JSArray::kElementsOffset), elements_array); - - // Initialize the fixed array. FixedArray length is stored as a smi. - // result: JSObject - // elements_array: elements array - // elements_array_end: start of next object - // array_size: size of array (smi) - __ mov(FieldOperand(elements_array, FixedArray::kMapOffset), - factory->fixed_array_map()); - // For non-empty JSArrays the length of the FixedArray and the JSArray is the - // same. - __ mov(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size); - - // Fill the allocated FixedArray with the hole value if requested. - // result: JSObject - // elements_array: elements array - if (fill_with_hole) { - __ SmiUntag(array_size); - __ lea(edi, Operand(elements_array, - FixedArray::kHeaderSize - kHeapObjectTag)); - __ mov(eax, factory->the_hole_value()); - __ cld(); - // Do not use rep stos when filling less than kRepStosThreshold - // words. - const int kRepStosThreshold = 16; - Label loop, entry, done; - __ cmp(ecx, kRepStosThreshold); - __ j(below, &loop); // Note: ecx > 0. - __ rep_stos(); - __ jmp(&done); - __ bind(&loop); - __ stos(); - __ bind(&entry); - __ cmp(edi, elements_array_end); - __ j(below, &loop); - __ bind(&done); - } -} - - -// Create a new array for the built-in Array function. This function allocates -// the JSArray object and the FixedArray elements array and initializes these. -// If the Array cannot be constructed in native code the runtime is called. This -// function assumes the following state: -// edi: constructor (built-in Array function) -// eax: argc -// esp[0]: return address -// esp[4]: last argument -// This function is used for both construct and normal calls of Array. Whether -// it is a construct call or not is indicated by the construct_call parameter. -// The only difference between handling a construct call and a normal call is -// that for a construct call the constructor function in edi needs to be -// preserved for entering the generic code. In both cases argc in eax needs to -// be preserved. -void ArrayNativeCode(MacroAssembler* masm, - bool construct_call, - Label* call_generic_code) { - Label argc_one_or_more, argc_two_or_more, prepare_generic_code_call, - empty_array, not_empty_array, finish, cant_transition_map, not_double; - - // Push the constructor and argc. No need to tag argc as a smi, as there will - // be no garbage collection with this on the stack. - int push_count = 0; - if (construct_call) { - push_count++; - __ push(edi); - } - push_count++; - __ push(eax); - - // Check for array construction with zero arguments. - __ test(eax, eax); - __ j(not_zero, &argc_one_or_more); - - __ bind(&empty_array); - // Handle construction of an empty array. - AllocateEmptyJSArray(masm, - edi, - eax, - ebx, - ecx, - edi, - &prepare_generic_code_call); - __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1); - __ pop(ebx); - if (construct_call) { - __ pop(edi); - } - __ ret(kPointerSize); - - // Check for one argument. Bail out if argument is not smi or if it is - // negative. - __ bind(&argc_one_or_more); - __ cmp(eax, 1); - __ j(not_equal, &argc_two_or_more); - STATIC_ASSERT(kSmiTag == 0); - __ mov(ecx, Operand(esp, (push_count + 1) * kPointerSize)); - __ test(ecx, ecx); - __ j(not_zero, ¬_empty_array); - - // The single argument passed is zero, so we jump to the code above used to - // handle the case of no arguments passed. To adapt the stack for that we move - // the return address and the pushed constructor (if pushed) one stack slot up - // thereby removing the passed argument. Argc is also on the stack - at the - // bottom - and it needs to be changed from 1 to 0 to have the call into the - // runtime system work in case a GC is required. - for (int i = push_count; i > 0; i--) { - __ mov(eax, Operand(esp, i * kPointerSize)); - __ mov(Operand(esp, (i + 1) * kPointerSize), eax); - } - __ Drop(2); // Drop two stack slots. - __ push(Immediate(0)); // Treat this as a call with argc of zero. - __ jmp(&empty_array); - - __ bind(¬_empty_array); - __ test(ecx, Immediate(kIntptrSignBit | kSmiTagMask)); - __ j(not_zero, &prepare_generic_code_call); - - // Handle construction of an empty array of a certain size. Get the size from - // the stack and bail out if size is to large to actually allocate an elements - // array. - __ cmp(ecx, JSObject::kInitialMaxFastElementArray << kSmiTagSize); - __ j(greater_equal, &prepare_generic_code_call); - - // edx: array_size (smi) - // edi: constructor - // esp[0]: argc (cannot be 0 here) - // esp[4]: constructor (only if construct_call) - // esp[8]: return address - // esp[C]: argument - AllocateJSArray(masm, - edi, - ecx, - ebx, - eax, - edx, - edi, - true, - &prepare_generic_code_call); - Counters* counters = masm->isolate()->counters(); - __ IncrementCounter(counters->array_function_native(), 1); - __ mov(eax, ebx); - __ pop(ebx); - if (construct_call) { - __ pop(edi); - } - __ ret(2 * kPointerSize); - - // Handle construction of an array from a list of arguments. - __ bind(&argc_two_or_more); - STATIC_ASSERT(kSmiTag == 0); - __ SmiTag(eax); // Convet argc to a smi. - // eax: array_size (smi) - // edi: constructor - // esp[0] : argc - // esp[4]: constructor (only if construct_call) - // esp[8] : return address - // esp[C] : last argument - AllocateJSArray(masm, - edi, - eax, - ebx, - ecx, - edx, - edi, - false, - &prepare_generic_code_call); - __ IncrementCounter(counters->array_function_native(), 1); - __ push(ebx); - __ mov(ebx, Operand(esp, kPointerSize)); - // ebx: argc - // edx: elements_array_end (untagged) - // esp[0]: JSArray - // esp[4]: argc - // esp[8]: constructor (only if construct_call) - // esp[12]: return address - // esp[16]: last argument - - // Location of the last argument - int last_arg_offset = (construct_call ? 4 : 3) * kPointerSize; - __ lea(edi, Operand(esp, last_arg_offset)); - - // Location of the first array element (Parameter fill_with_holes to - // AllocateJSArray is false, so the FixedArray is returned in ecx). - __ lea(edx, Operand(ecx, FixedArray::kHeaderSize - kHeapObjectTag)); - - Label has_non_smi_element; - - // ebx: argc - // edx: location of the first array element - // edi: location of the last argument - // esp[0]: JSArray - // esp[4]: argc - // esp[8]: constructor (only if construct_call) - // esp[12]: return address - // esp[16]: last argument - Label loop, entry; - __ mov(ecx, ebx); - __ jmp(&entry); - __ bind(&loop); - __ mov(eax, Operand(edi, ecx, times_pointer_size, 0)); - if (FLAG_smi_only_arrays) { - __ JumpIfNotSmi(eax, &has_non_smi_element); - } - __ mov(Operand(edx, 0), eax); - __ add(edx, Immediate(kPointerSize)); - __ bind(&entry); - __ dec(ecx); - __ j(greater_equal, &loop); - - // Remove caller arguments from the stack and return. - // ebx: argc - // esp[0]: JSArray - // esp[4]: argc - // esp[8]: constructor (only if construct_call) - // esp[12]: return address - // esp[16]: last argument - __ bind(&finish); - __ mov(ecx, Operand(esp, last_arg_offset - kPointerSize)); - __ pop(eax); - __ pop(ebx); - __ lea(esp, Operand(esp, ebx, times_pointer_size, - last_arg_offset - kPointerSize)); - __ jmp(ecx); - - __ bind(&has_non_smi_element); - // Double values are handled by the runtime. - __ CheckMap(eax, - masm->isolate()->factory()->heap_number_map(), - ¬_double, - DONT_DO_SMI_CHECK); - __ bind(&cant_transition_map); - // Throw away the array that's only been partially constructed. - __ pop(eax); - __ UndoAllocationInNewSpace(eax); - __ jmp(&prepare_generic_code_call); - - __ bind(¬_double); - // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS. - __ mov(ebx, Operand(esp, 0)); - __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); - __ LoadTransitionedArrayMapConditional( - FAST_SMI_ELEMENTS, - FAST_ELEMENTS, - edi, - eax, - &cant_transition_map); - __ mov(FieldOperand(ebx, HeapObject::kMapOffset), edi); - __ RecordWriteField(ebx, HeapObject::kMapOffset, edi, eax, - kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); - - // Prepare to re-enter the loop - __ lea(edi, Operand(esp, last_arg_offset)); - - // Finish the array initialization loop. - Label loop2; - __ bind(&loop2); - __ mov(eax, Operand(edi, ecx, times_pointer_size, 0)); - __ mov(Operand(edx, 0), eax); - __ add(edx, Immediate(kPointerSize)); - __ dec(ecx); - __ j(greater_equal, &loop2); - __ jmp(&finish); - - // Restore argc and constructor before running the generic code. - __ bind(&prepare_generic_code_call); - __ pop(eax); - if (construct_call) { - __ pop(edi); - } - __ jmp(call_generic_code); -} - - void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : argc @@ -1459,20 +1040,9 @@ void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { // Run the native code for the InternalArray function called as a normal // function. - if (FLAG_optimize_constructed_arrays) { - // tail call a stub - InternalArrayConstructorStub stub(masm->isolate()); - __ TailCallStub(&stub); - } else { - ArrayNativeCode(masm, false, &generic_array_code); - - // Jump to the generic internal array code in case the specialized code - // cannot handle the construction. - __ bind(&generic_array_code); - Handle<Code> array_code = - masm->isolate()->builtins()->InternalArrayCodeGeneric(); - __ jmp(array_code, RelocInfo::CODE_TARGET); - } + // tail call a stub + InternalArrayConstructorStub stub(masm->isolate()); + __ TailCallStub(&stub); } @@ -1498,58 +1068,13 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { } // Run the native code for the Array function called as a normal function. - if (FLAG_optimize_constructed_arrays) { - // tail call a stub - Handle<Object> undefined_sentinel( - masm->isolate()->heap()->undefined_value(), - masm->isolate()); - __ mov(ebx, Immediate(undefined_sentinel)); - ArrayConstructorStub stub(masm->isolate()); - __ TailCallStub(&stub); - } else { - ArrayNativeCode(masm, false, &generic_array_code); - - // Jump to the generic internal array code in case the specialized code - // cannot handle the construction. - __ bind(&generic_array_code); - Handle<Code> array_code = - masm->isolate()->builtins()->ArrayCodeGeneric(); - __ jmp(array_code, RelocInfo::CODE_TARGET); - } -} - - -void Builtins::Generate_CommonArrayConstructCode(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- eax : argc - // -- ebx : type info cell - // -- edi : constructor - // -- esp[0] : return address - // -- esp[4] : last argument - // ----------------------------------- - if (FLAG_debug_code) { - // The array construct code is only set for the global and natives - // builtin Array functions which always have maps. - - // Initial map for the builtin Array function should be a map. - __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); - // Will both indicate a NULL and a Smi. - __ test(ecx, Immediate(kSmiTagMask)); - __ Assert(not_zero, "Unexpected initial map for Array function"); - __ CmpObjectType(ecx, MAP_TYPE, ecx); - __ Assert(equal, "Unexpected initial map for Array function"); - } - - Label generic_constructor; - // Run the native code for the Array function called as constructor. - ArrayNativeCode(masm, true, &generic_constructor); - - // Jump to the generic construct code in case the specialized code cannot - // handle the construction. - __ bind(&generic_constructor); - Handle<Code> generic_construct_stub = - masm->isolate()->builtins()->JSConstructStubGeneric(); - __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); + // tail call a stub + Handle<Object> undefined_sentinel( + masm->isolate()->heap()->undefined_value(), + masm->isolate()); + __ mov(ebx, Immediate(undefined_sentinel)); + ArrayConstructorStub stub(masm->isolate()); + __ TailCallStub(&stub); } |