From b195db5174448da36f9a23c7a2297dad782541c8 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Wed, 26 Oct 2011 12:35:10 +0000 Subject: [PATCH] MIPS: port Refactor and clean up array allocation across platforms. Port r9747 (dc33375) BUG= TEST= Review URL: http://codereview.chromium.org/8395030 Patch from Paul Lind . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9802 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/builtins-mips.cc | 63 ++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc index 16b6a202ad..1687abe880 100644 --- a/src/mips/builtins-mips.cc +++ b/src/mips/builtins-mips.cc @@ -88,12 +88,6 @@ static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { } -// This constant has the same value as JSArray::kPreallocatedArrayElements and -// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding -// below should be reconsidered. -static const int kLoopUnfoldLimit = 4; - - // 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. @@ -103,9 +97,9 @@ static void AllocateEmptyJSArray(MacroAssembler* masm, Register scratch1, Register scratch2, Register scratch3, - int initial_capacity, Label* gc_required) { - ASSERT(initial_capacity > 0); + const int initial_capacity = JSArray::kPreallocatedArrayElements; + STATIC_ASSERT(initial_capacity >= 0); // Load the initial map from the array function. __ lw(scratch1, FieldMemOperand(array_function, JSFunction::kPrototypeOrInitialMapOffset)); @@ -155,13 +149,24 @@ static void AllocateEmptyJSArray(MacroAssembler* masm, __ sw(scratch3, MemOperand(scratch1)); __ Addu(scratch1, scratch1, kPointerSize); - // Fill the FixedArray with the hole value. + // Fill the FixedArray with the hole value. Inline the code if short. + if (initial_capacity == 0) return; ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); - ASSERT(initial_capacity <= kLoopUnfoldLimit); __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); - for (int i = 0; i < initial_capacity; i++) { + 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)); } } @@ -177,7 +182,7 @@ static void AllocateEmptyJSArray(MacroAssembler* masm, // register elements_array_storage is scratched. static void AllocateJSArray(MacroAssembler* masm, Register array_function, // Array function. - Register array_size, // As a smi. + Register array_size, // As a smi, cannot be 0. Register result, Register elements_array_storage, Register elements_array_end, @@ -185,31 +190,18 @@ static void AllocateJSArray(MacroAssembler* masm, Register scratch2, bool fill_with_hole, Label* gc_required) { - Label not_empty, allocated; - // Load the initial map from the array function. __ lw(elements_array_storage, FieldMemOperand(array_function, JSFunction::kPrototypeOrInitialMapOffset)); - // Check whether an empty sized array is requested. - __ Branch(¬_empty, ne, array_size, Operand(zero_reg)); - - // If an empty array is requested allocate a small elements array anyway. This - // keeps the code below free of special casing for the empty array. - int size = JSArray::kSize + - FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); - __ AllocateInNewSpace(size, - result, - elements_array_end, - scratch1, - gc_required, - TAG_OBJECT); - __ Branch(&allocated); + 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. - __ bind(¬_empty); STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); __ li(elements_array_end, (JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize); @@ -228,7 +220,6 @@ static void AllocateJSArray(MacroAssembler* masm, // result: JSObject // elements_array_storage: initial map // array_size: size of array (smi) - __ bind(&allocated); __ sw(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); __ sw(elements_array_storage, @@ -262,8 +253,6 @@ static void AllocateJSArray(MacroAssembler* masm, // 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); - __ li(at, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements))); - __ movz(array_size, at, array_size); ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); __ sw(array_size, MemOperand(elements_array_storage)); @@ -312,18 +301,18 @@ static void AllocateJSArray(MacroAssembler* masm, static void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code) { Counters* counters = masm->isolate()->counters(); - Label argc_one_or_more, argc_two_or_more; + Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array; // 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, - JSArray::kPreallocatedArrayElements, call_generic_code); __ IncrementCounter(counters->array_function_native(), 1, a3, t0); // Setup return value, remove receiver from stack and return. @@ -338,6 +327,12 @@ static void ArrayNativeCode(MacroAssembler* masm, 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));