| Index: src/a64/builtins-a64.cc
|
| diff --git a/src/a64/builtins-a64.cc b/src/a64/builtins-a64.cc
|
| index 309ec07a93020279d3774cc627627dc832b4ce4d..a83bcc586b41f65844e20e2adfc9390a7b4c4818 100644
|
| --- a/src/a64/builtins-a64.cc
|
| +++ b/src/a64/builtins-a64.cc
|
| @@ -55,155 +55,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) {
|
| - ASSERT(!AreAliased(array_function, result, scratch1, scratch2, scratch3));
|
| - const int initial_capacity = JSArray::kPreallocatedArrayElements;
|
| - STATIC_ASSERT(initial_capacity >= 0);
|
| - Register map = scratch1;
|
| - __ LoadInitialArrayMap(array_function, scratch2, map, kArrayCantHaveHoles);
|
| -
|
| - // 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.
|
| - __ Str(map, FieldMemOperand(result, JSObject::kMapOffset));
|
| -
|
| - Register empty_prop = scratch1;
|
| - __ LoadRoot(empty_prop, Heap::kEmptyFixedArrayRootIndex);
|
| - __ Str(empty_prop, FieldMemOperand(result, JSArray::kPropertiesOffset));
|
| -
|
| - // Field JSArray::kElementsOffset is initialized later.
|
| - __ Mov(scratch3, Operand(Smi::FromInt(0)));
|
| - __ Str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
|
| -
|
| - if (initial_capacity == 0) {
|
| - __ Str(empty_prop, FieldMemOperand(result, JSArray::kElementsOffset));
|
| - return;
|
| - }
|
| -
|
| - // Calculate the location of the elements array and set elements array member
|
| - // of the JSArray.
|
| - Register elements_offset = scratch1;
|
| - __ Add(elements_offset, result, JSArray::kSize);
|
| - __ Str(elements_offset, FieldMemOperand(result, JSArray::kElementsOffset));
|
| -
|
| - // Set up fixed array map.
|
| - __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
|
| - __ Str(scratch3, FieldMemOperand(elements_offset, FixedArray::kMapOffset));
|
| -
|
| - // Set up fixed array length.
|
| - __ Mov(scratch3, Operand(Smi::FromInt(initial_capacity)));
|
| - __ Str(scratch3, FieldMemOperand(elements_offset, FixedArray::kLengthOffset));
|
| -
|
| - // Set elements_offset to point to first element of fixed array.
|
| - __ Add(elements_offset, elements_offset,
|
| - FixedArray::kHeaderSize - kHeapObjectTag);
|
| -
|
| - // Set elements_end to the element after the last in the fixed array.
|
| - Register elements_end = scratch2;
|
| - STATIC_ASSERT(initial_capacity > 0);
|
| - __ Add(elements_end, elements_offset, initial_capacity * kPointerSize);
|
| -
|
| - // Fill the FixedArray with the hole value. Inline the code if short.
|
| - Register the_hole = scratch3;
|
| - __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex);
|
| - __ InitializeFieldsWithFiller(elements_offset, elements_end, the_hole);
|
| -}
|
| -
|
| -enum JSArrayFillMode { kDontFillWithHoles, kFillWithHoles };
|
| -
|
| -// 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_mode is
|
| -// kFillWithHoles, 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,
|
| - Register array_size,
|
| - Register result,
|
| - Register elements_array_storage,
|
| - Register elements_array_end,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - JSArrayFillMode fill_mode,
|
| - Label* gc_required) {
|
| - ASSERT(!AreAliased(array_function, array_size, result, elements_array_storage,
|
| - elements_array_end, scratch1, scratch2));
|
| - // Load the initial map from the array function.
|
| - Register map = elements_array_storage;
|
| - __ LoadInitialArrayMap(array_function, scratch2, map,
|
| - (fill_mode == kFillWithHoles) ? kArrayCanHaveHoles
|
| - : kArrayCantHaveHoles);
|
| - if (FLAG_debug_code) {
|
| - __ Cmp(array_size, Operand(Smi::FromInt(0)));
|
| - __ 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,
|
| - (JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize);
|
| - __ Add(elements_array_end, elements_array_end, Operand::UntagSmi(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.
|
| - __ Str(map, FieldMemOperand(result, JSObject::kMapOffset));
|
| - Register empty_prop = elements_array_storage;
|
| - __ LoadRoot(empty_prop, Heap::kEmptyFixedArrayRootIndex);
|
| - __ Str(empty_prop, 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.
|
| - Register elements = elements_array_storage;
|
| - __ Add(elements, result, JSArray::kSize);
|
| - __ Str(elements, FieldMemOperand(result, JSArray::kElementsOffset));
|
| -
|
| - // Set up fixed array map.
|
| - __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
|
| - __ Str(scratch1, FieldMemOperand(elements, FixedArray::kMapOffset));
|
| -
|
| - // Set up fixed array length.
|
| - __ Str(array_size, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
| -
|
| - // Set elements to point to first element of fixed array.
|
| - __ Add(elements, elements, FixedArray::kHeaderSize - kHeapObjectTag);
|
| -
|
| - // Calculate elements array and elements array end.
|
| - __ Add(elements_array_end, elements,
|
| - Operand::UntagSmiAndScale(array_size, kPointerSizeLog2));
|
| -
|
| - // Fill the allocated FixedArray with the hole value if requested.
|
| - if (fill_mode == kFillWithHoles) {
|
| - Register the_hole = scratch1;
|
| - __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex);
|
| - __ InitializeFieldsWithFiller(elements, elements_array_end, the_hole);
|
| - }
|
| -}
|
| -
|
| -
|
| // Load the built-in InternalArray function from the current context.
|
| static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
|
| Register result) {
|
| @@ -247,143 +98,6 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// 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:
|
| -// x0: argc
|
| -// x1: 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 x1 needs to be preserved for
|
| -// entering the generic code. In both cases argc in x0 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;
|
| - Register result = x0;
|
| - Register argc = x0;
|
| - Register constructor = x1;
|
| - Register last_arg = x2;
|
| - Register jsarray = x3;
|
| -
|
| - __ Peek(last_arg, 0 * kPointerSize);
|
| -
|
| - // Check for array construction with zero arguments or one.
|
| - __ Cbnz(argc, &argc_one_or_more);
|
| -
|
| - // Handle construction of an empty array.
|
| - __ Bind(&empty_array);
|
| - AllocateEmptyJSArray(masm, constructor, jsarray, x10, x11, x12,
|
| - call_generic_code);
|
| - __ IncrementCounter(counters->array_function_native(), 1, x10, x11);
|
| - // Set up return value, remove receiver from stack and return.
|
| - __ Mov(result, jsarray);
|
| - __ Drop(1);
|
| - __ Ret();
|
| -
|
| - // Check for one argument. Bail out if argument is not smi or if it is
|
| - // negative.
|
| - __ Bind(&argc_one_or_more);
|
| - __ Cmp(argc, 1);
|
| - __ B(ne, &argc_two_or_more);
|
| - __ Cbnz(last_arg, ¬_empty_array);
|
| - __ Drop(1);
|
| - __ Mov(argc, 0); // Treat this as a call with argc of zero.
|
| - __ B(&empty_array);
|
| -
|
| - __ Bind(¬_empty_array);
|
| - // Call generic code for non-smi and negative smi values.
|
| - __ JumpIfNotSmi(last_arg, call_generic_code);
|
| - __ Tbnz(last_arg, MaskToBit(kIntptrSignBit), 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.
|
| - __ Cmp(last_arg,
|
| - Operand(Smi::FromInt(JSObject::kInitialMaxFastElementArray)));
|
| - __ B(ge, call_generic_code);
|
| -
|
| - AllocateJSArray(masm, constructor, last_arg, jsarray, x4, x5, x6, x7,
|
| - kFillWithHoles, call_generic_code);
|
| - __ IncrementCounter(counters->array_function_native(), 1, x10, x11);
|
| - __ Mov(result, jsarray);
|
| - __ Drop(2);
|
| - __ Ret();
|
| -
|
| - // Handle construction of an array from a list of arguments.
|
| - Register array_size = x10;
|
| - Register elements_array = x4;
|
| - Register elements_array_end = x5;
|
| - __ Bind(&argc_two_or_more);
|
| - __ SmiTag(array_size, argc);
|
| - AllocateJSArray(masm, constructor, array_size, jsarray, elements_array,
|
| - elements_array_end, x6, x7, kDontFillWithHoles,
|
| - call_generic_code);
|
| - __ IncrementCounter(counters->array_function_native(), 1, x10, x11);
|
| -
|
| - // 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.
|
| - Label loop, entry;
|
| - Register index = x6;
|
| - Register element = x7;
|
| - __ Mov(index, 0);
|
| - __ B(&entry);
|
| - __ Bind(&loop);
|
| - __ Peek(element, Operand(index, LSL, kPointerSizeLog2));
|
| - __ Add(index, index, 1);
|
| - if (FLAG_smi_only_arrays) {
|
| - __ JumpIfNotSmi(element, &has_non_smi_element);
|
| - }
|
| - __ Str(element, MemOperand(elements_array_end, -kPointerSize, PreIndex));
|
| - __ Bind(&entry);
|
| - __ Cmp(elements_array, elements_array_end);
|
| - __ B(lt, &loop);
|
| -
|
| - __ Bind(&finish);
|
| -
|
| - // Remove caller arguments and receiver from the stack, set up return value
|
| - // and return.
|
| - __ Drop(index);
|
| - __ Drop(1);
|
| - __ Mov(result, jsarray);
|
| - __ Ret();
|
| -
|
| - __ Bind(&has_non_smi_element);
|
| - // Double values are handled by the runtime.
|
| - __ CheckMap(element, x10, Heap::kHeapNumberMapRootIndex, ¬_double,
|
| - DONT_DO_SMI_CHECK);
|
| - __ Bind(&cant_transition_map);
|
| - __ UndoAllocationInNewSpace(jsarray, x4);
|
| - __ B(call_generic_code);
|
| -
|
| - __ Bind(¬_double);
|
| - // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS.
|
| - __ Ldr(element, FieldMemOperand(jsarray, HeapObject::kMapOffset));
|
| - __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS,
|
| - element, x10, &cant_transition_map);
|
| - __ Str(element, FieldMemOperand(jsarray, HeapObject::kMapOffset));
|
| - __ RecordWriteField(jsarray, HeapObject::kMapOffset, element, x10,
|
| - kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
| - OMIT_SMI_CHECK);
|
| -
|
| - Label loop2;
|
| - __ Sub(index, index, 1);
|
| - __ Bind(&loop2);
|
| - __ Peek(element, Operand(index, LSL, kPointerSizeLog2));
|
| - __ Add(index, index, 1);
|
| - __ Str(element, MemOperand(elements_array_end, -kPointerSize, PreIndex));
|
| - __ Cmp(elements_array, elements_array_end);
|
| - __ B(lt, &loop2);
|
| - __ B(&finish);
|
| -}
|
| -
|
| -
|
| void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
|
| // ----------- S t a t e -------------
|
| // -- x0 : number of arguments
|
| @@ -407,20 +121,8 @@ 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);
|
| - }
|
| + InternalArrayConstructorStub stub(masm->isolate());
|
| + __ TailCallStub(&stub);
|
| }
|
|
|
|
|
| @@ -446,59 +148,12 @@ 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(x2, 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 -------------
|
| - // -- x0 : number of arguments
|
| - // -- x1 : constructor function
|
| - // -- x2 : type info cell
|
| - // -- lr : return address
|
| - // -- sp[...]: constructor arguments
|
| - // -----------------------------------
|
| - ASM_LOCATION("Builtins::Generate_CommonArrayConstructCode");
|
| -
|
| - if (FLAG_debug_code) {
|
| - Register constructor = x1;
|
| - // 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(x3, FieldMemOperand(constructor,
|
| - JSFunction::kPrototypeOrInitialMapOffset));
|
| - __ Tst(x3, kSmiTagMask);
|
| - __ Assert(ne, "Unexpected initial map for Array function");
|
| - __ CompareObjectType(x3, x10, x11, 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);
|
| + Handle<Object> undefined_sentinel(
|
| + masm->isolate()->heap()->undefined_value(),
|
| + masm->isolate());
|
| + __ Mov(x2, Operand(undefined_sentinel));
|
| + ArrayConstructorStub stub(masm->isolate());
|
| + __ TailCallStub(&stub);
|
| }
|
|
|
|
|
|
|