diff options
Diffstat (limited to 'deps/v8/src/arm/builtins-arm.cc')
-rw-r--r-- | deps/v8/src/arm/builtins-arm.cc | 431 |
1 files changed, 12 insertions, 419 deletions
diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc index 4d7bc8ef2f..69ba00ac5c 100644 --- a/deps/v8/src/arm/builtins-arm.cc +++ b/deps/v8/src/arm/builtins-arm.cc @@ -27,7 +27,7 @@ #include "v8.h" -#if defined(V8_TARGET_ARCH_ARM) +#if V8_TARGET_ARCH_ARM #include "codegen.h" #include "debug.h" @@ -104,360 +104,6 @@ static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { } -// Allocate an empty JSArray. The allocated array is put into the result -// register. An elements backing store is allocated with size initial_capacity -// and filled with the hole values. -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 - __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset)); - __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex); - __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset)); - // Field JSArray::kElementsOffset is initialized later. - __ mov(scratch3, Operand::Zero()); - __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset)); - - if (initial_capacity == 0) { - __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset)); - return; - } - - // Calculate the location of the elements array and set elements array member - // of the JSArray. - // result: JSObject - // scratch2: start of next object - __ add(scratch1, result, Operand(JSArray::kSize)); - __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset)); - - // Clear the heap tag on the elements array. - __ sub(scratch1, scratch1, Operand(kHeapObjectTag)); - - // Initialize the FixedArray and fill it with holes. FixedArray length is - // stored as a smi. - // result: JSObject - // scratch1: elements array (untagged) - // scratch2: start of next object - __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex); - STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset); - __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); - __ mov(scratch3, Operand(Smi::FromInt(initial_capacity))); - STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset); - __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); - - // Fill the FixedArray with the hole value. Inline the code if short. - STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize); - __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); - static const int kLoopUnfoldLimit = 4; - if (initial_capacity <= kLoopUnfoldLimit) { - for (int i = 0; i < initial_capacity; i++) { - __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); - } - } else { - Label loop, entry; - __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize)); - __ b(&entry); - __ bind(&loop); - __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); - __ bind(&entry); - __ cmp(scratch1, scratch2); - __ b(lt, &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_storage 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_storage 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_storage, - Register elements_array_end, - Register scratch1, - Register scratch2, - bool fill_with_hole, - Label* gc_required) { - // Load the initial map from the array function. - __ LoadInitialArrayMap(array_function, scratch2, - elements_array_storage, fill_with_hole); - - if (FLAG_debug_code) { // Assert that array size is not zero. - __ tst(array_size, array_size); - __ Assert(ne, "array size is unexpectedly 0"); - } - - // Allocate the JSArray object together with space for a FixedArray with the - // requested number of elements. - __ mov(elements_array_end, - Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); - __ add(elements_array_end, elements_array_end, Operand::SmiUntag(array_size)); - __ Allocate(elements_array_end, - result, - scratch1, - scratch2, - gc_required, - static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); - - // Allocated the JSArray. Now initialize the fields except for the elements - // array. - // result: JSObject - // elements_array_storage: initial map - // array_size: size of array (smi) - __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); - __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); - __ str(elements_array_storage, - FieldMemOperand(result, JSArray::kPropertiesOffset)); - // Field JSArray::kElementsOffset is initialized later. - __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); - - // Calculate the location of the elements array and set elements array member - // of the JSArray. - // result: JSObject - // array_size: size of array (smi) - __ add(elements_array_storage, result, Operand(JSArray::kSize)); - __ str(elements_array_storage, - FieldMemOperand(result, JSArray::kElementsOffset)); - - // Clear the heap tag on the elements array. - __ sub(elements_array_storage, - elements_array_storage, - Operand(kHeapObjectTag)); - // Initialize the fixed array and fill it with holes. FixedArray length is - // stored as a smi. - // result: JSObject - // elements_array_storage: elements array (untagged) - // array_size: size of array (smi) - __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); - ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); - __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); - ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); - __ str(array_size, - MemOperand(elements_array_storage, kPointerSize, PostIndex)); - - // Calculate elements array and elements array end. - // result: JSObject - // elements_array_storage: elements array element storage - // array_size: smi-tagged size of elements array - __ add(elements_array_end, - elements_array_storage, - Operand::PointerOffsetFromSmiKey(array_size)); - - // Fill the allocated FixedArray with the hole value if requested. - // result: JSObject - // elements_array_storage: elements array element storage - // elements_array_end: start of next object - if (fill_with_hole) { - Label loop, entry; - __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex); - __ jmp(&entry); - __ bind(&loop); - __ str(scratch1, - MemOperand(elements_array_storage, kPointerSize, PostIndex)); - __ bind(&entry); - __ cmp(elements_array_storage, elements_array_end); - __ b(lt, &loop); - } -} - -// 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: -// r0: argc -// r1: constructor (built-in Array function) -// lr: return address -// sp[0]: last argument -// This function is used for both construct and normal calls of Array. The only -// difference between handling a construct call and a normal call is that for a -// construct call the constructor function in r1 needs to be preserved for -// entering the generic code. In both cases argc in r0 needs to be preserved. -// Both registers are preserved by this code so no need to differentiate between -// construct call and normal call. -void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code) { - Counters* counters = masm->isolate()->counters(); - Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array, - has_non_smi_element, finish, cant_transition_map, not_double; - - // Check for array construction with zero arguments or one. - __ cmp(r0, Operand::Zero()); - __ b(ne, &argc_one_or_more); - - // Handle construction of an empty array. - __ bind(&empty_array); - AllocateEmptyJSArray(masm, - r1, - r2, - r3, - r4, - r5, - call_generic_code); - __ IncrementCounter(counters->array_function_native(), 1, r3, r4); - // Set up return value, remove receiver from stack and return. - __ mov(r0, r2); - __ add(sp, sp, Operand(kPointerSize)); - __ Jump(lr); - - // Check for one argument. Bail out if argument is not smi or if it is - // negative. - __ bind(&argc_one_or_more); - __ cmp(r0, Operand(1)); - __ b(ne, &argc_two_or_more); - __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. - __ tst(r2, r2); - __ b(ne, ¬_empty_array); - __ Drop(1); // Adjust stack. - __ mov(r0, Operand::Zero()); // Treat this as a call with argc of zero. - __ b(&empty_array); - - __ bind(¬_empty_array); - STATIC_ASSERT(kSmiTag == 0); - __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); - __ b(ne, call_generic_code); - - // Handle construction of an empty array of a certain size. Bail out if size - // is too large to actually allocate an elements array. - STATIC_ASSERT(kSmiTag == 0); - __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize)); - __ b(ge, call_generic_code); - - // r0: argc - // r1: constructor - // r2: array_size (smi) - // sp[0]: argument - AllocateJSArray(masm, - r1, - r2, - r3, - r4, - r5, - r6, - r7, - true, - call_generic_code); - __ IncrementCounter(counters->array_function_native(), 1, r2, r4); - // Set up return value, remove receiver and argument from stack and return. - __ mov(r0, r3); - __ add(sp, sp, Operand(2 * kPointerSize)); - __ Jump(lr); - - // Handle construction of an array from a list of arguments. - __ bind(&argc_two_or_more); - __ SmiTag(r2, r0); - - // r0: argc - // r1: constructor - // r2: array_size (smi) - // sp[0]: last argument - AllocateJSArray(masm, - r1, - r2, - r3, - r4, - r5, - r6, - r7, - false, - call_generic_code); - __ IncrementCounter(counters->array_function_native(), 1, r2, r6); - - // Fill arguments as array elements. Copy from the top of the stack (last - // element) to the array backing store filling it backwards. Note: - // elements_array_end points after the backing store therefore PreIndex is - // used when filling the backing store. - // r0: argc - // r3: JSArray - // r4: elements_array storage start (untagged) - // r5: elements_array_end (untagged) - // sp[0]: last argument - Label loop, entry; - __ mov(r7, sp); - __ jmp(&entry); - __ bind(&loop); - __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex)); - if (FLAG_smi_only_arrays) { - __ JumpIfNotSmi(r2, &has_non_smi_element); - } - __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); - __ bind(&entry); - __ cmp(r4, r5); - __ b(lt, &loop); - - __ bind(&finish); - __ mov(sp, r7); - - // Remove caller arguments and receiver from the stack, setup return value and - // return. - // r0: argc - // r3: JSArray - // sp[0]: receiver - __ add(sp, sp, Operand(kPointerSize)); - __ mov(r0, r3); - __ Jump(lr); - - __ bind(&has_non_smi_element); - // Double values are handled by the runtime. - __ CheckMap( - r2, r9, Heap::kHeapNumberMapRootIndex, ¬_double, DONT_DO_SMI_CHECK); - __ bind(&cant_transition_map); - __ UndoAllocationInNewSpace(r3, r4); - __ b(call_generic_code); - - __ bind(¬_double); - // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS. - // r3: JSArray - __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); - __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, - FAST_ELEMENTS, - r2, - r9, - &cant_transition_map); - __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); - __ RecordWriteField(r3, - HeapObject::kMapOffset, - r2, - r9, - kLRHasNotBeenSaved, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - Label loop2; - __ sub(r7, r7, Operand(kPointerSize)); - __ bind(&loop2); - __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex)); - __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); - __ cmp(r4, r5); - __ b(lt, &loop2); - __ b(&finish); -} - - void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r0 : number of arguments @@ -480,20 +126,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, &generic_array_code); - - // Jump to the generic array code if the specialized code cannot handle the - // construction. - __ bind(&generic_array_code); - Handle<Code> array_code = - masm->isolate()->builtins()->InternalArrayCodeGeneric(); - __ Jump(array_code, RelocInfo::CODE_TARGET); - } + // tail call a stub + InternalArrayConstructorStub stub(masm->isolate()); + __ TailCallStub(&stub); } @@ -518,56 +153,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(r2, Operand(undefined_sentinel)); - ArrayConstructorStub stub(masm->isolate()); - __ TailCallStub(&stub); - } else { - ArrayNativeCode(masm, &generic_array_code); - - // Jump to the generic array code if the specialized code cannot handle - // the construction. - __ bind(&generic_array_code); - Handle<Code> array_code = - masm->isolate()->builtins()->ArrayCodeGeneric(); - __ Jump(array_code, RelocInfo::CODE_TARGET); - } -} - - -void Builtins::Generate_CommonArrayConstructCode(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- r0 : number of arguments - // -- r1 : constructor function - // -- r2 : type info cell - // -- lr : return address - // -- sp[...]: constructor arguments - // ----------------------------------- - - if (FLAG_debug_code) { - // The array construct code is only set for the builtin and internal - // Array functions which always have a map. - // Initial map for the builtin Array function should be a map. - __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); - __ SmiTst(r3); - __ Assert(ne, "Unexpected initial map for Array function"); - __ CompareObjectType(r3, r3, r4, MAP_TYPE); - __ Assert(eq, "Unexpected initial map for Array function"); - } - Label generic_constructor; - // Run the native code for the Array function called as a constructor. - ArrayNativeCode(masm, &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(); - __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); + // tail call a stub + Handle<Object> undefined_sentinel( + masm->isolate()->heap()->undefined_value(), + masm->isolate()); + __ mov(r2, Operand(undefined_sentinel)); + ArrayConstructorStub stub(masm->isolate()); + __ TailCallStub(&stub); } @@ -1125,6 +717,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, // r3: argc // r4: argv // r5-r7, cp may be clobbered + ProfileEntryHookStub::MaybeCallEntryHook(masm); // Clear the context before we push it when entering the internal frame. __ mov(cp, Operand::Zero()); |