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

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

Issue 650028: Improve stores to global variables. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 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/ia32/codegen-ia32.h ('k') | src/ia32/virtual-frame-ia32.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 if (property->key()->IsPropertyName()) { 688 if (property->key()->IsPropertyName()) {
689 ref->set_type(Reference::NAMED); 689 ref->set_type(Reference::NAMED);
690 } else { 690 } else {
691 Load(property->key()); 691 Load(property->key());
692 ref->set_type(Reference::KEYED); 692 ref->set_type(Reference::KEYED);
693 } 693 }
694 } else if (var != NULL) { 694 } else if (var != NULL) {
695 // The expression is a variable proxy that does not rewrite to a 695 // The expression is a variable proxy that does not rewrite to a
696 // property. Global variables are treated as named property references. 696 // property. Global variables are treated as named property references.
697 if (var->is_global()) { 697 if (var->is_global()) {
698 // Named loads require object in eax. Named stores don't use references. 698 // If eax is free, the register allocator prefers it. Thus the code
699 // Spilling eax makes it free, so LoadGlobal loads directly into eax. 699 // generator will load the global object into eax, which is where
700 // LoadIC wants it. Most uses of Reference call LoadIC directly
701 // after the reference is created.
700 frame_->Spill(eax); 702 frame_->Spill(eax);
701 LoadGlobal(); 703 LoadGlobal();
702 ref->set_type(Reference::NAMED); 704 ref->set_type(Reference::NAMED);
703 } else { 705 } else {
704 ASSERT(var->slot() != NULL); 706 ASSERT(var->slot() != NULL);
705 ref->set_type(Reference::SLOT); 707 ref->set_type(Reference::SLOT);
706 } 708 }
707 } else { 709 } else {
708 // Anything else is a runtime error. 710 // Anything else is a runtime error.
709 Load(e); 711 Load(e);
(...skipping 3599 matching lines...) Expand 10 before | Expand all | Expand 10 after
4309 // Load next context in chain. 4311 // Load next context in chain.
4310 __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX)); 4312 __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX));
4311 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); 4313 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
4312 __ jmp(&next); 4314 __ jmp(&next);
4313 __ bind(&fast); 4315 __ bind(&fast);
4314 } 4316 }
4315 tmp.Unuse(); 4317 tmp.Unuse();
4316 4318
4317 // All extension objects were empty and it is safe to use a global 4319 // All extension objects were empty and it is safe to use a global
4318 // load IC call. 4320 // load IC call.
4321 // The register allocator prefers eax if it is free, so the code generator
4322 // will load the global object directly into eax, which is where the LoadIC
4323 // expects it.
4324 frame_->Spill(eax);
4319 LoadGlobal(); 4325 LoadGlobal();
4320 frame_->Push(slot->var()->name()); 4326 frame_->Push(slot->var()->name());
4321 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 4327 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
4322 ? RelocInfo::CODE_TARGET 4328 ? RelocInfo::CODE_TARGET
4323 : RelocInfo::CODE_TARGET_CONTEXT; 4329 : RelocInfo::CODE_TARGET_CONTEXT;
4324 Result answer = frame_->CallLoadIC(mode); 4330 Result answer = frame_->CallLoadIC(mode);
4325 // A test eax instruction following the call signals that the inobject 4331 // A test eax instruction following the call signals that the inobject
4326 // property case was inlined. Ensure that there is not a test eax 4332 // property case was inlined. Ensure that there is not a test eax
4327 // instruction here. 4333 // instruction here.
4328 __ nop(); 4334 __ nop();
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
4594 break; 4600 break;
4595 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 4601 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
4596 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; 4602 if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
4597 // else fall through. 4603 // else fall through.
4598 case ObjectLiteral::Property::COMPUTED: { 4604 case ObjectLiteral::Property::COMPUTED: {
4599 Handle<Object> key(property->key()->handle()); 4605 Handle<Object> key(property->key()->handle());
4600 if (key->IsSymbol()) { 4606 if (key->IsSymbol()) {
4601 // Duplicate the object as the IC receiver. 4607 // Duplicate the object as the IC receiver.
4602 frame_->Dup(); 4608 frame_->Dup();
4603 Load(property->value()); 4609 Load(property->value());
4604 frame_->Push(key); 4610 Result dummy = frame_->CallStoreIC(Handle<String>::cast(key), false);
4605 Result ignored = frame_->CallStoreIC(); 4611 dummy.Unuse();
4606 break; 4612 break;
4607 } 4613 }
4608 // Fall through 4614 // Fall through
4609 } 4615 }
4610 case ObjectLiteral::Property::PROTOTYPE: { 4616 case ObjectLiteral::Property::PROTOTYPE: {
4611 // Duplicate the object as an argument to the runtime call. 4617 // Duplicate the object as an argument to the runtime call.
4612 frame_->Dup(); 4618 frame_->Dup();
4613 Load(property->key()); 4619 Load(property->key());
4614 Load(property->value()); 4620 Load(property->value());
4615 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); 4621 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
4769 Comment cmnt(masm(), "[ Named Property Assignment"); 4775 Comment cmnt(masm(), "[ Named Property Assignment");
4770 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 4776 Variable* var = node->target()->AsVariableProxy()->AsVariable();
4771 Property* prop = node->target()->AsProperty(); 4777 Property* prop = node->target()->AsProperty();
4772 ASSERT(var == NULL || (prop == NULL && var->is_global())); 4778 ASSERT(var == NULL || (prop == NULL && var->is_global()));
4773 4779
4774 // Initialize name and evaluate the receiver subexpression if necessary. 4780 // Initialize name and evaluate the receiver subexpression if necessary.
4775 Handle<String> name; 4781 Handle<String> name;
4776 bool is_trivial_receiver = false; 4782 bool is_trivial_receiver = false;
4777 if (var != NULL) { 4783 if (var != NULL) {
4778 name = var->name(); 4784 name = var->name();
4779 LoadGlobal();
4780 } else { 4785 } else {
4781 Literal* lit = prop->key()->AsLiteral(); 4786 Literal* lit = prop->key()->AsLiteral();
4782 ASSERT(lit != NULL); 4787 ASSERT_NOT_NULL(lit);
4783 name = Handle<String>::cast(lit->handle()); 4788 name = Handle<String>::cast(lit->handle());
4784 // Do not materialize the receiver on the frame if it is trivial. 4789 // Do not materialize the receiver on the frame if it is trivial.
4785 is_trivial_receiver = prop->obj()->IsTrivial(); 4790 is_trivial_receiver = prop->obj()->IsTrivial();
4786 if (!is_trivial_receiver) Load(prop->obj()); 4791 if (!is_trivial_receiver) Load(prop->obj());
4787 } 4792 }
4788 4793
4789 if (node->starts_initialization_block()) { 4794 if (node->starts_initialization_block()) {
4795 ASSERT_EQ(NULL, var);
4790 // Change to slow case in the beginning of an initialization block to 4796 // Change to slow case in the beginning of an initialization block to
4791 // avoid the quadratic behavior of repeatedly adding fast properties. 4797 // avoid the quadratic behavior of repeatedly adding fast properties.
4792 if (is_trivial_receiver) { 4798 if (is_trivial_receiver) {
4793 frame()->Push(prop->obj()); 4799 frame()->Push(prop->obj());
4794 } else { 4800 } else {
4795 frame()->Dup(); 4801 frame()->Dup();
4796 } 4802 }
4797 Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1); 4803 Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1);
4798 } 4804 }
4799 4805
4800 if (node->ends_initialization_block() && !is_trivial_receiver) { 4806 if (node->ends_initialization_block() && !is_trivial_receiver) {
4801 // Add an extra copy of the receiver to the frame, so that it can be 4807 // Add an extra copy of the receiver to the frame, so that it can be
4802 // converted back to fast case after the assignment. 4808 // converted back to fast case after the assignment.
4803 frame()->Dup(); 4809 frame()->Dup();
4804 } 4810 }
4805 4811
4806 // Evaluate the right-hand side. 4812 // Evaluate the right-hand side.
4807 if (node->is_compound()) { 4813 if (node->is_compound()) {
4808 if (is_trivial_receiver) { 4814 if (is_trivial_receiver) {
4809 frame()->Push(prop->obj()); 4815 frame()->Push(prop->obj());
4816 } else if (var != NULL) {
4817 // The LoadIC stub expects the object in eax.
4818 // Freeing eax causes the code generator to load the global into it.
4819 frame_->Spill(eax);
4820 LoadGlobal();
4810 } else { 4821 } else {
4811 frame()->Dup(); 4822 frame()->Dup();
4812 } 4823 }
4813 Result value = EmitNamedLoad(name, var != NULL); 4824 Result value = EmitNamedLoad(name, var != NULL);
4814 frame()->Push(&value); 4825 frame()->Push(&value);
4815 Load(node->value()); 4826 Load(node->value());
4816 4827
4817 bool overwrite_value = 4828 bool overwrite_value =
4818 (node->value()->AsBinaryOperation() != NULL && 4829 (node->value()->AsBinaryOperation() != NULL &&
4819 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 4830 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
4820 GenericBinaryOperation(node->binary_op(), 4831 GenericBinaryOperation(node->binary_op(),
4821 node->type(), 4832 node->type(),
4822 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); 4833 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
4823 } else { 4834 } else {
4824 Load(node->value()); 4835 Load(node->value());
4825 } 4836 }
4826 4837
4827 // Perform the assignment. It is safe to ignore constants here. 4838 // Perform the assignment. It is safe to ignore constants here.
4828 ASSERT(var == NULL || var->mode() != Variable::CONST); 4839 ASSERT(var == NULL || var->mode() != Variable::CONST);
4829 ASSERT(node->op() != Token::INIT_CONST); 4840 ASSERT_NE(Token::INIT_CONST, node->op());
4830 if (is_trivial_receiver) { 4841 if (is_trivial_receiver) {
4831 Result value = frame()->Pop(); 4842 Result value = frame()->Pop();
4832 frame()->Push(prop->obj()); 4843 frame()->Push(prop->obj());
4833 frame()->Push(&value); 4844 frame()->Push(&value);
4834 } 4845 }
4835 CodeForSourcePosition(node->position()); 4846 CodeForSourcePosition(node->position());
4836 Result answer = EmitNamedStore(name); 4847 bool is_contextual = (var != NULL);
4848 Result answer = EmitNamedStore(name, is_contextual);
4837 frame()->Push(&answer); 4849 frame()->Push(&answer);
4838 4850
4839 if (node->ends_initialization_block()) { 4851 if (node->ends_initialization_block()) {
4852 ASSERT_EQ(NULL, var);
4840 // The argument to the runtime call is the receiver. 4853 // The argument to the runtime call is the receiver.
4841 if (is_trivial_receiver) { 4854 if (is_trivial_receiver) {
4842 frame()->Push(prop->obj()); 4855 frame()->Push(prop->obj());
4843 } else { 4856 } else {
4844 // A copy of the receiver is below the value of the assignment. Swap 4857 // A copy of the receiver is below the value of the assignment. Swap
4845 // the receiver and the value of the assignment expression. 4858 // the receiver and the value of the assignment expression.
4846 Result result = frame()->Pop(); 4859 Result result = frame()->Pop();
4847 Result receiver = frame()->Pop(); 4860 Result receiver = frame()->Pop();
4848 frame()->Push(&result); 4861 frame()->Push(&result);
4849 frame()->Push(&receiver); 4862 frame()->Push(&receiver);
4850 } 4863 }
4851 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); 4864 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
4852 } 4865 }
4853 4866
4854 ASSERT(frame()->height() == original_height + 1); 4867 ASSERT_EQ(frame()->height(), original_height + 1);
4855 } 4868 }
4856 4869
4857 4870
4858 void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { 4871 void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
4859 #ifdef DEBUG 4872 #ifdef DEBUG
4860 int original_height = frame()->height(); 4873 int original_height = frame()->height();
4861 #endif 4874 #endif
4862 Comment cmnt(masm_, "[ Named Property Assignment"); 4875 Comment cmnt(masm_, "[ Named Property Assignment");
4863 Property* prop = node->target()->AsProperty(); 4876 Property* prop = node->target()->AsProperty();
4864 ASSERT(prop != NULL); 4877 ASSERT_NOT_NULL(prop);
4865 4878
4866 // Evaluate the receiver subexpression. 4879 // Evaluate the receiver subexpression.
4867 Load(prop->obj()); 4880 Load(prop->obj());
4868 4881
4869 if (node->starts_initialization_block()) { 4882 if (node->starts_initialization_block()) {
4870 // Change to slow case in the beginning of an initialization block to 4883 // Change to slow case in the beginning of an initialization block to
4871 // avoid the quadratic behavior of repeatedly adding fast properties. 4884 // avoid the quadratic behavior of repeatedly adding fast properties.
4872 frame_->Dup(); 4885 frame_->Dup();
4873 Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1); 4886 Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1);
4874 } 4887 }
(...skipping 1897 matching lines...) Expand 10 before | Expand all | Expand 10 after
6772 masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset)); 6785 masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset));
6773 6786
6774 __ IncrementCounter(&Counters::named_load_inline, 1); 6787 __ IncrementCounter(&Counters::named_load_inline, 1);
6775 deferred->BindExit(); 6788 deferred->BindExit();
6776 } 6789 }
6777 ASSERT(frame()->height() == original_height - 1); 6790 ASSERT(frame()->height() == original_height - 1);
6778 return result; 6791 return result;
6779 } 6792 }
6780 6793
6781 6794
6782 Result CodeGenerator::EmitNamedStore(Handle<String> name) { 6795 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
6783 #ifdef DEBUG 6796 #ifdef DEBUG
6784 int original_height = frame()->height(); 6797 int expected_height = frame()->height() - (is_contextual ? 1 : 2);
6785 #endif 6798 #endif
6786 frame()->Push(name); 6799 Result result = frame()->CallStoreIC(name, is_contextual);
6787 Result result = frame()->CallStoreIC();
6788 6800
6789 ASSERT(frame()->height() == original_height - 2); 6801 ASSERT_EQ(expected_height, frame()->height());
6790 return result; 6802 return result;
6791 } 6803 }
6792 6804
6793 6805
6794 Result CodeGenerator::EmitKeyedLoad() { 6806 Result CodeGenerator::EmitKeyedLoad() {
6795 #ifdef DEBUG 6807 #ifdef DEBUG
6796 int original_height = frame()->height(); 6808 int original_height = frame()->height();
6797 #endif 6809 #endif
6798 Result result; 6810 Result result;
6799 // Inline array load code if inside of a loop. We do not know the 6811 // Inline array load code if inside of a loop. We do not know the
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
7096 Comment cmnt(masm, "[ Store to Slot"); 7108 Comment cmnt(masm, "[ Store to Slot");
7097 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 7109 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
7098 ASSERT(slot != NULL); 7110 ASSERT(slot != NULL);
7099 cgen_->StoreToSlot(slot, init_state); 7111 cgen_->StoreToSlot(slot, init_state);
7100 set_unloaded(); 7112 set_unloaded();
7101 break; 7113 break;
7102 } 7114 }
7103 7115
7104 case NAMED: { 7116 case NAMED: {
7105 Comment cmnt(masm, "[ Store to named Property"); 7117 Comment cmnt(masm, "[ Store to named Property");
7106 Result answer = cgen_->EmitNamedStore(GetName()); 7118 Result answer = cgen_->EmitNamedStore(GetName(), false);
7107 cgen_->frame()->Push(&answer); 7119 cgen_->frame()->Push(&answer);
7108 set_unloaded(); 7120 set_unloaded();
7109 break; 7121 break;
7110 } 7122 }
7111 7123
7112 case KEYED: { 7124 case KEYED: {
7113 Comment cmnt(masm, "[ Store to keyed Property"); 7125 Comment cmnt(masm, "[ Store to keyed Property");
7114 Property* property = expression()->AsProperty(); 7126 Property* property = expression()->AsProperty();
7115 ASSERT(property != NULL); 7127 ASSERT(property != NULL);
7116 Result answer = cgen_->EmitKeyedStore(property->key()->type()); 7128 Result answer = cgen_->EmitKeyedStore(property->key()->type());
(...skipping 3664 matching lines...) Expand 10 before | Expand all | Expand 10 after
10781 10793
10782 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 10794 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
10783 // tagged as a small integer. 10795 // tagged as a small integer.
10784 __ bind(&runtime); 10796 __ bind(&runtime);
10785 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 10797 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
10786 } 10798 }
10787 10799
10788 #undef __ 10800 #undef __
10789 10801
10790 } } // namespace v8::internal 10802 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/virtual-frame-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698