| 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 |