// register elements_array 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,
Register elements_array_end,
Register scratch,
bool fill_with_hole,
Label* gc_required) {
- Label not_empty, allocated;
+ ASSERT(scratch.is(edi)); // rep stos destination
+ ASSERT(!fill_with_hole || array_size.is(ecx)); // rep stos count
// Load the initial map from the array function.
__ mov(elements_array,
FieldOperand(array_function,
JSFunction::kPrototypeOrInitialMapOffset));
- // Check whether an empty sized array is requested.
- __ test(array_size, Operand(array_size));
- __ j(not_zero, ¬_empty);
-
- // 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(kPreallocatedArrayElements);
- __ AllocateInNewSpace(size,
- result,
- elements_array_end,
- scratch,
- gc_required,
- TAG_OBJECT);
- __ jmp(&allocated);
-
// Allocate the JSArray object together with space for a FixedArray with the
// requested elements.
- __ bind(¬_empty);
ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize,
times_half_pointer_size, // array_size is a smi.
// elements_array: initial map
// elements_array_end: start of next object
// array_size: size of array (smi)
- __ bind(&allocated);
__ mov(FieldOperand(result, JSObject::kMapOffset), elements_array);
__ mov(elements_array, Factory::empty_fixed_array());
__ mov(FieldOperand(result, JSArray::kPropertiesOffset), elements_array);
__ SmiUntag(array_size); // Convert from smi to value.
__ mov(FieldOperand(elements_array, JSObject::kMapOffset),
Factory::fixed_array_map());
- Label not_empty_2, fill_array;
- __ test(array_size, Operand(array_size));
- __ j(not_zero, ¬_empty_2);
- // Length of the FixedArray is the number of pre-allocated elements even
- // though the actual JSArray has length 0.
- __ mov(FieldOperand(elements_array, Array::kLengthOffset),
- Immediate(kPreallocatedArrayElements));
- __ jmp(&fill_array);
- __ bind(¬_empty_2);
// For non-empty JSArrays the length of the FixedArray and the JSArray is the
// same.
__ mov(FieldOperand(elements_array, Array::kLengthOffset), array_size);
// Fill the allocated FixedArray with the hole value if requested.
// result: JSObject
// elements_array: elements array
- // elements_array_end: start of next object
- __ bind(&fill_array);
if (fill_with_hole) {
- Label loop, entry;
- __ mov(scratch, Factory::the_hole_value());
- __ lea(elements_array, Operand(elements_array,
- FixedArray::kHeaderSize - kHeapObjectTag));
- __ jmp(&entry);
- __ bind(&loop);
- __ mov(Operand(elements_array, 0), scratch);
- __ add(Operand(elements_array), Immediate(kPointerSize));
- __ bind(&entry);
- __ cmp(elements_array, Operand(elements_array_end));
- __ j(below, &loop);
+ __ lea(edi, Operand(elements_array,
+ FixedArray::kHeaderSize - kHeapObjectTag));
+
+ __ push(eax);
+ __ mov(eax, Factory::the_hole_value());
+
+ __ cld();
+ __ rep_stos();
+
+ // Restore saved registers.
+ __ pop(eax);
}
}
static void ArrayNativeCode(MacroAssembler* masm,
bool construct_call,
Label* call_generic_code) {
- Label argc_one_or_more, argc_two_or_more, prepare_generic_code_call;
+ Label argc_one_or_more, argc_two_or_more, prepare_generic_code_call,
+ empty_array, not_empty_array;
// Push the constructor and argc. No need to tag argc as a smi, as there will
// be no garbage collection with this on the stack.
__ test(eax, Operand(eax));
__ j(not_zero, &argc_one_or_more);
+ __ bind(&empty_array);
// Handle construction of an empty array.
AllocateEmptyJSArray(masm,
edi,
__ cmp(eax, 1);
__ j(not_equal, &argc_two_or_more);
ASSERT(kSmiTag == 0);
- __ test(Operand(esp, (push_count + 1) * kPointerSize),
- Immediate(kIntptrSignBit | kSmiTagMask));
+ __ mov(ecx, Operand(esp, (push_count + 1) * kPointerSize));
+ __ test(ecx, Operand(ecx));
+ __ j(not_zero, ¬_empty_array);
+
+ // Case above assumes there is only a single slot to drop in
+ // ret, but we have two.
+ for (int i = push_count; i >= 0; i--) {
+ __ mov(eax, Operand(esp, i * kPointerSize));
+ __ mov(Operand(esp, (i + 1) * kPointerSize), eax);
+ }
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(&empty_array);
+
+ __ bind(¬_empty_array);
+ __ test(ecx, Immediate(kIntptrSignBit | kSmiTagMask));
__ j(not_zero, &prepare_generic_code_call);
// Handle construction of an empty array of a certain size. Get the size from
// the stack and bail out if size is to large to actually allocate an elements
// array.
- __ mov(edx, Operand(esp, (push_count + 1) * kPointerSize));
- ASSERT(kSmiTag == 0);
- __ cmp(edx, JSObject::kInitialMaxFastElementArray << kSmiTagSize);
+ __ cmp(ecx, JSObject::kInitialMaxFastElementArray << kSmiTagSize);
__ j(greater_equal, &prepare_generic_code_call);
// edx: array_size (smi)
// edi: constructor
- // esp[0]: argc
+ // esp[0]: argc (cannot be 0 here)
// esp[4]: constructor (only if construct_call)
// esp[8]: return address
// esp[C]: argument
AllocateJSArray(masm,
edi,
- edx,
+ ecx,
eax,
ebx,
- ecx,
+ edx,
edi,
true,
&prepare_generic_code_call);