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

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

Issue 40295: Optimizing generation of nested literals for both object and array literals. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 9 months 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 | « src/codegen-arm.cc ('k') | src/heap.h » ('j') | 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-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "debug.h" 32 #include "debug.h"
33 #include "scopes.h" 33 #include "scopes.h"
34 #include "runtime.h" 34 #include "runtime.h"
35 #include "parser.h"
35 36
36 namespace v8 { namespace internal { 37 namespace v8 { namespace internal {
37 38
38 #define __ masm_-> 39 #define __ masm_->
39 40
40 // ------------------------------------------------------------------------- 41 // -------------------------------------------------------------------------
41 // CodeGenState implementation. 42 // CodeGenState implementation.
42 43
43 CodeGenState::CodeGenState(CodeGenerator* owner) 44 CodeGenState::CodeGenState(CodeGenerator* owner)
44 : owner_(owner), 45 : owner_(owner),
(...skipping 3436 matching lines...) Expand 10 before | Expand all | Expand 10 after
3481 deferred->enter()->Branch(equal, &literals, not_taken); 3482 deferred->enter()->Branch(equal, &literals, not_taken);
3482 3483
3483 literals.Unuse(); 3484 literals.Unuse();
3484 // The deferred code returns the boilerplate object. 3485 // The deferred code returns the boilerplate object.
3485 deferred->BindExit(&boilerplate); 3486 deferred->BindExit(&boilerplate);
3486 3487
3487 // Push the boilerplate object. 3488 // Push the boilerplate object.
3488 frame_->Push(&boilerplate); 3489 frame_->Push(&boilerplate);
3489 // Clone the boilerplate object. 3490 // Clone the boilerplate object.
3490 Result clone = 3491 Result clone =
3491 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); 3492 frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1);
3492 // Push the newly cloned literal object as the result. 3493 // Push the newly cloned literal object as the result.
3493 frame_->Push(&clone); 3494 frame_->Push(&clone);
3494 3495
3495 for (int i = 0; i < node->properties()->length(); i++) { 3496 for (int i = 0; i < node->properties()->length(); i++) {
3496 ObjectLiteral::Property* property = node->properties()->at(i); 3497 ObjectLiteral::Property* property = node->properties()->at(i);
3497 switch (property->kind()) { 3498 switch (property->kind()) {
3498 case ObjectLiteral::Property::CONSTANT: 3499 case ObjectLiteral::Property::CONSTANT:
3499 break; 3500 break;
3500 case ObjectLiteral::Property::OBJECT_LITERAL: 3501 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
3501 if (property->value()->AsObjectLiteral()->is_simple()) break; 3502 if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
3503 // else fall through.
3502 case ObjectLiteral::Property::COMPUTED: { 3504 case ObjectLiteral::Property::COMPUTED: {
3503 Handle<Object> key(property->key()->handle()); 3505 Handle<Object> key(property->key()->handle());
3504 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3506 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3505 if (key->IsSymbol()) { 3507 if (key->IsSymbol()) {
3506 // Duplicate the object as the IC receiver. 3508 // Duplicate the object as the IC receiver.
3507 frame_->Dup(); 3509 frame_->Dup();
3508 Load(property->value()); 3510 Load(property->value());
3509 Result value = frame_->Pop(); 3511 Result value = frame_->Pop();
3510 value.ToRegister(eax); 3512 value.ToRegister(eax);
3511 3513
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3549 Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4); 3551 Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4);
3550 // Ignore the result. 3552 // Ignore the result.
3551 break; 3553 break;
3552 } 3554 }
3553 default: UNREACHABLE(); 3555 default: UNREACHABLE();
3554 } 3556 }
3555 } 3557 }
3556 } 3558 }
3557 3559
3558 3560
3561 // This deferred code stub will be used for creating the boilerplate
3562 // by calling Runtime_CreateArrayLiteralBoilerplate.
3563 // Each created boilerplate is stored in the JSFunction and they are
3564 // therefore context dependent.
3565 class DeferredArrayLiteral: public DeferredCode {
3566 public:
3567 DeferredArrayLiteral(CodeGenerator* generator,
3568 ArrayLiteral* node)
3569 : DeferredCode(generator), node_(node) {
3570 set_comment("[ DeferredArrayLiteral");
3571 }
3572
3573 virtual void Generate();
3574
3575 private:
3576 ArrayLiteral* node_;
3577 };
3578
3579
3580 void DeferredArrayLiteral::Generate() {
3581 Result literals(generator());
3582 enter()->Bind(&literals);
3583 // Since the entry is undefined we call the runtime system to
3584 // compute the literal.
3585
3586 VirtualFrame* frame = generator()->frame();
3587 // Literal array (0).
3588 frame->Push(&literals);
3589 // Literal index (1).
3590 frame->Push(Smi::FromInt(node_->literal_index()));
3591 // Constant properties (2).
3592 frame->Push(node_->literals());
3593 Result boilerplate =
3594 frame->CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
3595 exit_.Jump(&boilerplate);
3596 }
3597
3598
3559 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 3599 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
3560 Comment cmnt(masm_, "[ ArrayLiteral"); 3600 Comment cmnt(masm_, "[ ArrayLiteral");
3601 DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node);
3561 3602
3562 // Call the runtime to create the array literal. 3603 // Retrieve the literals array and check the allocated entry. Begin
3563 frame_->Push(node->literals()); 3604 // with a writable copy of the function of this activation in a
3564 // Load the literals array of the current function. 3605 // register.
3565 frame_->PushFunction(); 3606 frame_->PushFunction();
3566 Result literals = frame_->Pop(); 3607 Result literals = frame_->Pop();
3567 literals.ToRegister(); 3608 literals.ToRegister();
3568 frame_->Spill(literals.reg()); // Make it writable. 3609 frame_->Spill(literals.reg());
3610
3611 // Load the literals array of the function.
3569 __ mov(literals.reg(), 3612 __ mov(literals.reg(),
3570 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); 3613 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
3571 frame_->Push(&literals); 3614
3572 Result array = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2); 3615 // Load the literal at the ast saved index.
3616 int literal_offset =
3617 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
3618 Result boilerplate = allocator_->Allocate();
3619 ASSERT(boilerplate.is_valid());
3620 __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset));
3621
3622 // Check whether we need to materialize the object literal boilerplate.
3623 // If so, jump to the deferred code passing the literals array.
3624 __ cmp(boilerplate.reg(), Factory::undefined_value());
3625 deferred->enter()->Branch(equal, &literals, not_taken);
3626
3627 literals.Unuse();
3628 // The deferred code returns the boilerplate object.
3629 deferred->BindExit(&boilerplate);
3573 3630
3574 // Push the resulting array literal on the stack. 3631 // Push the resulting array literal on the stack.
3575 frame_->Push(&array); 3632 frame_->Push(&boilerplate);
3633
3634 // Clone the boilerplate object.
3635 Result clone =
3636 frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1);
3637 // Push the newly cloned literal object as the result.
3638 frame_->Push(&clone);
3576 3639
3577 // Generate code to set the elements in the array that are not 3640 // Generate code to set the elements in the array that are not
3578 // literals. 3641 // literals.
3579 for (int i = 0; i < node->values()->length(); i++) { 3642 for (int i = 0; i < node->values()->length(); i++) {
3580 Expression* value = node->values()->at(i); 3643 Expression* value = node->values()->at(i);
3581 3644
3582 // If value is literal the property value is already set in the 3645 // If value is a literal the property value is already set in the
3583 // boilerplate object. 3646 // boilerplate object.
3584 if (value->AsLiteral() == NULL) { 3647 if (value->AsLiteral() != NULL) continue;
3585 // The property must be set by generated code. 3648 // If value is a materialized literal the property value is already set
3586 Load(value); 3649 // in the boilerplate object if it is simple.
3650 if (CompileTimeValue::IsCompileTimeValue(value)) continue;
3587 3651
3588 // Get the property value off the stack. 3652 // The property must be set by generated code.
3589 Result prop_value = frame_->Pop(); 3653 Load(value);
3590 prop_value.ToRegister();
3591 3654
3592 // Fetch the array literal while leaving a copy on the stack and 3655 // Get the property value off the stack.
3593 // use it to get the elements array. 3656 Result prop_value = frame_->Pop();
3594 frame_->Dup(); 3657 prop_value.ToRegister();
3595 Result elements = frame_->Pop();
3596 elements.ToRegister();
3597 frame_->Spill(elements.reg());
3598 // Get the elements array.
3599 __ mov(elements.reg(),
3600 FieldOperand(elements.reg(), JSObject::kElementsOffset));
3601 3658
3602 // Write to the indexed properties array. 3659 // Fetch the array literal while leaving a copy on the stack and
3603 int offset = i * kPointerSize + Array::kHeaderSize; 3660 // use it to get the elements array.
3604 __ mov(FieldOperand(elements.reg(), offset), prop_value.reg()); 3661 frame_->Dup();
3662 Result elements = frame_->Pop();
3663 elements.ToRegister();
3664 frame_->Spill(elements.reg());
3665 // Get the elements array.
3666 __ mov(elements.reg(),
3667 FieldOperand(elements.reg(), JSObject::kElementsOffset));
3605 3668
3606 // Update the write barrier for the array address. 3669 // Write to the indexed properties array.
3607 frame_->Spill(prop_value.reg()); // Overwritten by the write barrier. 3670 int offset = i * kPointerSize + Array::kHeaderSize;
3608 Result scratch = allocator_->Allocate(); 3671 __ mov(FieldOperand(elements.reg(), offset), prop_value.reg());
3609 ASSERT(scratch.is_valid()); 3672
3610 __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg()); 3673 // Update the write barrier for the array address.
3611 } 3674 frame_->Spill(prop_value.reg()); // Overwritten by the write barrier.
3675 Result scratch = allocator_->Allocate();
3676 ASSERT(scratch.is_valid());
3677 __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg());
3612 } 3678 }
3613 } 3679 }
3614 3680
3615 3681
3616 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { 3682 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) {
3617 ASSERT(!in_spilled_code()); 3683 ASSERT(!in_spilled_code());
3618 // Call runtime routine to allocate the catch extension object and 3684 // Call runtime routine to allocate the catch extension object and
3619 // assign the exception value to the catch variable. 3685 // assign the exception value to the catch variable.
3620 Comment cmnt(masm_, "[ CatchExtensionObject"); 3686 Comment cmnt(masm_, "[ CatchExtensionObject");
3621 Load(node->key()); 3687 Load(node->key());
(...skipping 3248 matching lines...) Expand 10 before | Expand all | Expand 10 after
6870 6936
6871 // Slow-case: Go through the JavaScript implementation. 6937 // Slow-case: Go through the JavaScript implementation.
6872 __ bind(&slow); 6938 __ bind(&slow);
6873 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6939 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6874 } 6940 }
6875 6941
6876 6942
6877 #undef __ 6943 #undef __
6878 6944
6879 } } // namespace v8::internal 6945 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | src/heap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698