| Index: bleeding_edge/src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- bleeding_edge/src/ia32/codegen-ia32.cc (revision 3484)
|
| +++ bleeding_edge/src/ia32/codegen-ia32.cc (working copy)
|
| @@ -4320,18 +4320,23 @@
|
|
|
| // Push the resulting array literal boilerplate on the stack.
|
| frame_->Push(&boilerplate);
|
| +
|
| // Clone the boilerplate object.
|
| - Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
|
| - if (node->depth() == 1) {
|
| - clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
|
| + int length = node->values()->length();
|
| + Result clone;
|
| + if (node->depth() == 1 &&
|
| + length <= FastCloneShallowArrayStub::kMaximumLength) {
|
| + FastCloneShallowArrayStub stub(length);
|
| + clone = frame_->CallStub(&stub, 1);
|
| + } else {
|
| + clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1);
|
| }
|
| - Result clone = frame_->CallRuntime(clone_function_id, 1);
|
| // Push the newly cloned literal object as the result.
|
| frame_->Push(&clone);
|
|
|
| // Generate code to set the elements in the array that are not
|
| // literals.
|
| - for (int i = 0; i < node->values()->length(); i++) {
|
| + for (int i = 0; i < length; i++) {
|
| Expression* value = node->values()->at(i);
|
|
|
| // If value is a literal the property value is already set in the
|
| @@ -6637,6 +6642,49 @@
|
| }
|
|
|
|
|
| +void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
|
| + int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0;
|
| + int size = JSArray::kSize + elements_size;
|
| +
|
| + // Allocate both the JS array and the elements array in one big
|
| + // allocation. This avoid multiple limit checks.
|
| + Label gc;
|
| + __ AllocateInNewSpace(size, eax, ebx, ecx, &gc, TAG_OBJECT);
|
| +
|
| + // Get the boilerplate from the stack.
|
| + __ mov(ecx, Operand(esp, 1 * kPointerSize));
|
| +
|
| + // Copy the JS array part.
|
| + for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
|
| + if ((i != JSArray::kElementsOffset) || (length_ == 0)) {
|
| + __ mov(ebx, FieldOperand(ecx, i));
|
| + __ mov(FieldOperand(eax, i), ebx);
|
| + }
|
| + }
|
| +
|
| + if (length_ > 0) {
|
| + // Get hold of the elements array of the boilerplate and setup the
|
| + // elements pointer in the resulting object.
|
| + __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
|
| + __ lea(edx, Operand(eax, JSArray::kSize));
|
| + __ mov(FieldOperand(eax, JSArray::kElementsOffset), edx);
|
| +
|
| + // Copy the elements array.
|
| + for (int i = 0; i < elements_size; i += kPointerSize) {
|
| + __ mov(ebx, FieldOperand(ecx, i));
|
| + __ mov(FieldOperand(edx, i), ebx);
|
| + }
|
| + }
|
| +
|
| + // Return and remove the on-stack parameter.
|
| + __ ret(1 * kPointerSize);
|
| +
|
| + __ bind(&gc);
|
| + ExternalReference runtime(Runtime::kCloneShallowLiteralBoilerplate);
|
| + __ TailCallRuntime(runtime, 1, 1);
|
| +}
|
| +
|
| +
|
| // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
|
| void ToBooleanStub::Generate(MacroAssembler* masm) {
|
| Label false_result, true_result, not_string;
|
| @@ -7549,18 +7597,90 @@
|
| static const int kDisplacement = 2 * kPointerSize;
|
|
|
| // Check if the calling frame is an arguments adaptor frame.
|
| - Label runtime;
|
| + Label adaptor_frame, try_allocate, runtime;
|
| __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
| __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
|
| __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
| - __ j(not_equal, &runtime);
|
| + __ j(equal, &adaptor_frame);
|
|
|
| + // Get the length from the frame.
|
| + __ mov(ecx, Operand(esp, 1 * kPointerSize));
|
| + __ jmp(&try_allocate);
|
| +
|
| // Patch the arguments.length and the parameters pointer.
|
| + __ bind(&adaptor_frame);
|
| __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
| __ mov(Operand(esp, 1 * kPointerSize), ecx);
|
| __ lea(edx, Operand(edx, ecx, times_2, kDisplacement));
|
| __ mov(Operand(esp, 2 * kPointerSize), edx);
|
|
|
| + // Try the new space allocation. Start out with computing the size of
|
| + // the arguments object and the elements array.
|
| + Label add_arguments_object;
|
| + __ bind(&try_allocate);
|
| + __ test(ecx, Operand(ecx));
|
| + __ j(zero, &add_arguments_object);
|
| + __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
|
| + __ bind(&add_arguments_object);
|
| + __ add(Operand(ecx), Immediate(Heap::kArgumentsObjectSize));
|
| +
|
| + // Do the allocation of both objects in one go.
|
| + __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
|
| +
|
| + // Get the arguments boilerplate from the current (global) context.
|
| + int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
|
| + __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
|
| + __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset));
|
| + __ mov(edi, Operand(edi, offset));
|
| +
|
| + // Copy the JS object part.
|
| + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
|
| + __ mov(ebx, FieldOperand(edi, i));
|
| + __ mov(FieldOperand(eax, i), ebx);
|
| + }
|
| +
|
| + // Setup the callee in-object property.
|
| + ASSERT(Heap::arguments_callee_index == 0);
|
| + __ mov(ebx, Operand(esp, 3 * kPointerSize));
|
| + __ mov(FieldOperand(eax, JSObject::kHeaderSize), ebx);
|
| +
|
| + // Get the length (smi tagged) and set that as an in-object property too.
|
| + ASSERT(Heap::arguments_length_index == 1);
|
| + __ mov(ecx, Operand(esp, 1 * kPointerSize));
|
| + __ mov(FieldOperand(eax, JSObject::kHeaderSize + kPointerSize), ecx);
|
| +
|
| + // If there are no actual arguments, we're done.
|
| + Label done;
|
| + __ test(ecx, Operand(ecx));
|
| + __ j(zero, &done);
|
| +
|
| + // Get the parameters pointer from the stack and untag the length.
|
| + __ mov(edx, Operand(esp, 2 * kPointerSize));
|
| + __ sar(ecx, kSmiTagSize);
|
| +
|
| + // Setup the elements pointer in the allocated arguments object and
|
| + // initialize the header in the elements fixed array.
|
| + __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize));
|
| + __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
|
| + __ mov(FieldOperand(edi, FixedArray::kMapOffset),
|
| + Immediate(Factory::fixed_array_map()));
|
| + __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
|
| +
|
| + // Copy the fixed array slots.
|
| + Label loop;
|
| + __ bind(&loop);
|
| + __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver.
|
| + __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
|
| + __ add(Operand(edi), Immediate(kPointerSize));
|
| + __ sub(Operand(edx), Immediate(kPointerSize));
|
| + __ dec(ecx);
|
| + __ test(ecx, Operand(ecx));
|
| + __ j(not_zero, &loop);
|
| +
|
| + // Return and remove the on-stack parameters.
|
| + __ bind(&done);
|
| + __ ret(3 * kPointerSize);
|
| +
|
| // Do the runtime call to allocate the arguments object.
|
| __ bind(&runtime);
|
| __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1);
|
|
|