OLD | NEW |
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 4744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4755 | 4755 |
4756 void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { | 4756 void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { |
4757 #ifdef DEBUG | 4757 #ifdef DEBUG |
4758 int original_height = frame()->height(); | 4758 int original_height = frame()->height(); |
4759 #endif | 4759 #endif |
4760 Comment cmnt(masm(), "[ Named Property Assignment"); | 4760 Comment cmnt(masm(), "[ Named Property Assignment"); |
4761 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | 4761 Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
4762 Property* prop = node->target()->AsProperty(); | 4762 Property* prop = node->target()->AsProperty(); |
4763 ASSERT(var == NULL || (prop == NULL && var->is_global())); | 4763 ASSERT(var == NULL || (prop == NULL && var->is_global())); |
4764 | 4764 |
4765 // Initialize name and evaluate the receiver subexpression. | 4765 // Initialize name and evaluate the receiver subexpression if necessary. |
4766 Handle<String> name; | 4766 Handle<String> name; |
| 4767 bool is_trivial_receiver = false; |
4767 if (var != NULL) { | 4768 if (var != NULL) { |
4768 name = var->name(); | 4769 name = var->name(); |
4769 LoadGlobal(); | 4770 LoadGlobal(); |
4770 } else { | 4771 } else { |
4771 Literal* lit = prop->key()->AsLiteral(); | 4772 Literal* lit = prop->key()->AsLiteral(); |
4772 ASSERT(lit != NULL); | 4773 ASSERT(lit != NULL); |
4773 name = Handle<String>::cast(lit->handle()); | 4774 name = Handle<String>::cast(lit->handle()); |
4774 Load(prop->obj()); | 4775 // Do not materialize the receiver on the frame if it is trivial. |
| 4776 is_trivial_receiver = prop->obj()->IsTrivial(); |
| 4777 if (!is_trivial_receiver) Load(prop->obj()); |
4775 } | 4778 } |
4776 | 4779 |
4777 if (node->starts_initialization_block()) { | 4780 if (node->starts_initialization_block()) { |
4778 // Change to slow case in the beginning of an initialization block to | 4781 // Change to slow case in the beginning of an initialization block to |
4779 // avoid the quadratic behavior of repeatedly adding fast properties. | 4782 // avoid the quadratic behavior of repeatedly adding fast properties. |
4780 frame()->Dup(); | 4783 if (is_trivial_receiver) { |
| 4784 frame()->Push(prop->obj()); |
| 4785 } else { |
| 4786 frame()->Dup(); |
| 4787 } |
4781 Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1); | 4788 Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1); |
4782 } | 4789 } |
4783 | 4790 |
4784 if (node->ends_initialization_block()) { | 4791 if (node->ends_initialization_block() && !is_trivial_receiver) { |
4785 // Add an extra copy of the receiver to the frame, so that it can be | 4792 // Add an extra copy of the receiver to the frame, so that it can be |
4786 // converted back to fast case after the assignment. | 4793 // converted back to fast case after the assignment. |
4787 frame()->Dup(); | 4794 frame()->Dup(); |
4788 } | 4795 } |
4789 | 4796 |
4790 // Evaluate the right-hand side. | 4797 // Evaluate the right-hand side. |
4791 if (node->is_compound()) { | 4798 if (node->is_compound()) { |
4792 frame()->Dup(); | 4799 if (is_trivial_receiver) { |
| 4800 frame()->Push(prop->obj()); |
| 4801 } else { |
| 4802 frame()->Dup(); |
| 4803 } |
4793 Result value = EmitNamedLoad(name, var != NULL); | 4804 Result value = EmitNamedLoad(name, var != NULL); |
4794 frame()->Push(&value); | 4805 frame()->Push(&value); |
4795 Load(node->value()); | 4806 Load(node->value()); |
4796 | 4807 |
4797 bool overwrite_value = | 4808 bool overwrite_value = |
4798 (node->value()->AsBinaryOperation() != NULL && | 4809 (node->value()->AsBinaryOperation() != NULL && |
4799 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 4810 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
4800 GenericBinaryOperation(node->binary_op(), | 4811 GenericBinaryOperation(node->binary_op(), |
4801 node->type(), | 4812 node->type(), |
4802 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 4813 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
4803 } else { | 4814 } else { |
4804 Load(node->value()); | 4815 Load(node->value()); |
4805 } | 4816 } |
4806 | 4817 |
4807 // Perform the assignment. It is safe to ignore constants here. | 4818 // Perform the assignment. It is safe to ignore constants here. |
4808 ASSERT(var == NULL || var->mode() != Variable::CONST); | 4819 ASSERT(var == NULL || var->mode() != Variable::CONST); |
4809 ASSERT(node->op() != Token::INIT_CONST); | 4820 ASSERT(node->op() != Token::INIT_CONST); |
| 4821 if (is_trivial_receiver) { |
| 4822 Result value = frame()->Pop(); |
| 4823 frame()->Push(prop->obj()); |
| 4824 frame()->Push(&value); |
| 4825 } |
4810 CodeForSourcePosition(node->position()); | 4826 CodeForSourcePosition(node->position()); |
4811 Result answer = EmitNamedStore(name); | 4827 Result answer = EmitNamedStore(name); |
4812 frame()->Push(&answer); | 4828 frame()->Push(&answer); |
4813 | 4829 |
4814 if (node->ends_initialization_block()) { | 4830 if (node->ends_initialization_block()) { |
4815 // The argument to the runtime call is the extra copy of the receiver, | 4831 // The argument to the runtime call is the receiver. |
4816 // which is below the value of the assignment. Swap the receiver and | 4832 if (is_trivial_receiver) { |
4817 // the value of the assignment expression. | 4833 frame()->Push(prop->obj()); |
4818 Result result = frame()->Pop(); | 4834 } else { |
4819 Result receiver = frame()->Pop(); | 4835 // A copy of the receiver is below the value of the assignment. Swap |
4820 frame()->Push(&result); | 4836 // the receiver and the value of the assignment expression. |
4821 frame()->Push(&receiver); | 4837 Result result = frame()->Pop(); |
| 4838 Result receiver = frame()->Pop(); |
| 4839 frame()->Push(&result); |
| 4840 frame()->Push(&receiver); |
| 4841 } |
4822 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); | 4842 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); |
4823 } | 4843 } |
4824 | 4844 |
4825 ASSERT(frame()->height() == original_height + 1); | 4845 ASSERT(frame()->height() == original_height + 1); |
4826 } | 4846 } |
4827 | 4847 |
4828 | 4848 |
4829 void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { | 4849 void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { |
4830 #ifdef DEBUG | 4850 #ifdef DEBUG |
4831 int original_height = frame()->height(); | 4851 int original_height = frame()->height(); |
(...skipping 5904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10736 | 10756 |
10737 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 10757 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
10738 // tagged as a small integer. | 10758 // tagged as a small integer. |
10739 __ bind(&runtime); | 10759 __ bind(&runtime); |
10740 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 10760 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
10741 } | 10761 } |
10742 | 10762 |
10743 #undef __ | 10763 #undef __ |
10744 | 10764 |
10745 } } // namespace v8::internal | 10765 } } // namespace v8::internal |
OLD | NEW |