Index: src/ia32/codegen-ia32.cc |
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc |
index 7ec3ff4c502ea67f98322fa8c7142741986be0a6..edf221bfb227689596b7d61e1500ee6d49c05f19 100644 |
--- a/src/ia32/codegen-ia32.cc |
+++ b/src/ia32/codegen-ia32.cc |
@@ -4762,8 +4762,9 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { |
Property* prop = node->target()->AsProperty(); |
ASSERT(var == NULL || (prop == NULL && var->is_global())); |
- // Initialize name and evaluate the receiver subexpression. |
+ // Initialize name and evaluate the receiver subexpression if necessary. |
Handle<String> name; |
+ bool is_trivial_receiver = false; |
if (var != NULL) { |
name = var->name(); |
LoadGlobal(); |
@@ -4771,17 +4772,23 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { |
Literal* lit = prop->key()->AsLiteral(); |
ASSERT(lit != NULL); |
name = Handle<String>::cast(lit->handle()); |
- Load(prop->obj()); |
+ // Do not materialize the receiver on the frame if it is trivial. |
+ is_trivial_receiver = prop->obj()->IsTrivial(); |
+ if (!is_trivial_receiver) Load(prop->obj()); |
} |
if (node->starts_initialization_block()) { |
// Change to slow case in the beginning of an initialization block to |
// avoid the quadratic behavior of repeatedly adding fast properties. |
- frame()->Dup(); |
+ if (is_trivial_receiver) { |
+ frame()->Push(prop->obj()); |
+ } else { |
+ frame()->Dup(); |
+ } |
Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1); |
} |
- if (node->ends_initialization_block()) { |
+ if (node->ends_initialization_block() && !is_trivial_receiver) { |
// Add an extra copy of the receiver to the frame, so that it can be |
// converted back to fast case after the assignment. |
frame()->Dup(); |
@@ -4789,7 +4796,11 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { |
// Evaluate the right-hand side. |
if (node->is_compound()) { |
- frame()->Dup(); |
+ if (is_trivial_receiver) { |
+ frame()->Push(prop->obj()); |
+ } else { |
+ frame()->Dup(); |
+ } |
Result value = EmitNamedLoad(name, var != NULL); |
frame()->Push(&value); |
Load(node->value()); |
@@ -4807,18 +4818,27 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { |
// Perform the assignment. It is safe to ignore constants here. |
ASSERT(var == NULL || var->mode() != Variable::CONST); |
ASSERT(node->op() != Token::INIT_CONST); |
+ if (is_trivial_receiver) { |
+ Result value = frame()->Pop(); |
+ frame()->Push(prop->obj()); |
+ frame()->Push(&value); |
+ } |
CodeForSourcePosition(node->position()); |
Result answer = EmitNamedStore(name); |
frame()->Push(&answer); |
if (node->ends_initialization_block()) { |
- // The argument to the runtime call is the extra copy of the receiver, |
- // which is below the value of the assignment. Swap the receiver and |
- // the value of the assignment expression. |
- Result result = frame()->Pop(); |
- Result receiver = frame()->Pop(); |
- frame()->Push(&result); |
- frame()->Push(&receiver); |
+ // The argument to the runtime call is the receiver. |
+ if (is_trivial_receiver) { |
+ frame()->Push(prop->obj()); |
+ } else { |
+ // A copy of the receiver is below the value of the assignment. Swap |
+ // the receiver and the value of the assignment expression. |
+ Result result = frame()->Pop(); |
+ Result receiver = frame()->Pop(); |
+ frame()->Push(&result); |
+ frame()->Push(&receiver); |
+ } |
Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); |
} |