| Index: src/mips/builtins-mips.cc
|
| diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
|
| index 06273caf788b70f1a031177e501178b892e7c7cf..e9188ef0c2b5bc44fc372419ceed20f0f79190bd 100644
|
| --- a/src/mips/builtins-mips.cc
|
| +++ b/src/mips/builtins-mips.cc
|
| @@ -108,372 +108,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
|
| - __ sw(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
|
| - __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
|
| - __ sw(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
|
| - // Field JSArray::kElementsOffset is initialized later.
|
| - __ mov(scratch3, zero_reg);
|
| - __ sw(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
|
| -
|
| - if (initial_capacity == 0) {
|
| - __ sw(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
|
| - __ Addu(scratch1, result, Operand(JSArray::kSize));
|
| - __ sw(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
|
| -
|
| - // Clear the heap tag on the elements array.
|
| - __ And(scratch1, scratch1, Operand(~kHeapObjectTagMask));
|
| -
|
| - // 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);
|
| - __ sw(scratch3, MemOperand(scratch1));
|
| - __ Addu(scratch1, scratch1, kPointerSize);
|
| - __ li(scratch3, Operand(Smi::FromInt(initial_capacity)));
|
| - STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
|
| - __ sw(scratch3, MemOperand(scratch1));
|
| - __ Addu(scratch1, scratch1, kPointerSize);
|
| -
|
| - // 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++) {
|
| - __ sw(scratch3, MemOperand(scratch1, i * kPointerSize));
|
| - }
|
| - } else {
|
| - Label loop, entry;
|
| - __ Addu(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
|
| - __ Branch(&entry);
|
| - __ bind(&loop);
|
| - __ sw(scratch3, MemOperand(scratch1));
|
| - __ Addu(scratch1, scratch1, kPointerSize);
|
| - __ bind(&entry);
|
| - __ Branch(&loop, lt, scratch1, Operand(scratch2));
|
| - }
|
| -}
|
| -
|
| -
|
| -// 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.
|
| - __ Assert(
|
| - ne, "array size is unexpectedly 0", array_size, Operand(zero_reg));
|
| - }
|
| -
|
| - // Allocate the JSArray object together with space for a FixedArray with the
|
| - // requested number of elements.
|
| - STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
|
| - __ li(elements_array_end,
|
| - (JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize);
|
| - __ sra(scratch1, array_size, kSmiTagSize);
|
| - __ Addu(elements_array_end, elements_array_end, scratch1);
|
| - __ 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)
|
| - __ sw(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
|
| - __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
|
| - __ sw(elements_array_storage,
|
| - FieldMemOperand(result, JSArray::kPropertiesOffset));
|
| - // Field JSArray::kElementsOffset is initialized later.
|
| - __ sw(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)
|
| - __ Addu(elements_array_storage, result, Operand(JSArray::kSize));
|
| - __ sw(elements_array_storage,
|
| - FieldMemOperand(result, JSArray::kElementsOffset));
|
| -
|
| - // Clear the heap tag on the elements array.
|
| - __ And(elements_array_storage,
|
| - elements_array_storage,
|
| - Operand(~kHeapObjectTagMask));
|
| - // 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);
|
| - __ sw(scratch1, MemOperand(elements_array_storage));
|
| - __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
|
| -
|
| - // Length of the FixedArray is the number of pre-allocated elements if
|
| - // the actual JSArray has length 0 and the size of the JSArray for non-empty
|
| - // JSArrays. The length of a FixedArray is stored as a smi.
|
| - STATIC_ASSERT(kSmiTag == 0);
|
| -
|
| - ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
|
| - __ sw(array_size, MemOperand(elements_array_storage));
|
| - __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
|
| -
|
| - // Calculate elements array and elements array end.
|
| - // result: JSObject
|
| - // elements_array_storage: elements array element storage
|
| - // array_size: smi-tagged size of elements array
|
| - STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| - __ sll(elements_array_end, array_size, kPointerSizeLog2 - kSmiTagSize);
|
| - __ Addu(elements_array_end, elements_array_storage, elements_array_end);
|
| -
|
| - // 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);
|
| - __ Branch(&entry);
|
| - __ bind(&loop);
|
| - __ sw(scratch1, MemOperand(elements_array_storage));
|
| - __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
|
| -
|
| - __ bind(&entry);
|
| - __ Branch(&loop, lt, elements_array_storage, Operand(elements_array_end));
|
| - }
|
| -}
|
| -
|
| -
|
| -// 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:
|
| -// a0: argc
|
| -// a1: constructor (built-in Array function)
|
| -// ra: 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 a1 needs to be preserved for
|
| -// entering the generic code. In both cases argc in a0 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.
|
| - __ Branch(&argc_one_or_more, ne, a0, Operand(zero_reg));
|
| - // Handle construction of an empty array.
|
| - __ bind(&empty_array);
|
| - AllocateEmptyJSArray(masm,
|
| - a1,
|
| - a2,
|
| - a3,
|
| - t0,
|
| - t1,
|
| - call_generic_code);
|
| - __ IncrementCounter(counters->array_function_native(), 1, a3, t0);
|
| - // Set up return value, remove receiver from stack and return.
|
| - __ Addu(sp, sp, Operand(kPointerSize));
|
| - __ Ret(USE_DELAY_SLOT);
|
| - __ mov(v0, a2);
|
| -
|
| - // Check for one argument. Bail out if argument is not smi or if it is
|
| - // negative.
|
| - __ bind(&argc_one_or_more);
|
| - __ Branch(&argc_two_or_more, ne, a0, Operand(1));
|
| -
|
| - STATIC_ASSERT(kSmiTag == 0);
|
| - __ lw(a2, MemOperand(sp)); // Get the argument from the stack.
|
| - __ Branch(¬_empty_array, ne, a2, Operand(zero_reg));
|
| - __ Drop(1); // Adjust stack.
|
| - __ mov(a0, zero_reg); // Treat this as a call with argc of zero.
|
| - __ Branch(&empty_array);
|
| -
|
| - __ bind(¬_empty_array);
|
| - __ And(a3, a2, Operand(kIntptrSignBit | kSmiTagMask));
|
| - __ Branch(call_generic_code, eq, a3, Operand(zero_reg));
|
| -
|
| - // 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);
|
| - __ Branch(call_generic_code, Ugreater_equal, a2,
|
| - Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
|
| -
|
| - // a0: argc
|
| - // a1: constructor
|
| - // a2: array_size (smi)
|
| - // sp[0]: argument
|
| - AllocateJSArray(masm,
|
| - a1,
|
| - a2,
|
| - a3,
|
| - t0,
|
| - t1,
|
| - t2,
|
| - t3,
|
| - true,
|
| - call_generic_code);
|
| - __ IncrementCounter(counters->array_function_native(), 1, a2, t0);
|
| -
|
| - // Set up return value, remove receiver and argument from stack and return.
|
| - __ Addu(sp, sp, Operand(2 * kPointerSize));
|
| - __ Ret(USE_DELAY_SLOT);
|
| - __ mov(v0, a3);
|
| -
|
| - // Handle construction of an array from a list of arguments.
|
| - __ bind(&argc_two_or_more);
|
| - __ sll(a2, a0, kSmiTagSize); // Convert argc to a smi.
|
| -
|
| - // a0: argc
|
| - // a1: constructor
|
| - // a2: array_size (smi)
|
| - // sp[0]: last argument
|
| - AllocateJSArray(masm,
|
| - a1,
|
| - a2,
|
| - a3,
|
| - t0,
|
| - t1,
|
| - t2,
|
| - t3,
|
| - false,
|
| - call_generic_code);
|
| - __ IncrementCounter(counters->array_function_native(), 1, a2, t2);
|
| -
|
| - // 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.
|
| - // a0: argc
|
| - // a3: JSArray
|
| - // t0: elements_array storage start (untagged)
|
| - // t1: elements_array_end (untagged)
|
| - // sp[0]: last argument
|
| -
|
| - Label loop, entry;
|
| - __ Branch(USE_DELAY_SLOT, &entry);
|
| - __ mov(t3, sp);
|
| - __ bind(&loop);
|
| - __ lw(a2, MemOperand(t3));
|
| - if (FLAG_smi_only_arrays) {
|
| - __ JumpIfNotSmi(a2, &has_non_smi_element);
|
| - }
|
| - __ Addu(t3, t3, kPointerSize);
|
| - __ Addu(t1, t1, -kPointerSize);
|
| - __ sw(a2, MemOperand(t1));
|
| - __ bind(&entry);
|
| - __ Branch(&loop, lt, t0, Operand(t1));
|
| -
|
| - __ bind(&finish);
|
| - __ mov(sp, t3);
|
| -
|
| - // Remove caller arguments and receiver from the stack, setup return value and
|
| - // return.
|
| - // a0: argc
|
| - // a3: JSArray
|
| - // sp[0]: receiver
|
| - __ Addu(sp, sp, Operand(kPointerSize));
|
| - __ Ret(USE_DELAY_SLOT);
|
| - __ mov(v0, a3);
|
| -
|
| - __ bind(&has_non_smi_element);
|
| - // Double values are handled by the runtime.
|
| - __ CheckMap(
|
| - a2, t5, Heap::kHeapNumberMapRootIndex, ¬_double, DONT_DO_SMI_CHECK);
|
| - __ bind(&cant_transition_map);
|
| - __ UndoAllocationInNewSpace(a3, t0);
|
| - __ Branch(call_generic_code);
|
| -
|
| - __ bind(¬_double);
|
| - // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS.
|
| - // a3: JSArray
|
| - __ lw(a2, FieldMemOperand(a3, HeapObject::kMapOffset));
|
| - __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
|
| - FAST_ELEMENTS,
|
| - a2,
|
| - t5,
|
| - &cant_transition_map);
|
| - __ sw(a2, FieldMemOperand(a3, HeapObject::kMapOffset));
|
| - __ RecordWriteField(a3,
|
| - HeapObject::kMapOffset,
|
| - a2,
|
| - t5,
|
| - kRAHasNotBeenSaved,
|
| - kDontSaveFPRegs,
|
| - EMIT_REMEMBERED_SET,
|
| - OMIT_SMI_CHECK);
|
| - Label loop2;
|
| - __ bind(&loop2);
|
| - __ lw(a2, MemOperand(t3));
|
| - __ Addu(t3, t3, kPointerSize);
|
| - __ Subu(t1, t1, kPointerSize);
|
| - __ sw(a2, MemOperand(t1));
|
| - __ Branch(&loop2, lt, t0, Operand(t1));
|
| - __ Branch(&finish);
|
| -}
|
| -
|
| -
|
| void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
|
| // ----------- S t a t e -------------
|
| // -- a0 : number of arguments
|
| @@ -498,20 +132,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);
|
| }
|
|
|
|
|
| @@ -538,58 +161,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());
|
| - __ li(a2, 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 -------------
|
| - // -- a0 : number of arguments
|
| - // -- a1 : constructor function
|
| - // -- a2 : type info cell
|
| - // -- ra : 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.
|
| - __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
|
| - __ And(t0, a3, Operand(kSmiTagMask));
|
| - __ Assert(ne, "Unexpected initial map for Array function (3)",
|
| - t0, Operand(zero_reg));
|
| - __ GetObjectType(a3, a3, t0);
|
| - __ Assert(eq, "Unexpected initial map for Array function (4)",
|
| - t0, Operand(MAP_TYPE));
|
| - }
|
| - 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());
|
| + __ li(a2, Operand(undefined_sentinel));
|
| + ArrayConstructorStub stub(masm->isolate());
|
| + __ TailCallStub(&stub);
|
| }
|
|
|
|
|
|
|