| Index: src/arm/builtins-arm.cc
|
| diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
|
| index 4d7bc8ef2f22d7e7589108fa6df4b677c1033f89..26419752551c55ef96bfde70d0c58903ce1f2ea2 100644
|
| --- a/src/arm/builtins-arm.cc
|
| +++ b/src/arm/builtins-arm.cc
|
| @@ -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);
|
| }
|
|
|
|
|
|
|