Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(547)

Side by Side Diff: bleeding_edge/src/ia32/codegen-ia32.cc

Issue 503042: Optimize the allocation of small, non-nested literal... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « bleeding_edge/src/heap.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4302 matching lines...) Expand 10 before | Expand all | Expand 10 after
4313 // If so, jump to the deferred code passing the literals array. 4313 // If so, jump to the deferred code passing the literals array.
4314 DeferredArrayLiteral* deferred = 4314 DeferredArrayLiteral* deferred =
4315 new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node); 4315 new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node);
4316 __ cmp(boilerplate.reg(), Factory::undefined_value()); 4316 __ cmp(boilerplate.reg(), Factory::undefined_value());
4317 deferred->Branch(equal); 4317 deferred->Branch(equal);
4318 deferred->BindExit(); 4318 deferred->BindExit();
4319 literals.Unuse(); 4319 literals.Unuse();
4320 4320
4321 // Push the resulting array literal boilerplate on the stack. 4321 // Push the resulting array literal boilerplate on the stack.
4322 frame_->Push(&boilerplate); 4322 frame_->Push(&boilerplate);
4323
4323 // Clone the boilerplate object. 4324 // Clone the boilerplate object.
4324 Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; 4325 int length = node->values()->length();
4325 if (node->depth() == 1) { 4326 Result clone;
4326 clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; 4327 if (node->depth() == 1 &&
4328 length <= FastCloneShallowArrayStub::kMaximumLength) {
4329 FastCloneShallowArrayStub stub(length);
4330 clone = frame_->CallStub(&stub, 1);
4331 } else {
4332 clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1);
4327 } 4333 }
4328 Result clone = frame_->CallRuntime(clone_function_id, 1);
4329 // Push the newly cloned literal object as the result. 4334 // Push the newly cloned literal object as the result.
4330 frame_->Push(&clone); 4335 frame_->Push(&clone);
4331 4336
4332 // Generate code to set the elements in the array that are not 4337 // Generate code to set the elements in the array that are not
4333 // literals. 4338 // literals.
4334 for (int i = 0; i < node->values()->length(); i++) { 4339 for (int i = 0; i < length; i++) {
4335 Expression* value = node->values()->at(i); 4340 Expression* value = node->values()->at(i);
4336 4341
4337 // If value is a literal the property value is already set in the 4342 // If value is a literal the property value is already set in the
4338 // boilerplate object. 4343 // boilerplate object.
4339 if (value->AsLiteral() != NULL) continue; 4344 if (value->AsLiteral() != NULL) continue;
4340 // If value is a materialized literal the property value is already set 4345 // If value is a materialized literal the property value is already set
4341 // in the boilerplate object if it is simple. 4346 // in the boilerplate object if it is simple.
4342 if (CompileTimeValue::IsCompileTimeValue(value)) continue; 4347 if (CompileTimeValue::IsCompileTimeValue(value)) continue;
4343 4348
4344 // The property must be set by generated code. 4349 // The property must be set by generated code.
(...skipping 2285 matching lines...) Expand 10 before | Expand all | Expand 10 after
6630 // Return and remove the on-stack parameter. 6635 // Return and remove the on-stack parameter.
6631 __ mov(esi, Operand(eax)); 6636 __ mov(esi, Operand(eax));
6632 __ ret(1 * kPointerSize); 6637 __ ret(1 * kPointerSize);
6633 6638
6634 // Need to collect. Call into runtime system. 6639 // Need to collect. Call into runtime system.
6635 __ bind(&gc); 6640 __ bind(&gc);
6636 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); 6641 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1);
6637 } 6642 }
6638 6643
6639 6644
6645 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
6646 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0;
6647 int size = JSArray::kSize + elements_size;
6648
6649 // Allocate both the JS array and the elements array in one big
6650 // allocation. This avoid multiple limit checks.
6651 Label gc;
6652 __ AllocateInNewSpace(size, eax, ebx, ecx, &gc, TAG_OBJECT);
6653
6654 // Get the boilerplate from the stack.
6655 __ mov(ecx, Operand(esp, 1 * kPointerSize));
6656
6657 // Copy the JS array part.
6658 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
6659 if ((i != JSArray::kElementsOffset) || (length_ == 0)) {
6660 __ mov(ebx, FieldOperand(ecx, i));
6661 __ mov(FieldOperand(eax, i), ebx);
6662 }
6663 }
6664
6665 if (length_ > 0) {
6666 // Get hold of the elements array of the boilerplate and setup the
6667 // elements pointer in the resulting object.
6668 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
6669 __ lea(edx, Operand(eax, JSArray::kSize));
6670 __ mov(FieldOperand(eax, JSArray::kElementsOffset), edx);
6671
6672 // Copy the elements array.
6673 for (int i = 0; i < elements_size; i += kPointerSize) {
6674 __ mov(ebx, FieldOperand(ecx, i));
6675 __ mov(FieldOperand(edx, i), ebx);
6676 }
6677 }
6678
6679 // Return and remove the on-stack parameter.
6680 __ ret(1 * kPointerSize);
6681
6682 __ bind(&gc);
6683 ExternalReference runtime(Runtime::kCloneShallowLiteralBoilerplate);
6684 __ TailCallRuntime(runtime, 1, 1);
6685 }
6686
6687
6640 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). 6688 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
6641 void ToBooleanStub::Generate(MacroAssembler* masm) { 6689 void ToBooleanStub::Generate(MacroAssembler* masm) {
6642 Label false_result, true_result, not_string; 6690 Label false_result, true_result, not_string;
6643 __ mov(eax, Operand(esp, 1 * kPointerSize)); 6691 __ mov(eax, Operand(esp, 1 * kPointerSize));
6644 6692
6645 // 'null' => false. 6693 // 'null' => false.
6646 __ cmp(eax, Factory::null_value()); 6694 __ cmp(eax, Factory::null_value());
6647 __ j(equal, &false_result); 6695 __ j(equal, &false_result);
6648 6696
6649 // Get the map and type of the heap object. 6697 // Get the map and type of the heap object.
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after
7542 } 7590 }
7543 7591
7544 7592
7545 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { 7593 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
7546 // The displacement is used for skipping the return address and the 7594 // The displacement is used for skipping the return address and the
7547 // frame pointer on the stack. It is the offset of the last 7595 // frame pointer on the stack. It is the offset of the last
7548 // parameter (if any) relative to the frame pointer. 7596 // parameter (if any) relative to the frame pointer.
7549 static const int kDisplacement = 2 * kPointerSize; 7597 static const int kDisplacement = 2 * kPointerSize;
7550 7598
7551 // Check if the calling frame is an arguments adaptor frame. 7599 // Check if the calling frame is an arguments adaptor frame.
7552 Label runtime; 7600 Label adaptor_frame, try_allocate, runtime;
7553 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 7601 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
7554 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); 7602 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
7555 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 7603 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
7556 __ j(not_equal, &runtime); 7604 __ j(equal, &adaptor_frame);
7605
7606 // Get the length from the frame.
7607 __ mov(ecx, Operand(esp, 1 * kPointerSize));
7608 __ jmp(&try_allocate);
7557 7609
7558 // Patch the arguments.length and the parameters pointer. 7610 // Patch the arguments.length and the parameters pointer.
7611 __ bind(&adaptor_frame);
7559 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 7612 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
7560 __ mov(Operand(esp, 1 * kPointerSize), ecx); 7613 __ mov(Operand(esp, 1 * kPointerSize), ecx);
7561 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); 7614 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement));
7562 __ mov(Operand(esp, 2 * kPointerSize), edx); 7615 __ mov(Operand(esp, 2 * kPointerSize), edx);
7563 7616
7617 // Try the new space allocation. Start out with computing the size of
7618 // the arguments object and the elements array.
7619 Label add_arguments_object;
7620 __ bind(&try_allocate);
7621 __ test(ecx, Operand(ecx));
7622 __ j(zero, &add_arguments_object);
7623 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
7624 __ bind(&add_arguments_object);
7625 __ add(Operand(ecx), Immediate(Heap::kArgumentsObjectSize));
7626
7627 // Do the allocation of both objects in one go.
7628 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
7629
7630 // Get the arguments boilerplate from the current (global) context.
7631 int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
7632 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
7633 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset));
7634 __ mov(edi, Operand(edi, offset));
7635
7636 // Copy the JS object part.
7637 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
7638 __ mov(ebx, FieldOperand(edi, i));
7639 __ mov(FieldOperand(eax, i), ebx);
7640 }
7641
7642 // Setup the callee in-object property.
7643 ASSERT(Heap::arguments_callee_index == 0);
7644 __ mov(ebx, Operand(esp, 3 * kPointerSize));
7645 __ mov(FieldOperand(eax, JSObject::kHeaderSize), ebx);
7646
7647 // Get the length (smi tagged) and set that as an in-object property too.
7648 ASSERT(Heap::arguments_length_index == 1);
7649 __ mov(ecx, Operand(esp, 1 * kPointerSize));
7650 __ mov(FieldOperand(eax, JSObject::kHeaderSize + kPointerSize), ecx);
7651
7652 // If there are no actual arguments, we're done.
7653 Label done;
7654 __ test(ecx, Operand(ecx));
7655 __ j(zero, &done);
7656
7657 // Get the parameters pointer from the stack and untag the length.
7658 __ mov(edx, Operand(esp, 2 * kPointerSize));
7659 __ sar(ecx, kSmiTagSize);
7660
7661 // Setup the elements pointer in the allocated arguments object and
7662 // initialize the header in the elements fixed array.
7663 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize));
7664 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
7665 __ mov(FieldOperand(edi, FixedArray::kMapOffset),
7666 Immediate(Factory::fixed_array_map()));
7667 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
7668
7669 // Copy the fixed array slots.
7670 Label loop;
7671 __ bind(&loop);
7672 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver.
7673 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
7674 __ add(Operand(edi), Immediate(kPointerSize));
7675 __ sub(Operand(edx), Immediate(kPointerSize));
7676 __ dec(ecx);
7677 __ test(ecx, Operand(ecx));
7678 __ j(not_zero, &loop);
7679
7680 // Return and remove the on-stack parameters.
7681 __ bind(&done);
7682 __ ret(3 * kPointerSize);
7683
7564 // Do the runtime call to allocate the arguments object. 7684 // Do the runtime call to allocate the arguments object.
7565 __ bind(&runtime); 7685 __ bind(&runtime);
7566 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); 7686 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1);
7567 } 7687 }
7568 7688
7569 7689
7570 void CompareStub::Generate(MacroAssembler* masm) { 7690 void CompareStub::Generate(MacroAssembler* masm) {
7571 Label call_builtin, done; 7691 Label call_builtin, done;
7572 7692
7573 // NOTICE! This code is only reached after a smi-fast-case check, so 7693 // NOTICE! This code is only reached after a smi-fast-case check, so
(...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after
8558 __ add(Operand(dest), Immediate(2)); 8678 __ add(Operand(dest), Immediate(2));
8559 } 8679 }
8560 __ sub(Operand(count), Immediate(1)); 8680 __ sub(Operand(count), Immediate(1));
8561 __ j(not_zero, &loop); 8681 __ j(not_zero, &loop);
8562 } 8682 }
8563 8683
8564 8684
8565 #undef __ 8685 #undef __
8566 8686
8567 } } // namespace v8::internal 8687 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « bleeding_edge/src/heap.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698